diff options
Diffstat (limited to 'examples')
470 files changed, 8540 insertions, 1443 deletions
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index f5f89ecb5..ccaa24e3e 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-nrf-examples" | 3 | name = "embassy-boot-nrf-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -9,9 +9,9 @@ publish = false | |||
| 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } |
| 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } |
| 12 | embassy-nrf = { version = "0.8.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } | 12 | embassy-nrf = { version = "0.9.0", path = "../../../../embassy-nrf", features = ["gpiote", ] } |
| 13 | embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } | 13 | embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } |
| 14 | embassy-boot-nrf = { version = "0.9.0", path = "../../../../embassy-boot-nrf", features = [] } | 14 | embassy-boot-nrf = { version = "0.10.0", path = "../../../../embassy-boot-nrf", features = [] } |
| 15 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } | 15 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 16 | 16 | ||
| 17 | defmt = { version = "1.0.1", optional = true } | 17 | defmt = { version = "1.0.1", optional = true } |
| @@ -33,12 +33,14 @@ defmt = [ | |||
| 33 | "embassy-boot-nrf/defmt", | 33 | "embassy-boot-nrf/defmt", |
| 34 | "embassy-sync/defmt", | 34 | "embassy-sync/defmt", |
| 35 | ] | 35 | ] |
| 36 | nrf54 = ["embassy-nrf/time-driver-grtc"] | ||
| 36 | 37 | ||
| 37 | [package.metadata.embassy] | 38 | [package.metadata.embassy] |
| 38 | build = [ | 39 | build = [ |
| 39 | { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" }, | 40 | { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" }, |
| 40 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" }, | 41 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" }, |
| 41 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" }, | 42 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" }, |
| 42 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" }, | 43 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" }, |
| 43 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" } | 44 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" }, |
| 45 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf54l15-app-s", "nrf54", "skip-include"], artifact-dir = "out/examples/boot/nrf54l15" } | ||
| 44 | ] | 46 | ] |
diff --git a/examples/boot/application/nrf/README.md b/examples/boot/application/nrf/README.md index 9d6d20336..c92ccb358 100644 --- a/examples/boot/application/nrf/README.md +++ b/examples/boot/application/nrf/README.md | |||
| @@ -22,7 +22,7 @@ cp memory-bl.x ../../bootloader/nrf/memory.x | |||
| 22 | # Flash bootloader | 22 | # Flash bootloader |
| 23 | cargo flash --manifest-path ../../bootloader/nrf/Cargo.toml --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi --release --chip nRF52840_xxAA | 23 | cargo flash --manifest-path ../../bootloader/nrf/Cargo.toml --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi --release --chip nRF52840_xxAA |
| 24 | # Build 'b' | 24 | # Build 'b' |
| 25 | cargo build --release --bin b --features embassy-nrf/nrf52840 | 25 | cargo build --release --bin b --features embassy-nrf/nrf52840,time-driver-rtc1 |
| 26 | # Generate binary for 'b' | 26 | # Generate binary for 'b' |
| 27 | cargo objcopy --release --bin b --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi -- -O binary b.bin | 27 | cargo objcopy --release --bin b --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi -- -O binary b.bin |
| 28 | ``` | 28 | ``` |
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs index 2c1d1a7bb..035ffe214 100644 --- a/examples/boot/application/nrf/src/bin/a.rs +++ b/examples/boot/application/nrf/src/bin/a.rs | |||
| @@ -23,10 +23,21 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); | |||
| 23 | async fn main(_spawner: Spawner) { | 23 | async fn main(_spawner: Spawner) { |
| 24 | let p = embassy_nrf::init(Default::default()); | 24 | let p = embassy_nrf::init(Default::default()); |
| 25 | 25 | ||
| 26 | #[cfg(not(feature = "nrf54"))] | ||
| 26 | let mut button = Input::new(p.P0_11, Pull::Up); | 27 | let mut button = Input::new(p.P0_11, Pull::Up); |
| 28 | #[cfg(not(feature = "nrf54"))] | ||
| 27 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); | 29 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); |
| 30 | #[cfg(not(feature = "nrf54"))] | ||
| 28 | let mut led_reverted = Output::new(p.P0_14, Level::High, OutputDrive::Standard); | 31 | let mut led_reverted = Output::new(p.P0_14, Level::High, OutputDrive::Standard); |
| 29 | 32 | ||
| 33 | // nRF54 DK | ||
| 34 | #[cfg(feature = "nrf54")] | ||
| 35 | let mut button = Input::new(p.P1_13, Pull::Up); | ||
| 36 | #[cfg(feature = "nrf54")] | ||
| 37 | let mut led = Output::new(p.P1_14, Level::Low, OutputDrive::Standard); | ||
| 38 | #[cfg(feature = "nrf54")] | ||
| 39 | let mut led_reverted = Output::new(p.P2_09, Level::High, OutputDrive::Standard); | ||
| 40 | |||
| 30 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); | 41 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); |
| 31 | //let mut button = Input::new(p.P1_02, Pull::Up); | 42 | //let mut button = Input::new(p.P1_02, Pull::Up); |
| 32 | 43 | ||
| @@ -40,8 +51,12 @@ async fn main(_spawner: Spawner) { | |||
| 40 | // the watchdog will cause the device to reset as per its configured timeout in the bootloader. | 51 | // the watchdog will cause the device to reset as per its configured timeout in the bootloader. |
| 41 | // This helps is avoid a situation where new firmware might be bad and block our executor. | 52 | // This helps is avoid a situation where new firmware might be bad and block our executor. |
| 42 | // If firmware is bad in this way then the bootloader will revert to any previous version. | 53 | // If firmware is bad in this way then the bootloader will revert to any previous version. |
| 43 | let wdt_config = wdt::Config::try_new(&p.WDT).unwrap(); | 54 | #[cfg(feature = "nrf54")] |
| 44 | let (_wdt, [_wdt_handle]) = match Watchdog::try_new(p.WDT, wdt_config) { | 55 | let wdt = p.WDT0; |
| 56 | #[cfg(not(feature = "nrf54"))] | ||
| 57 | let wdt = p.WDT; | ||
| 58 | let wdt_config = wdt::Config::try_new(&wdt).unwrap(); | ||
| 59 | let (_wdt, [_wdt_handle]) = match Watchdog::try_new(wdt, wdt_config) { | ||
| 45 | Ok(x) => x, | 60 | Ok(x) => x, |
| 46 | Err(_) => { | 61 | Err(_) => { |
| 47 | // Watchdog already active with the wrong number of handles, waiting for it to timeout... | 62 | // Watchdog already active with the wrong number of handles, waiting for it to timeout... |
| @@ -51,11 +66,15 @@ async fn main(_spawner: Spawner) { | |||
| 51 | } | 66 | } |
| 52 | }; | 67 | }; |
| 53 | 68 | ||
| 69 | // RRAMC for nRF54 | ||
| 70 | #[cfg(feature = "nrf54")] | ||
| 71 | let nvmc = Nvmc::new(p.RRAMC); | ||
| 72 | #[cfg(not(feature = "nrf54"))] | ||
| 54 | let nvmc = Nvmc::new(p.NVMC); | 73 | let nvmc = Nvmc::new(p.NVMC); |
| 55 | let nvmc = Mutex::new(BlockingAsync::new(nvmc)); | 74 | let nvmc = Mutex::new(BlockingAsync::new(nvmc)); |
| 56 | 75 | ||
| 57 | let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc, &nvmc); | 76 | let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc, &nvmc); |
| 58 | let mut magic = [0; 4]; | 77 | let mut magic = [0; 16]; |
| 59 | let mut updater = FirmwareUpdater::new(config, &mut magic); | 78 | let mut updater = FirmwareUpdater::new(config, &mut magic); |
| 60 | let state = updater.get_state().await.unwrap(); | 79 | let state = updater.get_state().await.unwrap(); |
| 61 | if state == State::Revert { | 80 | if state == State::Revert { |
diff --git a/examples/boot/application/nrf/src/bin/b.rs b/examples/boot/application/nrf/src/bin/b.rs index de97b6a22..6718df5a1 100644 --- a/examples/boot/application/nrf/src/bin/b.rs +++ b/examples/boot/application/nrf/src/bin/b.rs | |||
| @@ -10,11 +10,15 @@ use panic_reset as _; | |||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 11 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | #[cfg(not(feature = "nrf54"))] | ||
| 13 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); | 14 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); |
| 14 | // let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); | 15 | // let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); |
| 15 | 16 | ||
| 16 | // nRF91 DK | 17 | // nRF91 DK |
| 17 | // let mut led = Output::new(p.P0_02, Level::Low, OutputDrive::Standard); | 18 | // let mut led = Output::new(p.P0_02, Level::Low, OutputDrive::Standard); |
| 19 | // nrf54l15 dk | ||
| 20 | #[cfg(feature = "nrf54")] | ||
| 21 | let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); | ||
| 18 | 22 | ||
| 19 | loop { | 23 | loop { |
| 20 | led.set_high(); | 24 | led.set_high(); |
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index d86386b00..292d1abec 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-rp-examples" | 3 | name = "embassy-boot-rp-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -9,8 +9,8 @@ publish = false | |||
| 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } | 9 | embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } |
| 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } |
| 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } | 11 | embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } |
| 12 | embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } | 12 | embassy-rp = { version = "0.9.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } |
| 13 | embassy-boot-rp = { version = "0.8.0", path = "../../../../embassy-boot-rp", features = [] } | 13 | embassy-boot-rp = { version = "0.9.0", path = "../../../../embassy-boot-rp", features = [] } |
| 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } |
| 15 | 15 | ||
| 16 | defmt = "1.0.1" | 16 | defmt = "1.0.1" |
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index cd5f422fc..2dc75d939 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32f3-examples" | 3 | name = "embassy-boot-stm32f3-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs index b608b2e01..da3cbf1e6 100644 --- a/examples/boot/application/stm32f3/src/bin/a.rs +++ b/examples/boot/application/stm32f3/src/bin/a.rs | |||
| @@ -6,12 +6,18 @@ use defmt_rtt::*; | |||
| 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; | 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; |
| 7 | use embassy_embedded_hal::adapter::BlockingAsync; | 7 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::exti::ExtiInput; | 9 | use embassy_stm32::exti::{self, ExtiInput}; |
| 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 12 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 12 | use embassy_sync::mutex::Mutex; | 13 | use embassy_sync::mutex::Mutex; |
| 13 | use panic_reset as _; | 14 | use panic_reset as _; |
| 14 | 15 | ||
| 16 | bind_interrupts!( | ||
| 17 | pub struct Irqs{ | ||
| 18 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 19 | }); | ||
| 20 | |||
| 15 | #[cfg(feature = "skip-include")] | 21 | #[cfg(feature = "skip-include")] |
| 16 | static APP_B: &[u8] = &[0, 1, 2, 3]; | 22 | static APP_B: &[u8] = &[0, 1, 2, 3]; |
| 17 | #[cfg(not(feature = "skip-include"))] | 23 | #[cfg(not(feature = "skip-include"))] |
| @@ -23,7 +29,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | let flash = Flash::new_blocking(p.FLASH); | 29 | let flash = Flash::new_blocking(p.FLASH); |
| 24 | let flash = Mutex::new(BlockingAsync::new(flash)); | 30 | let flash = Mutex::new(BlockingAsync::new(flash)); |
| 25 | 31 | ||
| 26 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 32 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 27 | 33 | ||
| 28 | let mut led = Output::new(p.PA5, Level::Low, Speed::Low); | 34 | let mut led = Output::new(p.PA5, Level::Low, Speed::Low); |
| 29 | led.set_high(); | 35 | led.set_high(); |
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index c3921a166..5c372fb19 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32f7-examples" | 3 | name = "embassy-boot-stm32f7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs index 172b4c235..62f1da269 100644 --- a/examples/boot/application/stm32f7/src/bin/a.rs +++ b/examples/boot/application/stm32f7/src/bin/a.rs | |||
| @@ -7,9 +7,10 @@ use core::cell::RefCell; | |||
| 7 | use defmt_rtt::*; | 7 | use defmt_rtt::*; |
| 8 | use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; | 8 | use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::exti::ExtiInput; | 10 | use embassy_stm32::exti::{self, ExtiInput}; |
| 11 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 11 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 12 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 12 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 13 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 13 | use embassy_sync::blocking_mutex::Mutex; | 14 | use embassy_sync::blocking_mutex::Mutex; |
| 14 | use embedded_storage::nor_flash::NorFlash; | 15 | use embedded_storage::nor_flash::NorFlash; |
| 15 | use panic_reset as _; | 16 | use panic_reset as _; |
| @@ -19,13 +20,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3]; | |||
| 19 | #[cfg(not(feature = "skip-include"))] | 20 | #[cfg(not(feature = "skip-include"))] |
| 20 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 21 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| 21 | 22 | ||
| 23 | bind_interrupts!( | ||
| 24 | pub struct Irqs{ | ||
| 25 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 26 | }); | ||
| 27 | |||
| 22 | #[embassy_executor::main] | 28 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 29 | async fn main(_spawner: Spawner) { |
| 24 | let p = embassy_stm32::init(Default::default()); | 30 | let p = embassy_stm32::init(Default::default()); |
| 25 | let flash = Flash::new_blocking(p.FLASH); | 31 | let flash = Flash::new_blocking(p.FLASH); |
| 26 | let flash = Mutex::new(RefCell::new(flash)); | 32 | let flash = Mutex::new(RefCell::new(flash)); |
| 27 | 33 | ||
| 28 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 34 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 29 | 35 | ||
| 30 | let mut led = Output::new(p.PB7, Level::Low, Speed::Low); | 36 | let mut led = Output::new(p.PB7, Level::Low, Speed::Low); |
| 31 | led.set_high(); | 37 | led.set_high(); |
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index ca186d4d9..641a2ba96 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32h7-examples" | 3 | name = "embassy-boot-stm32h7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs index c1b1a267a..226971e02 100644 --- a/examples/boot/application/stm32h7/src/bin/a.rs +++ b/examples/boot/application/stm32h7/src/bin/a.rs | |||
| @@ -7,13 +7,19 @@ use core::cell::RefCell; | |||
| 7 | use defmt_rtt::*; | 7 | use defmt_rtt::*; |
| 8 | use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; | 8 | use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::exti::ExtiInput; | 10 | use embassy_stm32::exti::{self, ExtiInput}; |
| 11 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 11 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 12 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 12 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 13 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 13 | use embassy_sync::blocking_mutex::Mutex; | 14 | use embassy_sync::blocking_mutex::Mutex; |
| 14 | use embedded_storage::nor_flash::NorFlash; | 15 | use embedded_storage::nor_flash::NorFlash; |
| 15 | use panic_reset as _; | 16 | use panic_reset as _; |
| 16 | 17 | ||
| 18 | bind_interrupts!( | ||
| 19 | pub struct Irqs{ | ||
| 20 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 21 | }); | ||
| 22 | |||
| 17 | #[cfg(feature = "skip-include")] | 23 | #[cfg(feature = "skip-include")] |
| 18 | static APP_B: &[u8] = &[0, 1, 2, 3]; | 24 | static APP_B: &[u8] = &[0, 1, 2, 3]; |
| 19 | #[cfg(not(feature = "skip-include"))] | 25 | #[cfg(not(feature = "skip-include"))] |
| @@ -25,7 +31,7 @@ async fn main(_spawner: Spawner) { | |||
| 25 | let flash = Flash::new_blocking(p.FLASH); | 31 | let flash = Flash::new_blocking(p.FLASH); |
| 26 | let flash = Mutex::new(RefCell::new(flash)); | 32 | let flash = Mutex::new(RefCell::new(flash)); |
| 27 | 33 | ||
| 28 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 34 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 29 | 35 | ||
| 30 | let mut led = Output::new(p.PB14, Level::Low, Speed::Low); | 36 | let mut led = Output::new(p.PB14, Level::Low, Speed::Low); |
| 31 | led.set_high(); | 37 | led.set_high(); |
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index be08956f1..4a168be15 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32l0-examples" | 3 | name = "embassy-boot-stm32l0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs index dcc10e5c6..0aa723eaa 100644 --- a/examples/boot/application/stm32l0/src/bin/a.rs +++ b/examples/boot/application/stm32l0/src/bin/a.rs | |||
| @@ -6,13 +6,19 @@ use defmt_rtt::*; | |||
| 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; | 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; |
| 7 | use embassy_embedded_hal::adapter::BlockingAsync; | 7 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::exti::ExtiInput; | 9 | use embassy_stm32::exti::{self, ExtiInput}; |
| 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 12 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 12 | use embassy_sync::mutex::Mutex; | 13 | use embassy_sync::mutex::Mutex; |
| 13 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 14 | use panic_reset as _; | 15 | use panic_reset as _; |
| 15 | 16 | ||
| 17 | bind_interrupts!( | ||
| 18 | pub struct Irqs{ | ||
| 19 | EXTI2_3 => exti::InterruptHandler<interrupt::typelevel::EXTI2_3>; | ||
| 20 | }); | ||
| 21 | |||
| 16 | #[cfg(feature = "skip-include")] | 22 | #[cfg(feature = "skip-include")] |
| 17 | static APP_B: &[u8] = &[0, 1, 2, 3]; | 23 | static APP_B: &[u8] = &[0, 1, 2, 3]; |
| 18 | #[cfg(not(feature = "skip-include"))] | 24 | #[cfg(not(feature = "skip-include"))] |
| @@ -24,7 +30,7 @@ async fn main(_spawner: Spawner) { | |||
| 24 | let flash = Flash::new_blocking(p.FLASH); | 30 | let flash = Flash::new_blocking(p.FLASH); |
| 25 | let flash = Mutex::new(BlockingAsync::new(flash)); | 31 | let flash = Mutex::new(BlockingAsync::new(flash)); |
| 26 | 32 | ||
| 27 | let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); | 33 | let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs); |
| 28 | 34 | ||
| 29 | let mut led = Output::new(p.PB5, Level::Low, Speed::Low); | 35 | let mut led = Output::new(p.PB5, Level::Low, Speed::Low); |
| 30 | 36 | ||
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 207eed733..af2cb3881 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32l1-examples" | 3 | name = "embassy-boot-stm32l1-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs index dcc10e5c6..7ad7046fb 100644 --- a/examples/boot/application/stm32l1/src/bin/a.rs +++ b/examples/boot/application/stm32l1/src/bin/a.rs | |||
| @@ -6,9 +6,10 @@ use defmt_rtt::*; | |||
| 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; | 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; |
| 7 | use embassy_embedded_hal::adapter::BlockingAsync; | 7 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::exti::ExtiInput; | 9 | use embassy_stm32::exti::{self, ExtiInput}; |
| 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 12 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 12 | use embassy_sync::mutex::Mutex; | 13 | use embassy_sync::mutex::Mutex; |
| 13 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 14 | use panic_reset as _; | 15 | use panic_reset as _; |
| @@ -18,13 +19,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3]; | |||
| 18 | #[cfg(not(feature = "skip-include"))] | 19 | #[cfg(not(feature = "skip-include"))] |
| 19 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 20 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| 20 | 21 | ||
| 22 | bind_interrupts!( | ||
| 23 | pub struct Irqs{ | ||
| 24 | EXTI2 => exti::InterruptHandler<interrupt::typelevel::EXTI2>; | ||
| 25 | }); | ||
| 26 | |||
| 21 | #[embassy_executor::main] | 27 | #[embassy_executor::main] |
| 22 | async fn main(_spawner: Spawner) { | 28 | async fn main(_spawner: Spawner) { |
| 23 | let p = embassy_stm32::init(Default::default()); | 29 | let p = embassy_stm32::init(Default::default()); |
| 24 | let flash = Flash::new_blocking(p.FLASH); | 30 | let flash = Flash::new_blocking(p.FLASH); |
| 25 | let flash = Mutex::new(BlockingAsync::new(flash)); | 31 | let flash = Mutex::new(BlockingAsync::new(flash)); |
| 26 | 32 | ||
| 27 | let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); | 33 | let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs); |
| 28 | 34 | ||
| 29 | let mut led = Output::new(p.PB5, Level::Low, Speed::Low); | 35 | let mut led = Output::new(p.PB5, Level::Low, Speed::Low); |
| 30 | 36 | ||
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 22b9642d8..032e934aa 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32l4-examples" | 3 | name = "embassy-boot-stm32l4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs index 7f8015c04..4edd338c5 100644 --- a/examples/boot/application/stm32l4/src/bin/a.rs +++ b/examples/boot/application/stm32l4/src/bin/a.rs | |||
| @@ -6,9 +6,10 @@ use defmt_rtt::*; | |||
| 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; | 6 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; |
| 7 | use embassy_embedded_hal::adapter::BlockingAsync; | 7 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::exti::ExtiInput; | 9 | use embassy_stm32::exti::{self, ExtiInput}; |
| 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 10 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 12 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 12 | use embassy_sync::mutex::Mutex; | 13 | use embassy_sync::mutex::Mutex; |
| 13 | use panic_reset as _; | 14 | use panic_reset as _; |
| 14 | 15 | ||
| @@ -17,13 +18,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3]; | |||
| 17 | #[cfg(not(feature = "skip-include"))] | 18 | #[cfg(not(feature = "skip-include"))] |
| 18 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 19 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| 19 | 20 | ||
| 21 | bind_interrupts!( | ||
| 22 | pub struct Irqs{ | ||
| 23 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 24 | }); | ||
| 25 | |||
| 20 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 21 | async fn main(_spawner: Spawner) { | 27 | async fn main(_spawner: Spawner) { |
| 22 | let p = embassy_stm32::init(Default::default()); | 28 | let p = embassy_stm32::init(Default::default()); |
| 23 | let flash = Flash::new_blocking(p.FLASH); | 29 | let flash = Flash::new_blocking(p.FLASH); |
| 24 | let flash = Mutex::new(BlockingAsync::new(flash)); | 30 | let flash = Mutex::new(BlockingAsync::new(flash)); |
| 25 | 31 | ||
| 26 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 32 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 27 | 33 | ||
| 28 | let mut led = Output::new(p.PB14, Level::Low, Speed::Low); | 34 | let mut led = Output::new(p.PB14, Level::Low, Speed::Low); |
| 29 | led.set_high(); | 35 | led.set_high(); |
diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index e2be4f470..ea4c26681 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32wb-dfu-examples" | 3 | name = "embassy-boot-stm32wb-dfu-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index 5e7b71f5a..1ae28bf3a 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs | |||
| @@ -13,9 +13,9 @@ use embassy_stm32::usb::{self, Driver}; | |||
| 13 | use embassy_stm32::{bind_interrupts, peripherals}; | 13 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 14 | use embassy_sync::blocking_mutex::Mutex; | 14 | use embassy_sync::blocking_mutex::Mutex; |
| 15 | use embassy_time::Duration; | 15 | use embassy_time::Duration; |
| 16 | use embassy_usb::{msos, Builder}; | 16 | use embassy_usb::{Builder, msos}; |
| 17 | use embassy_usb_dfu::consts::DfuAttributes; | 17 | use embassy_usb_dfu::consts::DfuAttributes; |
| 18 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | 18 | use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu}; |
| 19 | use panic_reset as _; | 19 | use panic_reset as _; |
| 20 | 20 | ||
| 21 | bind_interrupts!(struct Irqs { | 21 | bind_interrupts!(struct Irqs { |
diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index 6f4213b2c..d6f7dc3b6 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32wba-dfu-examples" | 3 | name = "embassy-boot-stm32wba-dfu-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32wba-dfu/src/main.rs b/examples/boot/application/stm32wba-dfu/src/main.rs index bf17a7150..8adb2e7c0 100644 --- a/examples/boot/application/stm32wba-dfu/src/main.rs +++ b/examples/boot/application/stm32wba-dfu/src/main.rs | |||
| @@ -12,9 +12,9 @@ use embassy_stm32::usb::{self, Driver}; | |||
| 12 | use embassy_stm32::{bind_interrupts, peripherals}; | 12 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 13 | use embassy_sync::blocking_mutex::Mutex; | 13 | use embassy_sync::blocking_mutex::Mutex; |
| 14 | use embassy_time::Duration; | 14 | use embassy_time::Duration; |
| 15 | use embassy_usb::{msos, Builder}; | 15 | use embassy_usb::{Builder, msos}; |
| 16 | use embassy_usb_dfu::consts::DfuAttributes; | 16 | use embassy_usb_dfu::consts::DfuAttributes; |
| 17 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | 17 | use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu}; |
| 18 | use panic_reset as _; | 18 | use panic_reset as _; |
| 19 | 19 | ||
| 20 | bind_interrupts!(struct Irqs { | 20 | bind_interrupts!(struct Irqs { |
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 8d1446ba9..c7fa811c9 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-boot-stm32wl-examples" | 3 | name = "embassy-boot-stm32wl-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs index e4526927f..58063eb50 100644 --- a/examples/boot/application/stm32wl/src/bin/a.rs +++ b/examples/boot/application/stm32wl/src/bin/a.rs | |||
| @@ -8,10 +8,10 @@ use defmt_rtt::*; | |||
| 8 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; | 8 | use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; |
| 9 | use embassy_embedded_hal::adapter::BlockingAsync; | 9 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::exti::ExtiInput; | 11 | use embassy_stm32::exti::{self, ExtiInput}; |
| 12 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; | 12 | use embassy_stm32::flash::{Flash, WRITE_SIZE}; |
| 13 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 13 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 14 | use embassy_stm32::SharedData; | 14 | use embassy_stm32::{SharedData, bind_interrupts, interrupt}; |
| 15 | use embassy_sync::mutex::Mutex; | 15 | use embassy_sync::mutex::Mutex; |
| 16 | use panic_reset as _; | 16 | use panic_reset as _; |
| 17 | 17 | ||
| @@ -20,6 +20,11 @@ static APP_B: &[u8] = &[0, 1, 2, 3]; | |||
| 20 | #[cfg(not(feature = "skip-include"))] | 20 | #[cfg(not(feature = "skip-include"))] |
| 21 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 21 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| 22 | 22 | ||
| 23 | bind_interrupts!( | ||
| 24 | pub struct Irqs{ | ||
| 25 | EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>; | ||
| 26 | }); | ||
| 27 | |||
| 23 | #[unsafe(link_section = ".shared_data")] | 28 | #[unsafe(link_section = ".shared_data")] |
| 24 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | 29 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); |
| 25 | 30 | ||
| @@ -29,7 +34,7 @@ async fn main(_spawner: Spawner) { | |||
| 29 | let flash = Flash::new_blocking(p.FLASH); | 34 | let flash = Flash::new_blocking(p.FLASH); |
| 30 | let flash = Mutex::new(BlockingAsync::new(flash)); | 35 | let flash = Mutex::new(BlockingAsync::new(flash)); |
| 31 | 36 | ||
| 32 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); | 37 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs); |
| 33 | 38 | ||
| 34 | let mut led = Output::new(p.PB9, Level::Low, Speed::Low); | 39 | let mut led = Output::new(p.PB9, Level::Low, Speed::Low); |
| 35 | led.set_high(); | 40 | led.set_high(); |
diff --git a/examples/boot/application/stm32wl/src/bin/b.rs b/examples/boot/application/stm32wl/src/bin/b.rs index 6016a9555..952e94a58 100644 --- a/examples/boot/application/stm32wl/src/bin/b.rs +++ b/examples/boot/application/stm32wl/src/bin/b.rs | |||
| @@ -6,8 +6,8 @@ use core::mem::MaybeUninit; | |||
| 6 | #[cfg(feature = "defmt")] | 6 | #[cfg(feature = "defmt")] |
| 7 | use defmt_rtt::*; | 7 | use defmt_rtt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embassy_stm32::SharedData; | 9 | use embassy_stm32::SharedData; |
| 10 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use panic_reset as _; | 12 | use panic_reset as _; |
| 13 | 13 | ||
diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 72b7114d4..59fc6e4ed 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "nrf-bootloader-example" | 3 | name = "nrf-bootloader-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Bootloader for nRF chips" | 5 | description = "Bootloader for nRF chips" |
| @@ -27,6 +27,7 @@ defmt = [ | |||
| 27 | softdevice = [ | 27 | softdevice = [ |
| 28 | "embassy-boot-nrf/softdevice", | 28 | "embassy-boot-nrf/softdevice", |
| 29 | ] | 29 | ] |
| 30 | nrf54 = [] | ||
| 30 | 31 | ||
| 31 | [profile.dev] | 32 | [profile.dev] |
| 32 | debug = 2 | 33 | debug = 2 |
| @@ -65,5 +66,6 @@ build = [ | |||
| 65 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] }, | 66 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] }, |
| 66 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] }, | 67 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] }, |
| 67 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] }, | 68 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] }, |
| 68 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] } | 69 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] }, |
| 70 | { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf54l15-app-s", "nrf54"] } | ||
| 69 | ] | 71 | ] |
diff --git a/examples/boot/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs index b849a0df3..9ba57e81b 100644 --- a/examples/boot/bootloader/nrf/src/main.rs +++ b/examples/boot/bootloader/nrf/src/main.rs | |||
| @@ -28,7 +28,10 @@ fn main() -> ! { | |||
| 28 | wdt_config.action_during_sleep = SleepConfig::RUN; | 28 | wdt_config.action_during_sleep = SleepConfig::RUN; |
| 29 | wdt_config.action_during_debug_halt = HaltConfig::PAUSE; | 29 | wdt_config.action_during_debug_halt = HaltConfig::PAUSE; |
| 30 | 30 | ||
| 31 | #[cfg(not(feature = "nrf54"))] | ||
| 31 | let flash = WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, wdt_config); | 32 | let flash = WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, wdt_config); |
| 33 | #[cfg(feature = "nrf54")] | ||
| 34 | let flash = WatchdogFlash::start(Nvmc::new(p.RRAMC), p.WDT0, wdt_config); | ||
| 32 | let flash = Mutex::new(RefCell::new(flash)); | 35 | let flash = Mutex::new(RefCell::new(flash)); |
| 33 | 36 | ||
| 34 | let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash); | 37 | let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash); |
| @@ -38,8 +41,8 @@ fn main() -> ! { | |||
| 38 | unsafe { bl.load(active_offset) } | 41 | unsafe { bl.load(active_offset) } |
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | #[no_mangle] | 44 | #[unsafe(no_mangle)] |
| 42 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | 45 | #[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))] |
| 43 | unsafe extern "C" fn HardFault() { | 46 | unsafe extern "C" fn HardFault() { |
| 44 | cortex_m::peripheral::SCB::sys_reset(); | 47 | cortex_m::peripheral::SCB::sys_reset(); |
| 45 | } | 48 | } |
| @@ -47,7 +50,7 @@ unsafe extern "C" fn HardFault() { | |||
| 47 | #[exception] | 50 | #[exception] |
| 48 | unsafe fn DefaultHandler(_: i16) -> ! { | 51 | unsafe fn DefaultHandler(_: i16) -> ! { |
| 49 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | 52 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; |
| 50 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | 53 | let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16; |
| 51 | 54 | ||
| 52 | panic!("DefaultHandler #{:?}", irqn); | 55 | panic!("DefaultHandler #{:?}", irqn); |
| 53 | } | 56 | } |
diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index 93a1c4edf..188bcab36 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "rp-bootloader-example" | 3 | name = "rp-bootloader-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example bootloader for RP2040 chips" | 5 | description = "Example bootloader for RP2040 chips" |
diff --git a/examples/boot/bootloader/rp/src/main.rs b/examples/boot/bootloader/rp/src/main.rs index 25b1657b8..7ebefd374 100644 --- a/examples/boot/bootloader/rp/src/main.rs +++ b/examples/boot/bootloader/rp/src/main.rs | |||
| @@ -34,8 +34,8 @@ fn main() -> ! { | |||
| 34 | unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) } | 34 | unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) } |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | #[no_mangle] | 37 | #[unsafe(no_mangle)] |
| 38 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | 38 | #[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))] |
| 39 | unsafe extern "C" fn HardFault() { | 39 | unsafe extern "C" fn HardFault() { |
| 40 | cortex_m::peripheral::SCB::sys_reset(); | 40 | cortex_m::peripheral::SCB::sys_reset(); |
| 41 | } | 41 | } |
| @@ -43,7 +43,7 @@ unsafe extern "C" fn HardFault() { | |||
| 43 | #[exception] | 43 | #[exception] |
| 44 | unsafe fn DefaultHandler(_: i16) -> ! { | 44 | unsafe fn DefaultHandler(_: i16) -> ! { |
| 45 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | 45 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; |
| 46 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | 46 | let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16; |
| 47 | 47 | ||
| 48 | panic!("DefaultHandler #{:?}", irqn); | 48 | panic!("DefaultHandler #{:?}", irqn); |
| 49 | } | 49 | } |
diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index 95ca20a59..cf68921dc 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "stm32-bootloader-dual-bank-flash-example" | 3 | name = "stm32-bootloader-dual-bank-flash-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example bootloader for dual-bank flash STM32 chips" | 5 | description = "Example bootloader for dual-bank flash STM32 chips" |
diff --git a/examples/boot/bootloader/stm32-dual-bank/src/main.rs b/examples/boot/bootloader/stm32-dual-bank/src/main.rs index 4d2e82d26..f0063fb5c 100644 --- a/examples/boot/bootloader/stm32-dual-bank/src/main.rs +++ b/examples/boot/bootloader/stm32-dual-bank/src/main.rs | |||
| @@ -7,7 +7,7 @@ use cortex_m_rt::{entry, exception}; | |||
| 7 | #[cfg(feature = "defmt")] | 7 | #[cfg(feature = "defmt")] |
| 8 | use defmt_rtt as _; | 8 | use defmt_rtt as _; |
| 9 | use embassy_boot_stm32::*; | 9 | use embassy_boot_stm32::*; |
| 10 | use embassy_stm32::flash::{Flash, BANK1_REGION}; | 10 | use embassy_stm32::flash::{BANK1_REGION, Flash}; |
| 11 | use embassy_sync::blocking_mutex::Mutex; | 11 | use embassy_sync::blocking_mutex::Mutex; |
| 12 | 12 | ||
| 13 | #[entry] | 13 | #[entry] |
| @@ -33,8 +33,8 @@ fn main() -> ! { | |||
| 33 | unsafe { bl.load(BANK1_REGION.base + active_offset) } | 33 | unsafe { bl.load(BANK1_REGION.base + active_offset) } |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | #[no_mangle] | 36 | #[unsafe(no_mangle)] |
| 37 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | 37 | #[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))] |
| 38 | unsafe extern "C" fn HardFault() { | 38 | unsafe extern "C" fn HardFault() { |
| 39 | cortex_m::peripheral::SCB::sys_reset(); | 39 | cortex_m::peripheral::SCB::sys_reset(); |
| 40 | } | 40 | } |
| @@ -42,7 +42,7 @@ unsafe extern "C" fn HardFault() { | |||
| 42 | #[exception] | 42 | #[exception] |
| 43 | unsafe fn DefaultHandler(_: i16) -> ! { | 43 | unsafe fn DefaultHandler(_: i16) -> ! { |
| 44 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | 44 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; |
| 45 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | 45 | let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16; |
| 46 | 46 | ||
| 47 | panic!("DefaultHandler #{:?}", irqn); | 47 | panic!("DefaultHandler #{:?}", irqn); |
| 48 | } | 48 | } |
diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index 526637f37..e457310b9 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "stm32-bootloader-example" | 3 | name = "stm32-bootloader-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example bootloader for STM32 chips" | 5 | description = "Example bootloader for STM32 chips" |
diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs index 99a7a6a6b..383ad912d 100644 --- a/examples/boot/bootloader/stm32/src/main.rs +++ b/examples/boot/bootloader/stm32/src/main.rs | |||
| @@ -7,7 +7,7 @@ use cortex_m_rt::{entry, exception}; | |||
| 7 | #[cfg(feature = "defmt")] | 7 | #[cfg(feature = "defmt")] |
| 8 | use defmt_rtt as _; | 8 | use defmt_rtt as _; |
| 9 | use embassy_boot_stm32::*; | 9 | use embassy_boot_stm32::*; |
| 10 | use embassy_stm32::flash::{Flash, BANK1_REGION}; | 10 | use embassy_stm32::flash::{BANK1_REGION, Flash}; |
| 11 | use embassy_sync::blocking_mutex::Mutex; | 11 | use embassy_sync::blocking_mutex::Mutex; |
| 12 | 12 | ||
| 13 | #[entry] | 13 | #[entry] |
| @@ -32,8 +32,8 @@ fn main() -> ! { | |||
| 32 | unsafe { bl.load(BANK1_REGION.base + active_offset) } | 32 | unsafe { bl.load(BANK1_REGION.base + active_offset) } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | #[no_mangle] | 35 | #[unsafe(no_mangle)] |
| 36 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | 36 | #[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))] |
| 37 | unsafe extern "C" fn HardFault() { | 37 | unsafe extern "C" fn HardFault() { |
| 38 | cortex_m::peripheral::SCB::sys_reset(); | 38 | cortex_m::peripheral::SCB::sys_reset(); |
| 39 | } | 39 | } |
| @@ -41,7 +41,7 @@ unsafe extern "C" fn HardFault() { | |||
| 41 | #[exception] | 41 | #[exception] |
| 42 | unsafe fn DefaultHandler(_: i16) -> ! { | 42 | unsafe fn DefaultHandler(_: i16) -> ! { |
| 43 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | 43 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; |
| 44 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | 44 | let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16; |
| 45 | 45 | ||
| 46 | panic!("DefaultHandler #{:?}", irqn); | 46 | panic!("DefaultHandler #{:?}", irqn); |
| 47 | } | 47 | } |
diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index ef10aeabf..75b7081df 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "stm32wb-dfu-bootloader-example" | 3 | name = "stm32wb-dfu-bootloader-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example USB DFUbootloader for the STM32WB series of chips" | 5 | description = "Example USB DFUbootloader for the STM32WB series of chips" |
diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 107f243fd..9ee82846d 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs | |||
| @@ -7,14 +7,14 @@ use cortex_m_rt::{entry, exception}; | |||
| 7 | #[cfg(feature = "defmt")] | 7 | #[cfg(feature = "defmt")] |
| 8 | use defmt_rtt as _; | 8 | use defmt_rtt as _; |
| 9 | use embassy_boot_stm32::*; | 9 | use embassy_boot_stm32::*; |
| 10 | use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE}; | 10 | use embassy_stm32::flash::{BANK1_REGION, Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::rcc::WPAN_DEFAULT; | 11 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 12 | use embassy_stm32::usb::Driver; | 12 | use embassy_stm32::usb::Driver; |
| 13 | use embassy_stm32::{bind_interrupts, peripherals, usb}; | 13 | use embassy_stm32::{bind_interrupts, peripherals, usb}; |
| 14 | use embassy_sync::blocking_mutex::Mutex; | 14 | use embassy_sync::blocking_mutex::Mutex; |
| 15 | use embassy_usb::{msos, Builder}; | 15 | use embassy_usb::{Builder, msos}; |
| 16 | use embassy_usb_dfu::consts::DfuAttributes; | 16 | use embassy_usb_dfu::consts::DfuAttributes; |
| 17 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | 17 | use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu}; |
| 18 | 18 | ||
| 19 | bind_interrupts!(struct Irqs { | 19 | bind_interrupts!(struct Irqs { |
| 20 | USB_LP => usb::InterruptHandler<peripherals::USB>; | 20 | USB_LP => usb::InterruptHandler<peripherals::USB>; |
| @@ -109,8 +109,8 @@ fn main() -> ! { | |||
| 109 | unsafe { bl.load(BANK1_REGION.base + active_offset) } | 109 | unsafe { bl.load(BANK1_REGION.base + active_offset) } |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | #[no_mangle] | 112 | #[unsafe(no_mangle)] |
| 113 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | 113 | #[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))] |
| 114 | unsafe extern "C" fn HardFault() { | 114 | unsafe extern "C" fn HardFault() { |
| 115 | cortex_m::peripheral::SCB::sys_reset(); | 115 | cortex_m::peripheral::SCB::sys_reset(); |
| 116 | } | 116 | } |
| @@ -118,7 +118,7 @@ unsafe extern "C" fn HardFault() { | |||
| 118 | #[exception] | 118 | #[exception] |
| 119 | unsafe fn DefaultHandler(_: i16) -> ! { | 119 | unsafe fn DefaultHandler(_: i16) -> ! { |
| 120 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | 120 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; |
| 121 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | 121 | let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16; |
| 122 | 122 | ||
| 123 | panic!("DefaultHandler #{:?}", irqn); | 123 | panic!("DefaultHandler #{:?}", irqn); |
| 124 | } | 124 | } |
diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml index 16de7684e..eee2b2f71 100644 --- a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "stm32wba6-dfu-bootloader-example" | 3 | name = "stm32wba6-dfu-bootloader-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | description = "Example USB DFUbootloader for the STM32WBA series of chips" | 5 | description = "Example USB DFUbootloader for the STM32WBA series of chips" |
diff --git a/examples/boot/bootloader/stm32wba-dfu/src/main.rs b/examples/boot/bootloader/stm32wba-dfu/src/main.rs index 75d8d4199..b33a75d95 100644 --- a/examples/boot/bootloader/stm32wba-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wba-dfu/src/main.rs | |||
| @@ -7,13 +7,13 @@ use cortex_m_rt::{entry, exception}; | |||
| 7 | #[cfg(feature = "defmt")] | 7 | #[cfg(feature = "defmt")] |
| 8 | use defmt_rtt as _; | 8 | use defmt_rtt as _; |
| 9 | use embassy_boot_stm32::*; | 9 | use embassy_boot_stm32::*; |
| 10 | use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE}; | 10 | use embassy_stm32::flash::{BANK1_REGION, Flash, WRITE_SIZE}; |
| 11 | use embassy_stm32::usb::Driver; | 11 | use embassy_stm32::usb::Driver; |
| 12 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 12 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 13 | use embassy_sync::blocking_mutex::Mutex; | 13 | use embassy_sync::blocking_mutex::Mutex; |
| 14 | use embassy_usb::{msos, Builder}; | 14 | use embassy_usb::{Builder, msos}; |
| 15 | use embassy_usb_dfu::consts::DfuAttributes; | 15 | use embassy_usb_dfu::consts::DfuAttributes; |
| 16 | use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; | 16 | use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu}; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs { | 18 | bind_interrupts!(struct Irqs { |
| 19 | USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>; | 19 | USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>; |
| @@ -138,8 +138,8 @@ fn main() -> ! { | |||
| 138 | unsafe { bl.load(BANK1_REGION.base + active_offset) } | 138 | unsafe { bl.load(BANK1_REGION.base + active_offset) } |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | #[no_mangle] | 141 | #[unsafe(no_mangle)] |
| 142 | #[cfg_attr(target_os = "none", link_section = ".HardFault.user")] | 142 | #[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))] |
| 143 | unsafe extern "C" fn HardFault() { | 143 | unsafe extern "C" fn HardFault() { |
| 144 | cortex_m::peripheral::SCB::sys_reset(); | 144 | cortex_m::peripheral::SCB::sys_reset(); |
| 145 | } | 145 | } |
| @@ -147,7 +147,7 @@ unsafe extern "C" fn HardFault() { | |||
| 147 | #[exception] | 147 | #[exception] |
| 148 | unsafe fn DefaultHandler(_: i16) -> ! { | 148 | unsafe fn DefaultHandler(_: i16) -> ! { |
| 149 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; | 149 | const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; |
| 150 | let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; | 150 | let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16; |
| 151 | 151 | ||
| 152 | panic!("DefaultHandler #{:?}", irqn); | 152 | panic!("DefaultHandler #{:?}", irqn); |
| 153 | } | 153 | } |
diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 579748595..94903b3f8 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nxp-lpc55s69-examples" | 3 | name = "embassy-nxp-lpc55s69-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/lpc55s69/src/bin/pwm.rs b/examples/lpc55s69/src/bin/pwm.rs new file mode 100644 index 000000000..8a9894b94 --- /dev/null +++ b/examples/lpc55s69/src/bin/pwm.rs | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nxp::pwm::{Config, Pwm}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nxp::init(Default::default()); | ||
| 13 | let pwm = Pwm::new_output(p.SCT0_OUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000)); | ||
| 14 | loop { | ||
| 15 | info!("Counter: {}", pwm.counter()); | ||
| 16 | Timer::after_millis(50).await; | ||
| 17 | } | ||
| 18 | } | ||
diff --git a/examples/lpc55s69/src/bin/usart_async.rs b/examples/lpc55s69/src/bin/usart_async.rs index b06abd477..a9815b920 100644 --- a/examples/lpc55s69/src/bin/usart_async.rs +++ b/examples/lpc55s69/src/bin/usart_async.rs | |||
| @@ -38,8 +38,8 @@ async fn main(spawner: Spawner) { | |||
| 38 | p.PIO0_27, | 38 | p.PIO0_27, |
| 39 | p.PIO1_24, | 39 | p.PIO1_24, |
| 40 | Irqs, | 40 | Irqs, |
| 41 | p.DMA_CH11, | 41 | p.DMA0_CH11, |
| 42 | p.DMA_CH10, | 42 | p.DMA0_CH10, |
| 43 | Config::default(), | 43 | Config::default(), |
| 44 | ); | 44 | ); |
| 45 | let led = Output::new(p.PIO1_6, Level::Low); | 45 | let led = Output::new(p.PIO1_6, Level::Low); |
diff --git a/examples/mcxa/.cargo/config.toml b/examples/mcxa/.cargo/config.toml new file mode 100644 index 000000000..aedc55b06 --- /dev/null +++ b/examples/mcxa/.cargo/config.toml | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | [target.thumbv8m.main-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip MCXA276 --preverify --verify --protocol swd --speed 12000' | ||
| 3 | |||
| 4 | rustflags = [ | ||
| 5 | "-C", "linker=flip-link", | ||
| 6 | "-C", "link-arg=-Tlink.x", | ||
| 7 | "-C", "link-arg=-Tdefmt.x", | ||
| 8 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x | ||
| 9 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 | ||
| 10 | "-C", "link-arg=--nmagic", | ||
| 11 | ] | ||
| 12 | |||
| 13 | [build] | ||
| 14 | target = "thumbv8m.main-none-eabihf" # Cortex-M33 | ||
| 15 | |||
| 16 | [env] | ||
| 17 | DEFMT_LOG = "trace" | ||
diff --git a/examples/mcxa/.gitignore b/examples/mcxa/.gitignore new file mode 100644 index 000000000..2f7896d1d --- /dev/null +++ b/examples/mcxa/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| target/ | |||
diff --git a/examples/mcxa/Cargo.toml b/examples/mcxa/Cargo.toml new file mode 100644 index 000000000..347659f5b --- /dev/null +++ b/examples/mcxa/Cargo.toml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-mcxa-examples" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | cortex-m = { version = "0.7", features = ["critical-section-single-core"] } | ||
| 10 | cortex-m-rt = { version = "0.7", features = ["set-sp", "set-vtor"] } | ||
| 11 | crc = "3.4.0" | ||
| 12 | critical-section = "1.2.0" | ||
| 13 | defmt = "1.0" | ||
| 14 | defmt-rtt = "1.0" | ||
| 15 | embassy-embedded-hal = "0.5.0" | ||
| 16 | embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false } | ||
| 17 | embassy-mcxa = { path = "../../embassy-mcxa", features = ["defmt", "unstable-pac", "time"] } | ||
| 18 | embassy-sync = "0.7.2" | ||
| 19 | embassy-time = "0.5.0" | ||
| 20 | embassy-time-driver = "0.2.1" | ||
| 21 | embedded-io-async = "0.6.1" | ||
| 22 | heapless = "0.9.2" | ||
| 23 | panic-probe = { version = "1.0", features = ["print-defmt"] } | ||
| 24 | rand_core = "0.9" | ||
| 25 | static_cell = "2.1.1" | ||
| 26 | tmp108 = "0.4.0" | ||
| 27 | |||
| 28 | [profile.release] | ||
| 29 | lto = true # better optimizations | ||
| 30 | debug = 2 # enough information for defmt/rtt locations | ||
| 31 | |||
| 32 | [package.metadata.embassy] | ||
| 33 | build = [ | ||
| 34 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/mcxa" } | ||
| 35 | ] | ||
diff --git a/examples/mcxa/build.rs b/examples/mcxa/build.rs new file mode 100644 index 000000000..f076bba9f --- /dev/null +++ b/examples/mcxa/build.rs | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | use std::env; | ||
| 2 | use std::fs::File; | ||
| 3 | use std::io::Write; | ||
| 4 | use std::path::PathBuf; | ||
| 5 | |||
| 6 | fn main() { | ||
| 7 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 8 | |||
| 9 | // Generate memory.x - put "FLASH" at start of RAM, RAM after "FLASH" | ||
| 10 | // cortex-m-rt expects FLASH for code, RAM for data/bss/stack | ||
| 11 | // Both are in RAM, but separated to satisfy cortex-m-rt's expectations | ||
| 12 | // MCXA256 has 128KB RAM total | ||
| 13 | File::create(out.join("memory.x")) | ||
| 14 | .unwrap() | ||
| 15 | .write_all(include_bytes!("memory.x")) | ||
| 16 | .unwrap(); | ||
| 17 | |||
| 18 | println!("cargo:rustc-link-search={}", out.display()); | ||
| 19 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 20 | } | ||
diff --git a/examples/mcxa/memory.x b/examples/mcxa/memory.x new file mode 100644 index 000000000..315ced58a --- /dev/null +++ b/examples/mcxa/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1M | ||
| 4 | RAM : ORIGIN = 0x20000000, LENGTH = 128K | ||
| 5 | } | ||
diff --git a/examples/mcxa/src/bin/adc_interrupt.rs b/examples/mcxa/src/bin/adc_interrupt.rs new file mode 100644 index 000000000..d2cda631c --- /dev/null +++ b/examples/mcxa/src/bin/adc_interrupt.rs | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::{Duration, Ticker}; | ||
| 6 | use hal::adc::{Adc, InterruptHandler, LpadcConfig, TriggerPriorityPolicy}; | ||
| 7 | use hal::bind_interrupts; | ||
| 8 | use hal::clocks::PoweredClock; | ||
| 9 | use hal::clocks::config::Div8; | ||
| 10 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; | ||
| 11 | use hal::config::Config; | ||
| 12 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; | ||
| 13 | use hal::pac::adc1::cmdl1::Mode; | ||
| 14 | use hal::pac::adc1::ctrl::CalAvgs; | ||
| 15 | use hal::peripherals::ADC1; | ||
| 16 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | ADC1 => InterruptHandler<ADC1>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) { | ||
| 24 | let mut config = Config::default(); | ||
| 25 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 26 | |||
| 27 | let p = hal::init(config); | ||
| 28 | |||
| 29 | defmt::info!("ADC interrupt Example"); | ||
| 30 | |||
| 31 | let adc_config = LpadcConfig { | ||
| 32 | enable_in_doze_mode: true, | ||
| 33 | conversion_average_mode: CalAvgs::Average128, | ||
| 34 | enable_analog_preliminary: true, | ||
| 35 | power_up_delay: 0x80, | ||
| 36 | reference_voltage_source: Refsel::Option3, | ||
| 37 | power_level_mode: Pwrsel::Lowest, | ||
| 38 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, | ||
| 39 | enable_conv_pause: false, | ||
| 40 | conv_pause_delay: 0, | ||
| 41 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 42 | source: AdcClockSel::FroLfDiv, | ||
| 43 | div: Div4::no_div(), | ||
| 44 | }; | ||
| 45 | let mut adc = Adc::new_async(p.ADC1, p.P1_10, Irqs, adc_config).unwrap(); | ||
| 46 | |||
| 47 | adc.do_offset_calibration(); | ||
| 48 | adc.do_auto_calibration(); | ||
| 49 | adc.set_resolution(Mode::Data16Bits); | ||
| 50 | |||
| 51 | defmt::info!("ADC configuration done..."); | ||
| 52 | let mut ticker = Ticker::every(Duration::from_millis(100)); | ||
| 53 | |||
| 54 | loop { | ||
| 55 | ticker.next().await; | ||
| 56 | match adc.read().await { | ||
| 57 | Ok(value) => { | ||
| 58 | defmt::info!("ADC value: {}", value); | ||
| 59 | } | ||
| 60 | Err(e) => { | ||
| 61 | defmt::error!("ADC read error: {:?}", e); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
diff --git a/examples/mcxa/src/bin/adc_polling.rs b/examples/mcxa/src/bin/adc_polling.rs new file mode 100644 index 000000000..5c4d5524c --- /dev/null +++ b/examples/mcxa/src/bin/adc_polling.rs | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::adc::{ConvCommandConfig, ConvTriggerConfig}; | ||
| 6 | use embassy_time::{Duration, Ticker}; | ||
| 7 | use hal::adc::{Adc, LpadcConfig, TriggerPriorityPolicy}; | ||
| 8 | use hal::clocks::PoweredClock; | ||
| 9 | use hal::clocks::config::Div8; | ||
| 10 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; | ||
| 11 | use hal::config::Config; | ||
| 12 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; | ||
| 13 | use hal::pac::adc1::cmdl1::Mode; | ||
| 14 | use hal::pac::adc1::ctrl::CalAvgs; | ||
| 15 | use hal::pac::adc1::tctrl::Tcmd; | ||
| 16 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 17 | |||
| 18 | const G_LPADC_RESULT_SHIFT: u32 = 0; | ||
| 19 | |||
| 20 | #[embassy_executor::main] | ||
| 21 | async fn main(_spawner: Spawner) { | ||
| 22 | let mut config = Config::default(); | ||
| 23 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 24 | |||
| 25 | let p = hal::init(config); | ||
| 26 | |||
| 27 | defmt::info!("=== ADC polling Example ==="); | ||
| 28 | |||
| 29 | let adc_config = LpadcConfig { | ||
| 30 | enable_in_doze_mode: true, | ||
| 31 | conversion_average_mode: CalAvgs::Average128, | ||
| 32 | enable_analog_preliminary: true, | ||
| 33 | power_up_delay: 0x80, | ||
| 34 | reference_voltage_source: Refsel::Option3, | ||
| 35 | power_level_mode: Pwrsel::Lowest, | ||
| 36 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, | ||
| 37 | enable_conv_pause: false, | ||
| 38 | conv_pause_delay: 0, | ||
| 39 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 40 | source: AdcClockSel::FroLfDiv, | ||
| 41 | div: Div4::no_div(), | ||
| 42 | }; | ||
| 43 | let adc = Adc::new_blocking(p.ADC1, p.P1_10, adc_config).unwrap(); | ||
| 44 | |||
| 45 | adc.do_offset_calibration(); | ||
| 46 | adc.do_auto_calibration(); | ||
| 47 | |||
| 48 | let conv_command_config = ConvCommandConfig { | ||
| 49 | conversion_resolution_mode: Mode::Data16Bits, | ||
| 50 | ..ConvCommandConfig::default() | ||
| 51 | }; | ||
| 52 | adc.set_conv_command_config(1, &conv_command_config).unwrap(); | ||
| 53 | |||
| 54 | let conv_trigger_config = ConvTriggerConfig { | ||
| 55 | target_command_id: Tcmd::ExecuteCmd1, | ||
| 56 | enable_hardware_trigger: false, | ||
| 57 | ..Default::default() | ||
| 58 | }; | ||
| 59 | adc.set_conv_trigger_config(0, &conv_trigger_config).unwrap(); | ||
| 60 | |||
| 61 | defmt::info!("=== ADC configuration done... ==="); | ||
| 62 | let mut tick = Ticker::every(Duration::from_millis(100)); | ||
| 63 | |||
| 64 | loop { | ||
| 65 | tick.next().await; | ||
| 66 | adc.do_software_trigger(1).unwrap(); | ||
| 67 | let result = loop { | ||
| 68 | match adc.get_conv_result() { | ||
| 69 | Ok(res) => break res, | ||
| 70 | Err(_) => { | ||
| 71 | // Conversion not ready, continue polling | ||
| 72 | } | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | let value = result.conv_value >> G_LPADC_RESULT_SHIFT; | ||
| 76 | defmt::info!("ADC value: {=u16}", value); | ||
| 77 | } | ||
| 78 | } | ||
diff --git a/examples/mcxa/src/bin/blinky.rs b/examples/mcxa/src/bin/blinky.rs new file mode 100644 index 000000000..dd08ec0d9 --- /dev/null +++ b/examples/mcxa/src/bin/blinky.rs | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::gpio::{DriveStrength, Level, Output, SlewRate}; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = hal::init(hal::config::Config::default()); | ||
| 12 | |||
| 13 | defmt::info!("Blink example"); | ||
| 14 | |||
| 15 | let mut red = Output::new(p.P3_18, Level::High, DriveStrength::Normal, SlewRate::Fast); | ||
| 16 | let mut green = Output::new(p.P3_19, Level::High, DriveStrength::Normal, SlewRate::Fast); | ||
| 17 | let mut blue = Output::new(p.P3_21, Level::High, DriveStrength::Normal, SlewRate::Fast); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | defmt::info!("Toggle LEDs"); | ||
| 21 | |||
| 22 | red.toggle(); | ||
| 23 | Timer::after_millis(250).await; | ||
| 24 | |||
| 25 | red.toggle(); | ||
| 26 | green.toggle(); | ||
| 27 | Timer::after_millis(250).await; | ||
| 28 | |||
| 29 | green.toggle(); | ||
| 30 | blue.toggle(); | ||
| 31 | Timer::after_millis(250).await; | ||
| 32 | blue.toggle(); | ||
| 33 | |||
| 34 | Timer::after_millis(250).await; | ||
| 35 | } | ||
| 36 | } | ||
diff --git a/examples/mcxa/src/bin/button.rs b/examples/mcxa/src/bin/button.rs new file mode 100644 index 000000000..943edbb15 --- /dev/null +++ b/examples/mcxa/src/bin/button.rs | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::gpio::{Input, Pull}; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = hal::init(hal::config::Config::default()); | ||
| 12 | |||
| 13 | defmt::info!("Button example"); | ||
| 14 | |||
| 15 | // This button is labeled "WAKEUP" on the FRDM-MCXA276 | ||
| 16 | // The board already has a 10K pullup | ||
| 17 | let monitor = Input::new(p.P1_7, Pull::Disabled); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | defmt::info!("Pin level is {:?}", monitor.get_level()); | ||
| 21 | Timer::after_millis(1000).await; | ||
| 22 | } | ||
| 23 | } | ||
diff --git a/examples/mcxa/src/bin/button_async.rs b/examples/mcxa/src/bin/button_async.rs new file mode 100644 index 000000000..6cc7b62cd --- /dev/null +++ b/examples/mcxa/src/bin/button_async.rs | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::gpio::{Input, Pull}; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = hal::init(hal::config::Config::default()); | ||
| 12 | |||
| 13 | defmt::info!("GPIO interrupt example"); | ||
| 14 | |||
| 15 | // This button is labeled "WAKEUP" on the FRDM-MCXA276 | ||
| 16 | // The board already has a 10K pullup | ||
| 17 | let mut pin = Input::new(p.P1_7, Pull::Disabled); | ||
| 18 | |||
| 19 | let mut press_count = 0u32; | ||
| 20 | |||
| 21 | loop { | ||
| 22 | pin.wait_for_falling_edge().await; | ||
| 23 | |||
| 24 | press_count += 1; | ||
| 25 | |||
| 26 | defmt::info!("Button pressed! Count: {}", press_count); | ||
| 27 | Timer::after_millis(50).await; | ||
| 28 | } | ||
| 29 | } | ||
diff --git a/examples/mcxa/src/bin/clkout.rs b/examples/mcxa/src/bin/clkout.rs new file mode 100644 index 000000000..1e52912d3 --- /dev/null +++ b/examples/mcxa/src/bin/clkout.rs | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; | ||
| 6 | use embassy_mcxa::clocks::PoweredClock; | ||
| 7 | use embassy_mcxa::gpio::{DriveStrength, Level, Output, SlewRate}; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 10 | |||
| 11 | /// Demonstrate CLKOUT, using Pin P4.2 | ||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let p = hal::init(hal::config::Config::default()); | ||
| 15 | let mut pin = p.P4_2; | ||
| 16 | let mut clkout = p.CLKOUT; | ||
| 17 | |||
| 18 | loop { | ||
| 19 | defmt::info!("Set Low..."); | ||
| 20 | let mut output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); | ||
| 21 | Timer::after_millis(500).await; | ||
| 22 | |||
| 23 | defmt::info!("Set High..."); | ||
| 24 | output.set_high(); | ||
| 25 | Timer::after_millis(400).await; | ||
| 26 | |||
| 27 | defmt::info!("Set Low..."); | ||
| 28 | output.set_low(); | ||
| 29 | Timer::after_millis(500).await; | ||
| 30 | |||
| 31 | defmt::info!("16k..."); | ||
| 32 | // Run Clock Out with the 16K clock | ||
| 33 | let _clock_out = ClockOut::new( | ||
| 34 | clkout.reborrow(), | ||
| 35 | pin.reborrow(), | ||
| 36 | Config { | ||
| 37 | sel: ClockOutSel::Clk16K, | ||
| 38 | div: Div4::no_div(), | ||
| 39 | level: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 40 | }, | ||
| 41 | ) | ||
| 42 | .unwrap(); | ||
| 43 | |||
| 44 | Timer::after_millis(3000).await; | ||
| 45 | |||
| 46 | defmt::info!("Set Low..."); | ||
| 47 | drop(_clock_out); | ||
| 48 | |||
| 49 | let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); | ||
| 50 | Timer::after_millis(500).await; | ||
| 51 | |||
| 52 | // Run Clock Out with the 12M clock, divided by 3 | ||
| 53 | defmt::info!("4M..."); | ||
| 54 | let _clock_out = ClockOut::new( | ||
| 55 | clkout.reborrow(), | ||
| 56 | pin.reborrow(), | ||
| 57 | Config { | ||
| 58 | sel: ClockOutSel::Fro12M, | ||
| 59 | div: const { Div4::from_divisor(3).unwrap() }, | ||
| 60 | level: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 61 | }, | ||
| 62 | ) | ||
| 63 | .unwrap(); | ||
| 64 | |||
| 65 | // Let it run for 3 seconds... | ||
| 66 | Timer::after_millis(3000).await; | ||
| 67 | } | ||
| 68 | } | ||
diff --git a/examples/mcxa/src/bin/crc.rs b/examples/mcxa/src/bin/crc.rs new file mode 100644 index 000000000..0125e625c --- /dev/null +++ b/examples/mcxa/src/bin/crc.rs | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use hal::config::Config; | ||
| 6 | use hal::crc::Crc; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | const CCITT_FALSE: crc::Algorithm<u16> = crc::Algorithm { | ||
| 10 | width: 16, | ||
| 11 | poly: 0x1021, | ||
| 12 | init: 0xffff, | ||
| 13 | refin: false, | ||
| 14 | refout: false, | ||
| 15 | xorout: 0, | ||
| 16 | check: 0x29b1, | ||
| 17 | residue: 0x0000, | ||
| 18 | }; | ||
| 19 | |||
| 20 | const POSIX: crc::Algorithm<u32> = crc::Algorithm { | ||
| 21 | width: 32, | ||
| 22 | poly: 0x04c1_1db7, | ||
| 23 | init: 0, | ||
| 24 | refin: false, | ||
| 25 | refout: false, | ||
| 26 | xorout: 0xffff_ffff, | ||
| 27 | check: 0x765e_7680, | ||
| 28 | residue: 0x0000, | ||
| 29 | }; | ||
| 30 | |||
| 31 | #[embassy_executor::main] | ||
| 32 | async fn main(_spawner: Spawner) { | ||
| 33 | let config = Config::default(); | ||
| 34 | let mut p = hal::init(config); | ||
| 35 | |||
| 36 | defmt::info!("CRC example"); | ||
| 37 | |||
| 38 | let buf_u8 = [0x00u8, 0x11, 0x22, 0x33]; | ||
| 39 | let buf_u16 = [0x0000u16, 0x1111, 0x2222, 0x3333]; | ||
| 40 | let buf_u32 = [0x0000_0000u32, 0x1111_1111, 0x2222_2222, 0x3333_3333]; | ||
| 41 | |||
| 42 | // CCITT False | ||
| 43 | |||
| 44 | let sw_crc = crc::Crc::<u16>::new(&CCITT_FALSE); | ||
| 45 | let mut digest = sw_crc.digest(); | ||
| 46 | digest.update(&buf_u8); | ||
| 47 | let sw_sum = digest.finalize(); | ||
| 48 | |||
| 49 | let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow()); | ||
| 50 | crc.feed(&buf_u8); | ||
| 51 | let sum = crc.finalize(); | ||
| 52 | assert_eq!(sum, sw_sum); | ||
| 53 | |||
| 54 | let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow()); | ||
| 55 | crc.feed(&buf_u16); | ||
| 56 | let sum = crc.finalize(); | ||
| 57 | assert_eq!(sum, 0xa467); | ||
| 58 | |||
| 59 | let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow()); | ||
| 60 | crc.feed(&buf_u32); | ||
| 61 | let sum = crc.finalize(); | ||
| 62 | assert_eq!(sum, 0xe5c7); | ||
| 63 | |||
| 64 | // Maxim | ||
| 65 | |||
| 66 | let sw_crc = crc::Crc::<u16>::new(&crc::CRC_16_MAXIM_DOW); | ||
| 67 | let mut digest = sw_crc.digest(); | ||
| 68 | digest.update(&buf_u8); | ||
| 69 | let sw_sum = digest.finalize(); | ||
| 70 | |||
| 71 | let mut crc = Crc::new_maxim(p.CRC0.reborrow()); | ||
| 72 | crc.feed(&buf_u8); | ||
| 73 | let sum = crc.finalize(); | ||
| 74 | assert_eq!(sum, sw_sum); | ||
| 75 | |||
| 76 | let mut crc = Crc::new_maxim(p.CRC0.reborrow()); | ||
| 77 | crc.feed(&buf_u16); | ||
| 78 | let sum = crc.finalize(); | ||
| 79 | assert_eq!(sum, 0x2afe); | ||
| 80 | |||
| 81 | let mut crc = Crc::new_maxim(p.CRC0.reborrow()); | ||
| 82 | crc.feed(&buf_u32); | ||
| 83 | let sum = crc.finalize(); | ||
| 84 | assert_eq!(sum, 0x17d7); | ||
| 85 | |||
| 86 | // Kermit | ||
| 87 | |||
| 88 | let sw_crc = crc::Crc::<u16>::new(&crc::CRC_16_KERMIT); | ||
| 89 | let mut digest = sw_crc.digest(); | ||
| 90 | digest.update(&buf_u8); | ||
| 91 | let sw_sum = digest.finalize(); | ||
| 92 | |||
| 93 | let mut crc = Crc::new_kermit(p.CRC0.reborrow()); | ||
| 94 | crc.feed(&buf_u8); | ||
| 95 | let sum = crc.finalize(); | ||
| 96 | assert_eq!(sum, sw_sum); | ||
| 97 | |||
| 98 | let mut crc = Crc::new_kermit(p.CRC0.reborrow()); | ||
| 99 | crc.feed(&buf_u16); | ||
| 100 | let sum = crc.finalize(); | ||
| 101 | assert_eq!(sum, 0x66eb); | ||
| 102 | |||
| 103 | let mut crc = Crc::new_kermit(p.CRC0.reborrow()); | ||
| 104 | crc.feed(&buf_u32); | ||
| 105 | let sum = crc.finalize(); | ||
| 106 | assert_eq!(sum, 0x75ea); | ||
| 107 | |||
| 108 | // ISO HDLC | ||
| 109 | |||
| 110 | let sw_crc = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC); | ||
| 111 | let mut digest = sw_crc.digest(); | ||
| 112 | digest.update(&buf_u8); | ||
| 113 | let sw_sum = digest.finalize(); | ||
| 114 | |||
| 115 | let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow()); | ||
| 116 | crc.feed(&buf_u8); | ||
| 117 | let sum = crc.finalize(); | ||
| 118 | assert_eq!(sum, sw_sum); | ||
| 119 | |||
| 120 | let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow()); | ||
| 121 | crc.feed(&buf_u16); | ||
| 122 | let sum = crc.finalize(); | ||
| 123 | assert_eq!(sum, 0x8a61_4178); | ||
| 124 | |||
| 125 | let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow()); | ||
| 126 | crc.feed(&buf_u32); | ||
| 127 | let sum = crc.finalize(); | ||
| 128 | assert_eq!(sum, 0xfab5_d04e); | ||
| 129 | |||
| 130 | // POSIX | ||
| 131 | |||
| 132 | let sw_crc = crc::Crc::<u32>::new(&POSIX); | ||
| 133 | let mut digest = sw_crc.digest(); | ||
| 134 | digest.update(&buf_u8); | ||
| 135 | let sw_sum = digest.finalize(); | ||
| 136 | |||
| 137 | let mut crc = Crc::new_posix(p.CRC0.reborrow()); | ||
| 138 | crc.feed(&buf_u8); | ||
| 139 | let sum = crc.finalize(); | ||
| 140 | |||
| 141 | assert_eq!(sum, sw_sum); | ||
| 142 | |||
| 143 | let mut crc = Crc::new_posix(p.CRC0.reborrow()); | ||
| 144 | crc.feed(&buf_u16); | ||
| 145 | let sum = crc.finalize(); | ||
| 146 | assert_eq!(sum, 0x6d76_4f58); | ||
| 147 | |||
| 148 | let mut crc = Crc::new_posix(p.CRC0.reborrow()); | ||
| 149 | crc.feed(&buf_u32); | ||
| 150 | let sum = crc.finalize(); | ||
| 151 | assert_eq!(sum, 0x2a5b_cb90); | ||
| 152 | |||
| 153 | defmt::info!("CRC successful"); | ||
| 154 | } | ||
diff --git a/examples/mcxa/src/bin/dma_mem_to_mem.rs b/examples/mcxa/src/bin/dma_mem_to_mem.rs new file mode 100644 index 000000000..b38baccb5 --- /dev/null +++ b/examples/mcxa/src/bin/dma_mem_to_mem.rs | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | //! DMA memory-to-memory transfer example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! This example demonstrates using DMA to copy data between memory buffers | ||
| 4 | //! using the Embassy-style async API with type-safe transfers. | ||
| 5 | //! | ||
| 6 | //! # Embassy-style features demonstrated: | ||
| 7 | //! - `TransferOptions` for configuration | ||
| 8 | //! - Type-safe `mem_to_mem<u32>()` method with async `.await` | ||
| 9 | //! - `Transfer` Future that can be `.await`ed | ||
| 10 | //! - `Word` trait for automatic transfer width detection | ||
| 11 | //! - `memset()` method for filling memory with a pattern | ||
| 12 | |||
| 13 | #![no_std] | ||
| 14 | #![no_main] | ||
| 15 | |||
| 16 | use embassy_executor::Spawner; | ||
| 17 | use embassy_mcxa::clocks::config::Div8; | ||
| 18 | use embassy_mcxa::dma::{DmaChannel, TransferOptions}; | ||
| 19 | use static_cell::ConstStaticCell; | ||
| 20 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 21 | |||
| 22 | const BUFFER_LENGTH: usize = 4; | ||
| 23 | |||
| 24 | // Buffers in RAM (static mut is automatically placed in .bss/.data) | ||
| 25 | static SRC_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([1, 2, 3, 4]); | ||
| 26 | static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); | ||
| 27 | static MEMSET_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(_spawner: Spawner) { | ||
| 31 | // Small delay to allow probe-rs to attach after reset | ||
| 32 | for _ in 0..100_000 { | ||
| 33 | cortex_m::asm::nop(); | ||
| 34 | } | ||
| 35 | |||
| 36 | let mut cfg = hal::config::Config::default(); | ||
| 37 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 38 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 39 | let p = hal::init(cfg); | ||
| 40 | |||
| 41 | defmt::info!("DMA memory-to-memory example starting..."); | ||
| 42 | |||
| 43 | defmt::info!("EDMA memory to memory example begin."); | ||
| 44 | |||
| 45 | let src = SRC_BUFFER.take(); | ||
| 46 | let dst = DEST_BUFFER.take(); | ||
| 47 | let mst = MEMSET_BUFFER.take(); | ||
| 48 | |||
| 49 | defmt::info!("Source Buffer: {=[?]}", src.as_slice()); | ||
| 50 | defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice()); | ||
| 51 | defmt::info!("Configuring DMA with Embassy-style API..."); | ||
| 52 | |||
| 53 | // Create DMA channel | ||
| 54 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 55 | |||
| 56 | // Configure transfer options (Embassy-style) | ||
| 57 | // TransferOptions defaults to: complete_transfer_interrupt = true | ||
| 58 | let options = TransferOptions::default(); | ||
| 59 | |||
| 60 | // ========================================================================= | ||
| 61 | // Part 1: Embassy-style async API demonstration (mem_to_mem) | ||
| 62 | // ========================================================================= | ||
| 63 | // | ||
| 64 | // Use the new type-safe `mem_to_mem<u32>()` method: | ||
| 65 | // - Automatically determines transfer width from buffer element type (u32) | ||
| 66 | // - Returns a `Transfer` future that can be `.await`ed | ||
| 67 | // - Uses TransferOptions for consistent configuration | ||
| 68 | // | ||
| 69 | // Using async `.await` - the executor can run other tasks while waiting! | ||
| 70 | |||
| 71 | // Perform type-safe memory-to-memory transfer using Embassy-style async API | ||
| 72 | // Using async `.await` - the executor can run other tasks while waiting! | ||
| 73 | let transfer = dma_ch0.mem_to_mem(src, dst, options).unwrap(); | ||
| 74 | transfer.await.unwrap(); | ||
| 75 | |||
| 76 | defmt::info!("DMA mem-to-mem transfer complete!"); | ||
| 77 | defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); | ||
| 78 | |||
| 79 | // Verify data | ||
| 80 | if src != dst { | ||
| 81 | defmt::error!("FAIL: mem_to_mem mismatch!"); | ||
| 82 | } else { | ||
| 83 | defmt::info!("PASS: mem_to_mem verified."); | ||
| 84 | } | ||
| 85 | |||
| 86 | // ========================================================================= | ||
| 87 | // Part 2: memset() demonstration | ||
| 88 | // ========================================================================= | ||
| 89 | // | ||
| 90 | // The `memset()` method fills a buffer with a pattern value: | ||
| 91 | // - Fixed source address (pattern is read repeatedly) | ||
| 92 | // - Incrementing destination address | ||
| 93 | // - Uses the same Transfer future pattern | ||
| 94 | |||
| 95 | defmt::info!("--- Demonstrating memset() feature ---"); | ||
| 96 | |||
| 97 | defmt::info!("Memset Buffer (before): {=[?]}", mst.as_slice()); | ||
| 98 | |||
| 99 | // Fill buffer with a pattern value using DMA memset | ||
| 100 | let pattern: u32 = 0xDEADBEEF; | ||
| 101 | defmt::info!("Filling with pattern 0xDEADBEEF..."); | ||
| 102 | |||
| 103 | // Using blocking_wait() for demonstration - also shows non-async usage | ||
| 104 | let transfer = dma_ch0.memset(&pattern, mst, options); | ||
| 105 | transfer.blocking_wait(); | ||
| 106 | |||
| 107 | defmt::info!("DMA memset complete!"); | ||
| 108 | defmt::info!("Memset Buffer (after): {=[?]}", mst.as_slice()); | ||
| 109 | |||
| 110 | // Verify memset result | ||
| 111 | if !mst.iter().all(|&v| v == pattern) { | ||
| 112 | defmt::error!("FAIL: memset mismatch!"); | ||
| 113 | } else { | ||
| 114 | defmt::info!("PASS: memset verified."); | ||
| 115 | } | ||
| 116 | |||
| 117 | defmt::info!("=== All DMA tests complete ==="); | ||
| 118 | } | ||
diff --git a/examples/mcxa/src/bin/dma_scatter_gather_builder.rs b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs new file mode 100644 index 000000000..30ce20c96 --- /dev/null +++ b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | //! DMA Scatter-Gather Builder example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! This example demonstrates using the new `ScatterGatherBuilder` API for | ||
| 4 | //! chaining multiple DMA transfers with a type-safe builder pattern. | ||
| 5 | //! | ||
| 6 | //! # Features demonstrated: | ||
| 7 | //! - `ScatterGatherBuilder::new()` for creating a builder | ||
| 8 | //! - `add_transfer()` for adding memory-to-memory segments | ||
| 9 | //! - `build()` to start the chained transfer | ||
| 10 | //! - Automatic TCD linking and ESG bit management | ||
| 11 | //! | ||
| 12 | //! # Comparison with manual scatter-gather: | ||
| 13 | //! The manual approach (see `dma_scatter_gather.rs`) requires: | ||
| 14 | //! - Manual TCD pool allocation and alignment | ||
| 15 | //! - Manual CSR/ESG/INTMAJOR bit manipulation | ||
| 16 | //! - Manual dlast_sga address calculations | ||
| 17 | //! | ||
| 18 | //! The builder approach handles all of this automatically! | ||
| 19 | |||
| 20 | #![no_std] | ||
| 21 | #![no_main] | ||
| 22 | |||
| 23 | use embassy_executor::Spawner; | ||
| 24 | use embassy_mcxa::clocks::config::Div8; | ||
| 25 | use embassy_mcxa::dma::{DmaChannel, ScatterGatherBuilder}; | ||
| 26 | use static_cell::ConstStaticCell; | ||
| 27 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 28 | |||
| 29 | // Source buffers (multiple segments) | ||
| 30 | static SRC1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0x11111111, 0x22222222, 0x33333333, 0x44444444]); | ||
| 31 | static SRC2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD]); | ||
| 32 | static SRC3: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210]); | ||
| 33 | |||
| 34 | // Destination buffers (one per segment) | ||
| 35 | static DST1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); | ||
| 36 | static DST2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); | ||
| 37 | static DST3: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); | ||
| 38 | |||
| 39 | #[embassy_executor::main] | ||
| 40 | async fn main(_spawner: Spawner) { | ||
| 41 | // Small delay to allow probe-rs to attach after reset | ||
| 42 | for _ in 0..100_000 { | ||
| 43 | cortex_m::asm::nop(); | ||
| 44 | } | ||
| 45 | |||
| 46 | let mut cfg = hal::config::Config::default(); | ||
| 47 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 48 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 49 | let p = hal::init(cfg); | ||
| 50 | |||
| 51 | defmt::info!("DMA Scatter-Gather Builder example starting..."); | ||
| 52 | |||
| 53 | defmt::info!("DMA Scatter-Gather Builder Example"); | ||
| 54 | defmt::info!("==================================="); | ||
| 55 | let src1 = SRC1.take(); | ||
| 56 | let src2 = SRC2.take(); | ||
| 57 | let src3 = SRC3.take(); | ||
| 58 | let dst1 = DST1.take(); | ||
| 59 | let dst2 = DST2.take(); | ||
| 60 | let dst3 = DST3.take(); | ||
| 61 | |||
| 62 | // Show source buffers | ||
| 63 | defmt::info!("Source buffers:"); | ||
| 64 | defmt::info!(" SRC1: {=[?]}", src1.as_slice()); | ||
| 65 | defmt::info!(" SRC2: {=[?]}", src2.as_slice()); | ||
| 66 | defmt::info!(" SRC3: {=[?]}", src3.as_slice()); | ||
| 67 | |||
| 68 | defmt::info!("Destination buffers (before):"); | ||
| 69 | defmt::info!(" DST1: {=[?]}", dst1.as_slice()); | ||
| 70 | defmt::info!(" DST2: {=[?]}", dst2.as_slice()); | ||
| 71 | defmt::info!(" DST3: {=[?]}", dst3.as_slice()); | ||
| 72 | |||
| 73 | // Create DMA channel | ||
| 74 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 75 | |||
| 76 | defmt::info!("Building scatter-gather chain with builder API..."); | ||
| 77 | |||
| 78 | // ========================================================================= | ||
| 79 | // ScatterGatherBuilder API demonstration | ||
| 80 | // ========================================================================= | ||
| 81 | // | ||
| 82 | // The builder pattern makes scatter-gather transfers much easier: | ||
| 83 | // 1. Create a builder | ||
| 84 | // 2. Add transfer segments with add_transfer() | ||
| 85 | // 3. Call build() to start the entire chain | ||
| 86 | // No manual TCD manipulation required! | ||
| 87 | |||
| 88 | let mut builder = ScatterGatherBuilder::<u32>::new(); | ||
| 89 | |||
| 90 | // Add three transfer segments - the builder handles TCD linking automatically | ||
| 91 | builder.add_transfer(src1, dst1); | ||
| 92 | builder.add_transfer(src2, dst2); | ||
| 93 | builder.add_transfer(src3, dst3); | ||
| 94 | |||
| 95 | defmt::info!("Added 3 transfer segments to chain."); | ||
| 96 | defmt::info!("Starting scatter-gather transfer with .await..."); | ||
| 97 | |||
| 98 | // Build and execute the scatter-gather chain | ||
| 99 | // The build() method: | ||
| 100 | // - Links all TCDs together with ESG bit | ||
| 101 | // - Sets INTMAJOR on all TCDs | ||
| 102 | // - Loads the first TCD into hardware | ||
| 103 | // - Returns a Transfer future | ||
| 104 | let transfer = builder.build(&dma_ch0).expect("Failed to build scatter-gather"); | ||
| 105 | transfer.blocking_wait(); | ||
| 106 | |||
| 107 | defmt::info!("Scatter-gather transfer complete!"); | ||
| 108 | |||
| 109 | // Show results | ||
| 110 | defmt::info!("Destination buffers (after):"); | ||
| 111 | defmt::info!(" DST1: {=[?]}", dst1.as_slice()); | ||
| 112 | defmt::info!(" DST2: {=[?]}", dst2.as_slice()); | ||
| 113 | defmt::info!(" DST3: {=[?]}", dst3.as_slice()); | ||
| 114 | |||
| 115 | let comps = [(src1, dst1), (src2, dst2), (src3, dst3)]; | ||
| 116 | |||
| 117 | // Verify all three segments | ||
| 118 | let mut all_ok = true; | ||
| 119 | for (src, dst) in comps { | ||
| 120 | all_ok &= src == dst; | ||
| 121 | } | ||
| 122 | |||
| 123 | if all_ok { | ||
| 124 | defmt::info!("PASS: All segments verified!"); | ||
| 125 | } else { | ||
| 126 | defmt::error!("FAIL: Mismatch detected!"); | ||
| 127 | } | ||
| 128 | |||
| 129 | defmt::info!("=== Scatter-Gather Builder example complete ==="); | ||
| 130 | } | ||
diff --git a/examples/mcxa/src/bin/dma_wrap_transfer.rs b/examples/mcxa/src/bin/dma_wrap_transfer.rs new file mode 100644 index 000000000..acfd29f08 --- /dev/null +++ b/examples/mcxa/src/bin/dma_wrap_transfer.rs | |||
| @@ -0,0 +1,184 @@ | |||
| 1 | //! DMA wrap transfer example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! This example demonstrates using DMA with modulo addressing to wrap around | ||
| 4 | //! a source buffer, effectively repeating the source data in the destination. | ||
| 5 | //! | ||
| 6 | //! # Embassy-style features demonstrated: | ||
| 7 | //! - `DmaChannel::is_done()` and `clear_done()` helper methods | ||
| 8 | //! - No need to pass register block around | ||
| 9 | |||
| 10 | #![no_std] | ||
| 11 | #![no_main] | ||
| 12 | |||
| 13 | use core::fmt::Write as _; | ||
| 14 | |||
| 15 | use embassy_executor::Spawner; | ||
| 16 | use embassy_mcxa::clocks::config::Div8; | ||
| 17 | use embassy_mcxa::dma::DmaChannel; | ||
| 18 | use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; | ||
| 19 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 20 | |||
| 21 | // Source buffer: 4 words (16 bytes), aligned to 16 bytes for modulo | ||
| 22 | #[repr(align(16))] | ||
| 23 | struct AlignedSrc([u32; 4]); | ||
| 24 | |||
| 25 | static mut SRC: AlignedSrc = AlignedSrc([0; 4]); | ||
| 26 | static mut DST: [u32; 8] = [0; 8]; | ||
| 27 | |||
| 28 | /// Helper to print a buffer to UART | ||
| 29 | fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) { | ||
| 30 | write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok(); | ||
| 31 | } | ||
| 32 | |||
| 33 | #[embassy_executor::main] | ||
| 34 | async fn main(_spawner: Spawner) { | ||
| 35 | // Small delay to allow probe-rs to attach after reset | ||
| 36 | for _ in 0..100_000 { | ||
| 37 | cortex_m::asm::nop(); | ||
| 38 | } | ||
| 39 | |||
| 40 | let mut cfg = hal::config::Config::default(); | ||
| 41 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 42 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 43 | let p = hal::init(cfg); | ||
| 44 | |||
| 45 | defmt::info!("DMA wrap transfer example starting..."); | ||
| 46 | |||
| 47 | let config = Config { | ||
| 48 | baudrate_bps: 115_200, | ||
| 49 | ..Default::default() | ||
| 50 | }; | ||
| 51 | |||
| 52 | let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap(); | ||
| 53 | let (mut tx, _rx) = lpuart.split(); | ||
| 54 | |||
| 55 | tx.blocking_write(b"EDMA wrap transfer example begin.\r\n\r\n").unwrap(); | ||
| 56 | |||
| 57 | // Initialize buffers | ||
| 58 | unsafe { | ||
| 59 | SRC.0 = [1, 2, 3, 4]; | ||
| 60 | DST = [0; 8]; | ||
| 61 | } | ||
| 62 | |||
| 63 | tx.blocking_write(b"Source Buffer: ").unwrap(); | ||
| 64 | print_buffer(&mut tx, unsafe { core::ptr::addr_of!(SRC.0) } as *const u32, 4); | ||
| 65 | tx.blocking_write(b"\r\n").unwrap(); | ||
| 66 | |||
| 67 | tx.blocking_write(b"Destination Buffer (before): ").unwrap(); | ||
| 68 | print_buffer(&mut tx, core::ptr::addr_of!(DST) as *const u32, 8); | ||
| 69 | tx.blocking_write(b"\r\n").unwrap(); | ||
| 70 | |||
| 71 | tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n") | ||
| 72 | .unwrap(); | ||
| 73 | |||
| 74 | // Create DMA channel using Embassy-style API | ||
| 75 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 76 | |||
| 77 | // Configure wrap transfer using direct TCD access: | ||
| 78 | // SRC is 16 bytes (4 * u32). We want to transfer 32 bytes (8 * u32). | ||
| 79 | // SRC modulo is 16 bytes (2^4 = 16) - wraps source address. | ||
| 80 | // DST modulo is 0 (disabled). | ||
| 81 | // This causes the source address to wrap around after 16 bytes, | ||
| 82 | // effectively repeating the source data. | ||
| 83 | unsafe { | ||
| 84 | let t = dma_ch0.tcd(); | ||
| 85 | |||
| 86 | // Reset channel state | ||
| 87 | t.ch_csr().write(|w| { | ||
| 88 | w.erq() | ||
| 89 | .disable() | ||
| 90 | .earq() | ||
| 91 | .disable() | ||
| 92 | .eei() | ||
| 93 | .no_error() | ||
| 94 | .ebw() | ||
| 95 | .disable() | ||
| 96 | .done() | ||
| 97 | .clear_bit_by_one() | ||
| 98 | }); | ||
| 99 | t.ch_es().write(|w| w.bits(0)); | ||
| 100 | t.ch_int().write(|w| w.int().clear_bit_by_one()); | ||
| 101 | |||
| 102 | // Source/destination addresses | ||
| 103 | t.tcd_saddr() | ||
| 104 | .write(|w| w.saddr().bits(core::ptr::addr_of!(SRC.0) as u32)); | ||
| 105 | t.tcd_daddr() | ||
| 106 | .write(|w| w.daddr().bits(core::ptr::addr_of_mut!(DST) as u32)); | ||
| 107 | |||
| 108 | // Offsets: both increment by 4 bytes | ||
| 109 | t.tcd_soff().write(|w| w.soff().bits(4)); | ||
| 110 | t.tcd_doff().write(|w| w.doff().bits(4)); | ||
| 111 | |||
| 112 | // Attributes: 32-bit transfers (size = 2) | ||
| 113 | // SMOD = 4 (2^4 = 16 byte modulo for source), DMOD = 0 (disabled) | ||
| 114 | t.tcd_attr().write(|w| { | ||
| 115 | w.ssize() | ||
| 116 | .bits(2) | ||
| 117 | .dsize() | ||
| 118 | .bits(2) | ||
| 119 | .smod() | ||
| 120 | .bits(4) // Source modulo: 2^4 = 16 bytes | ||
| 121 | .dmod() | ||
| 122 | .bits(0) // Dest modulo: disabled | ||
| 123 | }); | ||
| 124 | |||
| 125 | // Transfer 32 bytes total in one minor loop | ||
| 126 | let nbytes = 32u32; | ||
| 127 | t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes)); | ||
| 128 | |||
| 129 | // Source wraps via modulo, no adjustment needed | ||
| 130 | t.tcd_slast_sda().write(|w| w.slast_sda().bits(0)); | ||
| 131 | // Reset dest address after major loop | ||
| 132 | t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32)); | ||
| 133 | |||
| 134 | // Major loop count = 1 | ||
| 135 | t.tcd_biter_elinkno().write(|w| w.biter().bits(1)); | ||
| 136 | t.tcd_citer_elinkno().write(|w| w.citer().bits(1)); | ||
| 137 | |||
| 138 | // Enable interrupt on major loop completion | ||
| 139 | t.tcd_csr().write(|w| w.intmajor().set_bit()); | ||
| 140 | |||
| 141 | cortex_m::asm::dsb(); | ||
| 142 | |||
| 143 | tx.blocking_write(b"Triggering transfer...\r\n").unwrap(); | ||
| 144 | dma_ch0.trigger_start(); | ||
| 145 | } | ||
| 146 | |||
| 147 | // Wait for completion using channel helper method | ||
| 148 | while !dma_ch0.is_done() { | ||
| 149 | cortex_m::asm::nop(); | ||
| 150 | } | ||
| 151 | unsafe { | ||
| 152 | dma_ch0.clear_done(); | ||
| 153 | } | ||
| 154 | |||
| 155 | tx.blocking_write(b"\r\nEDMA wrap transfer example finish.\r\n\r\n") | ||
| 156 | .unwrap(); | ||
| 157 | tx.blocking_write(b"Destination Buffer (after): ").unwrap(); | ||
| 158 | print_buffer(&mut tx, core::ptr::addr_of!(DST) as *const u32, 8); | ||
| 159 | tx.blocking_write(b"\r\n\r\n").unwrap(); | ||
| 160 | |||
| 161 | // Verify: DST should be [1, 2, 3, 4, 1, 2, 3, 4] | ||
| 162 | let expected = [1u32, 2, 3, 4, 1, 2, 3, 4]; | ||
| 163 | let mut mismatch = false; | ||
| 164 | unsafe { | ||
| 165 | for i in 0..8 { | ||
| 166 | if DST[i] != expected[i] { | ||
| 167 | mismatch = true; | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | if mismatch { | ||
| 174 | tx.blocking_write(b"FAIL: Mismatch detected!\r\n").unwrap(); | ||
| 175 | defmt::error!("FAIL: Mismatch detected!"); | ||
| 176 | } else { | ||
| 177 | tx.blocking_write(b"PASS: Data verified.\r\n").unwrap(); | ||
| 178 | defmt::info!("PASS: Data verified."); | ||
| 179 | } | ||
| 180 | |||
| 181 | loop { | ||
| 182 | cortex_m::asm::wfe(); | ||
| 183 | } | ||
| 184 | } | ||
diff --git a/examples/mcxa/src/bin/hello.rs b/examples/mcxa/src/bin/hello.rs new file mode 100644 index 000000000..e371d9413 --- /dev/null +++ b/examples/mcxa/src/bin/hello.rs | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::clocks::config::Div8; | ||
| 6 | use hal::lpuart::{Blocking, Config, Lpuart}; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | /// Simple helper to write a byte as hex to UART | ||
| 10 | fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { | ||
| 11 | const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; | ||
| 12 | let _ = uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); | ||
| 13 | let _ = uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); | ||
| 14 | } | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let mut cfg = hal::config::Config::default(); | ||
| 19 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 20 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 21 | let p = hal::init(cfg); | ||
| 22 | |||
| 23 | defmt::info!("boot"); | ||
| 24 | |||
| 25 | // Create UART configuration | ||
| 26 | let config = Config { | ||
| 27 | baudrate_bps: 115_200, | ||
| 28 | ..Default::default() | ||
| 29 | }; | ||
| 30 | |||
| 31 | // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX | ||
| 32 | let mut uart = Lpuart::new_blocking( | ||
| 33 | p.LPUART2, // Peripheral | ||
| 34 | p.P2_2, // TX pin | ||
| 35 | p.P2_3, // RX pin | ||
| 36 | config, | ||
| 37 | ) | ||
| 38 | .unwrap(); | ||
| 39 | |||
| 40 | // Print welcome message before any async delays to guarantee early console output | ||
| 41 | uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); | ||
| 42 | uart.write_str_blocking("Available commands:\r\n"); | ||
| 43 | uart.write_str_blocking(" help - Show this help\r\n"); | ||
| 44 | uart.write_str_blocking(" echo <text> - Echo back the text\r\n"); | ||
| 45 | uart.write_str_blocking(" hex <byte> - Display byte in hex (0-255)\r\n"); | ||
| 46 | uart.write_str_blocking("Type a command: "); | ||
| 47 | |||
| 48 | let mut buffer = [0u8; 64]; | ||
| 49 | let mut buf_idx = 0; | ||
| 50 | |||
| 51 | loop { | ||
| 52 | // Read a byte from UART | ||
| 53 | let byte = uart.read_byte_blocking(); | ||
| 54 | |||
| 55 | // Echo the character back | ||
| 56 | if byte == b'\r' || byte == b'\n' { | ||
| 57 | // Enter pressed - process command | ||
| 58 | uart.write_str_blocking("\r\n"); | ||
| 59 | |||
| 60 | if buf_idx > 0 { | ||
| 61 | let command = &buffer[0..buf_idx]; | ||
| 62 | |||
| 63 | if command == b"help" { | ||
| 64 | uart.write_str_blocking("Available commands:\r\n"); | ||
| 65 | uart.write_str_blocking(" help - Show this help\r\n"); | ||
| 66 | uart.write_str_blocking(" echo <text> - Echo back the text\r\n"); | ||
| 67 | uart.write_str_blocking(" hex <byte> - Display byte in hex (0-255)\r\n"); | ||
| 68 | } else if command.starts_with(b"echo ") && command.len() > 5 { | ||
| 69 | uart.write_str_blocking("Echo: "); | ||
| 70 | uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or("")); | ||
| 71 | uart.write_str_blocking("\r\n"); | ||
| 72 | } else if command.starts_with(b"hex ") && command.len() > 4 { | ||
| 73 | // Parse the byte value | ||
| 74 | let num_str = &command[4..]; | ||
| 75 | if let Ok(num) = parse_u8(num_str) { | ||
| 76 | uart.write_str_blocking("Hex: 0x"); | ||
| 77 | write_hex_byte(&mut uart, num); | ||
| 78 | uart.write_str_blocking("\r\n"); | ||
| 79 | } else { | ||
| 80 | uart.write_str_blocking("Invalid number for hex command\r\n"); | ||
| 81 | } | ||
| 82 | } else if !command.is_empty() { | ||
| 83 | uart.write_str_blocking("Unknown command: "); | ||
| 84 | uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); | ||
| 85 | uart.write_str_blocking("\r\n"); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | // Reset buffer and prompt | ||
| 90 | buf_idx = 0; | ||
| 91 | uart.write_str_blocking("Type a command: "); | ||
| 92 | } else if byte == 8 || byte == 127 { | ||
| 93 | // Backspace | ||
| 94 | if buf_idx > 0 { | ||
| 95 | buf_idx -= 1; | ||
| 96 | uart.write_str_blocking("\x08 \x08"); // Erase character | ||
| 97 | } | ||
| 98 | } else if buf_idx < buffer.len() - 1 { | ||
| 99 | // Regular character | ||
| 100 | buffer[buf_idx] = byte; | ||
| 101 | buf_idx += 1; | ||
| 102 | let _ = uart.write_byte(byte); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Simple parser for u8 from ASCII bytes | ||
| 108 | fn parse_u8(bytes: &[u8]) -> Result<u8, ()> { | ||
| 109 | let mut result = 0u8; | ||
| 110 | for &b in bytes { | ||
| 111 | if b.is_ascii_digit() { | ||
| 112 | result = result.checked_mul(10).ok_or(())?; | ||
| 113 | result = result.checked_add(b - b'0').ok_or(())?; | ||
| 114 | } else { | ||
| 115 | return Err(()); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | Ok(result) | ||
| 119 | } | ||
diff --git a/examples/mcxa/src/bin/i2c-async.rs b/examples/mcxa/src/bin/i2c-async.rs new file mode 100644 index 000000000..edcfd5f22 --- /dev/null +++ b/examples/mcxa/src/bin/i2c-async.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::bind_interrupts; | ||
| 7 | use hal::clocks::config::Div8; | ||
| 8 | use hal::config::Config; | ||
| 9 | use hal::i2c::InterruptHandler; | ||
| 10 | use hal::i2c::controller::{self, I2c, Speed}; | ||
| 11 | use hal::peripherals::LPI2C3; | ||
| 12 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_interrupts!( | ||
| 15 | struct Irqs { | ||
| 16 | LPI2C3 => InterruptHandler<LPI2C3>; | ||
| 17 | } | ||
| 18 | ); | ||
| 19 | |||
| 20 | #[embassy_executor::main] | ||
| 21 | async fn main(_spawner: Spawner) { | ||
| 22 | let mut config = Config::default(); | ||
| 23 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 24 | |||
| 25 | let p = hal::init(config); | ||
| 26 | |||
| 27 | defmt::info!("I2C example"); | ||
| 28 | |||
| 29 | let mut config = controller::Config::default(); | ||
| 30 | config.speed = Speed::Standard; | ||
| 31 | let mut i2c = I2c::new_async(p.LPI2C3, p.P3_27, p.P3_28, Irqs, config).unwrap(); | ||
| 32 | let mut buf = [0u8; 2]; | ||
| 33 | |||
| 34 | loop { | ||
| 35 | i2c.async_write_read(0x48, &[0x00], &mut buf).await.unwrap(); | ||
| 36 | defmt::info!("Buffer: {:02x}", buf); | ||
| 37 | Timer::after_secs(1).await; | ||
| 38 | } | ||
| 39 | } | ||
diff --git a/examples/mcxa/src/bin/i2c-blocking.rs b/examples/mcxa/src/bin/i2c-blocking.rs new file mode 100644 index 000000000..0f6c8cbae --- /dev/null +++ b/examples/mcxa/src/bin/i2c-blocking.rs | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::clocks::config::Div8; | ||
| 7 | use hal::config::Config; | ||
| 8 | use hal::i2c::controller::{self, I2c, Speed}; | ||
| 9 | use tmp108::Tmp108; | ||
| 10 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let mut config = Config::default(); | ||
| 15 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 16 | |||
| 17 | let p = hal::init(config); | ||
| 18 | |||
| 19 | defmt::info!("I2C example"); | ||
| 20 | |||
| 21 | let mut config = controller::Config::default(); | ||
| 22 | config.speed = Speed::Standard; | ||
| 23 | let i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); | ||
| 24 | let mut tmp = Tmp108::new_with_a0_gnd(i2c); | ||
| 25 | |||
| 26 | loop { | ||
| 27 | let temperature = tmp.temperature().unwrap(); | ||
| 28 | defmt::info!("Temperature: {}C", temperature); | ||
| 29 | Timer::after_secs(1).await; | ||
| 30 | } | ||
| 31 | } | ||
diff --git a/examples/mcxa/src/bin/i2c-scan-blocking.rs b/examples/mcxa/src/bin/i2c-scan-blocking.rs new file mode 100644 index 000000000..bd706d712 --- /dev/null +++ b/examples/mcxa/src/bin/i2c-scan-blocking.rs | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::gpio::{Input, Pull}; | ||
| 6 | use embassy_time::Timer; | ||
| 7 | use hal::clocks::config::Div8; | ||
| 8 | use hal::config::Config; | ||
| 9 | use hal::i2c::controller::{self, I2c, Speed}; | ||
| 10 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let mut config = Config::default(); | ||
| 15 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 16 | |||
| 17 | let p = hal::init(config); | ||
| 18 | |||
| 19 | defmt::info!("I2C example"); | ||
| 20 | |||
| 21 | let mut config = controller::Config::default(); | ||
| 22 | config.speed = Speed::Standard; | ||
| 23 | |||
| 24 | // Note: P0_2 is connected to P1_8 on the FRDM_MCXA276 via a resistor, and | ||
| 25 | // defaults to SWO on the debug peripheral. Explicitly make it a high-z | ||
| 26 | // input. | ||
| 27 | let _pin = Input::new(p.P0_2, Pull::Disabled); | ||
| 28 | let mut i2c = I2c::new_blocking(p.LPI2C2, p.P1_9, p.P1_8, config).unwrap(); | ||
| 29 | |||
| 30 | for addr in 0x01..=0x7f { | ||
| 31 | let result = i2c.blocking_write(addr, &[]); | ||
| 32 | if result.is_ok() { | ||
| 33 | defmt::info!("Device found at addr {:02x}", addr); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | loop { | ||
| 38 | Timer::after_secs(10).await; | ||
| 39 | } | ||
| 40 | } | ||
diff --git a/examples/mcxa/src/bin/lpuart_buffered.rs b/examples/mcxa/src/bin/lpuart_buffered.rs new file mode 100644 index 000000000..47b56b7c7 --- /dev/null +++ b/examples/mcxa/src/bin/lpuart_buffered.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::clocks::config::Div8; | ||
| 6 | use embassy_mcxa::lpuart::Config; | ||
| 7 | use embassy_mcxa::lpuart::buffered::BufferedLpuart; | ||
| 8 | use embassy_mcxa::{bind_interrupts, lpuart}; | ||
| 9 | use embedded_io_async::Write; | ||
| 10 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 11 | |||
| 12 | // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver | ||
| 13 | bind_interrupts!(struct Irqs { | ||
| 14 | LPUART2 => lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>; | ||
| 15 | }); | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) { | ||
| 19 | let mut cfg = hal::config::Config::default(); | ||
| 20 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 21 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 22 | let p = hal::init(cfg); | ||
| 23 | |||
| 24 | // Configure NVIC for LPUART2 | ||
| 25 | hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); | ||
| 26 | |||
| 27 | // UART configuration (enable both TX and RX) | ||
| 28 | let config = Config { | ||
| 29 | baudrate_bps: 115_200, | ||
| 30 | rx_fifo_watermark: 0, | ||
| 31 | tx_fifo_watermark: 0, | ||
| 32 | ..Default::default() | ||
| 33 | }; | ||
| 34 | |||
| 35 | let mut tx_buf = [0u8; 256]; | ||
| 36 | let mut rx_buf = [0u8; 256]; | ||
| 37 | |||
| 38 | // Create a buffered LPUART2 instance with both TX and RX | ||
| 39 | let mut uart = BufferedLpuart::new( | ||
| 40 | p.LPUART2, | ||
| 41 | p.P2_2, // TX pin | ||
| 42 | p.P2_3, // RX pin | ||
| 43 | Irqs, | ||
| 44 | &mut tx_buf, | ||
| 45 | &mut rx_buf, | ||
| 46 | config, | ||
| 47 | ) | ||
| 48 | .unwrap(); | ||
| 49 | |||
| 50 | // Split into TX and RX parts | ||
| 51 | let (tx, rx) = uart.split_ref(); | ||
| 52 | |||
| 53 | tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); | ||
| 54 | tx.write(b"Type characters to echo them back.\r\n").await.unwrap(); | ||
| 55 | |||
| 56 | // Echo loop | ||
| 57 | let mut buf = [0u8; 4]; | ||
| 58 | loop { | ||
| 59 | let used = rx.read(&mut buf).await.unwrap(); | ||
| 60 | tx.write_all(&buf[..used]).await.unwrap(); | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/examples/mcxa/src/bin/lpuart_dma.rs b/examples/mcxa/src/bin/lpuart_dma.rs new file mode 100644 index 000000000..cc86f6a40 --- /dev/null +++ b/examples/mcxa/src/bin/lpuart_dma.rs | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | //! LPUART DMA example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! This example demonstrates using DMA for UART TX and RX operations. | ||
| 4 | //! It sends a message using DMA, then waits for 16 characters to be received | ||
| 5 | //! via DMA and echoes them back. | ||
| 6 | //! | ||
| 7 | //! The DMA request sources are automatically derived from the LPUART instance type. | ||
| 8 | //! DMA clock/reset/init is handled automatically by the HAL. | ||
| 9 | |||
| 10 | #![no_std] | ||
| 11 | #![no_main] | ||
| 12 | |||
| 13 | use embassy_executor::Spawner; | ||
| 14 | use embassy_mcxa::clocks::config::Div8; | ||
| 15 | use embassy_mcxa::lpuart::{Config, LpuartDma}; | ||
| 16 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 17 | |||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | let mut cfg = hal::config::Config::default(); | ||
| 21 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 22 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 23 | let p = hal::init(cfg); | ||
| 24 | |||
| 25 | defmt::info!("LPUART DMA example starting..."); | ||
| 26 | |||
| 27 | // Create UART configuration | ||
| 28 | let config = Config { | ||
| 29 | baudrate_bps: 115_200, | ||
| 30 | ..Default::default() | ||
| 31 | }; | ||
| 32 | |||
| 33 | // Create UART instance with DMA channels | ||
| 34 | let mut lpuart = LpuartDma::new( | ||
| 35 | p.LPUART2, // Instance | ||
| 36 | p.P2_2, // TX pin | ||
| 37 | p.P2_3, // RX pin | ||
| 38 | p.DMA_CH0, // TX DMA channel | ||
| 39 | p.DMA_CH1, // RX DMA channel | ||
| 40 | config, | ||
| 41 | ) | ||
| 42 | .unwrap(); | ||
| 43 | |||
| 44 | // Send a message using DMA (DMA request source is automatically derived from LPUART2) | ||
| 45 | let tx_msg = b"Hello from LPUART2 DMA TX!\r\n"; | ||
| 46 | lpuart.write_dma(tx_msg).await.unwrap(); | ||
| 47 | |||
| 48 | defmt::info!("TX DMA complete"); | ||
| 49 | |||
| 50 | // Send prompt | ||
| 51 | let prompt = b"Type 16 characters to echo via DMA:\r\n"; | ||
| 52 | lpuart.write_dma(prompt).await.unwrap(); | ||
| 53 | |||
| 54 | // Receive 16 characters using DMA | ||
| 55 | let mut rx_buf = [0u8; 16]; | ||
| 56 | lpuart.read_dma(&mut rx_buf).await.unwrap(); | ||
| 57 | |||
| 58 | defmt::info!("RX DMA complete"); | ||
| 59 | |||
| 60 | // Echo back the received data | ||
| 61 | let echo_prefix = b"\r\nReceived: "; | ||
| 62 | lpuart.write_dma(echo_prefix).await.unwrap(); | ||
| 63 | lpuart.write_dma(&rx_buf).await.unwrap(); | ||
| 64 | let done_msg = b"\r\nDone!\r\n"; | ||
| 65 | lpuart.write_dma(done_msg).await.unwrap(); | ||
| 66 | |||
| 67 | defmt::info!("Example complete"); | ||
| 68 | } | ||
diff --git a/examples/mcxa/src/bin/lpuart_polling.rs b/examples/mcxa/src/bin/lpuart_polling.rs new file mode 100644 index 000000000..b80668834 --- /dev/null +++ b/examples/mcxa/src/bin/lpuart_polling.rs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::clocks::config::Div8; | ||
| 6 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 7 | |||
| 8 | use crate::hal::lpuart::{Config, Lpuart}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let mut cfg = hal::config::Config::default(); | ||
| 13 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 14 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 15 | let p = hal::init(cfg); | ||
| 16 | |||
| 17 | defmt::info!("boot"); | ||
| 18 | |||
| 19 | // Create UART configuration | ||
| 20 | let config = Config { | ||
| 21 | baudrate_bps: 115_200, | ||
| 22 | ..Default::default() | ||
| 23 | }; | ||
| 24 | |||
| 25 | // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX | ||
| 26 | let lpuart = Lpuart::new_blocking( | ||
| 27 | p.LPUART2, // Peripheral | ||
| 28 | p.P2_2, // TX pin | ||
| 29 | p.P2_3, // RX pin | ||
| 30 | config, | ||
| 31 | ) | ||
| 32 | .unwrap(); | ||
| 33 | |||
| 34 | // Split into separate TX and RX parts | ||
| 35 | let (mut tx, mut rx) = lpuart.split(); | ||
| 36 | |||
| 37 | // Write hello messages | ||
| 38 | tx.blocking_write(b"Hello world.\r\n").unwrap(); | ||
| 39 | tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap(); | ||
| 40 | |||
| 41 | // Echo loop | ||
| 42 | loop { | ||
| 43 | let mut buf = [0u8; 1]; | ||
| 44 | rx.blocking_read(&mut buf).unwrap(); | ||
| 45 | tx.blocking_write(&buf).unwrap(); | ||
| 46 | } | ||
| 47 | } | ||
diff --git a/examples/mcxa/src/bin/lpuart_ring_buffer.rs b/examples/mcxa/src/bin/lpuart_ring_buffer.rs new file mode 100644 index 000000000..be7fd4534 --- /dev/null +++ b/examples/mcxa/src/bin/lpuart_ring_buffer.rs | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | //! LPUART Ring Buffer DMA example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! This example demonstrates using the high-level `LpuartRxDma::setup_ring_buffer()` | ||
| 4 | //! API for continuous circular DMA reception from a UART peripheral. | ||
| 5 | //! | ||
| 6 | //! # Features demonstrated: | ||
| 7 | //! - `LpuartRxDma::setup_ring_buffer()` for continuous peripheral-to-memory DMA | ||
| 8 | //! - `RingBuffer` for async reading of received data | ||
| 9 | //! - Handling of potential overrun conditions | ||
| 10 | //! - Half-transfer and complete-transfer interrupts for timely wakeups | ||
| 11 | //! | ||
| 12 | //! # How it works: | ||
| 13 | //! 1. Create an `LpuartRxDma` driver with a DMA channel | ||
| 14 | //! 2. Call `setup_ring_buffer()` which handles all low-level DMA configuration | ||
| 15 | //! 3. Application asynchronously reads data as it arrives via `ring_buf.read()` | ||
| 16 | //! 4. Both half-transfer and complete-transfer interrupts wake the reader | ||
| 17 | |||
| 18 | #![no_std] | ||
| 19 | #![no_main] | ||
| 20 | |||
| 21 | use embassy_executor::Spawner; | ||
| 22 | use embassy_mcxa::clocks::config::Div8; | ||
| 23 | use embassy_mcxa::lpuart::{Config, LpuartDma, LpuartTxDma}; | ||
| 24 | use static_cell::ConstStaticCell; | ||
| 25 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 26 | |||
| 27 | // Ring buffer for RX - power of 2 is ideal for modulo efficiency | ||
| 28 | static RX_RING_BUFFER: ConstStaticCell<[u8; 64]> = ConstStaticCell::new([0; 64]); | ||
| 29 | |||
| 30 | /// Helper to write a byte as hex to UART | ||
| 31 | fn write_hex<T: embassy_mcxa::lpuart::Instance, C: embassy_mcxa::dma::Channel>( | ||
| 32 | tx: &mut LpuartTxDma<'_, T, C>, | ||
| 33 | byte: u8, | ||
| 34 | ) { | ||
| 35 | const HEX: &[u8; 16] = b"0123456789ABCDEF"; | ||
| 36 | let buf = [HEX[(byte >> 4) as usize], HEX[(byte & 0x0F) as usize]]; | ||
| 37 | tx.blocking_write(&buf).ok(); | ||
| 38 | } | ||
| 39 | |||
| 40 | #[embassy_executor::main] | ||
| 41 | async fn main(_spawner: Spawner) { | ||
| 42 | // Small delay to allow probe-rs to attach after reset | ||
| 43 | for _ in 0..100_000 { | ||
| 44 | cortex_m::asm::nop(); | ||
| 45 | } | ||
| 46 | |||
| 47 | let mut cfg = hal::config::Config::default(); | ||
| 48 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 49 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 50 | let p = hal::init(cfg); | ||
| 51 | |||
| 52 | defmt::info!("LPUART Ring Buffer DMA example starting..."); | ||
| 53 | |||
| 54 | // Create UART configuration | ||
| 55 | let config = Config { | ||
| 56 | baudrate_bps: 115_200, | ||
| 57 | ..Default::default() | ||
| 58 | }; | ||
| 59 | |||
| 60 | // Create LPUART with DMA support for both TX and RX, then split | ||
| 61 | // This is the proper Embassy pattern - create once, split into TX and RX | ||
| 62 | let lpuart = LpuartDma::new(p.LPUART2, p.P2_2, p.P2_3, p.DMA_CH1, p.DMA_CH0, config).unwrap(); | ||
| 63 | let (mut tx, rx) = lpuart.split(); | ||
| 64 | |||
| 65 | tx.blocking_write(b"LPUART Ring Buffer DMA Example\r\n").unwrap(); | ||
| 66 | tx.blocking_write(b"==============================\r\n\r\n").unwrap(); | ||
| 67 | |||
| 68 | tx.blocking_write(b"Setting up circular DMA for UART RX...\r\n") | ||
| 69 | .unwrap(); | ||
| 70 | |||
| 71 | let buf = RX_RING_BUFFER.take(); | ||
| 72 | // Set up the ring buffer with circular DMA | ||
| 73 | let mut ring_buf = rx.into_ring_dma_rx(buf); | ||
| 74 | |||
| 75 | tx.blocking_write(b"Ring buffer ready! Type characters to see them echoed.\r\n") | ||
| 76 | .unwrap(); | ||
| 77 | tx.blocking_write(b"The DMA continuously receives in the background.\r\n\r\n") | ||
| 78 | .unwrap(); | ||
| 79 | |||
| 80 | // Main loop: read from ring buffer and echo back | ||
| 81 | let mut read_buf = [0u8; 16]; | ||
| 82 | let mut total_received: usize = 0; | ||
| 83 | |||
| 84 | loop { | ||
| 85 | // Async read - waits until data is available | ||
| 86 | match ring_buf.read(&mut read_buf).await { | ||
| 87 | Ok(n) if n > 0 => { | ||
| 88 | total_received += n; | ||
| 89 | |||
| 90 | // Echo back what we received | ||
| 91 | tx.blocking_write(b"RX[").unwrap(); | ||
| 92 | for (i, &byte) in read_buf.iter().enumerate().take(n) { | ||
| 93 | write_hex(&mut tx, byte); | ||
| 94 | if i < n - 1 { | ||
| 95 | tx.blocking_write(b" ").unwrap(); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | tx.blocking_write(b"]: ").unwrap(); | ||
| 99 | tx.blocking_write(&read_buf[..n]).unwrap(); | ||
| 100 | tx.blocking_write(b"\r\n").unwrap(); | ||
| 101 | |||
| 102 | defmt::info!("Received {} bytes, total: {}", n, total_received); | ||
| 103 | } | ||
| 104 | Ok(_) => { | ||
| 105 | // No data, shouldn't happen with async read | ||
| 106 | } | ||
| 107 | Err(_) => { | ||
| 108 | // Overrun detected | ||
| 109 | tx.blocking_write(b"ERROR: Ring buffer overrun!\r\n").unwrap(); | ||
| 110 | defmt::error!("Ring buffer overrun!"); | ||
| 111 | ring_buf.clear(); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
diff --git a/examples/mcxa/src/bin/raw_dma_channel_link.rs b/examples/mcxa/src/bin/raw_dma_channel_link.rs new file mode 100644 index 000000000..74785e4f3 --- /dev/null +++ b/examples/mcxa/src/bin/raw_dma_channel_link.rs | |||
| @@ -0,0 +1,278 @@ | |||
| 1 | //! DMA channel linking example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have | ||
| 4 | //! a high-level and safe API for. It should not be taken as typical, recommended, or | ||
| 5 | //! stable usage! | ||
| 6 | //! | ||
| 7 | //! This example demonstrates DMA channel linking (minor and major loop linking): | ||
| 8 | //! - Channel 0: Transfers SRC_BUFFER to DEST_BUFFER0, with: | ||
| 9 | //! - Minor Link to Channel 1 (triggers CH1 after each minor loop) | ||
| 10 | //! - Major Link to Channel 2 (triggers CH2 after major loop completes) | ||
| 11 | //! - Channel 1: Transfers SRC_BUFFER to DEST_BUFFER1 (triggered by CH0 minor link) | ||
| 12 | //! - Channel 2: Transfers SRC_BUFFER to DEST_BUFFER2 (triggered by CH0 major link) | ||
| 13 | //! | ||
| 14 | //! # Embassy-style features demonstrated: | ||
| 15 | //! - `DmaChannel::new()` for channel creation | ||
| 16 | //! - `DmaChannel::is_done()` and `clear_done()` helper methods | ||
| 17 | //! - Channel linking with `set_minor_link()` and `set_major_link()` | ||
| 18 | |||
| 19 | #![no_std] | ||
| 20 | #![no_main] | ||
| 21 | |||
| 22 | use embassy_executor::Spawner; | ||
| 23 | use embassy_mcxa::clocks::config::Div8; | ||
| 24 | use embassy_mcxa::dma::DmaChannel; | ||
| 25 | use embassy_mcxa::pac; | ||
| 26 | use static_cell::ConstStaticCell; | ||
| 27 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 28 | |||
| 29 | // Buffers | ||
| 30 | static SRC_BUFFER: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([1, 2, 3, 4]); | ||
| 31 | static DEST_BUFFER0: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); | ||
| 32 | static DEST_BUFFER1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); | ||
| 33 | static DEST_BUFFER2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); | ||
| 34 | |||
| 35 | #[embassy_executor::main] | ||
| 36 | async fn main(_spawner: Spawner) { | ||
| 37 | // Small delay to allow probe-rs to attach after reset | ||
| 38 | for _ in 0..100_000 { | ||
| 39 | cortex_m::asm::nop(); | ||
| 40 | } | ||
| 41 | |||
| 42 | let mut cfg = hal::config::Config::default(); | ||
| 43 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 44 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 45 | let p = hal::init(cfg); | ||
| 46 | |||
| 47 | defmt::info!("DMA channel link example starting..."); | ||
| 48 | |||
| 49 | // DMA is initialized during hal::init() - no need to call ensure_init() | ||
| 50 | |||
| 51 | let pac_periphs = unsafe { pac::Peripherals::steal() }; | ||
| 52 | let dma0 = &pac_periphs.dma0; | ||
| 53 | let edma = unsafe { &*pac::Edma0Tcd0::ptr() }; | ||
| 54 | |||
| 55 | // Clear any residual state | ||
| 56 | for i in 0..3 { | ||
| 57 | let t = edma.tcd(i); | ||
| 58 | t.ch_csr().write(|w| w.erq().disable().done().clear_bit_by_one()); | ||
| 59 | t.ch_int().write(|w| w.int().clear_bit_by_one()); | ||
| 60 | t.ch_es().write(|w| w.err().clear_bit_by_one()); | ||
| 61 | t.ch_mux().write(|w| unsafe { w.bits(0) }); | ||
| 62 | } | ||
| 63 | |||
| 64 | // Clear Global Halt/Error state | ||
| 65 | dma0.mp_csr().modify(|_, w| { | ||
| 66 | w.halt() | ||
| 67 | .normal_operation() | ||
| 68 | .hae() | ||
| 69 | .normal_operation() | ||
| 70 | .ecx() | ||
| 71 | .normal_operation() | ||
| 72 | .cx() | ||
| 73 | .normal_operation() | ||
| 74 | }); | ||
| 75 | |||
| 76 | defmt::info!("EDMA channel link example begin."); | ||
| 77 | |||
| 78 | // Initialize buffers | ||
| 79 | let src = SRC_BUFFER.take(); | ||
| 80 | let dst0 = DEST_BUFFER0.take(); | ||
| 81 | let dst1 = DEST_BUFFER1.take(); | ||
| 82 | let dst2 = DEST_BUFFER2.take(); | ||
| 83 | |||
| 84 | defmt::info!("Source Buffer: {=[?]}", src.as_slice()); | ||
| 85 | defmt::info!("DEST0 (before): {=[?]}", dst0.as_slice()); | ||
| 86 | defmt::info!("DEST1 (before): {=[?]}", dst1.as_slice()); | ||
| 87 | defmt::info!("DEST2 (before): {=[?]}", dst2.as_slice()); | ||
| 88 | |||
| 89 | defmt::info!("Configuring DMA channels with Embassy-style API..."); | ||
| 90 | |||
| 91 | let ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 92 | let ch1 = DmaChannel::new(p.DMA_CH1); | ||
| 93 | let ch2 = DmaChannel::new(p.DMA_CH2); | ||
| 94 | |||
| 95 | // Configure channels using direct TCD access (advanced feature demo) | ||
| 96 | // This example demonstrates channel linking which requires direct TCD manipulation | ||
| 97 | |||
| 98 | // Helper to configure TCD for memory-to-memory transfer | ||
| 99 | // Parameters: channel, src, dst, width, nbytes (minor loop), count (major loop), interrupt | ||
| 100 | #[allow(clippy::too_many_arguments)] | ||
| 101 | unsafe fn configure_tcd( | ||
| 102 | edma: &embassy_mcxa::pac::edma_0_tcd0::RegisterBlock, | ||
| 103 | ch: usize, | ||
| 104 | src: u32, | ||
| 105 | dst: u32, | ||
| 106 | width: u8, | ||
| 107 | nbytes: u32, | ||
| 108 | count: u16, | ||
| 109 | enable_int: bool, | ||
| 110 | ) { | ||
| 111 | let t = edma.tcd(ch); | ||
| 112 | |||
| 113 | // Reset channel state | ||
| 114 | t.ch_csr().write(|w| { | ||
| 115 | w.erq() | ||
| 116 | .disable() | ||
| 117 | .earq() | ||
| 118 | .disable() | ||
| 119 | .eei() | ||
| 120 | .no_error() | ||
| 121 | .ebw() | ||
| 122 | .disable() | ||
| 123 | .done() | ||
| 124 | .clear_bit_by_one() | ||
| 125 | }); | ||
| 126 | t.ch_es().write(|w| w.bits(0)); | ||
| 127 | t.ch_int().write(|w| w.int().clear_bit_by_one()); | ||
| 128 | |||
| 129 | // Source/destination addresses | ||
| 130 | t.tcd_saddr().write(|w| w.saddr().bits(src)); | ||
| 131 | t.tcd_daddr().write(|w| w.daddr().bits(dst)); | ||
| 132 | |||
| 133 | // Offsets: increment by width | ||
| 134 | t.tcd_soff().write(|w| w.soff().bits(width as u16)); | ||
| 135 | t.tcd_doff().write(|w| w.doff().bits(width as u16)); | ||
| 136 | |||
| 137 | // Attributes: size = log2(width) | ||
| 138 | let size = match width { | ||
| 139 | 1 => 0, | ||
| 140 | 2 => 1, | ||
| 141 | 4 => 2, | ||
| 142 | _ => 0, | ||
| 143 | }; | ||
| 144 | t.tcd_attr().write(|w| w.ssize().bits(size).dsize().bits(size)); | ||
| 145 | |||
| 146 | // Number of bytes per minor loop | ||
| 147 | t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes)); | ||
| 148 | |||
| 149 | // Major loop: reset source address after major loop | ||
| 150 | let total_bytes = nbytes * count as u32; | ||
| 151 | t.tcd_slast_sda() | ||
| 152 | .write(|w| w.slast_sda().bits(-(total_bytes as i32) as u32)); | ||
| 153 | t.tcd_dlast_sga() | ||
| 154 | .write(|w| w.dlast_sga().bits(-(total_bytes as i32) as u32)); | ||
| 155 | |||
| 156 | // Major loop count | ||
| 157 | t.tcd_biter_elinkno().write(|w| w.biter().bits(count)); | ||
| 158 | t.tcd_citer_elinkno().write(|w| w.citer().bits(count)); | ||
| 159 | |||
| 160 | // Control/status: enable interrupt if requested | ||
| 161 | if enable_int { | ||
| 162 | t.tcd_csr().write(|w| w.intmajor().set_bit()); | ||
| 163 | } else { | ||
| 164 | t.tcd_csr().write(|w| w.intmajor().clear_bit()); | ||
| 165 | } | ||
| 166 | |||
| 167 | cortex_m::asm::dsb(); | ||
| 168 | } | ||
| 169 | |||
| 170 | unsafe { | ||
| 171 | // Channel 0: Transfer 16 bytes total (8 bytes per minor loop, 2 major iterations) | ||
| 172 | // Minor Link -> Channel 1 | ||
| 173 | // Major Link -> Channel 2 | ||
| 174 | configure_tcd( | ||
| 175 | edma, | ||
| 176 | 0, | ||
| 177 | src.as_ptr() as u32, | ||
| 178 | dst0.as_mut_ptr() as u32, | ||
| 179 | 4, // src width | ||
| 180 | 8, // nbytes (minor loop = 2 words) | ||
| 181 | 2, // count (major loop = 2 iterations) | ||
| 182 | false, // no interrupt | ||
| 183 | ); | ||
| 184 | ch0.set_minor_link(1); // Link to CH1 after each minor loop | ||
| 185 | ch0.set_major_link(2); // Link to CH2 after major loop | ||
| 186 | |||
| 187 | // Channel 1: Transfer 16 bytes (triggered by CH0 minor link) | ||
| 188 | configure_tcd( | ||
| 189 | edma, | ||
| 190 | 1, | ||
| 191 | src.as_ptr() as u32, | ||
| 192 | dst1.as_mut_ptr() as u32, | ||
| 193 | 4, | ||
| 194 | 16, // full buffer in one minor loop | ||
| 195 | 1, // 1 major iteration | ||
| 196 | false, | ||
| 197 | ); | ||
| 198 | |||
| 199 | // Channel 2: Transfer 16 bytes (triggered by CH0 major link) | ||
| 200 | configure_tcd( | ||
| 201 | edma, | ||
| 202 | 2, | ||
| 203 | src.as_ptr() as u32, | ||
| 204 | dst2.as_mut_ptr() as u32, | ||
| 205 | 4, | ||
| 206 | 16, // full buffer in one minor loop | ||
| 207 | 1, // 1 major iteration | ||
| 208 | true, // enable interrupt | ||
| 209 | ); | ||
| 210 | } | ||
| 211 | |||
| 212 | defmt::info!("Triggering Channel 0 (1st minor loop)..."); | ||
| 213 | |||
| 214 | // Trigger first minor loop of CH0 | ||
| 215 | unsafe { | ||
| 216 | ch0.trigger_start(); | ||
| 217 | } | ||
| 218 | |||
| 219 | // Wait for CH1 to complete (triggered by CH0 minor link) | ||
| 220 | while !ch1.is_done() { | ||
| 221 | cortex_m::asm::nop(); | ||
| 222 | } | ||
| 223 | unsafe { | ||
| 224 | ch1.clear_done(); | ||
| 225 | } | ||
| 226 | |||
| 227 | defmt::info!("CH1 done (via minor link)."); | ||
| 228 | defmt::info!("Triggering Channel 0 (2nd minor loop)..."); | ||
| 229 | |||
| 230 | // Trigger second minor loop of CH0 | ||
| 231 | unsafe { | ||
| 232 | ch0.trigger_start(); | ||
| 233 | } | ||
| 234 | |||
| 235 | // Wait for CH0 major loop to complete | ||
| 236 | while !ch0.is_done() { | ||
| 237 | cortex_m::asm::nop(); | ||
| 238 | } | ||
| 239 | unsafe { | ||
| 240 | ch0.clear_done(); | ||
| 241 | } | ||
| 242 | |||
| 243 | defmt::info!("CH0 major loop done."); | ||
| 244 | |||
| 245 | // Wait for CH2 to complete (triggered by CH0 major link) | ||
| 246 | // Using is_done() instead of AtomicBool - the standard interrupt handler | ||
| 247 | // clears the interrupt flag and wakes wakers, but DONE bit remains set | ||
| 248 | while !ch2.is_done() { | ||
| 249 | cortex_m::asm::nop(); | ||
| 250 | } | ||
| 251 | unsafe { | ||
| 252 | ch2.clear_done(); | ||
| 253 | } | ||
| 254 | |||
| 255 | defmt::info!("CH2 done (via major link)."); | ||
| 256 | |||
| 257 | defmt::info!("EDMA channel link example finish."); | ||
| 258 | |||
| 259 | defmt::info!("DEST0 (after): {=[?]}", dst0.as_slice()); | ||
| 260 | defmt::info!("DEST1 (after): {=[?]}", dst1.as_slice()); | ||
| 261 | defmt::info!("DEST2 (after): {=[?]}", dst2.as_slice()); | ||
| 262 | |||
| 263 | // Verify all buffers match source | ||
| 264 | let mut success = true; | ||
| 265 | for sli in [dst0, dst1, dst2] { | ||
| 266 | success &= sli == src; | ||
| 267 | } | ||
| 268 | |||
| 269 | if success { | ||
| 270 | defmt::info!("PASS: Data verified."); | ||
| 271 | } else { | ||
| 272 | defmt::error!("FAIL: Mismatch detected!"); | ||
| 273 | } | ||
| 274 | |||
| 275 | loop { | ||
| 276 | cortex_m::asm::wfe(); | ||
| 277 | } | ||
| 278 | } | ||
diff --git a/examples/mcxa/src/bin/raw_dma_interleave_transfer.rs b/examples/mcxa/src/bin/raw_dma_interleave_transfer.rs new file mode 100644 index 000000000..a383b6cf4 --- /dev/null +++ b/examples/mcxa/src/bin/raw_dma_interleave_transfer.rs | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | //! DMA interleaved transfer example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have | ||
| 4 | //! a high-level and safe API for. It should not be taken as typical, recommended, or | ||
| 5 | //! stable usage! | ||
| 6 | //! | ||
| 7 | //! This example demonstrates using DMA with custom source/destination offsets | ||
| 8 | //! to interleave data during transfer. | ||
| 9 | //! | ||
| 10 | //! # Embassy-style features demonstrated: | ||
| 11 | //! - `TransferOptions::default()` for configuration (used internally) | ||
| 12 | //! - DMA channel with `DmaChannel::new()` | ||
| 13 | |||
| 14 | #![no_std] | ||
| 15 | #![no_main] | ||
| 16 | |||
| 17 | use embassy_executor::Spawner; | ||
| 18 | use embassy_mcxa::clocks::config::Div8; | ||
| 19 | use embassy_mcxa::dma::DmaChannel; | ||
| 20 | use static_cell::ConstStaticCell; | ||
| 21 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 22 | |||
| 23 | const BUFFER_LENGTH: usize = 16; | ||
| 24 | const HALF_BUFF_LENGTH: usize = BUFFER_LENGTH / 2; | ||
| 25 | |||
| 26 | // Buffers in RAM | ||
| 27 | static SRC_BUFFER: ConstStaticCell<[u32; HALF_BUFF_LENGTH]> = ConstStaticCell::new([0; HALF_BUFF_LENGTH]); | ||
| 28 | static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); | ||
| 29 | |||
| 30 | #[embassy_executor::main] | ||
| 31 | async fn main(_spawner: Spawner) { | ||
| 32 | // Small delay to allow probe-rs to attach after reset | ||
| 33 | for _ in 0..100_000 { | ||
| 34 | cortex_m::asm::nop(); | ||
| 35 | } | ||
| 36 | |||
| 37 | let mut cfg = hal::config::Config::default(); | ||
| 38 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 39 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 40 | let p = hal::init(cfg); | ||
| 41 | |||
| 42 | defmt::info!("DMA interleave transfer example starting..."); | ||
| 43 | |||
| 44 | defmt::info!("EDMA interleave transfer example begin."); | ||
| 45 | |||
| 46 | // Initialize buffers | ||
| 47 | let src = SRC_BUFFER.take(); | ||
| 48 | *src = [1, 2, 3, 4, 5, 6, 7, 8]; | ||
| 49 | let dst = DEST_BUFFER.take(); | ||
| 50 | |||
| 51 | defmt::info!("Source Buffer: {=[?]}", src.as_slice()); | ||
| 52 | defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice()); | ||
| 53 | |||
| 54 | defmt::info!("Configuring DMA with Embassy-style API..."); | ||
| 55 | |||
| 56 | // Create DMA channel using Embassy-style API | ||
| 57 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 58 | |||
| 59 | // Configure interleaved transfer using direct TCD access: | ||
| 60 | // - src_offset = 4: advance source by 4 bytes after each read | ||
| 61 | // - dst_offset = 8: advance dest by 8 bytes after each write | ||
| 62 | // This spreads source data across every other word in destination | ||
| 63 | unsafe { | ||
| 64 | let t = dma_ch0.tcd(); | ||
| 65 | |||
| 66 | // Reset channel state | ||
| 67 | t.ch_csr().write(|w| { | ||
| 68 | w.erq() | ||
| 69 | .disable() | ||
| 70 | .earq() | ||
| 71 | .disable() | ||
| 72 | .eei() | ||
| 73 | .no_error() | ||
| 74 | .ebw() | ||
| 75 | .disable() | ||
| 76 | .done() | ||
| 77 | .clear_bit_by_one() | ||
| 78 | }); | ||
| 79 | t.ch_es().write(|w| w.bits(0)); | ||
| 80 | t.ch_int().write(|w| w.int().clear_bit_by_one()); | ||
| 81 | |||
| 82 | // Source/destination addresses | ||
| 83 | t.tcd_saddr().write(|w| w.saddr().bits(src.as_ptr() as u32)); | ||
| 84 | t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32)); | ||
| 85 | |||
| 86 | // Custom offsets for interleaving | ||
| 87 | t.tcd_soff().write(|w| w.soff().bits(4)); // src: +4 bytes per read | ||
| 88 | t.tcd_doff().write(|w| w.doff().bits(8)); // dst: +8 bytes per write | ||
| 89 | |||
| 90 | // Attributes: 32-bit transfers (size = 2) | ||
| 91 | t.tcd_attr().write(|w| w.ssize().bits(2).dsize().bits(2)); | ||
| 92 | |||
| 93 | // Transfer entire source buffer in one minor loop | ||
| 94 | let nbytes = (HALF_BUFF_LENGTH * 4) as u32; | ||
| 95 | t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes)); | ||
| 96 | |||
| 97 | // Reset source address after major loop | ||
| 98 | t.tcd_slast_sda().write(|w| w.slast_sda().bits(-(nbytes as i32) as u32)); | ||
| 99 | // Destination uses 2x offset, so adjust accordingly | ||
| 100 | let dst_total = (HALF_BUFF_LENGTH * 8) as u32; | ||
| 101 | t.tcd_dlast_sga() | ||
| 102 | .write(|w| w.dlast_sga().bits(-(dst_total as i32) as u32)); | ||
| 103 | |||
| 104 | // Major loop count = 1 | ||
| 105 | t.tcd_biter_elinkno().write(|w| w.biter().bits(1)); | ||
| 106 | t.tcd_citer_elinkno().write(|w| w.citer().bits(1)); | ||
| 107 | |||
| 108 | // Enable interrupt on major loop completion | ||
| 109 | t.tcd_csr().write(|w| w.intmajor().set_bit()); | ||
| 110 | |||
| 111 | cortex_m::asm::dsb(); | ||
| 112 | |||
| 113 | defmt::info!("Triggering transfer..."); | ||
| 114 | dma_ch0.trigger_start(); | ||
| 115 | } | ||
| 116 | |||
| 117 | // Wait for completion using channel helper method | ||
| 118 | while !dma_ch0.is_done() { | ||
| 119 | cortex_m::asm::nop(); | ||
| 120 | } | ||
| 121 | unsafe { | ||
| 122 | dma_ch0.clear_done(); | ||
| 123 | } | ||
| 124 | |||
| 125 | defmt::info!("EDMA interleave transfer example finish."); | ||
| 126 | defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); | ||
| 127 | |||
| 128 | // Verify: Even indices should match SRC_BUFFER[i/2], odd indices should be 0 | ||
| 129 | let mut mismatch = false; | ||
| 130 | let diter = dst.chunks_exact(2); | ||
| 131 | let siter = src.iter(); | ||
| 132 | for (ch, src) in diter.zip(siter) { | ||
| 133 | mismatch |= !matches!(ch, [a, 0] if a == src); | ||
| 134 | } | ||
| 135 | |||
| 136 | if mismatch { | ||
| 137 | defmt::error!("FAIL: Mismatch detected!"); | ||
| 138 | } else { | ||
| 139 | defmt::info!("PASS: Data verified."); | ||
| 140 | } | ||
| 141 | } | ||
diff --git a/examples/mcxa/src/bin/raw_dma_memset.rs b/examples/mcxa/src/bin/raw_dma_memset.rs new file mode 100644 index 000000000..7b3c06ffa --- /dev/null +++ b/examples/mcxa/src/bin/raw_dma_memset.rs | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | //! DMA memset example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have | ||
| 4 | //! a high-level and safe API for. It should not be taken as typical, recommended, or | ||
| 5 | //! stable usage! | ||
| 6 | //! | ||
| 7 | //! This example demonstrates using DMA to fill a buffer with a repeated pattern. | ||
| 8 | //! The source address stays fixed while the destination increments. | ||
| 9 | //! | ||
| 10 | //! # Embassy-style features demonstrated: | ||
| 11 | //! - `DmaChannel::is_done()` and `clear_done()` helper methods | ||
| 12 | //! - No need to pass register block around | ||
| 13 | |||
| 14 | #![no_std] | ||
| 15 | #![no_main] | ||
| 16 | |||
| 17 | use embassy_executor::Spawner; | ||
| 18 | use embassy_mcxa::clocks::config::Div8; | ||
| 19 | use embassy_mcxa::dma::DmaChannel; | ||
| 20 | use static_cell::ConstStaticCell; | ||
| 21 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 22 | |||
| 23 | const BUFFER_LENGTH: usize = 4; | ||
| 24 | |||
| 25 | // Buffers in RAM | ||
| 26 | static PATTERN: u32 = 0xDEADBEEF; | ||
| 27 | static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(_spawner: Spawner) { | ||
| 31 | // Small delay to allow probe-rs to attach after reset | ||
| 32 | for _ in 0..100_000 { | ||
| 33 | cortex_m::asm::nop(); | ||
| 34 | } | ||
| 35 | |||
| 36 | let mut cfg = hal::config::Config::default(); | ||
| 37 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 38 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 39 | let p = hal::init(cfg); | ||
| 40 | |||
| 41 | defmt::info!("DMA memset example starting..."); | ||
| 42 | defmt::info!("EDMA memset example begin."); | ||
| 43 | |||
| 44 | // Initialize buffers | ||
| 45 | let pat = &PATTERN; | ||
| 46 | let dst = DEST_BUFFER.take(); | ||
| 47 | defmt::info!("Pattern Value: {=u32}", pat); | ||
| 48 | defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice()); | ||
| 49 | defmt::info!("Configuring DMA with Embassy-style API..."); | ||
| 50 | |||
| 51 | // Create DMA channel using Embassy-style API | ||
| 52 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 53 | |||
| 54 | // Configure memset transfer using direct TCD access: | ||
| 55 | // Source stays fixed (soff = 0, reads same pattern repeatedly) | ||
| 56 | // Destination increments (doff = 4) | ||
| 57 | unsafe { | ||
| 58 | let t = dma_ch0.tcd(); | ||
| 59 | |||
| 60 | // Reset channel state | ||
| 61 | t.ch_csr().write(|w| { | ||
| 62 | w.erq() | ||
| 63 | .disable() | ||
| 64 | .earq() | ||
| 65 | .disable() | ||
| 66 | .eei() | ||
| 67 | .no_error() | ||
| 68 | .ebw() | ||
| 69 | .disable() | ||
| 70 | .done() | ||
| 71 | .clear_bit_by_one() | ||
| 72 | }); | ||
| 73 | t.ch_es().write(|w| w.bits(0)); | ||
| 74 | t.ch_int().write(|w| w.int().clear_bit_by_one()); | ||
| 75 | |||
| 76 | // Source address (pattern) - fixed | ||
| 77 | t.tcd_saddr().write(|w| w.saddr().bits(pat as *const _ as u32)); | ||
| 78 | // Destination address - increments | ||
| 79 | t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32)); | ||
| 80 | |||
| 81 | // Source offset = 0 (stays fixed), Dest offset = 4 (increments) | ||
| 82 | t.tcd_soff().write(|w| w.soff().bits(0)); | ||
| 83 | t.tcd_doff().write(|w| w.doff().bits(4)); | ||
| 84 | |||
| 85 | // Attributes: 32-bit transfers (size = 2) | ||
| 86 | t.tcd_attr().write(|w| w.ssize().bits(2).dsize().bits(2)); | ||
| 87 | |||
| 88 | // Transfer entire buffer in one minor loop | ||
| 89 | let nbytes = (BUFFER_LENGTH * 4) as u32; | ||
| 90 | t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes)); | ||
| 91 | |||
| 92 | // Source doesn't need adjustment (stays fixed) | ||
| 93 | t.tcd_slast_sda().write(|w| w.slast_sda().bits(0)); | ||
| 94 | // Reset dest address after major loop | ||
| 95 | t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32)); | ||
| 96 | |||
| 97 | // Major loop count = 1 | ||
| 98 | t.tcd_biter_elinkno().write(|w| w.biter().bits(1)); | ||
| 99 | t.tcd_citer_elinkno().write(|w| w.citer().bits(1)); | ||
| 100 | |||
| 101 | // Enable interrupt on major loop completion | ||
| 102 | t.tcd_csr().write(|w| w.intmajor().set_bit()); | ||
| 103 | |||
| 104 | cortex_m::asm::dsb(); | ||
| 105 | |||
| 106 | defmt::info!("Triggering transfer..."); | ||
| 107 | dma_ch0.trigger_start(); | ||
| 108 | } | ||
| 109 | |||
| 110 | // Wait for completion using channel helper method | ||
| 111 | while !dma_ch0.is_done() { | ||
| 112 | cortex_m::asm::nop(); | ||
| 113 | } | ||
| 114 | unsafe { | ||
| 115 | dma_ch0.clear_done(); | ||
| 116 | } | ||
| 117 | |||
| 118 | defmt::info!("EDMA memset example finish."); | ||
| 119 | defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); | ||
| 120 | |||
| 121 | // Verify: All elements should equal PATTERN | ||
| 122 | let mismatch = dst.iter().any(|i| *i != *pat); | ||
| 123 | |||
| 124 | if mismatch { | ||
| 125 | defmt::error!("FAIL: Mismatch detected!"); | ||
| 126 | } else { | ||
| 127 | defmt::info!("PASS: Data verified."); | ||
| 128 | } | ||
| 129 | } | ||
diff --git a/examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs b/examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs new file mode 100644 index 000000000..80df40449 --- /dev/null +++ b/examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs | |||
| @@ -0,0 +1,244 @@ | |||
| 1 | //! DMA ping-pong/double-buffer transfer example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have | ||
| 4 | //! a high-level and safe API for. It should not be taken as typical, recommended, or | ||
| 5 | //! stable usage! | ||
| 6 | //! | ||
| 7 | //! This example demonstrates two approaches for ping-pong/double-buffering: | ||
| 8 | //! | ||
| 9 | //! ## Approach 1: Scatter/Gather with linked TCDs (manual) | ||
| 10 | //! - Two TCDs link to each other for alternating transfers | ||
| 11 | //! - Uses custom handler that delegates to on_interrupt() then signals completion | ||
| 12 | //! - Note: With ESG=1, DONE bit is cleared by hardware when next TCD loads, | ||
| 13 | //! so we need an AtomicBool to track completion | ||
| 14 | //! | ||
| 15 | //! ## Approach 2: Half-transfer interrupt with wait_half() (NEW!) | ||
| 16 | //! - Single continuous transfer over entire buffer | ||
| 17 | //! - Uses half-transfer interrupt to know when first half is ready | ||
| 18 | //! - Application can process first half while second half is being filled | ||
| 19 | //! | ||
| 20 | //! # Embassy-style features demonstrated: | ||
| 21 | //! - `DmaChannel::new()` for channel creation | ||
| 22 | //! - Scatter/gather with linked TCDs | ||
| 23 | //! - Custom handler that delegates to HAL's `on_interrupt()` (best practice) | ||
| 24 | //! - Standard `DmaCh1InterruptHandler` with `bind_interrupts!` macro | ||
| 25 | //! - NEW: `wait_half()` for half-transfer interrupt handling | ||
| 26 | |||
| 27 | #![no_std] | ||
| 28 | #![no_main] | ||
| 29 | |||
| 30 | use embassy_executor::Spawner; | ||
| 31 | use embassy_mcxa::clocks::config::Div8; | ||
| 32 | use embassy_mcxa::dma::{DmaChannel, Tcd, TransferOptions}; | ||
| 33 | use embassy_mcxa::pac; | ||
| 34 | use static_cell::ConstStaticCell; | ||
| 35 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 36 | |||
| 37 | // Source and destination buffers for Approach 1 (scatter/gather) | ||
| 38 | static SRC: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([1, 2, 3, 4, 5, 6, 7, 8]); | ||
| 39 | static DST: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([0; 8]); | ||
| 40 | |||
| 41 | // Source and destination buffers for Approach 2 (wait_half) | ||
| 42 | static SRC2: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([0xA1, 0xA2, 0xA3, 0xA4, 0xB1, 0xB2, 0xB3, 0xB4]); | ||
| 43 | static DST2: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([0; 8]); | ||
| 44 | |||
| 45 | // TCD pool for scatter/gather - must be 32-byte aligned | ||
| 46 | #[repr(C, align(32))] | ||
| 47 | struct TcdPool([Tcd; 2]); | ||
| 48 | |||
| 49 | static TCD_POOL: ConstStaticCell<TcdPool> = ConstStaticCell::new(TcdPool( | ||
| 50 | [Tcd { | ||
| 51 | saddr: 0, | ||
| 52 | soff: 0, | ||
| 53 | attr: 0, | ||
| 54 | nbytes: 0, | ||
| 55 | slast: 0, | ||
| 56 | daddr: 0, | ||
| 57 | doff: 0, | ||
| 58 | citer: 0, | ||
| 59 | dlast_sga: 0, | ||
| 60 | csr: 0, | ||
| 61 | biter: 0, | ||
| 62 | }; 2], | ||
| 63 | )); | ||
| 64 | |||
| 65 | #[embassy_executor::main] | ||
| 66 | async fn main(_spawner: Spawner) { | ||
| 67 | // Small delay to allow probe-rs to attach after reset | ||
| 68 | for _ in 0..100_000 { | ||
| 69 | cortex_m::asm::nop(); | ||
| 70 | } | ||
| 71 | |||
| 72 | let mut cfg = hal::config::Config::default(); | ||
| 73 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 74 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 75 | let p = hal::init(cfg); | ||
| 76 | |||
| 77 | defmt::info!("DMA ping-pong transfer example starting..."); | ||
| 78 | |||
| 79 | defmt::info!("EDMA ping-pong transfer example begin."); | ||
| 80 | |||
| 81 | // Initialize buffers | ||
| 82 | let src = SRC.take(); | ||
| 83 | let dst = DST.take(); | ||
| 84 | |||
| 85 | defmt::info!("Source Buffer: {=[?]}", src.as_slice()); | ||
| 86 | defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice()); | ||
| 87 | |||
| 88 | defmt::info!("Configuring ping-pong DMA with Embassy-style API..."); | ||
| 89 | |||
| 90 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 91 | |||
| 92 | // Configure ping-pong transfer using direct TCD access: | ||
| 93 | // This sets up TCD0 and TCD1 in RAM, and loads TCD0 into the channel. | ||
| 94 | // TCD0 transfers first half (SRC[0..4] -> DST[0..4]), links to TCD1. | ||
| 95 | // TCD1 transfers second half (SRC[4..8] -> DST[4..8]), links to TCD0. | ||
| 96 | let tcds = &mut TCD_POOL.take().0; | ||
| 97 | |||
| 98 | let half_len = 4usize; | ||
| 99 | let half_bytes = (half_len * 4) as u32; | ||
| 100 | |||
| 101 | unsafe { | ||
| 102 | let tcd0_addr = &tcds[0] as *const _ as u32; | ||
| 103 | let tcd1_addr = &tcds[1] as *const _ as u32; | ||
| 104 | |||
| 105 | // TCD0: First half -> Links to TCD1 | ||
| 106 | tcds[0] = Tcd { | ||
| 107 | saddr: src.as_ptr() as u32, | ||
| 108 | soff: 4, | ||
| 109 | attr: 0x0202, // 32-bit src/dst | ||
| 110 | nbytes: half_bytes, | ||
| 111 | slast: 0, | ||
| 112 | daddr: dst.as_mut_ptr() as u32, | ||
| 113 | doff: 4, | ||
| 114 | citer: 1, | ||
| 115 | dlast_sga: tcd1_addr as i32, | ||
| 116 | csr: 0x0012, // ESG | INTMAJOR | ||
| 117 | biter: 1, | ||
| 118 | }; | ||
| 119 | |||
| 120 | // TCD1: Second half -> Links to TCD0 | ||
| 121 | tcds[1] = Tcd { | ||
| 122 | saddr: src.as_ptr().add(half_len) as u32, | ||
| 123 | soff: 4, | ||
| 124 | attr: 0x0202, | ||
| 125 | nbytes: half_bytes, | ||
| 126 | slast: 0, | ||
| 127 | daddr: dst.as_mut_ptr().add(half_len) as u32, | ||
| 128 | doff: 4, | ||
| 129 | citer: 1, | ||
| 130 | dlast_sga: tcd0_addr as i32, | ||
| 131 | csr: 0x0012, | ||
| 132 | biter: 1, | ||
| 133 | }; | ||
| 134 | |||
| 135 | // Load TCD0 into hardware registers | ||
| 136 | dma_ch0.load_tcd(&tcds[0]); | ||
| 137 | } | ||
| 138 | |||
| 139 | defmt::info!("Triggering first half transfer..."); | ||
| 140 | |||
| 141 | // Trigger first transfer (first half: SRC[0..4] -> DST[0..4]) | ||
| 142 | unsafe { | ||
| 143 | dma_ch0.trigger_start(); | ||
| 144 | } | ||
| 145 | |||
| 146 | let tcd = dma_ch0.tcd(); | ||
| 147 | // Wait for first half | ||
| 148 | loop { | ||
| 149 | if tcd.tcd_saddr().read().bits() != src.as_ptr() as u32 { | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | defmt::info!("First half transferred."); | ||
| 155 | defmt::info!("Triggering second half transfer..."); | ||
| 156 | |||
| 157 | // Trigger second transfer (second half: SRC[4..8] -> DST[4..8]) | ||
| 158 | unsafe { | ||
| 159 | dma_ch0.trigger_start(); | ||
| 160 | } | ||
| 161 | |||
| 162 | // Wait for second half | ||
| 163 | loop { | ||
| 164 | if tcd.tcd_saddr().read().bits() != unsafe { src.as_ptr().add(half_len) } as u32 { | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | defmt::info!("Second half transferred."); | ||
| 170 | |||
| 171 | defmt::info!("EDMA ping-pong transfer example finish."); | ||
| 172 | defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); | ||
| 173 | |||
| 174 | // Verify: DST should match SRC | ||
| 175 | let mismatch = src != dst; | ||
| 176 | |||
| 177 | if mismatch { | ||
| 178 | defmt::error!("FAIL: Approach 1 mismatch detected!"); | ||
| 179 | } else { | ||
| 180 | defmt::info!("PASS: Approach 1 data verified."); | ||
| 181 | } | ||
| 182 | |||
| 183 | // ========================================================================= | ||
| 184 | // Approach 2: Half-Transfer Interrupt with wait_half() (NEW!) | ||
| 185 | // ========================================================================= | ||
| 186 | // | ||
| 187 | // This approach uses a single continuous DMA transfer with half-transfer | ||
| 188 | // interrupt enabled. The wait_half() method allows you to be notified | ||
| 189 | // when the first half of the buffer is complete, so you can process it | ||
| 190 | // while the second half is still being filled. | ||
| 191 | // | ||
| 192 | // Benefits: | ||
| 193 | // - Simpler setup (no TCD pool needed) | ||
| 194 | // - True async/await support | ||
| 195 | // - Good for streaming data processing | ||
| 196 | |||
| 197 | defmt::info!("--- Approach 2: wait_half() demo ---"); | ||
| 198 | |||
| 199 | // Enable DMA CH1 interrupt | ||
| 200 | unsafe { | ||
| 201 | cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH1); | ||
| 202 | } | ||
| 203 | |||
| 204 | // Initialize approach 2 buffers | ||
| 205 | let src2 = SRC2.take(); | ||
| 206 | let dst2 = DST2.take(); | ||
| 207 | |||
| 208 | defmt::info!("SRC2: {=[?]}", src2.as_slice()); | ||
| 209 | |||
| 210 | let dma_ch1 = DmaChannel::new(p.DMA_CH1); | ||
| 211 | |||
| 212 | // Configure transfer with half-transfer interrupt enabled | ||
| 213 | let mut options = TransferOptions::default(); | ||
| 214 | options.half_transfer_interrupt = true; // Enable half-transfer interrupt | ||
| 215 | options.complete_transfer_interrupt = true; | ||
| 216 | |||
| 217 | defmt::info!("Starting transfer with half_transfer_interrupt..."); | ||
| 218 | |||
| 219 | // Create the transfer | ||
| 220 | let mut transfer = dma_ch1.mem_to_mem(src2, dst2, options).unwrap(); | ||
| 221 | |||
| 222 | // Wait for half-transfer (first 4 elements) | ||
| 223 | defmt::info!("Waiting for first half..."); | ||
| 224 | let _ok = transfer.wait_half().await.unwrap(); | ||
| 225 | |||
| 226 | defmt::info!("Half-transfer complete!"); | ||
| 227 | |||
| 228 | // Wait for complete transfer | ||
| 229 | defmt::info!("Waiting for second half..."); | ||
| 230 | transfer.await.unwrap(); | ||
| 231 | |||
| 232 | defmt::info!("Transfer complete! Full DST2: {=[?]}", dst2.as_slice()); | ||
| 233 | |||
| 234 | // Verify approach 2 | ||
| 235 | let mismatch2 = src2 != dst2; | ||
| 236 | |||
| 237 | if mismatch2 { | ||
| 238 | defmt::error!("FAIL: Approach 2 mismatch!"); | ||
| 239 | } else { | ||
| 240 | defmt::info!("PASS: Approach 2 verified."); | ||
| 241 | } | ||
| 242 | |||
| 243 | defmt::info!("=== All ping-pong demos complete ==="); | ||
| 244 | } | ||
diff --git a/examples/mcxa/src/bin/raw_dma_scatter_gather.rs b/examples/mcxa/src/bin/raw_dma_scatter_gather.rs new file mode 100644 index 000000000..eb9960764 --- /dev/null +++ b/examples/mcxa/src/bin/raw_dma_scatter_gather.rs | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | //! DMA scatter-gather transfer example for MCXA276. | ||
| 2 | //! | ||
| 3 | //! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have | ||
| 4 | //! a high-level and safe API for. It should not be taken as typical, recommended, or | ||
| 5 | //! stable usage! | ||
| 6 | //! | ||
| 7 | //! This example demonstrates using DMA with scatter/gather to chain multiple | ||
| 8 | //! transfer descriptors. The first TCD transfers the first half of the buffer, | ||
| 9 | //! then automatically loads the second TCD to transfer the second half. | ||
| 10 | //! | ||
| 11 | //! # Embassy-style features demonstrated: | ||
| 12 | //! - `DmaChannel::new()` for channel creation | ||
| 13 | //! - Scatter/gather with chained TCDs | ||
| 14 | //! - Custom handler that delegates to HAL's `on_interrupt()` (best practice) | ||
| 15 | |||
| 16 | #![no_std] | ||
| 17 | #![no_main] | ||
| 18 | |||
| 19 | use embassy_executor::Spawner; | ||
| 20 | use embassy_mcxa::clocks::config::Div8; | ||
| 21 | use embassy_mcxa::dma::{DmaChannel, Tcd}; | ||
| 22 | use static_cell::ConstStaticCell; | ||
| 23 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 24 | |||
| 25 | // Source and destination buffers | ||
| 26 | static SRC: ConstStaticCell<[u32; 12]> = ConstStaticCell::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); | ||
| 27 | static DST: ConstStaticCell<[u32; 12]> = ConstStaticCell::new([0; 12]); | ||
| 28 | |||
| 29 | // TCD pool for scatter/gather - must be 32-byte aligned | ||
| 30 | #[repr(C, align(32))] | ||
| 31 | struct TcdPool([Tcd; 2]); | ||
| 32 | |||
| 33 | static TCD_POOL: ConstStaticCell<TcdPool> = ConstStaticCell::new(TcdPool( | ||
| 34 | [Tcd { | ||
| 35 | saddr: 0, | ||
| 36 | soff: 0, | ||
| 37 | attr: 0, | ||
| 38 | nbytes: 0, | ||
| 39 | slast: 0, | ||
| 40 | daddr: 0, | ||
| 41 | doff: 0, | ||
| 42 | citer: 0, | ||
| 43 | dlast_sga: 0, | ||
| 44 | csr: 0, | ||
| 45 | biter: 0, | ||
| 46 | }; 2], | ||
| 47 | )); | ||
| 48 | |||
| 49 | #[embassy_executor::main] | ||
| 50 | async fn main(_spawner: Spawner) { | ||
| 51 | // Small delay to allow probe-rs to attach after reset | ||
| 52 | for _ in 0..100_000 { | ||
| 53 | cortex_m::asm::nop(); | ||
| 54 | } | ||
| 55 | |||
| 56 | let mut cfg = hal::config::Config::default(); | ||
| 57 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 58 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 59 | let p = hal::init(cfg); | ||
| 60 | |||
| 61 | defmt::info!("DMA scatter-gather transfer example starting..."); | ||
| 62 | |||
| 63 | defmt::info!("EDMA scatter-gather transfer example begin."); | ||
| 64 | |||
| 65 | // Initialize buffers | ||
| 66 | let src = SRC.take(); | ||
| 67 | let dst = DST.take(); | ||
| 68 | |||
| 69 | defmt::info!("Source Buffer: {=[?]}", src.as_slice()); | ||
| 70 | defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice()); | ||
| 71 | defmt::info!("Configuring scatter-gather DMA with Embassy-style API..."); | ||
| 72 | |||
| 73 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | ||
| 74 | let src_ptr = src.as_ptr(); | ||
| 75 | let dst_ptr = dst.as_mut_ptr(); | ||
| 76 | |||
| 77 | // Configure scatter-gather transfer using direct TCD access: | ||
| 78 | // This sets up TCD0 and TCD1 in RAM, and loads TCD0 into the channel. | ||
| 79 | // TCD0 transfers first half (SRC[0..4] -> DST[0..4]), then loads TCD1. | ||
| 80 | // TCD1 transfers second half (SRC[4..12] -> DST[4..12]), last TCD. | ||
| 81 | unsafe { | ||
| 82 | let tcds = &mut TCD_POOL.take().0; | ||
| 83 | |||
| 84 | // In the first transfer, copy | ||
| 85 | tcds[0] = Tcd { | ||
| 86 | saddr: src_ptr as u32, | ||
| 87 | soff: 4, | ||
| 88 | attr: 0x0202, // 32-bit src/dst | ||
| 89 | nbytes: 4 * 4, | ||
| 90 | slast: 0, | ||
| 91 | daddr: dst_ptr as u32, | ||
| 92 | doff: 4, | ||
| 93 | citer: 1, | ||
| 94 | dlast_sga: tcds.as_ptr().add(1) as i32, | ||
| 95 | // ESG (scatter/gather) for non-last, INTMAJOR for all | ||
| 96 | csr: 0x0012, | ||
| 97 | biter: 1, | ||
| 98 | }; | ||
| 99 | |||
| 100 | tcds[1] = Tcd { | ||
| 101 | saddr: src_ptr.add(4) as u32, | ||
| 102 | soff: 4, | ||
| 103 | attr: 0x0202, // 32-bit src/dst | ||
| 104 | nbytes: 8 * 4, | ||
| 105 | slast: 0, | ||
| 106 | daddr: dst_ptr.add(4) as u32, | ||
| 107 | doff: 4, | ||
| 108 | citer: 1, | ||
| 109 | dlast_sga: 0, | ||
| 110 | // ESG (scatter/gather) for non-last, INTMAJOR for all | ||
| 111 | csr: 0x0002, | ||
| 112 | biter: 1, | ||
| 113 | }; | ||
| 114 | |||
| 115 | // Load TCD0 into hardware registers | ||
| 116 | dma_ch0.load_tcd(&tcds[0]); | ||
| 117 | } | ||
| 118 | |||
| 119 | defmt::info!("Triggering first half transfer..."); | ||
| 120 | |||
| 121 | let tcd = dma_ch0.tcd(); | ||
| 122 | |||
| 123 | // Trigger first transfer (first half: SRC[0..4] -> DST[0..4]) | ||
| 124 | // TCD0 is currently loaded. | ||
| 125 | unsafe { | ||
| 126 | dma_ch0.trigger_start(); | ||
| 127 | } | ||
| 128 | |||
| 129 | // Wait for first half | ||
| 130 | loop { | ||
| 131 | if tcd.tcd_saddr().read().bits() != src_ptr as u32 { | ||
| 132 | defmt::info!("saddr: {=u32}", tcd.tcd_saddr().read().bits()); | ||
| 133 | defmt::info!("srptr: {=u32}", src_ptr as u32); | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | defmt::info!("First half transferred."); | ||
| 139 | defmt::info!("Triggering second half transfer..."); | ||
| 140 | |||
| 141 | // Trigger second transfer (second half: SRC[4..8] -> DST[4..8]) | ||
| 142 | // TCD1 should have been loaded by the scatter/gather engine. | ||
| 143 | unsafe { | ||
| 144 | dma_ch0.trigger_start(); | ||
| 145 | } | ||
| 146 | |||
| 147 | // Wait for second half | ||
| 148 | while !dma_ch0.is_done() { | ||
| 149 | cortex_m::asm::nop(); | ||
| 150 | } | ||
| 151 | |||
| 152 | defmt::info!("Second half transferred."); | ||
| 153 | |||
| 154 | defmt::info!("EDMA scatter-gather transfer example finish."); | ||
| 155 | defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); | ||
| 156 | |||
| 157 | // Verify: DST should match SRC | ||
| 158 | let mismatch = src != dst; | ||
| 159 | |||
| 160 | if mismatch { | ||
| 161 | defmt::error!("FAIL: Mismatch detected!"); | ||
| 162 | } else { | ||
| 163 | defmt::info!("PASS: Data verified."); | ||
| 164 | } | ||
| 165 | } | ||
diff --git a/examples/mcxa/src/bin/reset-reason.rs b/examples/mcxa/src/bin/reset-reason.rs new file mode 100644 index 000000000..c244fbe04 --- /dev/null +++ b/examples/mcxa/src/bin/reset-reason.rs | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use hal::config::Config; | ||
| 6 | use hal::reset_reason::reset_reason; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let config = Config::default(); | ||
| 12 | let _p = hal::init(config); | ||
| 13 | |||
| 14 | defmt::info!("Reset Reason: '{}'", reset_reason()); | ||
| 15 | } | ||
diff --git a/examples/mcxa/src/bin/rtc_alarm.rs b/examples/mcxa/src/bin/rtc_alarm.rs new file mode 100644 index 000000000..fe355888b --- /dev/null +++ b/examples/mcxa/src/bin/rtc_alarm.rs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::bind_interrupts; | ||
| 6 | use hal::rtc::{InterruptHandler, Rtc, RtcDateTime}; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | bind_interrupts!(struct Irqs { | ||
| 10 | RTC => InterruptHandler<hal::rtc::Rtc0>; | ||
| 11 | }); | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = hal::init(hal::config::Config::default()); | ||
| 16 | |||
| 17 | defmt::info!("=== RTC Alarm Example ==="); | ||
| 18 | |||
| 19 | let rtc_config = hal::rtc::get_default_config(); | ||
| 20 | |||
| 21 | let mut rtc = Rtc::new(p.RTC0, Irqs, rtc_config); | ||
| 22 | |||
| 23 | let now = RtcDateTime { | ||
| 24 | year: 2025, | ||
| 25 | month: 10, | ||
| 26 | day: 15, | ||
| 27 | hour: 14, | ||
| 28 | minute: 30, | ||
| 29 | second: 0, | ||
| 30 | }; | ||
| 31 | |||
| 32 | rtc.stop(); | ||
| 33 | |||
| 34 | defmt::info!("Time set to: 2025-10-15 14:30:00"); | ||
| 35 | rtc.set_datetime(now); | ||
| 36 | |||
| 37 | let mut alarm = now; | ||
| 38 | alarm.second += 10; | ||
| 39 | |||
| 40 | defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)"); | ||
| 41 | defmt::info!("RTC started, waiting for alarm..."); | ||
| 42 | |||
| 43 | rtc.wait_for_alarm(alarm).await; | ||
| 44 | defmt::info!("*** ALARM TRIGGERED! ***"); | ||
| 45 | |||
| 46 | defmt::info!("Example complete - Test PASSED!"); | ||
| 47 | } | ||
diff --git a/examples/mcxa/src/bin/trng.rs b/examples/mcxa/src/bin/trng.rs new file mode 100644 index 000000000..5f6e2408c --- /dev/null +++ b/examples/mcxa/src/bin/trng.rs | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use hal::bind_interrupts; | ||
| 6 | use hal::config::Config; | ||
| 7 | use hal::trng::{self, InterruptHandler, Trng}; | ||
| 8 | use rand_core::RngCore; | ||
| 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 10 | |||
| 11 | bind_interrupts!( | ||
| 12 | struct Irqs { | ||
| 13 | TRNG0 => InterruptHandler; | ||
| 14 | } | ||
| 15 | ); | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) { | ||
| 19 | let config = Config::default(); | ||
| 20 | let mut p = hal::init(config); | ||
| 21 | |||
| 22 | defmt::info!("TRNG example"); | ||
| 23 | |||
| 24 | let mut trng = Trng::new_blocking_128(p.TRNG0.reborrow()); | ||
| 25 | let rand = trng.blocking_next_u32(); | ||
| 26 | defmt::info!("128-bit {}", rand); | ||
| 27 | |||
| 28 | drop(trng); | ||
| 29 | |||
| 30 | let mut trng = Trng::new_blocking_256(p.TRNG0.reborrow()); | ||
| 31 | let rand = trng.blocking_next_u32(); | ||
| 32 | defmt::info!("256-bit {}", rand); | ||
| 33 | |||
| 34 | drop(trng); | ||
| 35 | |||
| 36 | let mut trng = Trng::new_blocking_512(p.TRNG0.reborrow()); | ||
| 37 | let rand = trng.blocking_next_u32(); | ||
| 38 | defmt::info!("512-bit {}", rand); | ||
| 39 | |||
| 40 | drop(trng); | ||
| 41 | |||
| 42 | let config = trng::Config::default(); | ||
| 43 | let mut trng = Trng::new_blocking_with_custom_config(p.TRNG0.reborrow(), config); | ||
| 44 | |||
| 45 | defmt::info!("========== BLOCKING =========="); | ||
| 46 | |||
| 47 | defmt::info!("Generate 10 u32"); | ||
| 48 | for _ in 0..10 { | ||
| 49 | let rand = trng.blocking_next_u32(); | ||
| 50 | defmt::info!("{}", rand); | ||
| 51 | } | ||
| 52 | |||
| 53 | defmt::info!("Generate 10 u64"); | ||
| 54 | for _ in 0..10 { | ||
| 55 | let rand = trng.blocking_next_u64(); | ||
| 56 | defmt::info!("{}", rand); | ||
| 57 | } | ||
| 58 | |||
| 59 | let mut buf = [0_u8; 256]; | ||
| 60 | |||
| 61 | defmt::info!("Generate 10 256-byte buffers"); | ||
| 62 | for _ in 0..10 { | ||
| 63 | trng.blocking_fill_bytes(&mut buf); | ||
| 64 | defmt::info!("{:02x}", buf); | ||
| 65 | } | ||
| 66 | |||
| 67 | defmt::info!("RngCore"); | ||
| 68 | |||
| 69 | for _ in 0..10 { | ||
| 70 | defmt::info!("u32: {}", trng.next_u32()); | ||
| 71 | defmt::info!("u64: {}", trng.next_u64()); | ||
| 72 | } | ||
| 73 | |||
| 74 | drop(trng); | ||
| 75 | |||
| 76 | defmt::info!("========== ASYNC =========="); | ||
| 77 | |||
| 78 | let mut trng = Trng::new_with_custom_config(p.TRNG0.reborrow(), Irqs, config); | ||
| 79 | |||
| 80 | defmt::info!("Generate 10 u32"); | ||
| 81 | for _ in 0..10 { | ||
| 82 | let rand = trng.async_next_u32().await.unwrap(); | ||
| 83 | defmt::info!("{}", rand); | ||
| 84 | } | ||
| 85 | |||
| 86 | defmt::info!("Generate 10 u64"); | ||
| 87 | for _ in 0..10 { | ||
| 88 | let rand = trng.async_next_u64().await.unwrap(); | ||
| 89 | defmt::info!("{}", rand); | ||
| 90 | } | ||
| 91 | |||
| 92 | let mut buf = [0_u8; 256]; | ||
| 93 | |||
| 94 | defmt::info!("Generate 10 256-byte buffers"); | ||
| 95 | for _ in 0..10 { | ||
| 96 | trng.async_fill_bytes(&mut buf).await.unwrap(); | ||
| 97 | defmt::info!("{:02x}", buf); | ||
| 98 | } | ||
| 99 | |||
| 100 | defmt::info!("RngCore"); | ||
| 101 | |||
| 102 | for _ in 0..10 { | ||
| 103 | defmt::info!("u32: {}", trng.next_u32()); | ||
| 104 | defmt::info!("u64: {}", trng.next_u64()); | ||
| 105 | } | ||
| 106 | } | ||
diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml index 3038f5d4d..d784ce729 100644 --- a/examples/mimxrt1011/Cargo.toml +++ b/examples/mimxrt1011/Cargo.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-imxrt1011-examples" | 2 | name = "embassy-imxrt1011-examples" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2024" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
diff --git a/examples/mimxrt1011/src/lib.rs b/examples/mimxrt1011/src/lib.rs index f0391ef57..36d3e2fb3 100644 --- a/examples/mimxrt1011/src/lib.rs +++ b/examples/mimxrt1011/src/lib.rs | |||
| @@ -71,5 +71,5 @@ pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = | |||
| 71 | .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); | 71 | .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); |
| 72 | 72 | ||
| 73 | #[unsafe(no_mangle)] | 73 | #[unsafe(no_mangle)] |
| 74 | #[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] | 74 | #[cfg_attr(all(target_arch = "arm", target_os = "none"), unsafe(link_section = ".fcb"))] |
| 75 | pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; | 75 | pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; |
diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml index 82a24490d..29a80db12 100644 --- a/examples/mimxrt1062-evk/Cargo.toml +++ b/examples/mimxrt1062-evk/Cargo.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-imxrt1062-evk-examples" | 2 | name = "embassy-imxrt1062-evk-examples" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2024" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
diff --git a/examples/mimxrt1062-evk/src/lib.rs b/examples/mimxrt1062-evk/src/lib.rs index 3f99f9db3..e952b91ec 100644 --- a/examples/mimxrt1062-evk/src/lib.rs +++ b/examples/mimxrt1062-evk/src/lib.rs | |||
| @@ -55,6 +55,6 @@ pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = | |||
| 55 | .sector_size(4096) | 55 | .sector_size(4096) |
| 56 | .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); | 56 | .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); |
| 57 | 57 | ||
| 58 | #[no_mangle] | 58 | #[unsafe(no_mangle)] |
| 59 | #[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] | 59 | #[cfg_attr(all(target_arch = "arm", target_os = "none"), unsafe(link_section = ".fcb"))] |
| 60 | pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; | 60 | pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; |
diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 3f7ad8485..ada112833 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-imxrt-examples" | 2 | name = "embassy-imxrt-examples" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2024" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
| @@ -21,6 +21,8 @@ embedded-hal-async = "1.0.0" | |||
| 21 | 21 | ||
| 22 | mimxrt600-fcb = "0.2.2" | 22 | mimxrt600-fcb = "0.2.2" |
| 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 24 | embedded-hal-bus = "0.3.0" | ||
| 25 | is31fl3743b-driver = { version = "0.1.1", features = ["is_blocking"] } | ||
| 24 | 26 | ||
| 25 | # cargo build/run | 27 | # cargo build/run |
| 26 | [profile.dev] | 28 | [profile.dev] |
diff --git a/examples/mimxrt6/src/bin/button.rs b/examples/mimxrt6/src/bin/button.rs index efb7f14af..a9bdde98e 100644 --- a/examples/mimxrt6/src/bin/button.rs +++ b/examples/mimxrt6/src/bin/button.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::select::{select, Either}; | 6 | use embassy_futures::select::{Either, select}; |
| 7 | use embassy_imxrt::gpio; | 7 | use embassy_imxrt::gpio; |
| 8 | use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; | 8 | use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; |
| 9 | 9 | ||
diff --git a/examples/mimxrt6/src/bin/dma.rs b/examples/mimxrt6/src/bin/dma.rs new file mode 100644 index 000000000..b490efc6b --- /dev/null +++ b/examples/mimxrt6/src/bin/dma.rs | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | extern crate embassy_imxrt_examples; | ||
| 5 | |||
| 6 | use defmt::info; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_imxrt::dma::copy; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | const BUFLEN: usize = 1024; | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = embassy_imxrt::init(Default::default()); | ||
| 16 | |||
| 17 | info!("Test memory-to-memory DMA transfers"); | ||
| 18 | |||
| 19 | let src = [0x55u8; BUFLEN]; | ||
| 20 | let mut dst = [0u8; BUFLEN]; | ||
| 21 | |||
| 22 | unsafe { copy(p.DMA0_CH0, &src, &mut dst) }.await; | ||
| 23 | assert!(dst == src); | ||
| 24 | |||
| 25 | info!("DMA copy succeeded"); | ||
| 26 | } | ||
diff --git a/examples/mimxrt6/src/bin/spi-async.rs b/examples/mimxrt6/src/bin/spi-async.rs new file mode 100644 index 000000000..aa56f7c42 --- /dev/null +++ b/examples/mimxrt6/src/bin/spi-async.rs | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_imxrt::bind_interrupts; | ||
| 7 | use embassy_imxrt::flexcomm::spi::{InterruptHandler, Spi}; | ||
| 8 | use embassy_imxrt::peripherals::FLEXCOMM5; | ||
| 9 | use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; | ||
| 10 | |||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | FLEXCOMM5 => InterruptHandler<FLEXCOMM5>; | ||
| 13 | }); | ||
| 14 | |||
| 15 | const BUFLEN: usize = 1024; | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) { | ||
| 19 | let p = embassy_imxrt::init(Default::default()); | ||
| 20 | |||
| 21 | info!("Initializing SPI"); | ||
| 22 | |||
| 23 | let mut spi = Spi::new_async(p.FLEXCOMM5, p.PIO1_3, p.PIO1_5, p.PIO1_4, Irqs, Default::default()); | ||
| 24 | |||
| 25 | let mut rxbuf = [0x55; BUFLEN]; | ||
| 26 | let txbuf = [0xaa; BUFLEN]; | ||
| 27 | |||
| 28 | for _ in 0..10 { | ||
| 29 | spi.async_transfer(&mut rxbuf, &txbuf).await.unwrap(); | ||
| 30 | assert!(rxbuf.iter().all(|b| *b == 0xaa)); | ||
| 31 | rxbuf.fill(0x55); | ||
| 32 | } | ||
| 33 | |||
| 34 | info!("SPI transfers succeeded"); | ||
| 35 | } | ||
diff --git a/examples/mimxrt6/src/bin/spi.rs b/examples/mimxrt6/src/bin/spi.rs new file mode 100644 index 000000000..4854432e8 --- /dev/null +++ b/examples/mimxrt6/src/bin/spi.rs | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_imxrt::flexcomm::spi::Spi; | ||
| 7 | use embassy_imxrt::gpio; | ||
| 8 | use embassy_time::{Delay, Timer}; | ||
| 9 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 10 | use is31fl3743b_driver::{CSy, Is31fl3743b, SWx}; | ||
| 11 | use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = embassy_imxrt::init(Default::default()); | ||
| 16 | |||
| 17 | info!("Initializing SPI"); | ||
| 18 | |||
| 19 | let cs = gpio::Output::new( | ||
| 20 | p.PIO1_6, | ||
| 21 | gpio::Level::Low, | ||
| 22 | gpio::DriveMode::PushPull, | ||
| 23 | gpio::DriveStrength::Normal, | ||
| 24 | gpio::SlewRate::Standard, | ||
| 25 | ); | ||
| 26 | |||
| 27 | let spi = Spi::new_blocking(p.FLEXCOMM5, p.PIO1_3, p.PIO1_5, p.PIO1_4, Default::default()); | ||
| 28 | let delay = Delay; | ||
| 29 | |||
| 30 | // One SPI device only on the SPI bus | ||
| 31 | let spi_dev = ExclusiveDevice::new(spi, cs, delay).unwrap(); | ||
| 32 | |||
| 33 | // Instantiate IS31FL3743B device | ||
| 34 | let mut driver = Is31fl3743b::new(spi_dev).unwrap(); | ||
| 35 | |||
| 36 | // Enable phase delay to help reduce power noise | ||
| 37 | let _ = driver.enable_phase_delay(); | ||
| 38 | // Set global current, check method documentation for more info | ||
| 39 | let _ = driver.set_global_current(90); | ||
| 40 | |||
| 41 | let _ = driver.set_led_peak_current_bulk(SWx::SW1, CSy::CS1, &[100; 11 * 18]); | ||
| 42 | |||
| 43 | // Driver is fully set up, we can now start turning on LEDs! | ||
| 44 | // Create a white breathing effect | ||
| 45 | loop { | ||
| 46 | for brightness in (0..=255_u8).chain((0..=255).rev()) { | ||
| 47 | let _ = driver.set_led_brightness_bulk(SWx::SW1, CSy::CS1, &[brightness; 11 * 18]); | ||
| 48 | Timer::after_micros(1).await; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index 21434106a..74301bc9c 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-mspm0-c1104-examples" | 3 | name = "embassy-mspm0-c1104-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/mspm0c1104/src/bin/blinky.rs b/examples/mspm0c1104/src/bin/blinky.rs index 0d974cc5e..345077b37 100644 --- a/examples/mspm0c1104/src/bin/blinky.rs +++ b/examples/mspm0c1104/src/bin/blinky.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0c1104/src/bin/button.rs b/examples/mspm0c1104/src/bin/button.rs index 7face1618..557d997cd 100644 --- a/examples/mspm0c1104/src/bin/button.rs +++ b/examples/mspm0c1104/src/bin/button.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | 8 | use {defmt_rtt as _, panic_halt as _}; |
| 9 | 9 | ||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index 616b82adb..8c230f038 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-mspm0-g3507-examples" | 3 | name = "embassy-mspm0-g3507-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/mspm0g3507/src/bin/adc.rs b/examples/mspm0g3507/src/bin/adc.rs index ceccc7c02..cf1abb471 100644 --- a/examples/mspm0g3507/src/bin/adc.rs +++ b/examples/mspm0g3507/src/bin/adc.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::adc::{self, Adc, Vrsel}; | 6 | use embassy_mspm0::adc::{self, Adc, Vrsel}; |
| 7 | use embassy_mspm0::{bind_interrupts, peripherals, Config}; | 7 | use embassy_mspm0::{Config, bind_interrupts, peripherals}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0g3507/src/bin/blinky.rs b/examples/mspm0g3507/src/bin/blinky.rs index 055a5cd81..47eaf1535 100644 --- a/examples/mspm0g3507/src/bin/blinky.rs +++ b/examples/mspm0g3507/src/bin/blinky.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0g3507/src/bin/button.rs b/examples/mspm0g3507/src/bin/button.rs index cde1f2892..76f3a1aba 100644 --- a/examples/mspm0g3507/src/bin/button.rs +++ b/examples/mspm0g3507/src/bin/button.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | 8 | use {defmt_rtt as _, panic_halt as _}; |
| 9 | 9 | ||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs new file mode 100644 index 000000000..5dd718eaf --- /dev/null +++ b/examples/mspm0g3507/src/bin/i2c_target.rs | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | //! Example of using async I2C target | ||
| 2 | //! | ||
| 3 | //! This uses the virtual COM port provided on the LP-MSPM0G3507 board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::i2c::Config; | ||
| 11 | use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus}; | ||
| 12 | use embassy_mspm0::peripherals::I2C1; | ||
| 13 | use embassy_mspm0::{bind_interrupts, i2c}; | ||
| 14 | use {defmt_rtt as _, panic_halt as _}; | ||
| 15 | |||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | I2C1 => i2c::InterruptHandler<I2C1>; | ||
| 18 | }); | ||
| 19 | |||
| 20 | #[embassy_executor::main] | ||
| 21 | async fn main(_spawner: Spawner) -> ! { | ||
| 22 | let p = embassy_mspm0::init(Default::default()); | ||
| 23 | |||
| 24 | let instance = p.I2C1; | ||
| 25 | let scl = p.PB2; | ||
| 26 | let sda = p.PB3; | ||
| 27 | |||
| 28 | let config = Config::default(); | ||
| 29 | let mut target_config = TargetConfig::default(); | ||
| 30 | target_config.target_addr = 0x48; | ||
| 31 | target_config.general_call = true; | ||
| 32 | let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap(); | ||
| 33 | |||
| 34 | let mut read = [0u8; 8]; | ||
| 35 | let data = [8u8; 2]; | ||
| 36 | let data_wr = [9u8; 2]; | ||
| 37 | |||
| 38 | loop { | ||
| 39 | match i2c.listen(&mut read).await { | ||
| 40 | Ok(Command::GeneralCall(_)) => info!("General call received"), | ||
| 41 | Ok(Command::Read) => { | ||
| 42 | info!("Read command received"); | ||
| 43 | match i2c.respond_to_read(&data).await.unwrap() { | ||
| 44 | ReadStatus::Done => info!("Finished reading"), | ||
| 45 | ReadStatus::NeedMoreBytes => { | ||
| 46 | info!("Read needs more bytes - will reset"); | ||
| 47 | i2c.reset().unwrap(); | ||
| 48 | } | ||
| 49 | ReadStatus::LeftoverBytes(_) => { | ||
| 50 | info!("Leftover bytes received"); | ||
| 51 | i2c.flush_tx_fifo(); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | } | ||
| 55 | Ok(Command::Write(_)) => info!("Write command received"), | ||
| 56 | Ok(Command::WriteRead(_)) => { | ||
| 57 | info!("Write-Read command received"); | ||
| 58 | i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap(); | ||
| 59 | } | ||
| 60 | Err(e) => info!("Got error {}", e), | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
diff --git a/examples/mspm0g3507/src/bin/mathacl_ops.rs b/examples/mspm0g3507/src/bin/mathacl_ops.rs new file mode 100644 index 000000000..25d74b29b --- /dev/null +++ b/examples/mspm0g3507/src/bin/mathacl_ops.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | //! Example of using mathematical calculations performed by the MSPM0G3507 chip. | ||
| 2 | //! | ||
| 3 | //! It prints the result of basics trigonometric calculation. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use core::f32::consts::PI; | ||
| 9 | |||
| 10 | use defmt::*; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_mspm0::mathacl::{Mathacl, Precision}; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | use {defmt_rtt as _, panic_halt as _}; | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) -> ! { | ||
| 18 | info!("Hello world!"); | ||
| 19 | |||
| 20 | let d = embassy_mspm0::init(Default::default()); | ||
| 21 | |||
| 22 | let mut macl = Mathacl::new(d.MATHACL); | ||
| 23 | |||
| 24 | // value radians [-PI; PI] | ||
| 25 | let rads = PI * 0.5; | ||
| 26 | match macl.sin(rads, Precision::High) { | ||
| 27 | Ok(res) => info!("sin({}) = {}", rads, res), | ||
| 28 | Err(e) => error!("sin Error: {:?}", e), | ||
| 29 | } | ||
| 30 | |||
| 31 | match macl.cos(rads, Precision::Medium) { | ||
| 32 | Ok(res) => info!("cos({}) = {}", rads, res), | ||
| 33 | Err(e) => error!("cos Error: {:?}", e), | ||
| 34 | } | ||
| 35 | |||
| 36 | loop { | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | } | ||
diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index ae699d6f4..0f5e58343 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-mspm0-g3519-examples" | 3 | name = "embassy-mspm0-g3519-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/mspm0g3519/src/bin/blinky.rs b/examples/mspm0g3519/src/bin/blinky.rs index 055a5cd81..47eaf1535 100644 --- a/examples/mspm0g3519/src/bin/blinky.rs +++ b/examples/mspm0g3519/src/bin/blinky.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0g3519/src/bin/button.rs b/examples/mspm0g3519/src/bin/button.rs index c81cc2918..21e7873d8 100644 --- a/examples/mspm0g3519/src/bin/button.rs +++ b/examples/mspm0g3519/src/bin/button.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | 8 | use {defmt_rtt as _, panic_halt as _}; |
| 9 | 9 | ||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
diff --git a/examples/mspm0g5187/.cargo/config.toml b/examples/mspm0g5187/.cargo/config.toml new file mode 100644 index 000000000..ea407b411 --- /dev/null +++ b/examples/mspm0g5187/.cargo/config.toml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace MSPM0G5187 with your chip as listed in `probe-rs chip list` | ||
| 3 | runner = "probe-rs run --restore-unwritten --verify --chip MSPM0G5187 --protocol=swd" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv6m-none-eabi" | ||
| 7 | |||
| 8 | [env] | ||
| 9 | DEFMT_LOG = "trace" | ||
diff --git a/examples/mspm0g5187/Cargo.toml b/examples/mspm0g5187/Cargo.toml new file mode 100644 index 000000000..3d64a127a --- /dev/null +++ b/examples/mspm0g5187/Cargo.toml | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2024" | ||
| 3 | name = "embassy-mspm0-g5187-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g5187pm", "defmt", "rt", "time-driver-any"] } | ||
| 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | ||
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } | ||
| 13 | panic-halt = "1.0.0" | ||
| 14 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 15 | cortex-m-rt = { version = "0.7.0"} | ||
| 16 | defmt = "1.0.1" | ||
| 17 | defmt-rtt = "1.0.0" | ||
| 18 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 19 | panic-semihosting = "0.6.0" | ||
| 20 | |||
| 21 | [profile.release] | ||
| 22 | debug = 2 | ||
| 23 | |||
| 24 | [package.metadata.embassy] | ||
| 25 | build = [ | ||
| 26 | { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g5187" } | ||
| 27 | ] | ||
diff --git a/examples/mspm0g5187/README.md b/examples/mspm0g5187/README.md new file mode 100644 index 000000000..12e7846fb --- /dev/null +++ b/examples/mspm0g5187/README.md | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | # Examples for MSPM0G5187 | ||
| 2 | |||
| 3 | Run individual examples with | ||
| 4 | ``` | ||
| 5 | cargo run --bin <module-name> | ||
| 6 | ``` | ||
| 7 | for example | ||
| 8 | ``` | ||
| 9 | cargo run --bin blinky | ||
| 10 | ``` | ||
| 11 | |||
| 12 | ## Checklist before running examples | ||
| 13 | A large number of the examples are written for the [LP-MSPM0G5187](https://www.ti.com/tool/LP-MSPM0G5187) board. | ||
| 14 | |||
| 15 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | ||
| 16 | |||
| 17 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G5187 it should be `probe-rs run --chip MSPM0G5187`. (use `probe-rs chip list` to find your chip) | ||
| 18 | * [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3519 it should be `mspm0g3519pz`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. | ||
| 19 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | ||
| 20 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | ||
| 21 | |||
| 22 | If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: | ||
| 23 | |||
| 24 | * Which example you are trying to run | ||
| 25 | * Which chip and board you are using | ||
| 26 | |||
| 27 | Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org | ||
diff --git a/examples/mspm0g5187/build.rs b/examples/mspm0g5187/build.rs new file mode 100644 index 000000000..2d777c2d3 --- /dev/null +++ b/examples/mspm0g5187/build.rs | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | //! This build script copies the `memory.x` file from the crate root into | ||
| 2 | //! a directory where the linker can always find it at build time. | ||
| 3 | //! For many projects this is optional, as the linker always searches the | ||
| 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you | ||
| 5 | //! are using a workspace or have a more complicated build setup, this | ||
| 6 | //! build script becomes required. Additionally, by requesting that | ||
| 7 | //! Cargo re-run the build script whenever `memory.x` is changed, | ||
| 8 | //! updating `memory.x` ensures a rebuild of the application with the | ||
| 9 | //! new memory settings. | ||
| 10 | |||
| 11 | use std::env; | ||
| 12 | use std::fs::File; | ||
| 13 | use std::io::Write; | ||
| 14 | use std::path::PathBuf; | ||
| 15 | |||
| 16 | fn main() { | ||
| 17 | // Put `memory.x` in our output directory and ensure it's | ||
| 18 | // on the linker search path. | ||
| 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 20 | File::create(out.join("memory.x")) | ||
| 21 | .unwrap() | ||
| 22 | .write_all(include_bytes!("memory.x")) | ||
| 23 | .unwrap(); | ||
| 24 | println!("cargo:rustc-link-search={}", out.display()); | ||
| 25 | |||
| 26 | // By default, Cargo will re-run a build script whenever | ||
| 27 | // any file in the project changes. By specifying `memory.x` | ||
| 28 | // here, we ensure the build script is only re-run when | ||
| 29 | // `memory.x` is changed. | ||
| 30 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 31 | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 35 | // You must tell cargo to link interrupt groups if the rt feature is enabled. | ||
| 36 | println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); | ||
| 37 | } | ||
diff --git a/examples/mspm0g5187/memory.x b/examples/mspm0g5187/memory.x new file mode 100644 index 000000000..37e381fbd --- /dev/null +++ b/examples/mspm0g5187/memory.x | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 128K | ||
| 4 | /* Select non-parity range of SRAM due to SRAM_ERR_01 errata in SLAZ758 */ | ||
| 5 | RAM : ORIGIN = 0x20200000, LENGTH = 32K | ||
| 6 | } | ||
diff --git a/examples/mspm0g5187/src/bin/blinky.rs b/examples/mspm0g5187/src/bin/blinky.rs new file mode 100644 index 000000000..47eaf1535 --- /dev/null +++ b/examples/mspm0g5187/src/bin/blinky.rs | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_mspm0::Config; | ||
| 7 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, panic_halt as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async fn main(_spawner: Spawner) -> ! { | ||
| 13 | info!("Hello world!"); | ||
| 14 | let p = embassy_mspm0::init(Config::default()); | ||
| 15 | |||
| 16 | let mut led1 = Output::new(p.PA0, Level::Low); | ||
| 17 | led1.set_inversion(true); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | Timer::after_millis(400).await; | ||
| 21 | |||
| 22 | info!("Toggle"); | ||
| 23 | led1.toggle(); | ||
| 24 | } | ||
| 25 | } | ||
diff --git a/examples/mspm0g5187/src/bin/button.rs b/examples/mspm0g5187/src/bin/button.rs new file mode 100644 index 000000000..2ed15e354 --- /dev/null +++ b/examples/mspm0g5187/src/bin/button.rs | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_mspm0::Config; | ||
| 7 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) -> ! { | ||
| 12 | info!("Hello world!"); | ||
| 13 | |||
| 14 | let p = embassy_mspm0::init(Config::default()); | ||
| 15 | |||
| 16 | let led1 = p.PA0; | ||
| 17 | let s2 = p.PA7; | ||
| 18 | |||
| 19 | let mut led1 = Output::new(led1, Level::Low); | ||
| 20 | |||
| 21 | let mut s2 = Input::new(s2, Pull::Up); | ||
| 22 | |||
| 23 | // led1 is active low | ||
| 24 | led1.set_high(); | ||
| 25 | |||
| 26 | loop { | ||
| 27 | s2.wait_for_falling_edge().await; | ||
| 28 | |||
| 29 | info!("Switch 2 was pressed"); | ||
| 30 | |||
| 31 | led1.toggle(); | ||
| 32 | } | ||
| 33 | } | ||
diff --git a/examples/mspm0g5187/src/bin/wwdt.rs b/examples/mspm0g5187/src/bin/wwdt.rs new file mode 100644 index 000000000..a5de781f3 --- /dev/null +++ b/examples/mspm0g5187/src/bin/wwdt.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | //! Example of using window watchdog timer in the MSPM0G5187 chip. | ||
| 2 | //! | ||
| 3 | //! It tests the use case when watchdog timer is expired and when watchdog is pet too early. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 11 | use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | use {defmt_rtt as _, panic_halt as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) -> ! { | ||
| 17 | info!("Hello world!"); | ||
| 18 | |||
| 19 | let p = embassy_mspm0::init(Default::default()); | ||
| 20 | let mut conf = Config::default(); | ||
| 21 | conf.timeout = Timeout::Sec1; | ||
| 22 | |||
| 23 | // watchdog also resets the system if the pet comes too early, | ||
| 24 | // less than 250 msec == 25% from 1 sec | ||
| 25 | conf.closed_window = ClosedWindowPercentage::TwentyFive; | ||
| 26 | let mut wdt = Watchdog::new(p.WWDT0, conf); | ||
| 27 | info!("Started the watchdog timer"); | ||
| 28 | |||
| 29 | let mut led1 = Output::new(p.PA0, Level::High); | ||
| 30 | led1.set_inversion(true); | ||
| 31 | Timer::after_millis(900).await; | ||
| 32 | |||
| 33 | for _ in 1..=5 { | ||
| 34 | info!("pet watchdog"); | ||
| 35 | led1.toggle(); | ||
| 36 | wdt.pet(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | } | ||
| 39 | |||
| 40 | // watchdog timeout test | ||
| 41 | info!("Stopped the pet command, device will reset in less than 1 second"); | ||
| 42 | loop { | ||
| 43 | led1.toggle(); | ||
| 44 | Timer::after_millis(500).await; | ||
| 45 | } | ||
| 46 | |||
| 47 | // watchdog "too early" test | ||
| 48 | // info!("Device will reset when the pet comes too early"); | ||
| 49 | // loop { | ||
| 50 | // led1.toggle(); | ||
| 51 | // wdt.pet(); | ||
| 52 | // Timer::after_millis(200).await; | ||
| 53 | // } | ||
| 54 | } | ||
diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 8100e11da..d5b5e9d3e 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-mspm0-l1306-examples" | 3 | name = "embassy-mspm0-l1306-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/mspm0l1306/src/bin/adc.rs b/examples/mspm0l1306/src/bin/adc.rs index 2806b98cc..235396b8a 100644 --- a/examples/mspm0l1306/src/bin/adc.rs +++ b/examples/mspm0l1306/src/bin/adc.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::adc::{self, Adc, Vrsel}; | 6 | use embassy_mspm0::adc::{self, Adc, Vrsel}; |
| 7 | use embassy_mspm0::{bind_interrupts, peripherals, Config}; | 7 | use embassy_mspm0::{Config, bind_interrupts, peripherals}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0l1306/src/bin/blinky.rs b/examples/mspm0l1306/src/bin/blinky.rs index 055a5cd81..47eaf1535 100644 --- a/examples/mspm0l1306/src/bin/blinky.rs +++ b/examples/mspm0l1306/src/bin/blinky.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0l1306/src/bin/button.rs b/examples/mspm0l1306/src/bin/button.rs index d8c85947f..33e682272 100644 --- a/examples/mspm0l1306/src/bin/button.rs +++ b/examples/mspm0l1306/src/bin/button.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | 8 | use {defmt_rtt as _, panic_halt as _}; |
| 9 | 9 | ||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
diff --git a/examples/mspm0l1306/src/bin/i2c_target.rs b/examples/mspm0l1306/src/bin/i2c_target.rs new file mode 100644 index 000000000..4d147d08b --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c_target.rs | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | //! Example of using async I2C target | ||
| 2 | //! | ||
| 3 | //! This uses the virtual COM port provided on the LP-MSPM0L1306 board. | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_mspm0::i2c::Config; | ||
| 11 | use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus}; | ||
| 12 | use embassy_mspm0::peripherals::I2C0; | ||
| 13 | use embassy_mspm0::{bind_interrupts, i2c}; | ||
| 14 | use {defmt_rtt as _, panic_halt as _}; | ||
| 15 | |||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | I2C0 => i2c::InterruptHandler<I2C0>; | ||
| 18 | }); | ||
| 19 | |||
| 20 | #[embassy_executor::main] | ||
| 21 | async fn main(_spawner: Spawner) -> ! { | ||
| 22 | let p = embassy_mspm0::init(Default::default()); | ||
| 23 | |||
| 24 | let instance = p.I2C0; | ||
| 25 | let scl = p.PA1; | ||
| 26 | let sda = p.PA0; | ||
| 27 | |||
| 28 | let config = Config::default(); | ||
| 29 | let mut target_config = TargetConfig::default(); | ||
| 30 | target_config.target_addr = 0x48; | ||
| 31 | target_config.general_call = true; | ||
| 32 | let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap(); | ||
| 33 | |||
| 34 | let mut read = [0u8; 8]; | ||
| 35 | let data = [8u8; 2]; | ||
| 36 | let data_wr = [9u8; 2]; | ||
| 37 | |||
| 38 | loop { | ||
| 39 | match i2c.listen(&mut read).await { | ||
| 40 | Ok(Command::GeneralCall(_)) => info!("General call received"), | ||
| 41 | Ok(Command::Read) => { | ||
| 42 | info!("Read command received"); | ||
| 43 | match i2c.respond_to_read(&data).await.unwrap() { | ||
| 44 | ReadStatus::Done => info!("Finished reading"), | ||
| 45 | ReadStatus::NeedMoreBytes => { | ||
| 46 | info!("Read needs more bytes - will reset"); | ||
| 47 | i2c.reset().unwrap(); | ||
| 48 | } | ||
| 49 | ReadStatus::LeftoverBytes(_) => { | ||
| 50 | info!("Leftover bytes received"); | ||
| 51 | i2c.flush_tx_fifo(); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | } | ||
| 55 | Ok(Command::Write(_)) => info!("Write command received"), | ||
| 56 | Ok(Command::WriteRead(_)) => { | ||
| 57 | info!("Write-Read command received"); | ||
| 58 | i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap(); | ||
| 59 | } | ||
| 60 | Err(e) => info!("Got error {}", e), | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index 3add7b8e8..1d27ae64a 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-mspm0-l2228-examples" | 3 | name = "embassy-mspm0-l2228-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/mspm0l2228/src/bin/blinky.rs b/examples/mspm0l2228/src/bin/blinky.rs index 055a5cd81..47eaf1535 100644 --- a/examples/mspm0l2228/src/bin/blinky.rs +++ b/examples/mspm0l2228/src/bin/blinky.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Level, Output}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_halt as _}; | 9 | use {defmt_rtt as _, panic_halt as _}; |
| 10 | 10 | ||
diff --git a/examples/mspm0l2228/src/bin/button.rs b/examples/mspm0l2228/src/bin/button.rs index 47bfd274b..bad1cb138 100644 --- a/examples/mspm0l2228/src/bin/button.rs +++ b/examples/mspm0l2228/src/bin/button.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 7 | use embassy_mspm0::Config; | 6 | use embassy_mspm0::Config; |
| 7 | use embassy_mspm0::gpio::{Input, Level, Output, Pull}; | ||
| 8 | use {defmt_rtt as _, panic_halt as _}; | 8 | use {defmt_rtt as _, panic_halt as _}; |
| 9 | 9 | ||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index d2d0ae093..3d6b5e60a 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf-rtos-trace-examples" | 3 | name = "embassy-nrf-rtos-trace-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -19,7 +19,7 @@ log = [ | |||
| 19 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync" } | 19 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync" } |
| 20 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } | 20 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } |
| 21 | embassy-time = { version = "0.5.0", path = "../../embassy-time" } | 21 | embassy-time = { version = "0.5.0", path = "../../embassy-time" } |
| 22 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 22 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 23 | 23 | ||
| 24 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 24 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 25 | cortex-m-rt = "0.7.0" | 25 | cortex-m-rt = "0.7.0" |
diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 082d85e5b..e8375952b 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf51-examples" | 3 | name = "embassy-nrf51-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -8,7 +8,7 @@ publish = false | |||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 11 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } | 11 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } |
| 12 | 12 | ||
| 13 | defmt = "1.0.1" | 13 | defmt = "1.0.1" |
| 14 | defmt-rtt = "1.0.0" | 14 | defmt-rtt = "1.0.0" |
diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 7835320e5..73d129f91 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf52810-examples" | 3 | name = "embassy-nrf52810-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -10,7 +10,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | |||
| 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 13 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 14 | 14 | ||
| 15 | defmt = "1.0.1" | 15 | defmt = "1.0.1" |
| 16 | defmt-rtt = "1.0.0" | 16 | defmt-rtt = "1.0.0" |
diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml index 67a624d6d..8066a1150 100644 --- a/examples/nrf52840-edf/Cargo.toml +++ b/examples/nrf52840-edf/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf52840-edf-examples" | 3 | name = "embassy-nrf52840-edf-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -9,7 +9,7 @@ publish = false | |||
| 9 | # NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled | 9 | # NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled |
| 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] } |
| 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 12 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 13 | 13 | ||
| 14 | defmt = "1.0.1" | 14 | defmt = "1.0.1" |
| 15 | defmt-rtt = "1.0.0" | 15 | defmt-rtt = "1.0.0" |
diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs index d888e17d1..f7214790d 100644 --- a/examples/nrf52840-edf/src/bin/basic.rs +++ b/examples/nrf52840-edf/src/bin/basic.rs | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #![no_std] | 12 | #![no_std] |
| 13 | #![no_main] | 13 | #![no_main] |
| 14 | 14 | ||
| 15 | use core::sync::atomic::{compiler_fence, Ordering}; | 15 | use core::sync::atomic::{Ordering, compiler_fence}; |
| 16 | 16 | ||
| 17 | use defmt::unwrap; | 17 | use defmt::unwrap; |
| 18 | use embassy_executor::Spawner; | 18 | use embassy_executor::Spawner; |
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index d860626a1..13a7724fa 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf52840-rtic-examples" | 3 | name = "embassy-nrf52840-rtic-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -12,7 +12,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | |||
| 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } |
| 14 | embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } | 14 | embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } |
| 15 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 15 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 16 | 16 | ||
| 17 | defmt = "1.0.1" | 17 | defmt = "1.0.1" |
| 18 | defmt-rtt = "1.0.0" | 18 | defmt-rtt = "1.0.0" |
diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs index 2adac7e0a..671082117 100644 --- a/examples/nrf52840-rtic/src/bin/blinky.rs +++ b/examples/nrf52840-rtic/src/bin/blinky.rs | |||
| @@ -7,7 +7,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 7 | mod app { | 7 | mod app { |
| 8 | use defmt::info; | 8 | use defmt::info; |
| 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 10 | use embassy_nrf::{peripherals, Peri}; | 10 | use embassy_nrf::{Peri, peripherals}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | 12 | ||
| 13 | #[shared] | 13 | #[shared] |
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 5b3e176c0..a57bd7b24 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf52840-examples" | 3 | name = "embassy-nrf52840-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -10,7 +10,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | |||
| 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } | 13 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } |
| 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } |
| 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } | 16 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } |
| @@ -28,7 +28,7 @@ cortex-m-rt = "0.7.0" | |||
| 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 29 | rand = { version = "0.9.0", default-features = false } | 29 | rand = { version = "0.9.0", default-features = false } |
| 30 | embedded-storage = "0.3.1" | 30 | embedded-storage = "0.3.1" |
| 31 | usbd-hid = "0.8.1" | 31 | usbd-hid = "0.9.0" |
| 32 | serde = { version = "1.0.136", default-features = false } | 32 | serde = { version = "1.0.136", default-features = false } |
| 33 | embedded-hal = { version = "1.0" } | 33 | embedded-hal = { version = "1.0" } |
| 34 | embedded-hal-async = { version = "1.0" } | 34 | embedded-hal-async = { version = "1.0" } |
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs index 09050db68..de694eaa0 100644 --- a/examples/nrf52840/src/bin/channel_sender_receiver.rs +++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::unwrap; | 4 | use defmt::unwrap; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive}; | ||
| 7 | use embassy_nrf::Peri; | 6 | use embassy_nrf::Peri; |
| 7 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive}; | ||
| 8 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; |
| 9 | use embassy_sync::channel::{Channel, Receiver, Sender}; | 9 | use embassy_sync::channel::{Channel, Receiver, Sender}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
diff --git a/examples/nrf52840/src/bin/egu.rs b/examples/nrf52840/src/bin/egu.rs index 8bf712697..36eba8084 100644 --- a/examples/nrf52840/src/bin/egu.rs +++ b/examples/nrf52840/src/bin/egu.rs | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_nrf::egu::{Egu, TriggerNumber}; | 8 | use embassy_nrf::egu::{Egu, TriggerNumber}; |
| 9 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 9 | use embassy_nrf::gpio::{Level, OutputDrive, Pull}; |
| 10 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity}; | 10 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity}; |
| 11 | use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2}; | 11 | use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2}; |
| 12 | use embassy_nrf::ppi::Ppi; | 12 | use embassy_nrf::ppi::Ppi; |
| @@ -17,12 +17,15 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 17 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 18 | let p = embassy_nrf::init(Default::default()); | 18 | let p = embassy_nrf::init(Default::default()); |
| 19 | 19 | ||
| 20 | let led1 = Output::new(p.P0_13, Level::High, OutputDrive::Standard); | ||
| 21 | let btn1 = Input::new(p.P0_11, Pull::Up); | ||
| 22 | |||
| 23 | let mut egu1 = Egu::new(p.EGU0); | 20 | let mut egu1 = Egu::new(p.EGU0); |
| 24 | let led1 = OutputChannel::new(p.GPIOTE_CH0, led1, OutputChannelPolarity::Toggle); | 21 | let led1 = OutputChannel::new( |
| 25 | let btn1 = InputChannel::new(p.GPIOTE_CH1, btn1, InputChannelPolarity::LoToHi); | 22 | p.GPIOTE_CH0, |
| 23 | p.P0_13, | ||
| 24 | Level::High, | ||
| 25 | OutputDrive::Standard, | ||
| 26 | OutputChannelPolarity::Toggle, | ||
| 27 | ); | ||
| 28 | let btn1 = InputChannel::new(p.GPIOTE_CH1, p.P0_11, Pull::Up, InputChannelPolarity::LoToHi); | ||
| 26 | 29 | ||
| 27 | let trigger0 = egu1.trigger(TriggerNumber::Trigger0); | 30 | let trigger0 = egu1.trigger(TriggerNumber::Trigger0); |
| 28 | let trigger1 = egu1.trigger(TriggerNumber::Trigger1); | 31 | let trigger1 = egu1.trigger(TriggerNumber::Trigger1); |
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs index e59afd37f..5a988d89b 100644 --- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs +++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::StackResources; | 6 | use embassy_net::StackResources; |
| 7 | use embassy_net::tcp::TcpSocket; | ||
| 8 | use embassy_net_enc28j60::Enc28j60; | 8 | use embassy_net_enc28j60::Enc28j60; |
| 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 9 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 10 | use embassy_nrf::rng::Rng; | 10 | use embassy_nrf::rng::Rng; |
diff --git a/examples/nrf52840/src/bin/gpiote_channel.rs b/examples/nrf52840/src/bin/gpiote_channel.rs index dcfe7723a..e358779b2 100644 --- a/examples/nrf52840/src/bin/gpiote_channel.rs +++ b/examples/nrf52840/src/bin/gpiote_channel.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::gpio::{Input, Pull}; | 6 | use embassy_nrf::gpio::Pull; |
| 7 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; | 7 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) { | |||
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | info!("Starting!"); | 13 | info!("Starting!"); |
| 14 | 14 | ||
| 15 | let ch1 = InputChannel::new( | 15 | let mut ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); |
| 16 | p.GPIOTE_CH0, | 16 | let mut ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi); |
| 17 | Input::new(p.P0_11, Pull::Up), | 17 | let mut ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle); |
| 18 | InputChannelPolarity::HiToLo, | 18 | let mut ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle); |
| 19 | ); | ||
| 20 | let ch2 = InputChannel::new( | ||
| 21 | p.GPIOTE_CH1, | ||
| 22 | Input::new(p.P0_12, Pull::Up), | ||
| 23 | InputChannelPolarity::LoToHi, | ||
| 24 | ); | ||
| 25 | let ch3 = InputChannel::new( | ||
| 26 | p.GPIOTE_CH2, | ||
| 27 | Input::new(p.P0_24, Pull::Up), | ||
| 28 | InputChannelPolarity::Toggle, | ||
| 29 | ); | ||
| 30 | let ch4 = InputChannel::new( | ||
| 31 | p.GPIOTE_CH3, | ||
| 32 | Input::new(p.P0_25, Pull::Up), | ||
| 33 | InputChannelPolarity::Toggle, | ||
| 34 | ); | ||
| 35 | 19 | ||
| 36 | let button1 = async { | 20 | let button1 = async { |
| 37 | loop { | 21 | loop { |
diff --git a/examples/nrf52840/src/bin/i2s_effect.rs b/examples/nrf52840/src/bin/i2s_effect.rs index 9eadeb4e4..c31b78614 100644 --- a/examples/nrf52840/src/bin/i2s_effect.rs +++ b/examples/nrf52840/src/bin/i2s_effect.rs | |||
| @@ -5,7 +5,7 @@ use core::f32::consts::PI; | |||
| 5 | 5 | ||
| 6 | use defmt::{error, info}; | 6 | use defmt::{error, info}; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S}; | 8 | use embassy_nrf::i2s::{self, Channels, Config, I2S, MasterClock, MultiBuffering, Sample as _, SampleWidth}; |
| 9 | use embassy_nrf::{bind_interrupts, peripherals}; | 9 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -102,11 +102,7 @@ impl SineOsc { | |||
| 102 | 102 | ||
| 103 | #[inline] | 103 | #[inline] |
| 104 | fn abs(value: f32) -> f32 { | 104 | fn abs(value: f32) -> f32 { |
| 105 | if value < 0.0 { | 105 | if value < 0.0 { -value } else { value } |
| 106 | -value | ||
| 107 | } else { | ||
| 108 | value | ||
| 109 | } | ||
| 110 | } | 106 | } |
| 111 | 107 | ||
| 112 | #[inline] | 108 | #[inline] |
diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs index 799be351f..a54659101 100644 --- a/examples/nrf52840/src/bin/i2s_monitor.rs +++ b/examples/nrf52840/src/bin/i2s_monitor.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::{debug, error, info}; | 4 | use defmt::{debug, error, info}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; | 6 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth}; |
| 7 | use embassy_nrf::pwm::{Prescaler, SimplePwm}; | 7 | use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; |
| 8 | use embassy_nrf::{bind_interrupts, peripherals}; | 8 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { | |||
| 34 | I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); | 34 | I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); |
| 35 | 35 | ||
| 36 | // Configure the PWM to use the pins corresponding to the RGB leds | 36 | // Configure the PWM to use the pins corresponding to the RGB leds |
| 37 | let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); | 37 | let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24, &Default::default()); |
| 38 | pwm.set_prescaler(Prescaler::Div1); | 38 | pwm.set_prescaler(Prescaler::Div1); |
| 39 | pwm.set_max_duty(255); | 39 | pwm.set_max_duty(255); |
| 40 | 40 | ||
| @@ -47,9 +47,8 @@ async fn main(_spawner: Spawner) { | |||
| 47 | let rgb = rgb_from_rms(rms); | 47 | let rgb = rgb_from_rms(rms); |
| 48 | 48 | ||
| 49 | debug!("RMS: {}, RGB: {:?}", rms, rgb); | 49 | debug!("RMS: {}, RGB: {:?}", rms, rgb); |
| 50 | for i in 0..3 { | 50 | let duties = rgb.map(|byte| DutyCycle::normal(u16::from(byte))); |
| 51 | pwm.set_duty(i, rgb[i].into()); | 51 | pwm.set_all_duties([duties[0], duties[1], duties[2], DutyCycle::normal(0)]); |
| 52 | } | ||
| 53 | 52 | ||
| 54 | if let Err(err) = input_stream.receive().await { | 53 | if let Err(err) = input_stream.receive().await { |
| 55 | error!("{}", err); | 54 | error!("{}", err); |
diff --git a/examples/nrf52840/src/bin/i2s_waveform.rs b/examples/nrf52840/src/bin/i2s_waveform.rs index 137d82840..ce7a68d3a 100644 --- a/examples/nrf52840/src/bin/i2s_waveform.rs +++ b/examples/nrf52840/src/bin/i2s_waveform.rs | |||
| @@ -5,7 +5,7 @@ use core::f32::consts::PI; | |||
| 5 | 5 | ||
| 6 | use defmt::{error, info}; | 6 | use defmt::{error, info}; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; | 8 | use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth}; |
| 9 | use embassy_nrf::{bind_interrupts, peripherals}; | 9 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -140,11 +140,7 @@ impl SineOsc { | |||
| 140 | 140 | ||
| 141 | #[inline] | 141 | #[inline] |
| 142 | fn abs(value: f32) -> f32 { | 142 | fn abs(value: f32) -> f32 { |
| 143 | if value < 0.0 { | 143 | if value < 0.0 { -value } else { value } |
| 144 | -value | ||
| 145 | } else { | ||
| 146 | value | ||
| 147 | } | ||
| 148 | } | 144 | } |
| 149 | 145 | ||
| 150 | #[inline] | 146 | #[inline] |
diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs index 4d9b986d4..dc566adee 100644 --- a/examples/nrf52840/src/bin/multiprio.rs +++ b/examples/nrf52840/src/bin/multiprio.rs | |||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn EGU1_SWI1() { | 115 | unsafe fn EGU1_SWI1() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn EGU0_SWI0() { | 120 | unsafe fn EGU0_SWI0() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/nrf52840/src/bin/ppi.rs b/examples/nrf52840/src/bin/ppi.rs index 129ad06e7..177f6a06d 100644 --- a/examples/nrf52840/src/bin/ppi.rs +++ b/examples/nrf52840/src/bin/ppi.rs | |||
| @@ -5,7 +5,7 @@ use core::future::pending; | |||
| 5 | 5 | ||
| 6 | use defmt::info; | 6 | use defmt::info; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 8 | use embassy_nrf::gpio::{Level, OutputDrive, Pull}; |
| 9 | use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; | 9 | use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; |
| 10 | use embassy_nrf::ppi::Ppi; | 10 | use embassy_nrf::ppi::Ppi; |
| 11 | use gpiote::{OutputChannel, OutputChannelPolarity}; | 11 | use gpiote::{OutputChannel, OutputChannelPolarity}; |
| @@ -16,36 +16,24 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let p = embassy_nrf::init(Default::default()); | 16 | let p = embassy_nrf::init(Default::default()); |
| 17 | info!("Starting!"); | 17 | info!("Starting!"); |
| 18 | 18 | ||
| 19 | let button1 = InputChannel::new( | 19 | let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); |
| 20 | p.GPIOTE_CH0, | 20 | let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo); |
| 21 | Input::new(p.P0_11, Pull::Up), | 21 | let button3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::HiToLo); |
| 22 | InputChannelPolarity::HiToLo, | 22 | let button4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::HiToLo); |
| 23 | ); | ||
| 24 | let button2 = InputChannel::new( | ||
| 25 | p.GPIOTE_CH1, | ||
| 26 | Input::new(p.P0_12, Pull::Up), | ||
| 27 | InputChannelPolarity::HiToLo, | ||
| 28 | ); | ||
| 29 | let button3 = InputChannel::new( | ||
| 30 | p.GPIOTE_CH2, | ||
| 31 | Input::new(p.P0_24, Pull::Up), | ||
| 32 | InputChannelPolarity::HiToLo, | ||
| 33 | ); | ||
| 34 | let button4 = InputChannel::new( | ||
| 35 | p.GPIOTE_CH3, | ||
| 36 | Input::new(p.P0_25, Pull::Up), | ||
| 37 | InputChannelPolarity::HiToLo, | ||
| 38 | ); | ||
| 39 | 23 | ||
| 40 | let led1 = OutputChannel::new( | 24 | let led1 = OutputChannel::new( |
| 41 | p.GPIOTE_CH4, | 25 | p.GPIOTE_CH4, |
| 42 | Output::new(p.P0_13, Level::Low, OutputDrive::Standard), | 26 | p.P0_13, |
| 27 | Level::Low, | ||
| 28 | OutputDrive::Standard, | ||
| 43 | OutputChannelPolarity::Toggle, | 29 | OutputChannelPolarity::Toggle, |
| 44 | ); | 30 | ); |
| 45 | 31 | ||
| 46 | let led2 = OutputChannel::new( | 32 | let led2 = OutputChannel::new( |
| 47 | p.GPIOTE_CH5, | 33 | p.GPIOTE_CH5, |
| 48 | Output::new(p.P0_14, Level::Low, OutputDrive::Standard), | 34 | p.P0_14, |
| 35 | Level::Low, | ||
| 36 | OutputDrive::Standard, | ||
| 49 | OutputChannelPolarity::Toggle, | 37 | OutputChannelPolarity::Toggle, |
| 50 | ); | 38 | ); |
| 51 | 39 | ||
diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs index a5bb1347a..02f9b4191 100644 --- a/examples/nrf52840/src/bin/pwm.rs +++ b/examples/nrf52840/src/bin/pwm.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::pwm::{Prescaler, SimplePwm}; | 6 | use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -71,7 +71,7 @@ static DUTY: [u16; 1024] = [ | |||
| 71 | #[embassy_executor::main] | 71 | #[embassy_executor::main] |
| 72 | async fn main(_spawner: Spawner) { | 72 | async fn main(_spawner: Spawner) { |
| 73 | let p = embassy_nrf::init(Default::default()); | 73 | let p = embassy_nrf::init(Default::default()); |
| 74 | let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); | 74 | let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15, &Default::default()); |
| 75 | pwm.set_prescaler(Prescaler::Div1); | 75 | pwm.set_prescaler(Prescaler::Div1); |
| 76 | pwm.set_max_duty(32767); | 76 | pwm.set_max_duty(32767); |
| 77 | info!("pwm initialized!"); | 77 | info!("pwm initialized!"); |
| @@ -79,10 +79,12 @@ async fn main(_spawner: Spawner) { | |||
| 79 | let mut i = 0; | 79 | let mut i = 0; |
| 80 | loop { | 80 | loop { |
| 81 | i += 1; | 81 | i += 1; |
| 82 | pwm.set_duty(0, DUTY[i % 1024]); | 82 | pwm.set_all_duties([ |
| 83 | pwm.set_duty(1, DUTY[(i + 256) % 1024]); | 83 | DutyCycle::normal(DUTY[i % 1024]), |
| 84 | pwm.set_duty(2, DUTY[(i + 512) % 1024]); | 84 | DutyCycle::normal(DUTY[(i + 256) % 1024]), |
| 85 | pwm.set_duty(3, DUTY[(i + 768) % 1024]); | 85 | DutyCycle::normal(DUTY[(i + 512) % 1024]), |
| 86 | DutyCycle::normal(DUTY[(i + 768) % 1024]), | ||
| 87 | ]); | ||
| 86 | Timer::after_millis(3).await; | 88 | Timer::after_millis(3).await; |
| 87 | } | 89 | } |
| 88 | } | 90 | } |
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs index 60ea712b5..fff7decb2 100644 --- a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs +++ b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs | |||
| @@ -5,7 +5,7 @@ use core::future::pending; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_nrf::gpio::{Input, Pull}; | 8 | use embassy_nrf::gpio::Pull; |
| 9 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; | 9 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; |
| 10 | use embassy_nrf::ppi::Ppi; | 10 | use embassy_nrf::ppi::Ppi; |
| 11 | use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; | 11 | use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; |
| @@ -30,17 +30,9 @@ async fn main(_spawner: Spawner) { | |||
| 30 | // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work | 30 | // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work |
| 31 | // so its going to have to start running in order load the configuration | 31 | // so its going to have to start running in order load the configuration |
| 32 | 32 | ||
| 33 | let button1 = InputChannel::new( | 33 | let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo); |
| 34 | p.GPIOTE_CH0, | ||
| 35 | Input::new(p.P0_11, Pull::Up), | ||
| 36 | InputChannelPolarity::HiToLo, | ||
| 37 | ); | ||
| 38 | 34 | ||
| 39 | let button2 = InputChannel::new( | 35 | let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo); |
| 40 | p.GPIOTE_CH1, | ||
| 41 | Input::new(p.P0_12, Pull::Up), | ||
| 42 | InputChannelPolarity::HiToLo, | ||
| 43 | ); | ||
| 44 | 36 | ||
| 45 | // messing with the pwm tasks is ill advised | 37 | // messing with the pwm tasks is ill advised |
| 46 | // Times::Ininite and Times even are seq0, Times odd is seq1 | 38 | // Times::Ininite and Times even are seq0, Times odd is seq1 |
diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs index d772d2f5d..93cb984e6 100644 --- a/examples/nrf52840/src/bin/pwm_servo.rs +++ b/examples/nrf52840/src/bin/pwm_servo.rs | |||
| @@ -3,14 +3,14 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::pwm::{Prescaler, SimplePwm}; | 6 | use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| 10 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 11 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); | 13 | let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05, &Default::default()); |
| 14 | // sg90 microervo requires 50hz or 20ms period | 14 | // sg90 microervo requires 50hz or 20ms period |
| 15 | // set_period can only set down to 125khz so we cant use it directly | 15 | // set_period can only set down to 125khz so we cant use it directly |
| 16 | // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top | 16 | // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top |
| @@ -24,23 +24,23 @@ async fn main(_spawner: Spawner) { | |||
| 24 | loop { | 24 | loop { |
| 25 | info!("45 deg"); | 25 | info!("45 deg"); |
| 26 | // poor mans inverting, subtract our value from max_duty | 26 | // poor mans inverting, subtract our value from max_duty |
| 27 | pwm.set_duty(0, 2500 - 156); | 27 | pwm.set_duty(0, DutyCycle::normal(2500 - 156)); |
| 28 | Timer::after_millis(5000).await; | 28 | Timer::after_millis(5000).await; |
| 29 | 29 | ||
| 30 | info!("90 deg"); | 30 | info!("90 deg"); |
| 31 | pwm.set_duty(0, 2500 - 187); | 31 | pwm.set_duty(0, DutyCycle::normal(2500 - 187)); |
| 32 | Timer::after_millis(5000).await; | 32 | Timer::after_millis(5000).await; |
| 33 | 33 | ||
| 34 | info!("135 deg"); | 34 | info!("135 deg"); |
| 35 | pwm.set_duty(0, 2500 - 218); | 35 | pwm.set_duty(0, DutyCycle::normal(2500 - 218)); |
| 36 | Timer::after_millis(5000).await; | 36 | Timer::after_millis(5000).await; |
| 37 | 37 | ||
| 38 | info!("180 deg"); | 38 | info!("180 deg"); |
| 39 | pwm.set_duty(0, 2500 - 250); | 39 | pwm.set_duty(0, DutyCycle::normal(2500 - 250)); |
| 40 | Timer::after_millis(5000).await; | 40 | Timer::after_millis(5000).await; |
| 41 | 41 | ||
| 42 | info!("0 deg"); | 42 | info!("0 deg"); |
| 43 | pwm.set_duty(0, 2500 - 125); | 43 | pwm.set_duty(0, DutyCycle::normal(2500 - 125)); |
| 44 | Timer::after_millis(5000).await; | 44 | Timer::after_millis(5000).await; |
| 45 | } | 45 | } |
| 46 | } | 46 | } |
diff --git a/examples/nrf52840/src/bin/raw_spawn.rs b/examples/nrf52840/src/bin/raw_spawn.rs index b80954408..783be763d 100644 --- a/examples/nrf52840/src/bin/raw_spawn.rs +++ b/examples/nrf52840/src/bin/raw_spawn.rs | |||
| @@ -5,8 +5,8 @@ use core::mem; | |||
| 5 | 5 | ||
| 6 | use cortex_m_rt::entry; | 6 | use cortex_m_rt::entry; |
| 7 | use defmt::{info, unwrap}; | 7 | use defmt::{info, unwrap}; |
| 8 | use embassy_executor::raw::TaskStorage; | ||
| 9 | use embassy_executor::Executor; | 8 | use embassy_executor::Executor; |
| 9 | use embassy_executor::raw::TaskStorage; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use static_cell::StaticCell; | 11 | use static_cell::StaticCell; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -48,5 +48,5 @@ fn main() -> ! { | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | unsafe fn make_static<T>(t: &T) -> &'static T { | 50 | unsafe fn make_static<T>(t: &T) -> &'static T { |
| 51 | mem::transmute(t) | 51 | unsafe { mem::transmute(t) } |
| 52 | } | 52 | } |
diff --git a/examples/nrf52840/src/bin/rtc.rs b/examples/nrf52840/src/bin/rtc.rs index 9d475df7f..56a0c25f4 100644 --- a/examples/nrf52840/src/bin/rtc.rs +++ b/examples/nrf52840/src/bin/rtc.rs | |||
| @@ -7,8 +7,8 @@ use embassy_executor::Spawner; | |||
| 7 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 7 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 8 | use embassy_nrf::interrupt; | 8 | use embassy_nrf::interrupt; |
| 9 | use embassy_nrf::rtc::Rtc; | 9 | use embassy_nrf::rtc::Rtc; |
| 10 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 11 | use embassy_sync::blocking_mutex::Mutex; | 10 | use embassy_sync::blocking_mutex::Mutex; |
| 11 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 12 | use portable_atomic::AtomicU64; | 12 | use portable_atomic::AtomicU64; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index a75b967b4..14a1004d7 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::StackResources; | 6 | use embassy_net::StackResources; |
| 7 | use embassy_net::tcp::TcpSocket; | ||
| 8 | use embassy_nrf::rng::Rng; | 8 | use embassy_nrf::rng::Rng; |
| 9 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 10 | use embassy_nrf::usb::Driver; | 9 | use embassy_nrf::usb::Driver; |
| 10 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 11 | use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb}; | 11 | use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb}; |
| 12 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; | 12 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; |
| 13 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 13 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs index 5a9dc90a2..7b7303526 100644 --- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,19 +1,21 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 9 | use embassy_futures::select::{select, Either}; | 9 | use embassy_futures::select::{Either, select}; |
| 10 | use embassy_nrf::gpio::{Input, Pull}; | 10 | use embassy_nrf::gpio::{Input, Pull}; |
| 11 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 12 | use embassy_nrf::usb::Driver; | 11 | use embassy_nrf::usb::Driver; |
| 12 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 13 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 13 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 14 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 14 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 15 | use embassy_sync::signal::Signal; | 15 | use embassy_sync::signal::Signal; |
| 16 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 16 | use embassy_usb::class::hid::{ |
| 17 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 18 | }; | ||
| 17 | use embassy_usb::control::OutResponse; | 19 | use embassy_usb::control::OutResponse; |
| 18 | use embassy_usb::{Builder, Config, Handler}; | 20 | use embassy_usb::{Builder, Config, Handler}; |
| 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 21 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -26,6 +28,8 @@ bind_interrupts!(struct Irqs { | |||
| 26 | 28 | ||
| 27 | static SUSPENDED: AtomicBool = AtomicBool::new(false); | 29 | static SUSPENDED: AtomicBool = AtomicBool::new(false); |
| 28 | 30 | ||
| 31 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 32 | |||
| 29 | #[embassy_executor::main] | 33 | #[embassy_executor::main] |
| 30 | async fn main(_spawner: Spawner) { | 34 | async fn main(_spawner: Spawner) { |
| 31 | let p = embassy_nrf::init(Default::default()); | 35 | let p = embassy_nrf::init(Default::default()); |
| @@ -45,6 +49,10 @@ async fn main(_spawner: Spawner) { | |||
| 45 | config.max_power = 100; | 49 | config.max_power = 100; |
| 46 | config.max_packet_size_0 = 64; | 50 | config.max_packet_size_0 = 64; |
| 47 | config.supports_remote_wakeup = true; | 51 | config.supports_remote_wakeup = true; |
| 52 | config.composite_with_iads = false; | ||
| 53 | config.device_class = 0; | ||
| 54 | config.device_sub_class = 0; | ||
| 55 | config.device_protocol = 0; | ||
| 48 | 56 | ||
| 49 | // Create embassy-usb DeviceBuilder using the driver and config. | 57 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 50 | // It needs some buffers for building the descriptors. | 58 | // It needs some buffers for building the descriptors. |
| @@ -74,6 +82,8 @@ async fn main(_spawner: Spawner) { | |||
| 74 | request_handler: None, | 82 | request_handler: None, |
| 75 | poll_ms: 60, | 83 | poll_ms: 60, |
| 76 | max_packet_size: 64, | 84 | max_packet_size: 64, |
| 85 | hid_subclass: HidSubclass::Boot, | ||
| 86 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 77 | }; | 87 | }; |
| 78 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 88 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 79 | 89 | ||
| @@ -106,6 +116,11 @@ async fn main(_spawner: Spawner) { | |||
| 106 | if SUSPENDED.load(Ordering::Acquire) { | 116 | if SUSPENDED.load(Ordering::Acquire) { |
| 107 | info!("Triggering remote wakeup"); | 117 | info!("Triggering remote wakeup"); |
| 108 | remote_wakeup.signal(()); | 118 | remote_wakeup.signal(()); |
| 119 | } else if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { | ||
| 120 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { | ||
| 121 | Ok(()) => {} | ||
| 122 | Err(e) => warn!("Failed to send boot report: {:?}", e), | ||
| 123 | }; | ||
| 109 | } else { | 124 | } else { |
| 110 | let report = KeyboardReport { | 125 | let report = KeyboardReport { |
| 111 | keycodes: [4, 0, 0, 0, 0, 0], | 126 | keycodes: [4, 0, 0, 0, 0, 0], |
| @@ -121,16 +136,23 @@ async fn main(_spawner: Spawner) { | |||
| 121 | 136 | ||
| 122 | button.wait_for_high().await; | 137 | button.wait_for_high().await; |
| 123 | info!("RELEASED"); | 138 | info!("RELEASED"); |
| 124 | let report = KeyboardReport { | 139 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 125 | keycodes: [0, 0, 0, 0, 0, 0], | 140 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 126 | leds: 0, | 141 | Ok(()) => {} |
| 127 | modifier: 0, | 142 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 128 | reserved: 0, | 143 | }; |
| 129 | }; | 144 | } else { |
| 130 | match writer.write_serialize(&report).await { | 145 | let report = KeyboardReport { |
| 131 | Ok(()) => {} | 146 | keycodes: [0, 0, 0, 0, 0, 0], |
| 132 | Err(e) => warn!("Failed to send report: {:?}", e), | 147 | leds: 0, |
| 133 | }; | 148 | modifier: 0, |
| 149 | reserved: 0, | ||
| 150 | }; | ||
| 151 | match writer.write_serialize(&report).await { | ||
| 152 | Ok(()) => {} | ||
| 153 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 154 | }; | ||
| 155 | } | ||
| 134 | } | 156 | } |
| 135 | }; | 157 | }; |
| 136 | 158 | ||
| @@ -156,6 +178,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 156 | OutResponse::Accepted | 178 | OutResponse::Accepted |
| 157 | } | 179 | } |
| 158 | 180 | ||
| 181 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 182 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 183 | info!("The current HID protocol mode is: {}", protocol); | ||
| 184 | protocol | ||
| 185 | } | ||
| 186 | |||
| 187 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 188 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 189 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 190 | OutResponse::Accepted | ||
| 191 | } | ||
| 192 | |||
| 159 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 193 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 160 | info!("Set idle rate for {:?} to {:?}", id, dur); | 194 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 161 | } | 195 | } |
| @@ -210,7 +244,9 @@ impl Handler for MyDeviceHandler { | |||
| 210 | 244 | ||
| 211 | fn suspended(&mut self, suspended: bool) { | 245 | fn suspended(&mut self, suspended: bool) { |
| 212 | if suspended { | 246 | if suspended { |
| 213 | info!("Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled)."); | 247 | info!( |
| 248 | "Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled)." | ||
| 249 | ); | ||
| 214 | SUSPENDED.store(true, Ordering::Release); | 250 | SUSPENDED.store(true, Ordering::Release); |
| 215 | } else { | 251 | } else { |
| 216 | SUSPENDED.store(false, Ordering::Release); | 252 | SUSPENDED.store(false, Ordering::Release); |
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs index 80cda70e3..6bee4546b 100644 --- a/examples/nrf52840/src/bin/usb_hid_mouse.rs +++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs | |||
| @@ -1,14 +1,18 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 7 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 8 | use embassy_nrf::usb::Driver; | 9 | use embassy_nrf::usb::Driver; |
| 10 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 9 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 11 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 10 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 11 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 12 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 13 | use embassy_usb::{Builder, Config}; | 17 | use embassy_usb::{Builder, Config}; |
| 14 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| @@ -19,6 +23,8 @@ bind_interrupts!(struct Irqs { | |||
| 19 | CLOCK_POWER => usb::vbus_detect::InterruptHandler; | 23 | CLOCK_POWER => usb::vbus_detect::InterruptHandler; |
| 20 | }); | 24 | }); |
| 21 | 25 | ||
| 26 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 27 | |||
| 22 | #[embassy_executor::main] | 28 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 29 | async fn main(_spawner: Spawner) { |
| 24 | let p = embassy_nrf::init(Default::default()); | 30 | let p = embassy_nrf::init(Default::default()); |
| @@ -37,6 +43,10 @@ async fn main(_spawner: Spawner) { | |||
| 37 | config.serial_number = Some("12345678"); | 43 | config.serial_number = Some("12345678"); |
| 38 | config.max_power = 100; | 44 | config.max_power = 100; |
| 39 | config.max_packet_size_0 = 64; | 45 | config.max_packet_size_0 = 64; |
| 46 | config.composite_with_iads = false; | ||
| 47 | config.device_class = 0; | ||
| 48 | config.device_sub_class = 0; | ||
| 49 | config.device_protocol = 0; | ||
| 40 | 50 | ||
| 41 | // Create embassy-usb DeviceBuilder using the driver and config. | 51 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 42 | // It needs some buffers for building the descriptors. | 52 | // It needs some buffers for building the descriptors. |
| @@ -63,6 +73,8 @@ async fn main(_spawner: Spawner) { | |||
| 63 | request_handler: Some(&mut request_handler), | 73 | request_handler: Some(&mut request_handler), |
| 64 | poll_ms: 60, | 74 | poll_ms: 60, |
| 65 | max_packet_size: 8, | 75 | max_packet_size: 8, |
| 76 | hid_subclass: HidSubclass::Boot, | ||
| 77 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 66 | }; | 78 | }; |
| 67 | 79 | ||
| 68 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); | 80 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| @@ -80,16 +92,26 @@ async fn main(_spawner: Spawner) { | |||
| 80 | Timer::after_millis(500).await; | 92 | Timer::after_millis(500).await; |
| 81 | 93 | ||
| 82 | y = -y; | 94 | y = -y; |
| 83 | let report = MouseReport { | 95 | |
| 84 | buttons: 0, | 96 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 85 | x: 0, | 97 | let buttons = 0u8; |
| 86 | y, | 98 | let x = 0i8; |
| 87 | wheel: 0, | 99 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 88 | pan: 0, | 100 | Ok(()) => {} |
| 89 | }; | 101 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 90 | match writer.write_serialize(&report).await { | 102 | } |
| 91 | Ok(()) => {} | 103 | } else { |
| 92 | Err(e) => warn!("Failed to send report: {:?}", e), | 104 | let report = MouseReport { |
| 105 | buttons: 0, | ||
| 106 | x: 0, | ||
| 107 | y, | ||
| 108 | wheel: 0, | ||
| 109 | pan: 0, | ||
| 110 | }; | ||
| 111 | match writer.write_serialize(&report).await { | ||
| 112 | Ok(()) => {} | ||
| 113 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 114 | } | ||
| 93 | } | 115 | } |
| 94 | } | 116 | } |
| 95 | }; | 117 | }; |
| @@ -112,6 +134,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 112 | OutResponse::Accepted | 134 | OutResponse::Accepted |
| 113 | } | 135 | } |
| 114 | 136 | ||
| 137 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 138 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 139 | info!("The current HID protocol mode is: {}", protocol); | ||
| 140 | protocol | ||
| 141 | } | ||
| 142 | |||
| 143 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 144 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 145 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 146 | OutResponse::Accepted | ||
| 147 | } | ||
| 148 | |||
| 115 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 149 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 116 | info!("Set idle rate for {:?} to {:?}", id, dur); | 150 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 117 | } | 151 | } |
diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs index e7c2d0854..469002bc7 100644 --- a/examples/nrf52840/src/bin/usb_serial.rs +++ b/examples/nrf52840/src/bin/usb_serial.rs | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | use defmt::{info, panic}; | 4 | use defmt::{info, panic}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect}; | ||
| 8 | use embassy_nrf::usb::Driver; | 7 | use embassy_nrf::usb::Driver; |
| 8 | use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect}; | ||
| 9 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 9 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs index b6a983854..67b2bccbb 100644 --- a/examples/nrf52840/src/bin/usb_serial_multitask.rs +++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::{info, panic, unwrap}; | 4 | use defmt::{info, panic, unwrap}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 7 | use embassy_nrf::usb::Driver; | 6 | use embassy_nrf::usb::Driver; |
| 7 | use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; | ||
| 8 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 8 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 10 | use embassy_usb::driver::EndpointError; |
diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs index e30e08a01..cd4d5bca1 100644 --- a/examples/nrf52840/src/bin/usb_serial_winusb.rs +++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | use defmt::{info, panic}; | 4 | use defmt::{info, panic}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect}; | ||
| 8 | use embassy_nrf::usb::Driver; | 7 | use embassy_nrf::usb::Driver; |
| 8 | use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect}; | ||
| 9 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; | 9 | use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index 1bc35746a..2f9c06b56 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::{info, unwrap, warn}; | 4 | use defmt::{info, unwrap, warn}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::StackResources; | 6 | use embassy_net::StackResources; |
| 7 | use embassy_net::tcp::TcpSocket; | ||
| 8 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 8 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; |
| 9 | use embassy_nrf::rng::Rng; | 9 | use embassy_nrf::rng::Rng; |
| 10 | use embassy_nrf::spim::{self, Spim}; | 10 | use embassy_nrf::spim::{self, Spim}; |
| @@ -27,14 +27,12 @@ bind_interrupts!(struct Irqs { | |||
| 27 | async fn wifi_task( | 27 | async fn wifi_task( |
| 28 | runner: hosted::Runner< | 28 | runner: hosted::Runner< |
| 29 | 'static, | 29 | 'static, |
| 30 | ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, | 30 | hosted::SpiInterface<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Input<'static>>, |
| 31 | Input<'static>, | ||
| 32 | Output<'static>, | 31 | Output<'static>, |
| 33 | >, | 32 | >, |
| 34 | ) -> ! { | 33 | ) -> ! { |
| 35 | runner.run().await | 34 | runner.run().await |
| 36 | } | 35 | } |
| 37 | |||
| 38 | #[embassy_executor::task] | 36 | #[embassy_executor::task] |
| 39 | async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { | 37 | async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { |
| 40 | runner.run().await | 38 | runner.run().await |
| @@ -60,15 +58,11 @@ async fn main(spawner: Spawner) { | |||
| 60 | let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); | 58 | let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); |
| 61 | let spi = ExclusiveDevice::new(spi, cs, Delay); | 59 | let spi = ExclusiveDevice::new(spi, cs, Delay); |
| 62 | 60 | ||
| 61 | let iface = hosted::SpiInterface::new(spi, handshake, ready); | ||
| 62 | |||
| 63 | static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new(); | 63 | static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new(); |
| 64 | let (device, mut control, runner) = embassy_net_esp_hosted::new( | 64 | let (device, mut control, runner) = |
| 65 | ESP_STATE.init(embassy_net_esp_hosted::State::new()), | 65 | embassy_net_esp_hosted::new(ESP_STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await; |
| 66 | spi, | ||
| 67 | handshake, | ||
| 68 | ready, | ||
| 69 | reset, | ||
| 70 | ) | ||
| 71 | .await; | ||
| 72 | 66 | ||
| 73 | spawner.spawn(unwrap!(wifi_task(runner))); | 67 | spawner.spawn(unwrap!(wifi_task(runner))); |
| 74 | 68 | ||
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 256fee08d..b8d5dbfb1 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf5340-examples" | 3 | name = "embassy-nrf5340-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -10,7 +10,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | |||
| 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 13 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embedded-io-async = { version = "0.6.1" } | 16 | embedded-io-async = { version = "0.6.1" } |
| @@ -23,7 +23,7 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing | |||
| 23 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| 24 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | 24 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 25 | embedded-storage = "0.3.1" | 25 | embedded-storage = "0.3.1" |
| 26 | usbd-hid = "0.8.1" | 26 | usbd-hid = "0.9.0" |
| 27 | serde = { version = "1.0.136", default-features = false } | 27 | serde = { version = "1.0.136", default-features = false } |
| 28 | 28 | ||
| 29 | [profile.release] | 29 | [profile.release] |
diff --git a/examples/nrf5340/src/bin/gpiote_channel.rs b/examples/nrf5340/src/bin/gpiote_channel.rs index 23f6fca98..41ee732c3 100644 --- a/examples/nrf5340/src/bin/gpiote_channel.rs +++ b/examples/nrf5340/src/bin/gpiote_channel.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_nrf::gpio::{Input, Pull}; | 6 | use embassy_nrf::gpio::Pull; |
| 7 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; | 7 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) { | |||
| 12 | let p = embassy_nrf::init(Default::default()); | 12 | let p = embassy_nrf::init(Default::default()); |
| 13 | info!("Starting!"); | 13 | info!("Starting!"); |
| 14 | 14 | ||
| 15 | let ch1 = InputChannel::new( | 15 | let mut ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo); |
| 16 | p.GPIOTE_CH0, | 16 | let mut ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi); |
| 17 | Input::new(p.P0_23, Pull::Up), | 17 | let mut ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle); |
| 18 | InputChannelPolarity::HiToLo, | 18 | let mut ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle); |
| 19 | ); | ||
| 20 | let ch2 = InputChannel::new( | ||
| 21 | p.GPIOTE_CH1, | ||
| 22 | Input::new(p.P0_24, Pull::Up), | ||
| 23 | InputChannelPolarity::LoToHi, | ||
| 24 | ); | ||
| 25 | let ch3 = InputChannel::new( | ||
| 26 | p.GPIOTE_CH2, | ||
| 27 | Input::new(p.P0_08, Pull::Up), | ||
| 28 | InputChannelPolarity::Toggle, | ||
| 29 | ); | ||
| 30 | let ch4 = InputChannel::new( | ||
| 31 | p.GPIOTE_CH3, | ||
| 32 | Input::new(p.P0_09, Pull::Up), | ||
| 33 | InputChannelPolarity::Toggle, | ||
| 34 | ); | ||
| 35 | 19 | ||
| 36 | let button1 = async { | 20 | let button1 = async { |
| 37 | loop { | 21 | loop { |
diff --git a/examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs b/examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs new file mode 100644 index 000000000..0b1fb852e --- /dev/null +++ b/examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::config::{Config, HfclkSource, LfclkSource, LfxoCapacitance}; | ||
| 7 | use embassy_nrf::pac; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | fn print_xosc32mcaps() { | ||
| 11 | let value = pac::OSCILLATORS.xosc32mcaps().read(); | ||
| 12 | info!("XOSC32MCAPS.ENABLE = {}", value.enable()); | ||
| 13 | info!("XOSC32MCAPS.CAPVALUE = {}", value.capvalue()); | ||
| 14 | } | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | info!("Before init:"); | ||
| 19 | print_xosc32mcaps(); | ||
| 20 | |||
| 21 | let mut config = Config::default(); | ||
| 22 | config.hfclk_source = HfclkSource::Internal; | ||
| 23 | config.lfclk_source = LfclkSource::ExternalXtal; | ||
| 24 | config.internal_capacitors.hfxo = None; // keep the value from the FICR | ||
| 25 | config.internal_capacitors.lfxo = Some(LfxoCapacitance::_7pF); | ||
| 26 | let _p = embassy_nrf::init(config); | ||
| 27 | |||
| 28 | info!("After init:"); | ||
| 29 | print_xosc32mcaps(); | ||
| 30 | } | ||
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 9c24cdab4..353d1b46e 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml | |||
| @@ -1,14 +1,20 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf54l15-examples" | 3 | name = "embassy-nrf54l15-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 11 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 13 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] } | ||
| 14 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } | ||
| 15 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | ||
| 16 | |||
| 17 | rand = { version = "0.9.0", default-features = false } | ||
| 12 | 18 | ||
| 13 | defmt = "1.0.1" | 19 | defmt = "1.0.1" |
| 14 | defmt-rtt = "1.0.0" | 20 | defmt-rtt = "1.0.0" |
| @@ -18,6 +24,9 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing | |||
| 18 | cortex-m-rt = "0.7.0" | 24 | cortex-m-rt = "0.7.0" |
| 19 | 25 | ||
| 20 | embedded-storage = "0.3.1" | 26 | embedded-storage = "0.3.1" |
| 27 | portable-atomic = "1" | ||
| 28 | |||
| 29 | static_cell = "2" | ||
| 21 | 30 | ||
| 22 | [profile.release] | 31 | [profile.release] |
| 23 | debug = 2 | 32 | debug = 2 |
diff --git a/examples/nrf54l15/memory.x b/examples/nrf54l15/memory.x index 1064c8a5c..332200828 100644 --- a/examples/nrf54l15/memory.x +++ b/examples/nrf54l15/memory.x | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | MEMORY | 1 | MEMORY |
| 2 | { | 2 | { |
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1536K | 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 1524K |
| 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K | 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K |
| 5 | } | 5 | } |
diff --git a/examples/nrf54l15/src/bin/buffered_uart.rs b/examples/nrf54l15/src/bin/buffered_uart.rs new file mode 100644 index 000000000..41fa1ca4e --- /dev/null +++ b/examples/nrf54l15/src/bin/buffered_uart.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::buffered_uarte::{self, BufferedUarte}; | ||
| 7 | use embassy_nrf::{bind_interrupts, peripherals, uarte}; | ||
| 8 | use embedded_io_async::Write; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | SERIAL20 => buffered_uarte::InterruptHandler<peripherals::SERIAL20>; | ||
| 13 | }); | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) { | ||
| 17 | let p = embassy_nrf::init(Default::default()); | ||
| 18 | let mut config = uarte::Config::default(); | ||
| 19 | config.parity = uarte::Parity::EXCLUDED; | ||
| 20 | config.baudrate = uarte::Baudrate::BAUD115200; | ||
| 21 | |||
| 22 | let mut tx_buffer = [0u8; 4096]; | ||
| 23 | let mut rx_buffer = [0u8; 4096]; | ||
| 24 | |||
| 25 | let mut u = BufferedUarte::new( | ||
| 26 | p.SERIAL20, | ||
| 27 | p.P1_12, | ||
| 28 | p.P1_13, | ||
| 29 | Irqs, | ||
| 30 | config, | ||
| 31 | &mut rx_buffer, | ||
| 32 | &mut tx_buffer, | ||
| 33 | ); | ||
| 34 | |||
| 35 | info!("uarte initialized!"); | ||
| 36 | |||
| 37 | unwrap!(u.write_all(b"Hello!\r\n").await); | ||
| 38 | info!("wrote hello in uart!"); | ||
| 39 | |||
| 40 | loop { | ||
| 41 | info!("reading..."); | ||
| 42 | let buf = unwrap!(u.fill_buf().await); | ||
| 43 | info!("read done, got {}", buf); | ||
| 44 | |||
| 45 | // Read bytes have to be explicitly consumed, otherwise fill_buf() will return them again | ||
| 46 | let n = buf.len(); | ||
| 47 | u.consume(n); | ||
| 48 | } | ||
| 49 | } | ||
diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs new file mode 100644 index 000000000..cac8823f8 --- /dev/null +++ b/examples/nrf54l15/src/bin/gpiote_channel.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::gpio::Pull; | ||
| 7 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | info!("Starting!"); | ||
| 14 | |||
| 15 | let mut ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo); | ||
| 16 | let mut ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); | ||
| 17 | let mut ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); | ||
| 18 | let mut ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_04, Pull::Up, InputChannelPolarity::Toggle); | ||
| 19 | |||
| 20 | let button1 = async { | ||
| 21 | loop { | ||
| 22 | ch1.wait().await; | ||
| 23 | info!("Button 1 pressed") | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | let button2 = async { | ||
| 28 | loop { | ||
| 29 | ch2.wait().await; | ||
| 30 | info!("Button 2 released") | ||
| 31 | } | ||
| 32 | }; | ||
| 33 | |||
| 34 | let button3 = async { | ||
| 35 | loop { | ||
| 36 | ch3.wait().await; | ||
| 37 | info!("Button 3 toggled") | ||
| 38 | } | ||
| 39 | }; | ||
| 40 | |||
| 41 | let button4 = async { | ||
| 42 | loop { | ||
| 43 | ch4.wait().await; | ||
| 44 | info!("Button 4 toggled") | ||
| 45 | } | ||
| 46 | }; | ||
| 47 | |||
| 48 | embassy_futures::join::join4(button1, button2, button3, button4).await; | ||
| 49 | } | ||
diff --git a/examples/nrf54l15/src/bin/gpiote_port.rs b/examples/nrf54l15/src/bin/gpiote_port.rs new file mode 100644 index 000000000..620cb2435 --- /dev/null +++ b/examples/nrf54l15/src/bin/gpiote_port.rs | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::gpio::{Input, Pull}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::task(pool_size = 4)] | ||
| 10 | async fn button_task(n: usize, mut pin: Input<'static>) { | ||
| 11 | loop { | ||
| 12 | pin.wait_for_low().await; | ||
| 13 | info!("Button {:?} pressed!", n); | ||
| 14 | pin.wait_for_high().await; | ||
| 15 | info!("Button {:?} released!", n); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(spawner: Spawner) { | ||
| 21 | let p = embassy_nrf::init(Default::default()); | ||
| 22 | info!("Starting!"); | ||
| 23 | |||
| 24 | let btn1 = Input::new(p.P1_13, Pull::Up); | ||
| 25 | let btn2 = Input::new(p.P1_09, Pull::Up); | ||
| 26 | let btn3 = Input::new(p.P1_08, Pull::Up); | ||
| 27 | let btn4 = Input::new(p.P0_04, Pull::Up); | ||
| 28 | |||
| 29 | spawner.spawn(unwrap!(button_task(1, btn1))); | ||
| 30 | spawner.spawn(unwrap!(button_task(2, btn2))); | ||
| 31 | spawner.spawn(unwrap!(button_task(3, btn3))); | ||
| 32 | spawner.spawn(unwrap!(button_task(4, btn4))); | ||
| 33 | } | ||
diff --git a/examples/nrf54l15/src/bin/pwm.rs b/examples/nrf54l15/src/bin/pwm.rs new file mode 100644 index 000000000..b438978f1 --- /dev/null +++ b/examples/nrf54l15/src/bin/pwm.rs | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | // for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='') | ||
| 11 | static DUTY: [u16; 1024] = [ | ||
| 12 | 8191, 8272, 8353, 8434, 8516, 8598, 8681, 8764, 8847, 8931, 9015, 9099, 9184, 9269, 9354, 9440, 9526, 9613, 9700, | ||
| 13 | 9787, 9874, 9962, 10050, 10139, 10227, 10316, 10406, 10495, 10585, 10675, 10766, 10857, 10948, 11039, 11131, 11223, | ||
| 14 | 11315, 11407, 11500, 11592, 11685, 11779, 11872, 11966, 12060, 12154, 12248, 12343, 12438, 12533, 12628, 12723, | ||
| 15 | 12818, 12914, 13010, 13106, 13202, 13298, 13394, 13491, 13587, 13684, 13781, 13878, 13975, 14072, 14169, 14266, | ||
| 16 | 14364, 14461, 14558, 14656, 14754, 14851, 14949, 15046, 15144, 15242, 15339, 15437, 15535, 15632, 15730, 15828, | ||
| 17 | 15925, 16023, 16120, 16218, 16315, 16412, 16510, 16607, 16704, 16801, 16898, 16995, 17091, 17188, 17284, 17380, | ||
| 18 | 17477, 17572, 17668, 17764, 17859, 17955, 18050, 18145, 18239, 18334, 18428, 18522, 18616, 18710, 18803, 18896, | ||
| 19 | 18989, 19082, 19174, 19266, 19358, 19449, 19540, 19631, 19722, 19812, 19902, 19991, 20081, 20169, 20258, 20346, | ||
| 20 | 20434, 20521, 20608, 20695, 20781, 20867, 20952, 21037, 21122, 21206, 21290, 21373, 21456, 21538, 21620, 21701, | ||
| 21 | 21782, 21863, 21943, 22022, 22101, 22179, 22257, 22335, 22412, 22488, 22564, 22639, 22714, 22788, 22861, 22934, | ||
| 22 | 23007, 23079, 23150, 23220, 23290, 23360, 23429, 23497, 23564, 23631, 23698, 23763, 23828, 23892, 23956, 24019, | ||
| 23 | 24081, 24143, 24204, 24264, 24324, 24383, 24441, 24499, 24555, 24611, 24667, 24721, 24775, 24828, 24881, 24933, | ||
| 24 | 24983, 25034, 25083, 25132, 25180, 25227, 25273, 25319, 25363, 25407, 25451, 25493, 25535, 25575, 25615, 25655, | ||
| 25 | 25693, 25731, 25767, 25803, 25838, 25873, 25906, 25939, 25971, 26002, 26032, 26061, 26089, 26117, 26144, 26170, | ||
| 26 | 26195, 26219, 26242, 26264, 26286, 26307, 26327, 26346, 26364, 26381, 26397, 26413, 26427, 26441, 26454, 26466, | ||
| 27 | 26477, 26487, 26496, 26505, 26512, 26519, 26525, 26530, 26534, 26537, 26539, 26540, 26541, 26540, 26539, 26537, | ||
| 28 | 26534, 26530, 26525, 26519, 26512, 26505, 26496, 26487, 26477, 26466, 26454, 26441, 26427, 26413, 26397, 26381, | ||
| 29 | 26364, 26346, 26327, 26307, 26286, 26264, 26242, 26219, 26195, 26170, 26144, 26117, 26089, 26061, 26032, 26002, | ||
| 30 | 25971, 25939, 25906, 25873, 25838, 25803, 25767, 25731, 25693, 25655, 25615, 25575, 25535, 25493, 25451, 25407, | ||
| 31 | 25363, 25319, 25273, 25227, 25180, 25132, 25083, 25034, 24983, 24933, 24881, 24828, 24775, 24721, 24667, 24611, | ||
| 32 | 24555, 24499, 24441, 24383, 24324, 24264, 24204, 24143, 24081, 24019, 23956, 23892, 23828, 23763, 23698, 23631, | ||
| 33 | 23564, 23497, 23429, 23360, 23290, 23220, 23150, 23079, 23007, 22934, 22861, 22788, 22714, 22639, 22564, 22488, | ||
| 34 | 22412, 22335, 22257, 22179, 22101, 22022, 21943, 21863, 21782, 21701, 21620, 21538, 21456, 21373, 21290, 21206, | ||
| 35 | 21122, 21037, 20952, 20867, 20781, 20695, 20608, 20521, 20434, 20346, 20258, 20169, 20081, 19991, 19902, 19812, | ||
| 36 | 19722, 19631, 19540, 19449, 19358, 19266, 19174, 19082, 18989, 18896, 18803, 18710, 18616, 18522, 18428, 18334, | ||
| 37 | 18239, 18145, 18050, 17955, 17859, 17764, 17668, 17572, 17477, 17380, 17284, 17188, 17091, 16995, 16898, 16801, | ||
| 38 | 16704, 16607, 16510, 16412, 16315, 16218, 16120, 16023, 15925, 15828, 15730, 15632, 15535, 15437, 15339, 15242, | ||
| 39 | 15144, 15046, 14949, 14851, 14754, 14656, 14558, 14461, 14364, 14266, 14169, 14072, 13975, 13878, 13781, 13684, | ||
| 40 | 13587, 13491, 13394, 13298, 13202, 13106, 13010, 12914, 12818, 12723, 12628, 12533, 12438, 12343, 12248, 12154, | ||
| 41 | 12060, 11966, 11872, 11779, 11685, 11592, 11500, 11407, 11315, 11223, 11131, 11039, 10948, 10857, 10766, 10675, | ||
| 42 | 10585, 10495, 10406, 10316, 10227, 10139, 10050, 9962, 9874, 9787, 9700, 9613, 9526, 9440, 9354, 9269, 9184, 9099, | ||
| 43 | 9015, 8931, 8847, 8764, 8681, 8598, 8516, 8434, 8353, 8272, 8191, 8111, 8031, 7952, 7873, 7794, 7716, 7638, 7561, | ||
| 44 | 7484, 7407, 7331, 7255, 7180, 7105, 7031, 6957, 6883, 6810, 6738, 6665, 6594, 6522, 6451, 6381, 6311, 6241, 6172, | ||
| 45 | 6104, 6036, 5968, 5901, 5834, 5767, 5702, 5636, 5571, 5507, 5443, 5379, 5316, 5253, 5191, 5130, 5068, 5008, 4947, | ||
| 46 | 4888, 4828, 4769, 4711, 4653, 4596, 4539, 4482, 4426, 4371, 4316, 4261, 4207, 4153, 4100, 4047, 3995, 3943, 3892, | ||
| 47 | 3841, 3791, 3741, 3691, 3642, 3594, 3546, 3498, 3451, 3404, 3358, 3312, 3267, 3222, 3178, 3134, 3090, 3047, 3005, | ||
| 48 | 2962, 2921, 2879, 2839, 2798, 2758, 2719, 2680, 2641, 2603, 2565, 2528, 2491, 2454, 2418, 2382, 2347, 2312, 2278, | ||
| 49 | 2244, 2210, 2177, 2144, 2112, 2080, 2048, 2017, 1986, 1956, 1926, 1896, 1867, 1838, 1810, 1781, 1754, 1726, 1699, | ||
| 50 | 1673, 1646, 1620, 1595, 1570, 1545, 1520, 1496, 1472, 1449, 1426, 1403, 1380, 1358, 1336, 1315, 1294, 1273, 1252, | ||
| 51 | 1232, 1212, 1192, 1173, 1154, 1135, 1117, 1099, 1081, 1063, 1046, 1029, 1012, 996, 980, 964, 948, 933, 918, 903, | ||
| 52 | 888, 874, 860, 846, 833, 819, 806, 793, 781, 768, 756, 744, 733, 721, 710, 699, 688, 677, 667, 657, 647, 637, 627, | ||
| 53 | 618, 609, 599, 591, 582, 574, 565, 557, 549, 541, 534, 526, 519, 512, 505, 498, 492, 485, 479, 473, 467, 461, 455, | ||
| 54 | 450, 444, 439, 434, 429, 424, 419, 415, 410, 406, 402, 398, 394, 390, 386, 383, 379, 376, 373, 370, 367, 364, 361, | ||
| 55 | 359, 356, 354, 351, 349, 347, 345, 343, 342, 340, 338, 337, 336, 334, 333, 332, 331, 330, 330, 329, 328, 328, 328, | ||
| 56 | 327, 327, 327, 327, 327, 328, 328, 328, 329, 330, 330, 331, 332, 333, 334, 336, 337, 338, 340, 342, 343, 345, 347, | ||
| 57 | 349, 351, 354, 356, 359, 361, 364, 367, 370, 373, 376, 379, 383, 386, 390, 394, 398, 402, 406, 410, 415, 419, 424, | ||
| 58 | 429, 434, 439, 444, 450, 455, 461, 467, 473, 479, 485, 492, 498, 505, 512, 519, 526, 534, 541, 549, 557, 565, 574, | ||
| 59 | 582, 591, 599, 609, 618, 627, 637, 647, 657, 667, 677, 688, 699, 710, 721, 733, 744, 756, 768, 781, 793, 806, 819, | ||
| 60 | 833, 846, 860, 874, 888, 903, 918, 933, 948, 964, 980, 996, 1012, 1029, 1046, 1063, 1081, 1099, 1117, 1135, 1154, | ||
| 61 | 1173, 1192, 1212, 1232, 1252, 1273, 1294, 1315, 1336, 1358, 1380, 1403, 1426, 1449, 1472, 1496, 1520, 1545, 1570, | ||
| 62 | 1595, 1620, 1646, 1673, 1699, 1726, 1754, 1781, 1810, 1838, 1867, 1896, 1926, 1956, 1986, 2017, 2048, 2080, 2112, | ||
| 63 | 2144, 2177, 2210, 2244, 2278, 2312, 2347, 2382, 2418, 2454, 2491, 2528, 2565, 2603, 2641, 2680, 2719, 2758, 2798, | ||
| 64 | 2839, 2879, 2921, 2962, 3005, 3047, 3090, 3134, 3178, 3222, 3267, 3312, 3358, 3404, 3451, 3498, 3546, 3594, 3642, | ||
| 65 | 3691, 3741, 3791, 3841, 3892, 3943, 3995, 4047, 4100, 4153, 4207, 4261, 4316, 4371, 4426, 4482, 4539, 4596, 4653, | ||
| 66 | 4711, 4769, 4828, 4888, 4947, 5008, 5068, 5130, 5191, 5253, 5316, 5379, 5443, 5507, 5571, 5636, 5702, 5767, 5834, | ||
| 67 | 5901, 5968, 6036, 6104, 6172, 6241, 6311, 6381, 6451, 6522, 6594, 6665, 6738, 6810, 6883, 6957, 7031, 7105, 7180, | ||
| 68 | 7255, 7331, 7407, 7484, 7561, 7638, 7716, 7794, 7873, 7952, 8031, 8111, | ||
| 69 | ]; | ||
| 70 | |||
| 71 | #[embassy_executor::main] | ||
| 72 | async fn main(_spawner: Spawner) { | ||
| 73 | let p = embassy_nrf::init(Default::default()); | ||
| 74 | let mut pwm = SimplePwm::new_2ch(p.PWM20, p.P1_10, p.P1_14, &Default::default()); | ||
| 75 | pwm.set_prescaler(Prescaler::Div1); | ||
| 76 | pwm.set_max_duty(32767); | ||
| 77 | info!("pwm initialized!"); | ||
| 78 | |||
| 79 | let mut i = 0; | ||
| 80 | loop { | ||
| 81 | i += 1; | ||
| 82 | pwm.set_duty(0, DutyCycle::normal(DUTY[i % 1024])); | ||
| 83 | pwm.set_duty(1, DutyCycle::normal(DUTY[(i + 512) % 1024])); | ||
| 84 | Timer::after_millis(3).await; | ||
| 85 | } | ||
| 86 | } | ||
diff --git a/examples/nrf54l15/src/bin/rng.rs b/examples/nrf54l15/src/bin/rng.rs new file mode 100644 index 000000000..b2d7f906b --- /dev/null +++ b/examples/nrf54l15/src/bin/rng.rs | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_nrf::cracen::Cracen; | ||
| 6 | use rand::Rng as _; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_nrf::init(Default::default()); | ||
| 12 | let mut rng = Cracen::new_blocking(p.CRACEN); | ||
| 13 | |||
| 14 | // Async API | ||
| 15 | let mut bytes = [0; 4]; | ||
| 16 | rng.blocking_fill_bytes(&mut bytes); | ||
| 17 | defmt::info!("Some random bytes: {:?}", bytes); | ||
| 18 | |||
| 19 | // Sync API with `rand` | ||
| 20 | defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10)); | ||
| 21 | |||
| 22 | let mut bytes = [0; 1024]; | ||
| 23 | rng.blocking_fill_bytes(&mut bytes); | ||
| 24 | let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros()); | ||
| 25 | let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones()); | ||
| 26 | defmt::info!("Chance of zero: {}%", zero_count * 100 / (bytes.len() as u32 * 8)); | ||
| 27 | defmt::info!("Chance of one: {}%", one_count * 100 / (bytes.len() as u32 * 8)); | ||
| 28 | } | ||
diff --git a/examples/nrf54l15/src/bin/nvmc.rs b/examples/nrf54l15/src/bin/rramc.rs index f990604cd..f990604cd 100644 --- a/examples/nrf54l15/src/bin/nvmc.rs +++ b/examples/nrf54l15/src/bin/rramc.rs | |||
diff --git a/examples/nrf54l15/src/bin/rramc_buffered.rs b/examples/nrf54l15/src/bin/rramc_buffered.rs new file mode 100644 index 000000000..06c9585ed --- /dev/null +++ b/examples/nrf54l15/src/bin/rramc_buffered.rs | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::rramc::{Buffered, PAGE_SIZE, Rramc}; | ||
| 7 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | info!("Hello RRAMC NVMC!"); | ||
| 14 | |||
| 15 | // Buffer 8 word lines | ||
| 16 | let mut f: Rramc<'_, Buffered<128>> = Rramc::new_buffered(p.RRAMC); | ||
| 17 | |||
| 18 | const ADDR: u32 = 0x80000; | ||
| 19 | let mut buf = [0u8; 4]; | ||
| 20 | |||
| 21 | info!("Reading..."); | ||
| 22 | unwrap!(f.read(ADDR, &mut buf)); | ||
| 23 | info!("Read: {=[u8]:x}", buf); | ||
| 24 | |||
| 25 | info!("Erasing..."); | ||
| 26 | unwrap!(f.erase(ADDR, ADDR + PAGE_SIZE as u32)); | ||
| 27 | |||
| 28 | info!("Reading..."); | ||
| 29 | unwrap!(f.read(ADDR, &mut buf)); | ||
| 30 | info!("Read: {=[u8]:x}", buf); | ||
| 31 | |||
| 32 | info!("Writing..."); | ||
| 33 | // 16 B (128-bit) write minimum | ||
| 34 | let out: [u8; 256] = [ | ||
| 35 | 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, | ||
| 36 | 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, | ||
| 37 | 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, | ||
| 38 | 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, | ||
| 39 | 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, | ||
| 40 | 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 41 | 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, | ||
| 42 | 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, | ||
| 43 | 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, | ||
| 44 | 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, | ||
| 45 | 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, | ||
| 46 | 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, | ||
| 47 | 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, | ||
| 48 | 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 49 | 0xdd, 0xdd, 0xdd, 0xdd, | ||
| 50 | ]; | ||
| 51 | unwrap!(f.write(ADDR, &out)); | ||
| 52 | |||
| 53 | info!("Reading..."); | ||
| 54 | // Can read arbitrary sizes | ||
| 55 | for addr in (ADDR..ADDR + 256).step_by(4) { | ||
| 56 | unwrap!(f.read(addr, &mut buf)); | ||
| 57 | info!("Read: {=[u8]:x}", buf); | ||
| 58 | } | ||
| 59 | } | ||
diff --git a/examples/nrf54l15/src/bin/saadc.rs b/examples/nrf54l15/src/bin/saadc.rs new file mode 100644 index 000000000..567177894 --- /dev/null +++ b/examples/nrf54l15/src/bin/saadc.rs | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; | ||
| 7 | use embassy_nrf::{bind_interrupts, saadc}; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | SAADC => saadc::InterruptHandler; | ||
| 13 | }); | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_p: Spawner) { | ||
| 17 | let mut p = embassy_nrf::init(Default::default()); | ||
| 18 | let config = Config::default(); | ||
| 19 | let channel_config = ChannelConfig::single_ended(p.P1_04.reborrow()); | ||
| 20 | let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]); | ||
| 21 | |||
| 22 | loop { | ||
| 23 | let mut buf = [0; 1]; | ||
| 24 | saadc.sample(&mut buf).await; | ||
| 25 | info!("sample: {=i16}", &buf[0]); | ||
| 26 | Timer::after_millis(100).await; | ||
| 27 | } | ||
| 28 | } | ||
diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs new file mode 100644 index 000000000..3f5980647 --- /dev/null +++ b/examples/nrf54l15/src/bin/spim.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_nrf::{bind_interrupts, peripherals, spim}; | ||
| 6 | use {defmt_rtt as _, panic_probe as _}; | ||
| 7 | |||
| 8 | bind_interrupts!(struct Irqs { | ||
| 9 | SERIAL00 => spim::InterruptHandler<peripherals::SERIAL00>; | ||
| 10 | }); | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let p = embassy_nrf::init(Default::default()); | ||
| 15 | let mut config = spim::Config::default(); | ||
| 16 | config.frequency = spim::Frequency::M32; | ||
| 17 | let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P2_05, p.P2_09, p.P2_08, config.clone()); | ||
| 18 | let data = [ | ||
| 19 | 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77, | ||
| 20 | ]; | ||
| 21 | let mut buf = [0u8; 16]; | ||
| 22 | |||
| 23 | buf.fill(0); | ||
| 24 | spim.blocking_transfer(&mut buf, &data).unwrap(); | ||
| 25 | assert_eq!(data, buf); | ||
| 26 | |||
| 27 | buf.fill(0); | ||
| 28 | spim.transfer(&mut buf, &data).await.unwrap(); | ||
| 29 | assert_eq!(data, buf); | ||
| 30 | } | ||
diff --git a/examples/nrf54l15/src/bin/timer.rs b/examples/nrf54l15/src/bin/timer.rs new file mode 100644 index 000000000..68acc91c1 --- /dev/null +++ b/examples/nrf54l15/src/bin/timer.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_time::Timer; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::task] | ||
| 10 | async fn run1() { | ||
| 11 | loop { | ||
| 12 | info!("BIG INFREQUENT TICK"); | ||
| 13 | Timer::after_secs(10).await; | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | #[embassy_executor::task] | ||
| 18 | async fn run2() { | ||
| 19 | loop { | ||
| 20 | info!("tick"); | ||
| 21 | Timer::after_secs(1).await; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | #[embassy_executor::main] | ||
| 26 | async fn main(spawner: Spawner) { | ||
| 27 | let _p = embassy_nrf::init(Default::default()); | ||
| 28 | spawner.spawn(unwrap!(run1())); | ||
| 29 | spawner.spawn(unwrap!(run2())); | ||
| 30 | } | ||
diff --git a/examples/nrf54l15/src/bin/twim.rs b/examples/nrf54l15/src/bin/twim.rs new file mode 100644 index 000000000..53b85034e --- /dev/null +++ b/examples/nrf54l15/src/bin/twim.rs | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | //! Example on how to read a 24C/24LC i2c eeprom. | ||
| 2 | //! | ||
| 3 | //! Connect SDA to P0.03, SCL to P0.04 | ||
| 4 | |||
| 5 | #![no_std] | ||
| 6 | #![no_main] | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_nrf::twim::{self, Twim}; | ||
| 11 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 12 | use static_cell::ConstStaticCell; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | const ADDRESS: u8 = 0x18; | ||
| 16 | const WHOAMI: u8 = 0x0F; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs { | ||
| 19 | SERIAL20 => twim::InterruptHandler<peripherals::SERIAL20>; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::main] | ||
| 23 | async fn main(_spawner: Spawner) { | ||
| 24 | let p = embassy_nrf::init(Default::default()); | ||
| 25 | info!("Initializing TWI..."); | ||
| 26 | let config = twim::Config::default(); | ||
| 27 | static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]); | ||
| 28 | let mut twi = Twim::new(p.SERIAL20, Irqs, p.P1_13, p.P1_12, config, RAM_BUFFER.take()); | ||
| 29 | |||
| 30 | info!("Reading..."); | ||
| 31 | |||
| 32 | let mut data = [0u8; 1]; | ||
| 33 | match twi.write_read(ADDRESS, &[WHOAMI], &mut data).await { | ||
| 34 | Ok(()) => info!("Whoami: {}", data[0]), | ||
| 35 | Err(e) => error!("I2c Error: {:?}", e), | ||
| 36 | } | ||
| 37 | } | ||
diff --git a/examples/nrf54l15/src/bin/twis.rs b/examples/nrf54l15/src/bin/twis.rs new file mode 100644 index 000000000..34c04aee3 --- /dev/null +++ b/examples/nrf54l15/src/bin/twis.rs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | //! TWIS example | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | |||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_nrf::twis::{self, Command, Twis}; | ||
| 9 | use embassy_nrf::{bind_interrupts, peripherals}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | SERIAL20 => twis::InterruptHandler<peripherals::SERIAL20>; | ||
| 14 | }); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(_spawner: Spawner) { | ||
| 18 | let p = embassy_nrf::init(Default::default()); | ||
| 19 | |||
| 20 | let mut config = twis::Config::default(); | ||
| 21 | config.address0 = 0x55; // Set i2c address | ||
| 22 | let mut i2c = Twis::new(p.SERIAL20, Irqs, p.P0_03, p.P0_04, config); | ||
| 23 | |||
| 24 | info!("Listening..."); | ||
| 25 | loop { | ||
| 26 | let response = [1, 2, 3, 4, 5, 6, 7, 8]; | ||
| 27 | // This buffer is used if the i2c master performs a Write or WriteRead | ||
| 28 | let mut buf = [0u8; 16]; | ||
| 29 | match i2c.listen(&mut buf).await { | ||
| 30 | Ok(Command::Read) => { | ||
| 31 | info!("Got READ command. Respond with data:\n{:?}\n", response); | ||
| 32 | if let Err(e) = i2c.respond_to_read(&response).await { | ||
| 33 | error!("{:?}", e); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]), | ||
| 37 | Ok(Command::WriteRead(n)) => { | ||
| 38 | info!("Got WRITE/READ command with data:\n{:?}", buf[..n]); | ||
| 39 | info!("Respond with data:\n{:?}\n", response); | ||
| 40 | if let Err(e) = i2c.respond_to_read(&response).await { | ||
| 41 | error!("{:?}", e); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | Err(e) => error!("{:?}", e), | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
diff --git a/examples/nrf54l15/src/bin/uart.rs b/examples/nrf54l15/src/bin/uart.rs new file mode 100644 index 000000000..cc6528a6f --- /dev/null +++ b/examples/nrf54l15/src/bin/uart.rs | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::{bind_interrupts, peripherals, uarte}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | bind_interrupts!(struct Irqs { | ||
| 10 | SERIAL20 => uarte::InterruptHandler<peripherals::SERIAL20>; | ||
| 11 | }); | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = embassy_nrf::init(Default::default()); | ||
| 16 | let mut config = uarte::Config::default(); | ||
| 17 | config.parity = uarte::Parity::EXCLUDED; | ||
| 18 | config.baudrate = uarte::Baudrate::BAUD115200; | ||
| 19 | |||
| 20 | let mut uart = uarte::Uarte::new(p.SERIAL20, p.P1_12, p.P1_13, Irqs, config); | ||
| 21 | |||
| 22 | info!("uarte initialized!"); | ||
| 23 | |||
| 24 | // Message must be in SRAM | ||
| 25 | let mut buf = [0; 8]; | ||
| 26 | buf.copy_from_slice(b"Hello!\r\n"); | ||
| 27 | |||
| 28 | unwrap!(uart.write(&buf).await); | ||
| 29 | info!("wrote hello in uart!"); | ||
| 30 | |||
| 31 | loop { | ||
| 32 | info!("reading..."); | ||
| 33 | unwrap!(uart.read(&mut buf).await); | ||
| 34 | info!("writing..."); | ||
| 35 | unwrap!(uart.write(&buf).await); | ||
| 36 | } | ||
| 37 | } | ||
diff --git a/examples/nrf54lm20/.cargo/config.toml b/examples/nrf54lm20/.cargo/config.toml new file mode 100644 index 000000000..0ffebed14 --- /dev/null +++ b/examples/nrf54lm20/.cargo/config.toml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # Note: it needs the latest git version of probe-rs | ||
| 3 | runner = "probe-rs run --chip nrf54lm20a" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv8m.main-none-eabihf" | ||
| 7 | |||
| 8 | [env] | ||
| 9 | DEFMT_LOG = "trace" | ||
diff --git a/examples/nrf54lm20/Cargo.toml b/examples/nrf54lm20/Cargo.toml new file mode 100644 index 000000000..e3bf22b25 --- /dev/null +++ b/examples/nrf54lm20/Cargo.toml | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2024" | ||
| 3 | name = "embassy-nrf54lm20-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 10 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | ||
| 11 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | ||
| 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 13 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54lm20-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] } | ||
| 14 | embedded-io = { version = "0.6.0", features = ["defmt-03"] } | ||
| 15 | embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } | ||
| 16 | |||
| 17 | rand = { version = "0.9.0", default-features = false } | ||
| 18 | |||
| 19 | defmt = "1.0.1" | ||
| 20 | defmt-rtt = "1.0.0" | ||
| 21 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 22 | |||
| 23 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 24 | cortex-m-rt = "0.7.0" | ||
| 25 | |||
| 26 | embedded-storage = "0.3.1" | ||
| 27 | portable-atomic = "1" | ||
| 28 | |||
| 29 | static_cell = "2" | ||
| 30 | |||
| 31 | [profile.release] | ||
| 32 | debug = 2 | ||
| 33 | |||
| 34 | [package.metadata.embassy] | ||
| 35 | build = [ | ||
| 36 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf54lm20" } | ||
| 37 | ] | ||
diff --git a/examples/nrf54lm20/build.rs b/examples/nrf54lm20/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf54lm20/build.rs | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | //! This build script copies the `memory.x` file from the crate root into | ||
| 2 | //! a directory where the linker can always find it at build time. | ||
| 3 | //! For many projects this is optional, as the linker always searches the | ||
| 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you | ||
| 5 | //! are using a workspace or have a more complicated build setup, this | ||
| 6 | //! build script becomes required. Additionally, by requesting that | ||
| 7 | //! Cargo re-run the build script whenever `memory.x` is changed, | ||
| 8 | //! updating `memory.x` ensures a rebuild of the application with the | ||
| 9 | //! new memory settings. | ||
| 10 | |||
| 11 | use std::env; | ||
| 12 | use std::fs::File; | ||
| 13 | use std::io::Write; | ||
| 14 | use std::path::PathBuf; | ||
| 15 | |||
| 16 | fn main() { | ||
| 17 | // Put `memory.x` in our output directory and ensure it's | ||
| 18 | // on the linker search path. | ||
| 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 20 | File::create(out.join("memory.x")) | ||
| 21 | .unwrap() | ||
| 22 | .write_all(include_bytes!("memory.x")) | ||
| 23 | .unwrap(); | ||
| 24 | println!("cargo:rustc-link-search={}", out.display()); | ||
| 25 | |||
| 26 | // By default, Cargo will re-run a build script whenever | ||
| 27 | // any file in the project changes. By specifying `memory.x` | ||
| 28 | // here, we ensure the build script is only re-run when | ||
| 29 | // `memory.x` is changed. | ||
| 30 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 31 | |||
| 32 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 33 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 34 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 35 | } | ||
diff --git a/examples/nrf54lm20/memory.x b/examples/nrf54lm20/memory.x new file mode 100644 index 000000000..564f488ac --- /dev/null +++ b/examples/nrf54lm20/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x00000000, LENGTH = 2036K | ||
| 4 | RAM : ORIGIN = 0x20000000, LENGTH = 512K | ||
| 5 | } | ||
diff --git a/examples/nrf54lm20/src/bin/blinky.rs b/examples/nrf54lm20/src/bin/blinky.rs new file mode 100644 index 000000000..962e9f5a6 --- /dev/null +++ b/examples/nrf54lm20/src/bin/blinky.rs | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | let mut led = Output::new(p.P1_22, Level::Low, OutputDrive::HighDrive); | ||
| 14 | |||
| 15 | loop { | ||
| 16 | info!("high!"); | ||
| 17 | led.set_high(); | ||
| 18 | Timer::after_millis(300).await; | ||
| 19 | info!("low!"); | ||
| 20 | led.set_low(); | ||
| 21 | Timer::after_millis(300).await; | ||
| 22 | } | ||
| 23 | } | ||
diff --git a/examples/nrf54lm20/src/bin/gpio.rs b/examples/nrf54lm20/src/bin/gpio.rs new file mode 100644 index 000000000..4b6b4630d --- /dev/null +++ b/examples/nrf54lm20/src/bin/gpio.rs | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::gpio::{Input, Pull}; | ||
| 7 | use embassy_time::Timer; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | let btn = Input::new(p.P1_26, Pull::Up); | ||
| 14 | |||
| 15 | loop { | ||
| 16 | if btn.is_high() { | ||
| 17 | info!("high"); | ||
| 18 | } else { | ||
| 19 | info!("low"); | ||
| 20 | } | ||
| 21 | Timer::after_millis(100).await; | ||
| 22 | } | ||
| 23 | } | ||
diff --git a/examples/nrf54lm20/src/bin/gpiote_channel.rs b/examples/nrf54lm20/src/bin/gpiote_channel.rs new file mode 100644 index 000000000..0f30f06c7 --- /dev/null +++ b/examples/nrf54lm20/src/bin/gpiote_channel.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::gpio::Pull; | ||
| 7 | use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_nrf::init(Default::default()); | ||
| 13 | info!("Starting!"); | ||
| 14 | |||
| 15 | let mut ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_26, Pull::Up, InputChannelPolarity::HiToLo); | ||
| 16 | let mut ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi); | ||
| 17 | let mut ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle); | ||
| 18 | let mut ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_05, Pull::Up, InputChannelPolarity::Toggle); | ||
| 19 | |||
| 20 | let button1 = async { | ||
| 21 | loop { | ||
| 22 | ch1.wait().await; | ||
| 23 | info!("Button 1 pressed") | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | let button2 = async { | ||
| 28 | loop { | ||
| 29 | ch2.wait().await; | ||
| 30 | info!("Button 2 released") | ||
| 31 | } | ||
| 32 | }; | ||
| 33 | |||
| 34 | let button3 = async { | ||
| 35 | loop { | ||
| 36 | ch3.wait().await; | ||
| 37 | info!("Button 3 toggled") | ||
| 38 | } | ||
| 39 | }; | ||
| 40 | |||
| 41 | let button4 = async { | ||
| 42 | loop { | ||
| 43 | ch4.wait().await; | ||
| 44 | info!("Button 4 toggled") | ||
| 45 | } | ||
| 46 | }; | ||
| 47 | |||
| 48 | embassy_futures::join::join4(button1, button2, button3, button4).await; | ||
| 49 | } | ||
diff --git a/examples/nrf54lm20/src/bin/gpiote_port.rs b/examples/nrf54lm20/src/bin/gpiote_port.rs new file mode 100644 index 000000000..6dbd63d92 --- /dev/null +++ b/examples/nrf54lm20/src/bin/gpiote_port.rs | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_nrf::gpio::{Input, Pull}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::task(pool_size = 4)] | ||
| 10 | async fn button_task(n: usize, mut pin: Input<'static>) { | ||
| 11 | loop { | ||
| 12 | pin.wait_for_low().await; | ||
| 13 | info!("Button {:?} pressed!", n); | ||
| 14 | pin.wait_for_high().await; | ||
| 15 | info!("Button {:?} released!", n); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(spawner: Spawner) { | ||
| 21 | let p = embassy_nrf::init(Default::default()); | ||
| 22 | info!("Starting!"); | ||
| 23 | |||
| 24 | let btn1 = Input::new(p.P1_26, Pull::Up); | ||
| 25 | let btn2 = Input::new(p.P1_09, Pull::Up); | ||
| 26 | let btn3 = Input::new(p.P1_08, Pull::Up); | ||
| 27 | let btn4 = Input::new(p.P0_05, Pull::Up); | ||
| 28 | |||
| 29 | spawner.spawn(unwrap!(button_task(1, btn1))); | ||
| 30 | spawner.spawn(unwrap!(button_task(2, btn2))); | ||
| 31 | spawner.spawn(unwrap!(button_task(3, btn3))); | ||
| 32 | spawner.spawn(unwrap!(button_task(4, btn4))); | ||
| 33 | } | ||
diff --git a/examples/nrf54lm20/src/bin/timer.rs b/examples/nrf54lm20/src/bin/timer.rs new file mode 100644 index 000000000..68acc91c1 --- /dev/null +++ b/examples/nrf54lm20/src/bin/timer.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_time::Timer; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::task] | ||
| 10 | async fn run1() { | ||
| 11 | loop { | ||
| 12 | info!("BIG INFREQUENT TICK"); | ||
| 13 | Timer::after_secs(10).await; | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | #[embassy_executor::task] | ||
| 18 | async fn run2() { | ||
| 19 | loop { | ||
| 20 | info!("tick"); | ||
| 21 | Timer::after_secs(1).await; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | #[embassy_executor::main] | ||
| 26 | async fn main(spawner: Spawner) { | ||
| 27 | let _p = embassy_nrf::init(Default::default()); | ||
| 28 | spawner.spawn(unwrap!(run1())); | ||
| 29 | spawner.spawn(unwrap!(run2())); | ||
| 30 | } | ||
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 89a6c7c94..f6d6aab6f 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf9151-non-secure-examples" | 3 | name = "embassy-nrf9151-non-secure-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -8,7 +8,7 @@ publish = false | |||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 10 | embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 11 | embassy-nrf = { version = "0.8.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.9.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 12 | 12 | ||
| 13 | defmt = "1.0.1" | 13 | defmt = "1.0.1" |
| 14 | defmt-rtt = "1.0.0" | 14 | defmt-rtt = "1.0.0" |
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 870311c5d..1c9e7fb35 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf9151-secure-examples" | 3 | name = "embassy-nrf9151-secure-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -8,7 +8,7 @@ publish = false | |||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 10 | embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 11 | embassy-nrf = { version = "0.8.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.9.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 12 | 12 | ||
| 13 | defmt = "1.0.1" | 13 | defmt = "1.0.1" |
| 14 | defmt-rtt = "1.0.0" | 14 | defmt-rtt = "1.0.0" |
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 274e26dd6..907b06e6d 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-nrf9160-examples" | 3 | name = "embassy-nrf9160-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -8,7 +8,7 @@ publish = false | |||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 9 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 11 | embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 11 | embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 12 | embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } | 12 | embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } |
| 13 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } | 13 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } |
| 14 | 14 | ||
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index 460a4cfae..07fa57e63 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs | |||
| @@ -11,11 +11,11 @@ use defmt::{info, unwrap, warn}; | |||
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; | 12 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; |
| 13 | use embassy_net_nrf91::context::Status; | 13 | use embassy_net_nrf91::context::Status; |
| 14 | use embassy_net_nrf91::{context, Runner, State, TraceBuffer, TraceReader}; | 14 | use embassy_net_nrf91::{Runner, State, TraceBuffer, TraceReader, context}; |
| 15 | use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; | 15 | use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; |
| 16 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive}; | 16 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive}; |
| 17 | use embassy_nrf::uarte::Baudrate; | 17 | use embassy_nrf::uarte::Baudrate; |
| 18 | use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte, Peri}; | 18 | use embassy_nrf::{Peri, bind_interrupts, interrupt, peripherals, uarte}; |
| 19 | use embassy_time::{Duration, Timer}; | 19 | use embassy_time::{Duration, Timer}; |
| 20 | use embedded_io_async::Write; | 20 | use embedded_io_async::Write; |
| 21 | use heapless::Vec; | 21 | use heapless::Vec; |
| @@ -101,7 +101,7 @@ async fn blink_task(pin: Peri<'static, AnyPin>) { | |||
| 101 | } | 101 | } |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | extern "C" { | 104 | unsafe extern "C" { |
| 105 | static __start_ipc: u8; | 105 | static __start_ipc: u8; |
| 106 | static __end_ipc: u8; | 106 | static __end_ipc: u8; |
| 107 | } | 107 | } |
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 97e019cdf..e247f6f7a 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-rp-examples" | 3 | name = "embassy-rp-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -11,14 +11,14 @@ embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", | |||
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 14 | embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } | 14 | embassy-rp = { version = "0.9.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } |
| 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } | 16 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } |
| 17 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } | 17 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 19 | embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } | 19 | embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } |
| 20 | cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } | 20 | cyw43 = { version = "0.6.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } |
| 21 | cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } | 21 | cyw43-pio = { version = "0.9.0", path = "../../cyw43-pio", features = ["defmt"] } |
| 22 | 22 | ||
| 23 | defmt = "1.0.1" | 23 | defmt = "1.0.1" |
| 24 | defmt-rtt = "1.0.0" | 24 | defmt-rtt = "1.0.0" |
| @@ -45,7 +45,7 @@ display-interface = "0.5.0" | |||
| 45 | byte-slice-cast = { version = "1.2.0", default-features = false } | 45 | byte-slice-cast = { version = "1.2.0", default-features = false } |
| 46 | smart-leds = "0.4.0" | 46 | smart-leds = "0.4.0" |
| 47 | heapless = "0.8" | 47 | heapless = "0.8" |
| 48 | usbd-hid = "0.8.1" | 48 | usbd-hid = "0.9.0" |
| 49 | 49 | ||
| 50 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 50 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 51 | embedded-hal-async = "1.0" | 51 | embedded-hal-async = "1.0" |
diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs index 4ee4278b5..aaa134768 100644 --- a/examples/rp/src/bin/assign_resources.rs +++ b/examples/rp/src/bin/assign_resources.rs | |||
| @@ -14,9 +14,9 @@ | |||
| 14 | use assign_resources::assign_resources; | 14 | use assign_resources::assign_resources; |
| 15 | use defmt::*; | 15 | use defmt::*; |
| 16 | use embassy_executor::Spawner; | 16 | use embassy_executor::Spawner; |
| 17 | use embassy_rp::Peri; | ||
| 17 | use embassy_rp::gpio::{Level, Output}; | 18 | use embassy_rp::gpio::{Level, Output}; |
| 18 | use embassy_rp::peripherals::{self, PIN_20, PIN_21}; | 19 | use embassy_rp::peripherals::{self, PIN_20, PIN_21}; |
| 19 | use embassy_rp::Peri; | ||
| 20 | use embassy_time::Timer; | 20 | use embassy_time::Timer; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 22 | 22 | ||
diff --git a/examples/rp/src/bin/debounce.rs b/examples/rp/src/bin/debounce.rs index 0077f19fc..6eeb01d0a 100644 --- a/examples/rp/src/bin/debounce.rs +++ b/examples/rp/src/bin/debounce.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | use defmt::info; | 7 | use defmt::info; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_rp::gpio::{Input, Level, Pull}; | 9 | use embassy_rp::gpio::{Input, Level, Pull}; |
| 10 | use embassy_time::{with_deadline, Duration, Instant, Timer}; | 10 | use embassy_time::{Duration, Instant, Timer, with_deadline}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | pub struct Debouncer<'a> { | 13 | pub struct Debouncer<'a> { |
diff --git a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs index 49d28071a..cb667f24f 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs | |||
| @@ -12,8 +12,8 @@ use core::str::FromStr; | |||
| 12 | use defmt::*; | 12 | use defmt::*; |
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_futures::yield_now; | 14 | use embassy_futures::yield_now; |
| 15 | use embassy_net::icmp::ping::{PingManager, PingParams}; | ||
| 16 | use embassy_net::icmp::PacketMetadata; | 15 | use embassy_net::icmp::PacketMetadata; |
| 16 | use embassy_net::icmp::ping::{PingManager, PingParams}; | ||
| 17 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; | 17 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; |
| 18 | use embassy_net_wiznet::chip::W5500; | 18 | use embassy_net_wiznet::chip::W5500; |
| 19 | use embassy_net_wiznet::*; | 19 | use embassy_net_wiznet::*; |
| @@ -99,7 +99,7 @@ async fn main(spawner: Spawner) { | |||
| 99 | // Create the ping manager instance | 99 | // Create the ping manager instance |
| 100 | let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | 100 | let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); |
| 101 | let addr = "192.168.8.1"; // Address to ping to | 101 | let addr = "192.168.8.1"; // Address to ping to |
| 102 | // Create the PingParams with the target address | 102 | // Create the PingParams with the target address |
| 103 | let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); | 103 | let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); |
| 104 | // (optional) Set custom properties of the ping | 104 | // (optional) Set custom properties of the ping |
| 105 | ping_params.set_payload(b"Hello, Ping!"); // custom payload | 105 | ping_params.set_payload(b"Hello, Ping!"); // custom payload |
diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs index f51df2df9..b402029b5 100644 --- a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs | |||
| @@ -65,7 +65,7 @@ async fn main(spawner: Spawner) { | |||
| 65 | // Construct an SPI driver backed by a PIO state machine | 65 | // Construct an SPI driver backed by a PIO state machine |
| 66 | let mut spi_cfg = SpiConfig::default(); | 66 | let mut spi_cfg = SpiConfig::default(); |
| 67 | spi_cfg.frequency = 12_500_000; // The PIO SPI program is much less stable than the actual SPI | 67 | spi_cfg.frequency = 12_500_000; // The PIO SPI program is much less stable than the actual SPI |
| 68 | // peripheral, use higher speeds at your peril | 68 | // peripheral, use higher speeds at your peril |
| 69 | let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); | 69 | let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); |
| 70 | 70 | ||
| 71 | // Further control pins | 71 | // Further control pins |
diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs index 2748f778a..2605622ab 100644 --- a/examples/rp/src/bin/interrupt.rs +++ b/examples/rp/src/bin/interrupt.rs | |||
| @@ -16,8 +16,8 @@ use embassy_rp::adc::{self, Adc, Blocking}; | |||
| 16 | use embassy_rp::gpio::Pull; | 16 | use embassy_rp::gpio::Pull; |
| 17 | use embassy_rp::interrupt; | 17 | use embassy_rp::interrupt; |
| 18 | use embassy_rp::pwm::{Config, Pwm}; | 18 | use embassy_rp::pwm::{Config, Pwm}; |
| 19 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 20 | use embassy_sync::blocking_mutex::Mutex; | 19 | use embassy_sync::blocking_mutex::Mutex; |
| 20 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 21 | use embassy_sync::channel::Channel; | 21 | use embassy_sync::channel::Channel; |
| 22 | use embassy_time::{Duration, Ticker}; | 22 | use embassy_time::{Duration, Ticker}; |
| 23 | use portable_atomic::{AtomicU32, Ordering}; | 23 | use portable_atomic::{AtomicU32, Ordering}; |
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 3a6367420..d289f8020 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_rp::gpio::{Level, Output}; | 10 | use embassy_rp::gpio::{Level, Output}; |
| 11 | use embassy_rp::multicore::{spawn_core1, Stack}; | 11 | use embassy_rp::multicore::{Stack, spawn_core1}; |
| 12 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 12 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 13 | use embassy_sync::channel::Channel; | 13 | use embassy_sync::channel::Channel; |
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index 96cdf8fb1..310047505 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs | |||
| @@ -61,7 +61,7 @@ use defmt::{info, unwrap}; | |||
| 61 | use embassy_executor::{Executor, InterruptExecutor}; | 61 | use embassy_executor::{Executor, InterruptExecutor}; |
| 62 | use embassy_rp::interrupt; | 62 | use embassy_rp::interrupt; |
| 63 | use embassy_rp::interrupt::{InterruptExt, Priority}; | 63 | use embassy_rp::interrupt::{InterruptExt, Priority}; |
| 64 | use embassy_time::{Instant, Timer, TICK_HZ}; | 64 | use embassy_time::{Instant, TICK_HZ, Timer}; |
| 65 | use static_cell::StaticCell; | 65 | use static_cell::StaticCell; |
| 66 | use {defmt_rtt as _, panic_probe as _}; | 66 | use {defmt_rtt as _, panic_probe as _}; |
| 67 | 67 | ||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn SWI_IRQ_1() { | 115 | unsafe fn SWI_IRQ_1() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn SWI_IRQ_0() { | 120 | unsafe fn SWI_IRQ_0() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs index 9f25e1087..cd26a5371 100644 --- a/examples/rp/src/bin/orchestrate_tasks.rs +++ b/examples/rp/src/bin/orchestrate_tasks.rs | |||
| @@ -20,11 +20,11 @@ | |||
| 20 | use assign_resources::assign_resources; | 20 | use assign_resources::assign_resources; |
| 21 | use defmt::*; | 21 | use defmt::*; |
| 22 | use embassy_executor::Spawner; | 22 | use embassy_executor::Spawner; |
| 23 | use embassy_futures::select::{select, Either}; | 23 | use embassy_futures::select::{Either, select}; |
| 24 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; | 24 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; |
| 25 | use embassy_rp::clocks::RoscRng; | 25 | use embassy_rp::clocks::RoscRng; |
| 26 | use embassy_rp::gpio::{Input, Pull}; | 26 | use embassy_rp::gpio::{Input, Pull}; |
| 27 | use embassy_rp::{bind_interrupts, peripherals, Peri}; | 27 | use embassy_rp::{Peri, bind_interrupts, peripherals}; |
| 28 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 28 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 29 | use embassy_sync::mutex::Mutex; | 29 | use embassy_sync::mutex::Mutex; |
| 30 | use embassy_sync::{channel, signal}; | 30 | use embassy_sync::{channel, signal}; |
diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs index 83b17308b..a98185a8e 100644 --- a/examples/rp/src/bin/overclock.rs +++ b/examples/rp/src/bin/overclock.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig}; | 10 | use embassy_rp::clocks::{ClockConfig, clk_sys_freq, core_voltage}; |
| 11 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 12 | use embassy_rp::gpio::{Level, Output}; | 12 | use embassy_rp::gpio::{Level, Output}; |
| 13 | use embassy_time::{Duration, Instant, Timer}; | 13 | use embassy_time::{Duration, Instant, Timer}; |
diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs index dea5cfb3c..18397f9a8 100644 --- a/examples/rp/src/bin/overclock_manual.rs +++ b/examples/rp/src/bin/overclock_manual.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig}; | 10 | use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig, clk_sys_freq, core_voltage}; |
| 11 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 12 | use embassy_rp::gpio::{Level, Output}; | 12 | use embassy_rp::gpio::{Level, Output}; |
| 13 | use embassy_time::{Duration, Instant, Timer}; | 13 | use embassy_time::{Duration, Instant, Timer}; |
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 1743a417e..55e983c36 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -7,7 +7,7 @@ use embassy_executor::Spawner; | |||
| 7 | use embassy_rp::peripherals::PIO0; | 7 | use embassy_rp::peripherals::PIO0; |
| 8 | use embassy_rp::pio::program::pio_asm; | 8 | use embassy_rp::pio::program::pio_asm; |
| 9 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; | 9 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; |
| 10 | use embassy_rp::{bind_interrupts, Peri}; | 10 | use embassy_rp::{Peri, bind_interrupts}; |
| 11 | use fixed::traits::ToFixed; | 11 | use fixed::traits::ToFixed; |
| 12 | use fixed_macro::types::U56F8; | 12 | use fixed_macro::types::U56F8; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs index 102f13c45..6432edb8a 100644 --- a/examples/rp/src/bin/pio_onewire.rs +++ b/examples/rp/src/bin/pio_onewire.rs | |||
| @@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) { | |||
| 61 | let mut data = [0; 9]; | 61 | let mut data = [0; 9]; |
| 62 | onewire.read_bytes(&mut data).await; | 62 | onewire.read_bytes(&mut data).await; |
| 63 | if crc8(&data) == 0 { | 63 | if crc8(&data) == 0 { |
| 64 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; | 64 | let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.; |
| 65 | info!("Read device {:x}: {} deg C", device, temp); | 65 | info!("Read device {:x}: {} deg C", device, temp); |
| 66 | } else { | 66 | } else { |
| 67 | warn!("Reading device {:x} failed", device); | 67 | warn!("Reading device {:x} failed", device); |
diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs index fd076dee0..78fb94b18 100644 --- a/examples/rp/src/bin/pio_onewire_parasite.rs +++ b/examples/rp/src/bin/pio_onewire_parasite.rs | |||
| @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { | |||
| 63 | let mut data = [0; 9]; | 63 | let mut data = [0; 9]; |
| 64 | onewire.read_bytes(&mut data).await; | 64 | onewire.read_bytes(&mut data).await; |
| 65 | if crc8(&data) == 0 { | 65 | if crc8(&data) == 0 { |
| 66 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; | 66 | let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.; |
| 67 | info!("Read device {:x}: {} deg C", device, temp); | 67 | info!("Read device {:x}: {} deg C", device, temp); |
| 68 | } else { | 68 | } else { |
| 69 | warn!("Reading device {:x} failed. {:02x}", device, data); | 69 | warn!("Reading device {:x} failed. {:02x}", device, data); |
diff --git a/examples/rp/src/bin/pio_stepper.rs b/examples/rp/src/bin/pio_stepper.rs index 3862c248b..e8f203990 100644 --- a/examples/rp/src/bin/pio_stepper.rs +++ b/examples/rp/src/bin/pio_stepper.rs | |||
| @@ -10,7 +10,7 @@ use embassy_rp::bind_interrupts; | |||
| 10 | use embassy_rp::peripherals::PIO0; | 10 | use embassy_rp::peripherals::PIO0; |
| 11 | use embassy_rp::pio::{InterruptHandler, Pio}; | 11 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 12 | use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram}; | 12 | use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram}; |
| 13 | use embassy_time::{with_timeout, Duration, Timer}; | 13 | use embassy_time::{Duration, Timer, with_timeout}; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | 16 | bind_interrupts!(struct Irqs { |
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 9dd07ab6e..f985bf7cf 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs | |||
| @@ -9,9 +9,9 @@ | |||
| 9 | 9 | ||
| 10 | use defmt::*; | 10 | use defmt::*; |
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_rp::peripherals::{PIN_25, PIN_4, PWM_SLICE2, PWM_SLICE4}; | ||
| 13 | use embassy_rp::pwm::{Config, Pwm, SetDutyCycle}; | ||
| 14 | use embassy_rp::Peri; | 12 | use embassy_rp::Peri; |
| 13 | use embassy_rp::peripherals::{PIN_4, PIN_25, PWM_SLICE2, PWM_SLICE4}; | ||
| 14 | use embassy_rp::pwm::{Config, Pwm, SetDutyCycle}; | ||
| 15 | use embassy_time::Timer; | 15 | use embassy_time::Timer; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
diff --git a/examples/rp/src/bin/rtc_alarm.rs b/examples/rp/src/bin/rtc_alarm.rs index 94b5fbd27..bde49ccd5 100644 --- a/examples/rp/src/bin/rtc_alarm.rs +++ b/examples/rp/src/bin/rtc_alarm.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_futures::select::{select, Either}; | 8 | use embassy_futures::select::{Either, select}; |
| 9 | use embassy_rp::bind_interrupts; | 9 | use embassy_rp::bind_interrupts; |
| 10 | use embassy_rp::rtc::{DateTime, DateTimeFilter, DayOfWeek, Rtc}; | 10 | use embassy_rp::rtc::{DateTime, DateTimeFilter, DayOfWeek, Rtc}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs index d4c89946b..618ab9117 100644 --- a/examples/rp/src/bin/sharing.rs +++ b/examples/rp/src/bin/sharing.rs | |||
| @@ -52,7 +52,7 @@ bind_interrupts!(struct Irqs { | |||
| 52 | 52 | ||
| 53 | #[interrupt] | 53 | #[interrupt] |
| 54 | unsafe fn SWI_IRQ_0() { | 54 | unsafe fn SWI_IRQ_0() { |
| 55 | EXECUTOR_HI.on_interrupt() | 55 | unsafe { EXECUTOR_HI.on_interrupt() } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | #[entry] | 58 | #[entry] |
diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index dd114a4ae..4bf924e56 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs | |||
| @@ -15,19 +15,19 @@ use embassy_executor::Spawner; | |||
| 15 | use embassy_rp::gpio::{Level, Output}; | 15 | use embassy_rp::gpio::{Level, Output}; |
| 16 | use embassy_rp::spi; | 16 | use embassy_rp::spi; |
| 17 | use embassy_rp::spi::Spi; | 17 | use embassy_rp::spi::Spi; |
| 18 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 19 | use embassy_sync::blocking_mutex::Mutex; | 18 | use embassy_sync::blocking_mutex::Mutex; |
| 19 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 20 | use embassy_time::Delay; | 20 | use embassy_time::Delay; |
| 21 | use embedded_graphics::image::{Image, ImageRawLE}; | 21 | use embedded_graphics::image::{Image, ImageRawLE}; |
| 22 | use embedded_graphics::mono_font::ascii::FONT_10X20; | ||
| 23 | use embedded_graphics::mono_font::MonoTextStyle; | 22 | use embedded_graphics::mono_font::MonoTextStyle; |
| 23 | use embedded_graphics::mono_font::ascii::FONT_10X20; | ||
| 24 | use embedded_graphics::pixelcolor::Rgb565; | 24 | use embedded_graphics::pixelcolor::Rgb565; |
| 25 | use embedded_graphics::prelude::*; | 25 | use embedded_graphics::prelude::*; |
| 26 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; | 26 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; |
| 27 | use embedded_graphics::text::Text; | 27 | use embedded_graphics::text::Text; |
| 28 | use mipidsi::Builder; | ||
| 28 | use mipidsi::models::ST7789; | 29 | use mipidsi::models::ST7789; |
| 29 | use mipidsi::options::{Orientation, Rotation}; | 30 | use mipidsi::options::{Orientation, Rotation}; |
| 30 | use mipidsi::Builder; | ||
| 31 | use {defmt_rtt as _, panic_probe as _}; | 31 | use {defmt_rtt as _, panic_probe as _}; |
| 32 | 32 | ||
| 33 | use crate::touch::Touch; | 33 | use crate::touch::Touch; |
| @@ -167,11 +167,7 @@ mod touch { | |||
| 167 | 167 | ||
| 168 | let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); | 168 | let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); |
| 169 | let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); | 169 | let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); |
| 170 | if x == 0 && y == 0 { | 170 | if x == 0 && y == 0 { None } else { Some((x, y)) } |
| 171 | None | ||
| 172 | } else { | ||
| 173 | Some((x, y)) | ||
| 174 | } | ||
| 175 | } | 171 | } |
| 176 | } | 172 | } |
| 177 | } | 173 | } |
diff --git a/examples/rp/src/bin/spi_gc9a01.rs b/examples/rp/src/bin/spi_gc9a01.rs index fdef09d4b..fd007b9bd 100644 --- a/examples/rp/src/bin/spi_gc9a01.rs +++ b/examples/rp/src/bin/spi_gc9a01.rs | |||
| @@ -16,16 +16,16 @@ use embassy_rp::clocks::RoscRng; | |||
| 16 | use embassy_rp::gpio::{Level, Output}; | 16 | use embassy_rp::gpio::{Level, Output}; |
| 17 | use embassy_rp::spi; | 17 | use embassy_rp::spi; |
| 18 | use embassy_rp::spi::{Blocking, Spi}; | 18 | use embassy_rp::spi::{Blocking, Spi}; |
| 19 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 20 | use embassy_sync::blocking_mutex::Mutex; | 19 | use embassy_sync::blocking_mutex::Mutex; |
| 20 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 21 | use embassy_time::{Delay, Duration, Timer}; | 21 | use embassy_time::{Delay, Duration, Timer}; |
| 22 | use embedded_graphics::image::{Image, ImageRawLE}; | 22 | use embedded_graphics::image::{Image, ImageRawLE}; |
| 23 | use embedded_graphics::pixelcolor::Rgb565; | 23 | use embedded_graphics::pixelcolor::Rgb565; |
| 24 | use embedded_graphics::prelude::*; | 24 | use embedded_graphics::prelude::*; |
| 25 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; | 25 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; |
| 26 | use mipidsi::Builder; | ||
| 26 | use mipidsi::models::GC9A01; | 27 | use mipidsi::models::GC9A01; |
| 27 | use mipidsi::options::{ColorInversion, ColorOrder}; | 28 | use mipidsi::options::{ColorInversion, ColorOrder}; |
| 28 | use mipidsi::Builder; | ||
| 29 | use {defmt_rtt as _, panic_probe as _}; | 29 | use {defmt_rtt as _, panic_probe as _}; |
| 30 | 30 | ||
| 31 | const DISPLAY_FREQ: u32 = 64_000_000; | 31 | const DISPLAY_FREQ: u32 = 64_000_000; |
diff --git a/examples/rp/src/bin/uart_r503.rs b/examples/rp/src/bin/uart_r503.rs index 085be280b..a25d45b18 100644 --- a/examples/rp/src/bin/uart_r503.rs +++ b/examples/rp/src/bin/uart_r503.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_rp::bind_interrupts; | 6 | use embassy_rp::bind_interrupts; |
| 7 | use embassy_rp::peripherals::UART0; | 7 | use embassy_rp::peripherals::UART0; |
| 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; | 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; |
| 9 | use embassy_time::{with_timeout, Duration, Timer}; | 9 | use embassy_time::{Duration, Timer, with_timeout}; |
| 10 | use heapless::Vec; | 10 | use heapless::Vec; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 912e52e96..b62a602b1 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_net::tcp::TcpSocket; | ||
| 11 | use embassy_net::StackResources; | 10 | use embassy_net::StackResources; |
| 11 | use embassy_net::tcp::TcpSocket; | ||
| 12 | use embassy_rp::clocks::RoscRng; | 12 | use embassy_rp::clocks::RoscRng; |
| 13 | use embassy_rp::peripherals::USB; | 13 | use embassy_rp::peripherals::USB; |
| 14 | use embassy_rp::usb::{Driver, InterruptHandler}; | 14 | use embassy_rp::usb::{Driver, InterruptHandler}; |
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs index a7cb322d8..2f6d169bf 100644 --- a/examples/rp/src/bin/usb_hid_keyboard.rs +++ b/examples/rp/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts; | |||
| 10 | use embassy_rp::gpio::{Input, Pull}; | 10 | use embassy_rp::gpio::{Input, Pull}; |
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver, InterruptHandler}; |
| 13 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 14 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 15 | use embassy_usb::{Builder, Config, Handler}; | 17 | use embassy_usb::{Builder, Config, Handler}; |
| 16 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -20,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 20 | USBCTRL_IRQ => InterruptHandler<USB>; | 22 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 21 | }); | 23 | }); |
| 22 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 23 | #[embassy_executor::main] | 27 | #[embassy_executor::main] |
| 24 | async fn main(_spawner: Spawner) { | 28 | async fn main(_spawner: Spawner) { |
| 25 | let p = embassy_rp::init(Default::default()); | 29 | let p = embassy_rp::init(Default::default()); |
| @@ -33,6 +37,10 @@ async fn main(_spawner: Spawner) { | |||
| 33 | config.serial_number = Some("12345678"); | 37 | config.serial_number = Some("12345678"); |
| 34 | config.max_power = 100; | 38 | config.max_power = 100; |
| 35 | config.max_packet_size_0 = 64; | 39 | config.max_packet_size_0 = 64; |
| 40 | config.composite_with_iads = false; | ||
| 41 | config.device_class = 0; | ||
| 42 | config.device_sub_class = 0; | ||
| 43 | config.device_protocol = 0; | ||
| 36 | 44 | ||
| 37 | // Create embassy-usb DeviceBuilder using the driver and config. | 45 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 38 | // It needs some buffers for building the descriptors. | 46 | // It needs some buffers for building the descriptors. |
| @@ -63,6 +71,8 @@ async fn main(_spawner: Spawner) { | |||
| 63 | request_handler: None, | 71 | request_handler: None, |
| 64 | poll_ms: 60, | 72 | poll_ms: 60, |
| 65 | max_packet_size: 64, | 73 | max_packet_size: 64, |
| 74 | hid_subclass: HidSubclass::Boot, | ||
| 75 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 66 | }; | 76 | }; |
| 67 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 77 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 68 | 78 | ||
| @@ -86,30 +96,46 @@ async fn main(_spawner: Spawner) { | |||
| 86 | info!("Waiting for HIGH on pin 16"); | 96 | info!("Waiting for HIGH on pin 16"); |
| 87 | signal_pin.wait_for_high().await; | 97 | signal_pin.wait_for_high().await; |
| 88 | info!("HIGH DETECTED"); | 98 | info!("HIGH DETECTED"); |
| 89 | // Create a report with the A key pressed. (no shift modifier) | 99 | |
| 90 | let report = KeyboardReport { | 100 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 91 | keycodes: [4, 0, 0, 0, 0, 0], | 101 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 92 | leds: 0, | 102 | Ok(()) => {} |
| 93 | modifier: 0, | 103 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 94 | reserved: 0, | 104 | }; |
| 95 | }; | 105 | } else { |
| 96 | // Send the report. | 106 | // Create a report with the A key pressed. (no shift modifier) |
| 97 | match writer.write_serialize(&report).await { | 107 | let report = KeyboardReport { |
| 98 | Ok(()) => {} | 108 | keycodes: [4, 0, 0, 0, 0, 0], |
| 99 | Err(e) => warn!("Failed to send report: {:?}", e), | 109 | leds: 0, |
| 100 | }; | 110 | modifier: 0, |
| 111 | reserved: 0, | ||
| 112 | }; | ||
| 113 | // Send the report. | ||
| 114 | match writer.write_serialize(&report).await { | ||
| 115 | Ok(()) => {} | ||
| 116 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 117 | }; | ||
| 118 | } | ||
| 119 | |||
| 101 | signal_pin.wait_for_low().await; | 120 | signal_pin.wait_for_low().await; |
| 102 | info!("LOW DETECTED"); | 121 | info!("LOW DETECTED"); |
| 103 | let report = KeyboardReport { | 122 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 104 | keycodes: [0, 0, 0, 0, 0, 0], | 123 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 105 | leds: 0, | 124 | Ok(()) => {} |
| 106 | modifier: 0, | 125 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 107 | reserved: 0, | 126 | }; |
| 108 | }; | 127 | } else { |
| 109 | match writer.write_serialize(&report).await { | 128 | let report = KeyboardReport { |
| 110 | Ok(()) => {} | 129 | keycodes: [0, 0, 0, 0, 0, 0], |
| 111 | Err(e) => warn!("Failed to send report: {:?}", e), | 130 | leds: 0, |
| 112 | }; | 131 | modifier: 0, |
| 132 | reserved: 0, | ||
| 133 | }; | ||
| 134 | match writer.write_serialize(&report).await { | ||
| 135 | Ok(()) => {} | ||
| 136 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 137 | }; | ||
| 138 | } | ||
| 113 | } | 139 | } |
| 114 | }; | 140 | }; |
| 115 | 141 | ||
| @@ -135,6 +161,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 135 | OutResponse::Accepted | 161 | OutResponse::Accepted |
| 136 | } | 162 | } |
| 137 | 163 | ||
| 164 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 165 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 166 | info!("The current HID protocol mode is: {}", protocol); | ||
| 167 | protocol | ||
| 168 | } | ||
| 169 | |||
| 170 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 171 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 172 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 173 | OutResponse::Accepted | ||
| 174 | } | ||
| 175 | |||
| 138 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 176 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 139 | info!("Set idle rate for {:?} to {:?}", id, dur); | 177 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 140 | } | 178 | } |
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index 4454c593c..dc331cbdd 100755 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -11,7 +11,9 @@ use embassy_rp::clocks::RoscRng; | |||
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver, InterruptHandler}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{ |
| 15 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 15 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 16 | use embassy_usb::{Builder, Config, Handler}; | 18 | use embassy_usb::{Builder, Config, Handler}; |
| 17 | use rand::Rng; | 19 | use rand::Rng; |
| @@ -22,6 +24,8 @@ bind_interrupts!(struct Irqs { | |||
| 22 | USBCTRL_IRQ => InterruptHandler<USB>; | 24 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 23 | }); | 25 | }); |
| 24 | 26 | ||
| 27 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 28 | |||
| 25 | #[embassy_executor::main] | 29 | #[embassy_executor::main] |
| 26 | async fn main(_spawner: Spawner) { | 30 | async fn main(_spawner: Spawner) { |
| 27 | let p = embassy_rp::init(Default::default()); | 31 | let p = embassy_rp::init(Default::default()); |
| @@ -35,6 +39,10 @@ async fn main(_spawner: Spawner) { | |||
| 35 | config.serial_number = Some("12345678"); | 39 | config.serial_number = Some("12345678"); |
| 36 | config.max_power = 100; | 40 | config.max_power = 100; |
| 37 | config.max_packet_size_0 = 64; | 41 | config.max_packet_size_0 = 64; |
| 42 | config.composite_with_iads = false; | ||
| 43 | config.device_class = 0; | ||
| 44 | config.device_sub_class = 0; | ||
| 45 | config.device_protocol = 0; | ||
| 38 | 46 | ||
| 39 | // Create embassy-usb DeviceBuilder using the driver and config. | 47 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 40 | // It needs some buffers for building the descriptors. | 48 | // It needs some buffers for building the descriptors. |
| @@ -65,6 +73,8 @@ async fn main(_spawner: Spawner) { | |||
| 65 | request_handler: None, | 73 | request_handler: None, |
| 66 | poll_ms: 60, | 74 | poll_ms: 60, |
| 67 | max_packet_size: 64, | 75 | max_packet_size: 64, |
| 76 | hid_subclass: HidSubclass::Boot, | ||
| 77 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 68 | }; | 78 | }; |
| 69 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 79 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 70 | 80 | ||
| @@ -83,17 +93,29 @@ async fn main(_spawner: Spawner) { | |||
| 83 | loop { | 93 | loop { |
| 84 | // every 1 second | 94 | // every 1 second |
| 85 | _ = Timer::after_secs(1).await; | 95 | _ = Timer::after_secs(1).await; |
| 86 | let report = MouseReport { | 96 | |
| 87 | buttons: 0, | 97 | let x = rng.random_range(-100..100); // random small x movement |
| 88 | x: rng.random_range(-100..100), // random small x movement | 98 | let y = rng.random_range(-100..100); // random small y movement |
| 89 | y: rng.random_range(-100..100), // random small y movement | 99 | |
| 90 | wheel: 0, | 100 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 91 | pan: 0, | 101 | let buttons = 0u8; |
| 92 | }; | 102 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 93 | // Send the report. | 103 | Ok(()) => {} |
| 94 | match writer.write_serialize(&report).await { | 104 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 95 | Ok(()) => {} | 105 | } |
| 96 | Err(e) => warn!("Failed to send report: {:?}", e), | 106 | } else { |
| 107 | let report = MouseReport { | ||
| 108 | buttons: 0, | ||
| 109 | x, | ||
| 110 | y, | ||
| 111 | wheel: 0, | ||
| 112 | pan: 0, | ||
| 113 | }; | ||
| 114 | // Send the report. | ||
| 115 | match writer.write_serialize(&report).await { | ||
| 116 | Ok(()) => {} | ||
| 117 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 118 | } | ||
| 97 | } | 119 | } |
| 98 | } | 120 | } |
| 99 | }; | 121 | }; |
| @@ -120,6 +142,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 120 | OutResponse::Accepted | 142 | OutResponse::Accepted |
| 121 | } | 143 | } |
| 122 | 144 | ||
| 145 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 146 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 147 | info!("The current HID protocol mode is: {}", protocol); | ||
| 148 | protocol | ||
| 149 | } | ||
| 150 | |||
| 151 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 152 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 153 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 154 | OutResponse::Accepted | ||
| 155 | } | ||
| 156 | |||
| 123 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 157 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 124 | info!("Set idle rate for {:?} to {:?}", id, dur); | 158 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 125 | } | 159 | } |
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index b79012acb..23d0c9e8b 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs | |||
| @@ -10,9 +10,9 @@ use embassy_executor::Spawner; | |||
| 10 | use embassy_rp::bind_interrupts; | 10 | use embassy_rp::bind_interrupts; |
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver, Instance, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver, Instance, InterruptHandler}; |
| 13 | use embassy_usb::UsbDevice; | ||
| 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 14 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 14 | use embassy_usb::driver::EndpointError; | 15 | use embassy_usb::driver::EndpointError; |
| 15 | use embassy_usb::UsbDevice; | ||
| 16 | use static_cell::StaticCell; | 16 | use static_cell::StaticCell; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 128599e0d..0828dbbb9 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use core::str::from_utf8; | 8 | use core::str::from_utf8; |
| 9 | 9 | ||
| 10 | use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; | 10 | use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; |
| 11 | use defmt::*; | 11 | use defmt::*; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_net::tcp::TcpSocket; | 13 | use embassy_net::tcp::TcpSocket; |
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index b2e08c517..aa6ee4df0 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #![no_std] | 5 | #![no_std] |
| 6 | #![no_main] | 6 | #![no_main] |
| 7 | 7 | ||
| 8 | use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; | 8 | use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; |
| 9 | use defmt::*; | 9 | use defmt::*; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_rp::bind_interrupts; | 11 | use embassy_rp::bind_interrupts; |
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index c884aa2ba..7e3de1db9 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use core::str; | 8 | use core::str; |
| 9 | 9 | ||
| 10 | use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; | 10 | use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; |
| 11 | use defmt::*; | 11 | use defmt::*; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_rp::bind_interrupts; | 13 | use embassy_rp::bind_interrupts; |
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 126475779..ef8d08b76 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | use core::str::from_utf8; | 8 | use core::str::from_utf8; |
| 9 | 9 | ||
| 10 | use cyw43::JoinOptions; | 10 | use cyw43::JoinOptions; |
| 11 | use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; | 11 | use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; |
| 12 | use defmt::*; | 12 | use defmt::*; |
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_net::tcp::TcpSocket; | 14 | use embassy_net::tcp::TcpSocket; |
| @@ -101,7 +101,7 @@ async fn main(spawner: Spawner) { | |||
| 101 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) | 101 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 102 | .await | 102 | .await |
| 103 | { | 103 | { |
| 104 | info!("join failed with status={}", err.status); | 104 | info!("join failed: {:?}", err); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | info!("waiting for link..."); | 107 | info!("waiting for link..."); |
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index 079def370..069afc794 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs | |||
| @@ -1,14 +1,13 @@ | |||
| 1 | //! This example uses the RP Pico W board Wifi chip (cyw43). | 1 | //! This example uses the RP Pico W board Wifi chip (cyw43). |
| 2 | //! Connects to Wifi network and makes a web request to get the current time. | 2 | //! Connects to Wifi network and makes a web request to httpbin.org. |
| 3 | 3 | ||
| 4 | #![no_std] | 4 | #![no_std] |
| 5 | #![no_main] | 5 | #![no_main] |
| 6 | #![allow(async_fn_in_trait)] | ||
| 7 | 6 | ||
| 8 | use core::str::from_utf8; | 7 | use core::str::from_utf8; |
| 9 | 8 | ||
| 10 | use cyw43::JoinOptions; | 9 | use cyw43::JoinOptions; |
| 11 | use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; | 10 | use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi}; |
| 12 | use defmt::*; | 11 | use defmt::*; |
| 13 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 14 | use embassy_net::dns::DnsSocket; | 13 | use embassy_net::dns::DnsSocket; |
| @@ -20,11 +19,14 @@ use embassy_rp::gpio::{Level, Output}; | |||
| 20 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; | 19 | use embassy_rp::peripherals::{DMA_CH0, PIO0}; |
| 21 | use embassy_rp::pio::{InterruptHandler, Pio}; | 20 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 22 | use embassy_time::{Duration, Timer}; | 21 | use embassy_time::{Duration, Timer}; |
| 23 | use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; | 22 | use reqwless::client::HttpClient; |
| 23 | // Uncomment these for TLS requests: | ||
| 24 | // use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; | ||
| 24 | use reqwless::request::Method; | 25 | use reqwless::request::Method; |
| 25 | use serde::Deserialize; | 26 | use serde::Deserialize; |
| 27 | use serde_json_core::from_slice; | ||
| 26 | use static_cell::StaticCell; | 28 | use static_cell::StaticCell; |
| 27 | use {defmt_rtt as _, panic_probe as _, serde_json_core}; | 29 | use {defmt_rtt as _, panic_probe as _}; |
| 28 | 30 | ||
| 29 | bind_interrupts!(struct Irqs { | 31 | bind_interrupts!(struct Irqs { |
| 30 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | 32 | PIO0_IRQ_0 => InterruptHandler<PIO0>; |
| @@ -104,7 +106,7 @@ async fn main(spawner: Spawner) { | |||
| 104 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) | 106 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 105 | .await | 107 | .await |
| 106 | { | 108 | { |
| 107 | info!("join failed with status={}", err.status); | 109 | info!("join failed: {:?}", err); |
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | info!("waiting for link..."); | 112 | info!("waiting for link..."); |
| @@ -119,64 +121,90 @@ async fn main(spawner: Spawner) { | |||
| 119 | // And now we can use it! | 121 | // And now we can use it! |
| 120 | 122 | ||
| 121 | loop { | 123 | loop { |
| 122 | let mut rx_buffer = [0; 8192]; | 124 | let mut rx_buffer = [0; 4096]; |
| 123 | let mut tls_read_buffer = [0; 16640]; | 125 | // Uncomment these for TLS requests: |
| 124 | let mut tls_write_buffer = [0; 16640]; | 126 | // let mut tls_read_buffer = [0; 16640]; |
| 127 | // let mut tls_write_buffer = [0; 16640]; | ||
| 125 | 128 | ||
| 126 | let client_state = TcpClientState::<1, 1024, 1024>::new(); | 129 | let client_state = TcpClientState::<1, 4096, 4096>::new(); |
| 127 | let tcp_client = TcpClient::new(stack, &client_state); | 130 | let tcp_client = TcpClient::new(stack, &client_state); |
| 128 | let dns_client = DnsSocket::new(stack); | 131 | let dns_client = DnsSocket::new(stack); |
| 129 | let tls_config = TlsConfig::new(seed, &mut tls_read_buffer, &mut tls_write_buffer, TlsVerify::None); | 132 | // Uncomment these for TLS requests: |
| 133 | // let tls_config = TlsConfig::new(seed, &mut tls_read_buffer, &mut tls_write_buffer, TlsVerify::None); | ||
| 130 | 134 | ||
| 131 | let mut http_client = HttpClient::new_with_tls(&tcp_client, &dns_client, tls_config); | 135 | // Using non-TLS HTTP for this example |
| 132 | let url = "https://worldtimeapi.org/api/timezone/Europe/Berlin"; | 136 | let mut http_client = HttpClient::new(&tcp_client, &dns_client); |
| 133 | // for non-TLS requests, use this instead: | 137 | let url = "http://httpbin.org/json"; |
| 134 | // let mut http_client = HttpClient::new(&tcp_client, &dns_client); | 138 | // For TLS requests, use this instead: |
| 135 | // let url = "http://worldtimeapi.org/api/timezone/Europe/Berlin"; | 139 | // let mut http_client = HttpClient::new_with_tls(&tcp_client, &dns_client, tls_config); |
| 140 | // let url = "https://httpbin.org/json"; | ||
| 136 | 141 | ||
| 137 | info!("connecting to {}", &url); | 142 | info!("connecting to {}", &url); |
| 138 | 143 | ||
| 139 | let mut request = match http_client.request(Method::GET, &url).await { | 144 | let mut request = match http_client.request(Method::GET, url).await { |
| 140 | Ok(req) => req, | 145 | Ok(req) => req, |
| 141 | Err(e) => { | 146 | Err(e) => { |
| 142 | error!("Failed to make HTTP request: {:?}", e); | 147 | error!("Failed to make HTTP request: {:?}", e); |
| 143 | return; // handle the error | 148 | Timer::after(Duration::from_secs(5)).await; |
| 149 | continue; | ||
| 144 | } | 150 | } |
| 145 | }; | 151 | }; |
| 146 | 152 | ||
| 147 | let response = match request.send(&mut rx_buffer).await { | 153 | let response = match request.send(&mut rx_buffer).await { |
| 148 | Ok(resp) => resp, | 154 | Ok(resp) => resp, |
| 149 | Err(_e) => { | 155 | Err(e) => { |
| 150 | error!("Failed to send HTTP request"); | 156 | error!("Failed to send HTTP request: {:?}", e); |
| 151 | return; // handle the error; | 157 | Timer::after(Duration::from_secs(5)).await; |
| 158 | continue; | ||
| 152 | } | 159 | } |
| 153 | }; | 160 | }; |
| 154 | 161 | ||
| 155 | let body = match from_utf8(response.body().read_to_end().await.unwrap()) { | 162 | info!("Response status: {}", response.status.0); |
| 163 | |||
| 164 | let body_bytes = match response.body().read_to_end().await { | ||
| 156 | Ok(b) => b, | 165 | Ok(b) => b, |
| 157 | Err(_e) => { | 166 | Err(_e) => { |
| 158 | error!("Failed to read response body"); | 167 | error!("Failed to read response body"); |
| 159 | return; // handle the error | 168 | Timer::after(Duration::from_secs(5)).await; |
| 169 | continue; | ||
| 170 | } | ||
| 171 | }; | ||
| 172 | |||
| 173 | let body = match from_utf8(body_bytes) { | ||
| 174 | Ok(b) => b, | ||
| 175 | Err(_e) => { | ||
| 176 | error!("Failed to parse response body as UTF-8"); | ||
| 177 | Timer::after(Duration::from_secs(5)).await; | ||
| 178 | continue; | ||
| 160 | } | 179 | } |
| 161 | }; | 180 | }; |
| 162 | info!("Response body: {:?}", &body); | 181 | info!("Response body length: {} bytes", body.len()); |
| 163 | 182 | ||
| 164 | // parse the response body and update the RTC | 183 | // Parse the JSON response from httpbin.org/json |
| 184 | #[derive(Deserialize)] | ||
| 185 | struct SlideShow<'a> { | ||
| 186 | author: &'a str, | ||
| 187 | title: &'a str, | ||
| 188 | } | ||
| 165 | 189 | ||
| 166 | #[derive(Deserialize)] | 190 | #[derive(Deserialize)] |
| 167 | struct ApiResponse<'a> { | 191 | struct HttpBinResponse<'a> { |
| 168 | datetime: &'a str, | 192 | #[serde(borrow)] |
| 169 | // other fields as needed | 193 | slideshow: SlideShow<'a>, |
| 170 | } | 194 | } |
| 171 | 195 | ||
| 172 | let bytes = body.as_bytes(); | 196 | let bytes = body.as_bytes(); |
| 173 | match serde_json_core::de::from_slice::<ApiResponse>(bytes) { | 197 | match from_slice::<HttpBinResponse>(bytes) { |
| 174 | Ok((output, _used)) => { | 198 | Ok((output, _used)) => { |
| 175 | info!("Datetime: {:?}", output.datetime); | 199 | info!("Successfully parsed JSON response!"); |
| 200 | info!("Slideshow title: {:?}", output.slideshow.title); | ||
| 201 | info!("Slideshow author: {:?}", output.slideshow.author); | ||
| 176 | } | 202 | } |
| 177 | Err(_e) => { | 203 | Err(e) => { |
| 178 | error!("Failed to parse response body"); | 204 | error!("Failed to parse JSON response: {}", Debug2Format(&e)); |
| 179 | return; // handle the error | 205 | // Log preview of response for debugging |
| 206 | let preview = if body.len() > 200 { &body[..200] } else { body }; | ||
| 207 | info!("Response preview: {:?}", preview); | ||
| 180 | } | 208 | } |
| 181 | } | 209 | } |
| 182 | 210 | ||
diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs index d603e1ed3..fc5f95e6e 100644 --- a/examples/rp/src/bin/zerocopy.rs +++ b/examples/rp/src/bin/zerocopy.rs | |||
| @@ -11,7 +11,7 @@ use embassy_executor::Spawner; | |||
| 11 | use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; | 11 | use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; |
| 12 | use embassy_rp::gpio::Pull; | 12 | use embassy_rp::gpio::Pull; |
| 13 | use embassy_rp::peripherals::DMA_CH0; | 13 | use embassy_rp::peripherals::DMA_CH0; |
| 14 | use embassy_rp::{bind_interrupts, Peri}; | 14 | use embassy_rp::{Peri, bind_interrupts}; |
| 15 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | 15 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; |
| 16 | use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; | 16 | use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; |
| 17 | use embassy_time::{Duration, Ticker, Timer}; | 17 | use embassy_time::{Duration, Ticker, Timer}; |
diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 40fbb5798..16dfb5b77 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-rp2350-examples" | 3 | name = "embassy-rp2350-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -11,14 +11,14 @@ embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", | |||
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 14 | embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } | 14 | embassy-rp = { version = "0.9.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } |
| 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 16 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } | 16 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } |
| 17 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } | 17 | embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } |
| 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | 18 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 19 | embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } | 19 | embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } |
| 20 | cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } | 20 | cyw43 = { version = "0.6.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } |
| 21 | cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } | 21 | cyw43-pio = { version = "0.9.0", path = "../../cyw43-pio", features = ["defmt"] } |
| 22 | 22 | ||
| 23 | defmt = "1.0.1" | 23 | defmt = "1.0.1" |
| 24 | defmt-rtt = "1.0.0" | 24 | defmt-rtt = "1.0.0" |
| @@ -46,7 +46,7 @@ display-interface = "0.5.0" | |||
| 46 | byte-slice-cast = { version = "1.2.0", default-features = false } | 46 | byte-slice-cast = { version = "1.2.0", default-features = false } |
| 47 | smart-leds = "0.3.0" | 47 | smart-leds = "0.3.0" |
| 48 | heapless = "0.8" | 48 | heapless = "0.8" |
| 49 | usbd-hid = "0.8.1" | 49 | usbd-hid = "0.9.0" |
| 50 | 50 | ||
| 51 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 51 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 52 | embedded-hal-async = "1.0" | 52 | embedded-hal-async = "1.0" |
diff --git a/examples/rp235x/src/bin/assign_resources.rs b/examples/rp235x/src/bin/assign_resources.rs index 4ee4278b5..aaa134768 100644 --- a/examples/rp235x/src/bin/assign_resources.rs +++ b/examples/rp235x/src/bin/assign_resources.rs | |||
| @@ -14,9 +14,9 @@ | |||
| 14 | use assign_resources::assign_resources; | 14 | use assign_resources::assign_resources; |
| 15 | use defmt::*; | 15 | use defmt::*; |
| 16 | use embassy_executor::Spawner; | 16 | use embassy_executor::Spawner; |
| 17 | use embassy_rp::Peri; | ||
| 17 | use embassy_rp::gpio::{Level, Output}; | 18 | use embassy_rp::gpio::{Level, Output}; |
| 18 | use embassy_rp::peripherals::{self, PIN_20, PIN_21}; | 19 | use embassy_rp::peripherals::{self, PIN_20, PIN_21}; |
| 19 | use embassy_rp::Peri; | ||
| 20 | use embassy_time::Timer; | 20 | use embassy_time::Timer; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 22 | 22 | ||
diff --git a/examples/rp235x/src/bin/debounce.rs b/examples/rp235x/src/bin/debounce.rs index 0077f19fc..6eeb01d0a 100644 --- a/examples/rp235x/src/bin/debounce.rs +++ b/examples/rp235x/src/bin/debounce.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | use defmt::info; | 7 | use defmt::info; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_rp::gpio::{Input, Level, Pull}; | 9 | use embassy_rp::gpio::{Input, Level, Pull}; |
| 10 | use embassy_time::{with_deadline, Duration, Instant, Timer}; | 10 | use embassy_time::{Duration, Instant, Timer, with_deadline}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | pub struct Debouncer<'a> { | 13 | pub struct Debouncer<'a> { |
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs index 309d3e4f7..227e68029 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs | |||
| @@ -12,8 +12,8 @@ use core::str::FromStr; | |||
| 12 | use defmt::*; | 12 | use defmt::*; |
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_futures::yield_now; | 14 | use embassy_futures::yield_now; |
| 15 | use embassy_net::icmp::ping::{PingManager, PingParams}; | ||
| 16 | use embassy_net::icmp::PacketMetadata; | 15 | use embassy_net::icmp::PacketMetadata; |
| 16 | use embassy_net::icmp::ping::{PingManager, PingParams}; | ||
| 17 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; | 17 | use embassy_net::{Ipv4Cidr, Stack, StackResources}; |
| 18 | use embassy_net_wiznet::chip::W5500; | 18 | use embassy_net_wiznet::chip::W5500; |
| 19 | use embassy_net_wiznet::*; | 19 | use embassy_net_wiznet::*; |
| @@ -99,7 +99,7 @@ async fn main(spawner: Spawner) { | |||
| 99 | // Create the ping manager instance | 99 | // Create the ping manager instance |
| 100 | let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | 100 | let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); |
| 101 | let addr = "192.168.8.1"; // Address to ping to | 101 | let addr = "192.168.8.1"; // Address to ping to |
| 102 | // Create the PingParams with the target address | 102 | // Create the PingParams with the target address |
| 103 | let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); | 103 | let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); |
| 104 | // (optional) Set custom properties of the ping | 104 | // (optional) Set custom properties of the ping |
| 105 | ping_params.set_payload(b"Hello, Ping!"); // custom payload | 105 | ping_params.set_payload(b"Hello, Ping!"); // custom payload |
diff --git a/examples/rp235x/src/bin/interrupt.rs b/examples/rp235x/src/bin/interrupt.rs index 88513180c..1b18f6931 100644 --- a/examples/rp235x/src/bin/interrupt.rs +++ b/examples/rp235x/src/bin/interrupt.rs | |||
| @@ -16,8 +16,8 @@ use embassy_rp::adc::{self, Adc, Blocking}; | |||
| 16 | use embassy_rp::gpio::Pull; | 16 | use embassy_rp::gpio::Pull; |
| 17 | use embassy_rp::interrupt; | 17 | use embassy_rp::interrupt; |
| 18 | use embassy_rp::pwm::{Config, Pwm}; | 18 | use embassy_rp::pwm::{Config, Pwm}; |
| 19 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 20 | use embassy_sync::blocking_mutex::Mutex; | 19 | use embassy_sync::blocking_mutex::Mutex; |
| 20 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 21 | use embassy_sync::channel::Channel; | 21 | use embassy_sync::channel::Channel; |
| 22 | use embassy_time::{Duration, Ticker}; | 22 | use embassy_time::{Duration, Ticker}; |
| 23 | use portable_atomic::{AtomicU32, Ordering}; | 23 | use portable_atomic::{AtomicU32, Ordering}; |
diff --git a/examples/rp235x/src/bin/multicore.rs b/examples/rp235x/src/bin/multicore.rs index 4f82801d6..9b61fdbca 100644 --- a/examples/rp235x/src/bin/multicore.rs +++ b/examples/rp235x/src/bin/multicore.rs | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_rp::gpio::{Level, Output}; | 10 | use embassy_rp::gpio::{Level, Output}; |
| 11 | use embassy_rp::multicore::{spawn_core1, Stack}; | 11 | use embassy_rp::multicore::{Stack, spawn_core1}; |
| 12 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 12 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 13 | use embassy_sync::channel::Channel; | 13 | use embassy_sync::channel::Channel; |
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
diff --git a/examples/rp235x/src/bin/multicore_stack_overflow.rs b/examples/rp235x/src/bin/multicore_stack_overflow.rs index dba44aa23..9efe89318 100644 --- a/examples/rp235x/src/bin/multicore_stack_overflow.rs +++ b/examples/rp235x/src/bin/multicore_stack_overflow.rs | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Executor; | 7 | use embassy_executor::Executor; |
| 8 | use embassy_rp::gpio::{Level, Output}; | 8 | use embassy_rp::gpio::{Level, Output}; |
| 9 | use embassy_rp::multicore::{spawn_core1, Stack}; | 9 | use embassy_rp::multicore::{Stack, spawn_core1}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use static_cell::StaticCell; | 11 | use static_cell::StaticCell; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/rp235x/src/bin/multiprio.rs b/examples/rp235x/src/bin/multiprio.rs index 96cdf8fb1..310047505 100644 --- a/examples/rp235x/src/bin/multiprio.rs +++ b/examples/rp235x/src/bin/multiprio.rs | |||
| @@ -61,7 +61,7 @@ use defmt::{info, unwrap}; | |||
| 61 | use embassy_executor::{Executor, InterruptExecutor}; | 61 | use embassy_executor::{Executor, InterruptExecutor}; |
| 62 | use embassy_rp::interrupt; | 62 | use embassy_rp::interrupt; |
| 63 | use embassy_rp::interrupt::{InterruptExt, Priority}; | 63 | use embassy_rp::interrupt::{InterruptExt, Priority}; |
| 64 | use embassy_time::{Instant, Timer, TICK_HZ}; | 64 | use embassy_time::{Instant, TICK_HZ, Timer}; |
| 65 | use static_cell::StaticCell; | 65 | use static_cell::StaticCell; |
| 66 | use {defmt_rtt as _, panic_probe as _}; | 66 | use {defmt_rtt as _, panic_probe as _}; |
| 67 | 67 | ||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn SWI_IRQ_1() { | 115 | unsafe fn SWI_IRQ_1() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn SWI_IRQ_0() { | 120 | unsafe fn SWI_IRQ_0() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs index 5fd97ef97..cba137f3a 100644 --- a/examples/rp235x/src/bin/overclock.rs +++ b/examples/rp235x/src/bin/overclock.rs | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | use defmt::*; | 13 | use defmt::*; |
| 14 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 15 | use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; | 15 | use embassy_rp::clocks::{ClockConfig, CoreVoltage, clk_sys_freq, core_voltage}; |
| 16 | use embassy_rp::config::Config; | 16 | use embassy_rp::config::Config; |
| 17 | use embassy_rp::gpio::{Level, Output}; | 17 | use embassy_rp::gpio::{Level, Output}; |
| 18 | use embassy_time::{Duration, Instant, Timer}; | 18 | use embassy_time::{Duration, Instant, Timer}; |
diff --git a/examples/rp235x/src/bin/pio_async.rs b/examples/rp235x/src/bin/pio_async.rs index d76930f5c..a392fe37e 100644 --- a/examples/rp235x/src/bin/pio_async.rs +++ b/examples/rp235x/src/bin/pio_async.rs | |||
| @@ -7,7 +7,7 @@ use embassy_executor::Spawner; | |||
| 7 | use embassy_rp::peripherals::PIO0; | 7 | use embassy_rp::peripherals::PIO0; |
| 8 | use embassy_rp::pio::program::pio_asm; | 8 | use embassy_rp::pio::program::pio_asm; |
| 9 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; | 9 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; |
| 10 | use embassy_rp::{bind_interrupts, Peri}; | 10 | use embassy_rp::{Peri, bind_interrupts}; |
| 11 | use fixed::traits::ToFixed; | 11 | use fixed::traits::ToFixed; |
| 12 | use fixed_macro::types::U56F8; | 12 | use fixed_macro::types::U56F8; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/rp235x/src/bin/pio_i2s.rs b/examples/rp235x/src/bin/pio_i2s.rs index cfcb0221d..7ed952a40 100644 --- a/examples/rp235x/src/bin/pio_i2s.rs +++ b/examples/rp235x/src/bin/pio_i2s.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | //! bclk : GPIO 18 | 5 | //! bclk : GPIO 18 |
| 6 | //! lrc : GPIO 19 | 6 | //! lrc : GPIO 19 |
| 7 | //! din : GPIO 20 | 7 | //! din : GPIO 20 |
| 8 | //! Then hold down the boot select button to trigger a rising triangle waveform. | 8 | //! Then short GPIO 0 to GND to trigger a rising triangle waveform. |
| 9 | 9 | ||
| 10 | #![no_std] | 10 | #![no_std] |
| 11 | #![no_main] | 11 | #![no_main] |
| @@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) { | |||
| 70 | // but don't await the returned future, yet | 70 | // but don't await the returned future, yet |
| 71 | let dma_future = i2s.write(front_buffer); | 71 | let dma_future = i2s.write(front_buffer); |
| 72 | 72 | ||
| 73 | // fade in audio when bootsel is pressed | 73 | // fade in audio when GPIO 0 pin is shorted to GND |
| 74 | let fade_target = if fade_input.is_low() { i32::MAX } else { 0 }; | 74 | let fade_target = if fade_input.is_low() { i32::MAX } else { 0 }; |
| 75 | 75 | ||
| 76 | // fill back buffer with fresh audio samples before awaiting the dma future | 76 | // fill back buffer with fresh audio samples before awaiting the dma future |
diff --git a/examples/rp235x/src/bin/pio_i2s_rx.rs b/examples/rp235x/src/bin/pio_i2s_rx.rs index c3f505b13..6735c402f 100644 --- a/examples/rp235x/src/bin/pio_i2s_rx.rs +++ b/examples/rp235x/src/bin/pio_i2s_rx.rs | |||
| @@ -34,7 +34,7 @@ const SAMPLE_RATE: u32 = 48_000; | |||
| 34 | const BIT_DEPTH: u32 = 16; | 34 | const BIT_DEPTH: u32 = 16; |
| 35 | const CHANNELS: u32 = 2; | 35 | const CHANNELS: u32 = 2; |
| 36 | const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor, | 36 | const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor, |
| 37 | // which has documented issues on many RP235x boards | 37 | // which has documented issues on many RP235x boards |
| 38 | #[embassy_executor::main] | 38 | #[embassy_executor::main] |
| 39 | async fn main(_spawner: Spawner) { | 39 | async fn main(_spawner: Spawner) { |
| 40 | let p = embassy_rp::init(Default::default()); | 40 | let p = embassy_rp::init(Default::default()); |
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs index 102f13c45..6432edb8a 100644 --- a/examples/rp235x/src/bin/pio_onewire.rs +++ b/examples/rp235x/src/bin/pio_onewire.rs | |||
| @@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) { | |||
| 61 | let mut data = [0; 9]; | 61 | let mut data = [0; 9]; |
| 62 | onewire.read_bytes(&mut data).await; | 62 | onewire.read_bytes(&mut data).await; |
| 63 | if crc8(&data) == 0 { | 63 | if crc8(&data) == 0 { |
| 64 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; | 64 | let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.; |
| 65 | info!("Read device {:x}: {} deg C", device, temp); | 65 | info!("Read device {:x}: {} deg C", device, temp); |
| 66 | } else { | 66 | } else { |
| 67 | warn!("Reading device {:x} failed", device); | 67 | warn!("Reading device {:x} failed", device); |
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs index fd076dee0..78fb94b18 100644 --- a/examples/rp235x/src/bin/pio_onewire_parasite.rs +++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs | |||
| @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { | |||
| 63 | let mut data = [0; 9]; | 63 | let mut data = [0; 9]; |
| 64 | onewire.read_bytes(&mut data).await; | 64 | onewire.read_bytes(&mut data).await; |
| 65 | if crc8(&data) == 0 { | 65 | if crc8(&data) == 0 { |
| 66 | let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; | 66 | let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.; |
| 67 | info!("Read device {:x}: {} deg C", device, temp); | 67 | info!("Read device {:x}: {} deg C", device, temp); |
| 68 | } else { | 68 | } else { |
| 69 | warn!("Reading device {:x} failed. {:02x}", device, data); | 69 | warn!("Reading device {:x} failed. {:02x}", device, data); |
diff --git a/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs b/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs index 61af94560..948699e40 100644 --- a/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs +++ b/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs | |||
| @@ -9,7 +9,7 @@ use embassy_executor::Spawner; | |||
| 9 | use embassy_rp::gpio::Pull; | 9 | use embassy_rp::gpio::Pull; |
| 10 | use embassy_rp::peripherals::PIO0; | 10 | use embassy_rp::peripherals::PIO0; |
| 11 | use embassy_rp::pio::program::pio_asm; | 11 | use embassy_rp::pio::program::pio_asm; |
| 12 | use embassy_rp::{bind_interrupts, pio, Peri}; | 12 | use embassy_rp::{Peri, bind_interrupts, pio}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use fixed::traits::ToFixed; | 14 | use fixed::traits::ToFixed; |
| 15 | use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; | 15 | use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; |
diff --git a/examples/rp235x/src/bin/pio_stepper.rs b/examples/rp235x/src/bin/pio_stepper.rs index 931adbeda..9b33710ad 100644 --- a/examples/rp235x/src/bin/pio_stepper.rs +++ b/examples/rp235x/src/bin/pio_stepper.rs | |||
| @@ -10,7 +10,7 @@ use embassy_rp::bind_interrupts; | |||
| 10 | use embassy_rp::peripherals::PIO0; | 10 | use embassy_rp::peripherals::PIO0; |
| 11 | use embassy_rp::pio::{InterruptHandler, Pio}; | 11 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 12 | use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram}; | 12 | use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram}; |
| 13 | use embassy_time::{with_timeout, Duration, Timer}; | 13 | use embassy_time::{Duration, Timer, with_timeout}; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | 16 | bind_interrupts!(struct Irqs { |
diff --git a/examples/rp235x/src/bin/pwm.rs b/examples/rp235x/src/bin/pwm.rs index 289480c85..971e86aa7 100644 --- a/examples/rp235x/src/bin/pwm.rs +++ b/examples/rp235x/src/bin/pwm.rs | |||
| @@ -9,9 +9,9 @@ | |||
| 9 | 9 | ||
| 10 | use defmt::*; | 10 | use defmt::*; |
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_rp::peripherals::{PIN_25, PIN_4, PWM_SLICE2, PWM_SLICE4}; | ||
| 13 | use embassy_rp::pwm::{Config, Pwm, SetDutyCycle}; | ||
| 14 | use embassy_rp::Peri; | 12 | use embassy_rp::Peri; |
| 13 | use embassy_rp::peripherals::{PIN_4, PIN_25, PWM_SLICE2, PWM_SLICE4}; | ||
| 14 | use embassy_rp::pwm::{Config, Pwm, SetDutyCycle}; | ||
| 15 | use embassy_time::Timer; | 15 | use embassy_time::Timer; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
diff --git a/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs b/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs index 2cfb2038d..670f302a4 100644 --- a/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs +++ b/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs | |||
| @@ -10,7 +10,7 @@ use defmt::*; | |||
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_rp::config::Config; | 11 | use embassy_rp::config::Config; |
| 12 | use embassy_rp::gpio::Output; | 12 | use embassy_rp::gpio::Output; |
| 13 | use embassy_rp::{gpio, peripherals, pwm, Peri}; | 13 | use embassy_rp::{Peri, gpio, peripherals, pwm}; |
| 14 | use embassy_time::{Duration, Timer}; | 14 | use embassy_time::{Duration, Timer}; |
| 15 | use tb6612fng::{DriveCommand, Motor, Tb6612fng}; | 15 | use tb6612fng::{DriveCommand, Motor, Tb6612fng}; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/rp235x/src/bin/sharing.rs b/examples/rp235x/src/bin/sharing.rs index d4c89946b..618ab9117 100644 --- a/examples/rp235x/src/bin/sharing.rs +++ b/examples/rp235x/src/bin/sharing.rs | |||
| @@ -52,7 +52,7 @@ bind_interrupts!(struct Irqs { | |||
| 52 | 52 | ||
| 53 | #[interrupt] | 53 | #[interrupt] |
| 54 | unsafe fn SWI_IRQ_0() { | 54 | unsafe fn SWI_IRQ_0() { |
| 55 | EXECUTOR_HI.on_interrupt() | 55 | unsafe { EXECUTOR_HI.on_interrupt() } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | #[entry] | 58 | #[entry] |
diff --git a/examples/rp235x/src/bin/spi_display.rs b/examples/rp235x/src/bin/spi_display.rs index 9967abefd..3cef93f62 100644 --- a/examples/rp235x/src/bin/spi_display.rs +++ b/examples/rp235x/src/bin/spi_display.rs | |||
| @@ -15,19 +15,19 @@ use embassy_executor::Spawner; | |||
| 15 | use embassy_rp::gpio::{Level, Output}; | 15 | use embassy_rp::gpio::{Level, Output}; |
| 16 | use embassy_rp::spi; | 16 | use embassy_rp::spi; |
| 17 | use embassy_rp::spi::{Blocking, Spi}; | 17 | use embassy_rp::spi::{Blocking, Spi}; |
| 18 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 19 | use embassy_sync::blocking_mutex::Mutex; | 18 | use embassy_sync::blocking_mutex::Mutex; |
| 19 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 20 | use embassy_time::Delay; | 20 | use embassy_time::Delay; |
| 21 | use embedded_graphics::image::{Image, ImageRawLE}; | 21 | use embedded_graphics::image::{Image, ImageRawLE}; |
| 22 | use embedded_graphics::mono_font::ascii::FONT_10X20; | ||
| 23 | use embedded_graphics::mono_font::MonoTextStyle; | 22 | use embedded_graphics::mono_font::MonoTextStyle; |
| 23 | use embedded_graphics::mono_font::ascii::FONT_10X20; | ||
| 24 | use embedded_graphics::pixelcolor::Rgb565; | 24 | use embedded_graphics::pixelcolor::Rgb565; |
| 25 | use embedded_graphics::prelude::*; | 25 | use embedded_graphics::prelude::*; |
| 26 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; | 26 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; |
| 27 | use embedded_graphics::text::Text; | 27 | use embedded_graphics::text::Text; |
| 28 | use mipidsi::Builder; | ||
| 28 | use mipidsi::models::ST7789; | 29 | use mipidsi::models::ST7789; |
| 29 | use mipidsi::options::{Orientation, Rotation}; | 30 | use mipidsi::options::{Orientation, Rotation}; |
| 30 | use mipidsi::Builder; | ||
| 31 | use {defmt_rtt as _, panic_probe as _}; | 31 | use {defmt_rtt as _, panic_probe as _}; |
| 32 | 32 | ||
| 33 | use crate::touch::Touch; | 33 | use crate::touch::Touch; |
| @@ -167,11 +167,7 @@ mod touch { | |||
| 167 | 167 | ||
| 168 | let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); | 168 | let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); |
| 169 | let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); | 169 | let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); |
| 170 | if x == 0 && y == 0 { | 170 | if x == 0 && y == 0 { None } else { Some((x, y)) } |
| 171 | None | ||
| 172 | } else { | ||
| 173 | Some((x, y)) | ||
| 174 | } | ||
| 175 | } | 171 | } |
| 176 | } | 172 | } |
| 177 | } | 173 | } |
diff --git a/examples/rp235x/src/bin/uart_r503.rs b/examples/rp235x/src/bin/uart_r503.rs index 085be280b..a25d45b18 100644 --- a/examples/rp235x/src/bin/uart_r503.rs +++ b/examples/rp235x/src/bin/uart_r503.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_rp::bind_interrupts; | 6 | use embassy_rp::bind_interrupts; |
| 7 | use embassy_rp::peripherals::UART0; | 7 | use embassy_rp::peripherals::UART0; |
| 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; | 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; |
| 9 | use embassy_time::{with_timeout, Duration, Timer}; | 9 | use embassy_time::{Duration, Timer, with_timeout}; |
| 10 | use heapless::Vec; | 10 | use heapless::Vec; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/rp235x/src/bin/usb_hid_keyboard.rs b/examples/rp235x/src/bin/usb_hid_keyboard.rs index 6f496e23a..d8f64c470 100644 --- a/examples/rp235x/src/bin/usb_hid_keyboard.rs +++ b/examples/rp235x/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| @@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts; | |||
| 10 | use embassy_rp::gpio::{Input, Pull}; | 10 | use embassy_rp::gpio::{Input, Pull}; |
| 11 | use embassy_rp::peripherals::USB; | 11 | use embassy_rp::peripherals::USB; |
| 12 | use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; | 12 | use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; |
| 13 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State as HidState}; | 13 | use embassy_usb::class::hid::{ |
| 14 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State as HidState, | ||
| 15 | }; | ||
| 14 | use embassy_usb::control::OutResponse; | 16 | use embassy_usb::control::OutResponse; |
| 15 | use embassy_usb::{Builder, Config, Handler}; | 17 | use embassy_usb::{Builder, Config, Handler}; |
| 16 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -20,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 20 | USBCTRL_IRQ => InterruptHandler<USB>; | 22 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 21 | }); | 23 | }); |
| 22 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 23 | #[embassy_executor::main] | 27 | #[embassy_executor::main] |
| 24 | async fn main(_spawner: Spawner) { | 28 | async fn main(_spawner: Spawner) { |
| 25 | let p = embassy_rp::init(Default::default()); | 29 | let p = embassy_rp::init(Default::default()); |
| @@ -33,6 +37,10 @@ async fn main(_spawner: Spawner) { | |||
| 33 | config.serial_number = Some("12345678"); | 37 | config.serial_number = Some("12345678"); |
| 34 | config.max_power = 100; | 38 | config.max_power = 100; |
| 35 | config.max_packet_size_0 = 64; | 39 | config.max_packet_size_0 = 64; |
| 40 | config.composite_with_iads = false; | ||
| 41 | config.device_class = 0; | ||
| 42 | config.device_sub_class = 0; | ||
| 43 | config.device_protocol = 0; | ||
| 36 | 44 | ||
| 37 | // Create embassy-usb DeviceBuilder using the driver and config. | 45 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 38 | // It needs some buffers for building the descriptors. | 46 | // It needs some buffers for building the descriptors. |
| @@ -63,6 +71,8 @@ async fn main(_spawner: Spawner) { | |||
| 63 | request_handler: None, | 71 | request_handler: None, |
| 64 | poll_ms: 60, | 72 | poll_ms: 60, |
| 65 | max_packet_size: 64, | 73 | max_packet_size: 64, |
| 74 | hid_subclass: HidSubclass::Boot, | ||
| 75 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 66 | }; | 76 | }; |
| 67 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 77 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 68 | 78 | ||
| @@ -86,30 +96,45 @@ async fn main(_spawner: Spawner) { | |||
| 86 | info!("Waiting for HIGH on pin 16"); | 96 | info!("Waiting for HIGH on pin 16"); |
| 87 | signal_pin.wait_for_high().await; | 97 | signal_pin.wait_for_high().await; |
| 88 | info!("HIGH DETECTED"); | 98 | info!("HIGH DETECTED"); |
| 89 | // Create a report with the A key pressed. (no shift modifier) | 99 | |
| 90 | let report = KeyboardReport { | 100 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 91 | keycodes: [4, 0, 0, 0, 0, 0], | 101 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 92 | leds: 0, | 102 | Ok(()) => {} |
| 93 | modifier: 0, | 103 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 94 | reserved: 0, | 104 | }; |
| 95 | }; | 105 | } else { |
| 96 | // Send the report. | 106 | // Create a report with the A key pressed. (no shift modifier) |
| 97 | match writer.write_serialize(&report).await { | 107 | let report = KeyboardReport { |
| 98 | Ok(()) => {} | 108 | keycodes: [4, 0, 0, 0, 0, 0], |
| 99 | Err(e) => warn!("Failed to send report: {:?}", e), | 109 | leds: 0, |
| 100 | }; | 110 | modifier: 0, |
| 111 | reserved: 0, | ||
| 112 | }; | ||
| 113 | // Send the report. | ||
| 114 | match writer.write_serialize(&report).await { | ||
| 115 | Ok(()) => {} | ||
| 116 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 117 | }; | ||
| 118 | } | ||
| 101 | signal_pin.wait_for_low().await; | 119 | signal_pin.wait_for_low().await; |
| 102 | info!("LOW DETECTED"); | 120 | info!("LOW DETECTED"); |
| 103 | let report = KeyboardReport { | 121 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 104 | keycodes: [0, 0, 0, 0, 0, 0], | 122 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 105 | leds: 0, | 123 | Ok(()) => {} |
| 106 | modifier: 0, | 124 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 107 | reserved: 0, | 125 | }; |
| 108 | }; | 126 | } else { |
| 109 | match writer.write_serialize(&report).await { | 127 | let report = KeyboardReport { |
| 110 | Ok(()) => {} | 128 | keycodes: [0, 0, 0, 0, 0, 0], |
| 111 | Err(e) => warn!("Failed to send report: {:?}", e), | 129 | leds: 0, |
| 112 | }; | 130 | modifier: 0, |
| 131 | reserved: 0, | ||
| 132 | }; | ||
| 133 | match writer.write_serialize(&report).await { | ||
| 134 | Ok(()) => {} | ||
| 135 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 136 | }; | ||
| 137 | } | ||
| 113 | } | 138 | } |
| 114 | }; | 139 | }; |
| 115 | 140 | ||
| @@ -135,6 +160,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 135 | OutResponse::Accepted | 160 | OutResponse::Accepted |
| 136 | } | 161 | } |
| 137 | 162 | ||
| 163 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 164 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 165 | info!("The current HID protocol mode is: {}", protocol); | ||
| 166 | protocol | ||
| 167 | } | ||
| 168 | |||
| 169 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 170 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 171 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 172 | OutResponse::Accepted | ||
| 173 | } | ||
| 174 | |||
| 138 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 175 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 139 | info!("Set idle rate for {:?} to {:?}", id, dur); | 176 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 140 | } | 177 | } |
diff --git a/examples/rp235x/src/bin/zerocopy.rs b/examples/rp235x/src/bin/zerocopy.rs index 62ba4cfb8..55deffd5f 100644 --- a/examples/rp235x/src/bin/zerocopy.rs +++ b/examples/rp235x/src/bin/zerocopy.rs | |||
| @@ -11,7 +11,7 @@ use embassy_executor::Spawner; | |||
| 11 | use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; | 11 | use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; |
| 12 | use embassy_rp::gpio::Pull; | 12 | use embassy_rp::gpio::Pull; |
| 13 | use embassy_rp::peripherals::DMA_CH0; | 13 | use embassy_rp::peripherals::DMA_CH0; |
| 14 | use embassy_rp::{bind_interrupts, Peri}; | 14 | use embassy_rp::{Peri, bind_interrupts}; |
| 15 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | 15 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; |
| 16 | use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; | 16 | use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; |
| 17 | use embassy_time::{Duration, Ticker, Timer}; | 17 | use embassy_time::{Duration, Ticker, Timer}; |
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 449c5ddca..6dc6a353d 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-std-examples" | 3 | name = "embassy-std-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs index 82272c798..685dbf3d3 100644 --- a/examples/std/src/bin/net_ppp.rs +++ b/examples/std/src/bin/net_ppp.rs | |||
| @@ -52,7 +52,7 @@ async fn ppp_task(stack: Stack<'static>, mut runner: Runner<'static>, port: Seri | |||
| 52 | password: b"mypass", | 52 | password: b"mypass", |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | runner | 55 | let r = runner |
| 56 | .run(port, config, |ipv4| { | 56 | .run(port, config, |ipv4| { |
| 57 | let Some(addr) = ipv4.address else { | 57 | let Some(addr) = ipv4.address else { |
| 58 | warn!("PPP did not provide an IP address."); | 58 | warn!("PPP did not provide an IP address."); |
| @@ -69,9 +69,10 @@ async fn ppp_task(stack: Stack<'static>, mut runner: Runner<'static>, port: Seri | |||
| 69 | }); | 69 | }); |
| 70 | stack.set_config_v4(config); | 70 | stack.set_config_v4(config); |
| 71 | }) | 71 | }) |
| 72 | .await | 72 | .await; |
| 73 | .unwrap(); | 73 | match r { |
| 74 | unreachable!() | 74 | Err(e) => panic!("{:?}", e), |
| 75 | } | ||
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | #[embassy_executor::task] | 78 | #[embassy_executor::task] |
diff --git a/examples/std/src/bin/tick_cancel.rs b/examples/std/src/bin/tick_cancel.rs new file mode 100644 index 000000000..54e44790f --- /dev/null +++ b/examples/std/src/bin/tick_cancel.rs | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | use std::sync::atomic::{AtomicBool, Ordering}; | ||
| 2 | use std::thread; | ||
| 3 | use std::time::Duration; | ||
| 4 | |||
| 5 | use embassy_executor::Executor; | ||
| 6 | use embassy_time::Timer; | ||
| 7 | use log::*; | ||
| 8 | use static_cell::StaticCell; | ||
| 9 | |||
| 10 | #[embassy_executor::task] | ||
| 11 | async fn run() { | ||
| 12 | loop { | ||
| 13 | info!("tick"); | ||
| 14 | Timer::after_secs(1).await; | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | static DONE: StaticCell<AtomicBool> = StaticCell::new(); | ||
| 19 | static EXECUTOR: StaticCell<Executor> = StaticCell::new(); | ||
| 20 | |||
| 21 | fn main() { | ||
| 22 | env_logger::builder() | ||
| 23 | .filter_level(log::LevelFilter::Debug) | ||
| 24 | .format_timestamp_nanos() | ||
| 25 | .init(); | ||
| 26 | |||
| 27 | let done = DONE.init(AtomicBool::new(false)); | ||
| 28 | let done_cb = || done.load(Ordering::Relaxed); | ||
| 29 | |||
| 30 | let server_thread = thread::spawn(move || { | ||
| 31 | let executor = EXECUTOR.init(Executor::new()); | ||
| 32 | executor.run_until( | ||
| 33 | |spawner| { | ||
| 34 | spawner.spawn(run().unwrap()); | ||
| 35 | }, | ||
| 36 | done_cb, | ||
| 37 | ); | ||
| 38 | info!("Executor finished"); | ||
| 39 | }); | ||
| 40 | |||
| 41 | thread::sleep(Duration::from_secs(5)); | ||
| 42 | |||
| 43 | info!("Cancelling executor"); | ||
| 44 | done.store(true, Ordering::Relaxed); | ||
| 45 | |||
| 46 | server_thread.join().unwrap(); | ||
| 47 | } | ||
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index bb7b57496..696a95854 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32c0-examples" | 3 | name = "embassy-stm32c0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32c0/src/bin/adc.rs b/examples/stm32c0/src/bin/adc.rs index 1f54b0b18..ad597b63c 100644 --- a/examples/stm32c0/src/bin/adc.rs +++ b/examples/stm32c0/src/bin/adc.rs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::vals::Scandir; | ||
| 7 | use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime}; | 6 | use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime}; |
| 8 | use embassy_stm32::peripherals::ADC1; | 7 | use embassy_stm32::peripherals::ADC1; |
| 9 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| @@ -17,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 17 | info!("ADC STM32C0 example."); | 16 | info!("ADC STM32C0 example."); |
| 18 | 17 | ||
| 19 | // We need to set certain sample time to be able to read temp sensor. | 18 | // We need to set certain sample time to be able to read temp sensor. |
| 20 | let mut adc = Adc::new(p.ADC1, SampleTime::CYCLES12_5, Resolution::BITS12); | 19 | let mut adc = Adc::new(p.ADC1, Resolution::BITS12); |
| 21 | let mut temp = adc.enable_temperature().degrade_adc(); | 20 | let mut temp = adc.enable_temperature().degrade_adc(); |
| 22 | let mut vref = adc.enable_vrefint().degrade_adc(); | 21 | let mut vref = adc.enable_vrefint().degrade_adc(); |
| 23 | let mut pin0 = p.PA0.degrade_adc(); | 22 | let mut pin0 = p.PA0.degrade_adc(); |
| @@ -27,16 +26,20 @@ async fn main(_spawner: Spawner) { | |||
| 27 | 26 | ||
| 28 | loop { | 27 | loop { |
| 29 | info!("============================"); | 28 | info!("============================"); |
| 30 | let blocking_temp = adc.blocking_read(&mut temp); | 29 | let blocking_temp = adc.blocking_read(&mut temp, SampleTime::CYCLES12_5); |
| 31 | let blocking_vref = adc.blocking_read(&mut vref); | 30 | let blocking_vref = adc.blocking_read(&mut vref, SampleTime::CYCLES12_5); |
| 32 | let blocing_pin0 = adc.blocking_read(&mut pin0); | 31 | let blocing_pin0 = adc.blocking_read(&mut pin0, SampleTime::CYCLES12_5); |
| 33 | info!( | 32 | info!( |
| 34 | "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", | 33 | "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", |
| 35 | blocking_vref, blocking_temp, blocing_pin0 | 34 | blocking_vref, blocking_temp, blocing_pin0 |
| 36 | ); | 35 | ); |
| 37 | 36 | ||
| 38 | let channels_seqence: [&mut AnyAdcChannel<ADC1>; 3] = [&mut vref, &mut temp, &mut pin0]; | 37 | let channels_sequence: [(&mut AnyAdcChannel<ADC1>, SampleTime); 3] = [ |
| 39 | adc.read(dma.reborrow(), channels_seqence.into_iter(), &mut read_buffer) | 38 | (&mut vref, SampleTime::CYCLES12_5), |
| 39 | (&mut temp, SampleTime::CYCLES12_5), | ||
| 40 | (&mut pin0, SampleTime::CYCLES12_5), | ||
| 41 | ]; | ||
| 42 | adc.read(dma.reborrow(), channels_sequence.into_iter(), &mut read_buffer) | ||
| 40 | .await; | 43 | .await; |
| 41 | // Values are ordered according to hardware ADC channel number! | 44 | // Values are ordered according to hardware ADC channel number! |
| 42 | info!( | 45 | info!( |
| @@ -44,15 +47,6 @@ async fn main(_spawner: Spawner) { | |||
| 44 | read_buffer[0], read_buffer[1], read_buffer[2] | 47 | read_buffer[0], read_buffer[1], read_buffer[2] |
| 45 | ); | 48 | ); |
| 46 | 49 | ||
| 47 | let hw_channel_selection: u32 = | ||
| 48 | (1 << temp.get_hw_channel()) + (1 << vref.get_hw_channel()) + (1 << pin0.get_hw_channel()); | ||
| 49 | adc.read_in_hw_order(dma.reborrow(), hw_channel_selection, Scandir::UP, &mut read_buffer) | ||
| 50 | .await; | ||
| 51 | info!( | ||
| 52 | "DMA ADC read in hardware order: vref = {}, temp = {}, pin0 = {}.", | ||
| 53 | read_buffer[2], read_buffer[1], read_buffer[0] | ||
| 54 | ); | ||
| 55 | |||
| 56 | Timer::after_millis(2000).await; | 50 | Timer::after_millis(2000).await; |
| 57 | } | 51 | } |
| 58 | } | 52 | } |
diff --git a/examples/stm32c0/src/bin/button_exti.rs b/examples/stm32c0/src/bin/button_exti.rs index 34a08bbc6..9d54479da 100644 --- a/examples/stm32c0/src/bin/button_exti.rs +++ b/examples/stm32c0/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs index 82d8a37ba..5ff705ca2 100644 --- a/examples/stm32c0/src/bin/rtc.rs +++ b/examples/stm32c0/src/bin/rtc.rs | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 8 | use embassy_stm32::Config; | 7 | use embassy_stm32::Config; |
| 8 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) { | |||
| 21 | .and_hms_opt(10, 30, 15) | 21 | .and_hms_opt(10, 30, 15) |
| 22 | .unwrap(); | 22 | .unwrap(); |
| 23 | 23 | ||
| 24 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 24 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 25 | 25 | ||
| 26 | rtc.set_datetime(now.into()).expect("datetime not set"); | 26 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| 27 | 27 | ||
| 28 | loop { | 28 | loop { |
| 29 | let now: NaiveDateTime = rtc.now().unwrap().into(); | 29 | let now: NaiveDateTime = time_provider.now().unwrap().into(); |
| 30 | 30 | ||
| 31 | info!("{}", now.and_utc().timestamp()); | 31 | info!("{}", now.and_utc().timestamp()); |
| 32 | 32 | ||
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 11ecbe3c2..177dd0ac2 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-stm32f0-examples" | 2 | name = "embassy-stm32f0-examples" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2024" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
| @@ -16,6 +16,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 16 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 16 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 17 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } | 17 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } |
| 18 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 18 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 19 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 19 | static_cell = "2" | 20 | static_cell = "2" |
| 20 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } | 21 | portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } |
| 21 | 22 | ||
diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs index ff98aac8e..6879dd10a 100644 --- a/examples/stm32f0/src/bin/adc-watchdog.rs +++ b/examples/stm32f0/src/bin/adc-watchdog.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{self, Adc, WatchdogChannels}; | 6 | use embassy_stm32::adc::{self, Adc, SampleTime, WatchdogChannels}; |
| 7 | use embassy_stm32::bind_interrupts; | 7 | use embassy_stm32::bind_interrupts; |
| 8 | use embassy_stm32::peripherals::ADC1; | 8 | use embassy_stm32::peripherals::ADC1; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -23,12 +23,12 @@ async fn main(_spawner: Spawner) { | |||
| 23 | loop { | 23 | loop { |
| 24 | // Wait for pin to go high | 24 | // Wait for pin to go high |
| 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); | 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); |
| 26 | let v_high = adc.monitor_watchdog().await; | 26 | let v_high = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; |
| 27 | info!("ADC sample is high {}", v_high); | 27 | info!("ADC sample is high {}", v_high); |
| 28 | 28 | ||
| 29 | // Wait for pin to go low | 29 | // Wait for pin to go low |
| 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); | 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); |
| 31 | let v_low = adc.monitor_watchdog().await; | 31 | let v_low = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; |
| 32 | info!("ADC sample is low {}", v_low); | 32 | info!("ADC sample is low {}", v_low); |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs index 8825e2687..fafeeffaf 100644 --- a/examples/stm32f0/src/bin/adc.rs +++ b/examples/stm32f0/src/bin/adc.rs | |||
| @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1, Irqs); | 21 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 22 | adc.set_sample_time(SampleTime::CYCLES71_5); | ||
| 23 | let mut pin = p.PA1; | 22 | let mut pin = p.PA1; |
| 24 | 23 | ||
| 25 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 26 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; |
| 27 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 28 | // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf |
| 29 | // 6.3.4 Embedded reference voltage | 28 | // 6.3.4 Embedded reference voltage |
| @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | loop { | 34 | loop { |
| 36 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; |
| 37 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 38 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 39 | } | 38 | } |
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs index f232e3290..9c7bf8a95 100644 --- a/examples/stm32f0/src/bin/button_controlled_blink.rs +++ b/examples/stm32f0/src/bin/button_controlled_blink.rs | |||
| @@ -7,14 +7,19 @@ use core::sync::atomic::{AtomicU32, Ordering}; | |||
| 7 | 7 | ||
| 8 | use defmt::info; | 8 | use defmt::info; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::exti::ExtiInput; | 10 | use embassy_stm32::exti::{self, ExtiInput}; |
| 11 | use embassy_stm32::gpio::{AnyPin, Level, Output, Pull, Speed}; | 11 | use embassy_stm32::gpio::{AnyPin, Level, Output, Pull, Speed}; |
| 12 | use embassy_stm32::Peri; | 12 | use embassy_stm32::{Peri, bind_interrupts, interrupt}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | static BLINK_MS: AtomicU32 = AtomicU32::new(0); | 16 | static BLINK_MS: AtomicU32 = AtomicU32::new(0); |
| 17 | 17 | ||
| 18 | bind_interrupts!( | ||
| 19 | pub struct Irqs{ | ||
| 20 | EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>; | ||
| 21 | }); | ||
| 22 | |||
| 18 | #[embassy_executor::task] | 23 | #[embassy_executor::task] |
| 19 | async fn led_task(led: Peri<'static, AnyPin>) { | 24 | async fn led_task(led: Peri<'static, AnyPin>) { |
| 20 | // Configure the LED pin as a push pull output and obtain handler. | 25 | // Configure the LED pin as a push pull output and obtain handler. |
| @@ -37,7 +42,7 @@ async fn main(spawner: Spawner) { | |||
| 37 | 42 | ||
| 38 | // Configure the button pin and obtain handler. | 43 | // Configure the button pin and obtain handler. |
| 39 | // On the Nucleo F091RC there is a button connected to pin PC13. | 44 | // On the Nucleo F091RC there is a button connected to pin PC13. |
| 40 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::None); | 45 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::None, Irqs); |
| 41 | 46 | ||
| 42 | // Create and initialize a delay variable to manage delay loop | 47 | // Create and initialize a delay variable to manage delay loop |
| 43 | let mut del_var = 2000; | 48 | let mut del_var = 2000; |
diff --git a/examples/stm32f0/src/bin/button_exti.rs b/examples/stm32f0/src/bin/button_exti.rs index fd615a215..d1312e1be 100644 --- a/examples/stm32f0/src/bin/button_exti.rs +++ b/examples/stm32f0/src/bin/button_exti.rs | |||
| @@ -3,17 +3,23 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | // Initialize and create handle for devicer peripherals | 18 | // Initialize and create handle for devicer peripherals |
| 13 | let p = embassy_stm32::init(Default::default()); | 19 | let p = embassy_stm32::init(Default::default()); |
| 14 | // Configure the button pin and obtain handler. | 20 | // Configure the button pin and obtain handler. |
| 15 | // On the Nucleo F091RC there is a button connected to pin PC13. | 21 | // On the Nucleo F091RC there is a button connected to pin PC13. |
| 16 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 22 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 17 | 23 | ||
| 18 | info!("Press the USER button..."); | 24 | info!("Press the USER button..."); |
| 19 | loop { | 25 | loop { |
diff --git a/examples/stm32f0/src/bin/i2c_master.rs b/examples/stm32f0/src/bin/i2c_master.rs new file mode 100644 index 000000000..2e61ecdf7 --- /dev/null +++ b/examples/stm32f0/src/bin/i2c_master.rs | |||
| @@ -0,0 +1,609 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | // Hardware Setup for NUCLEO-F072RB: | ||
| 5 | // - I2C1 pins: PB8 (SCL), PB9 (SDA) on CN5 connector | ||
| 6 | // - Connect to I2C slave device (e.g., Digilent Analog Discovery I2C slave, or EEPROM) | ||
| 7 | // - Default slave address: 0x50 | ||
| 8 | // - Pull-up resistors: 4.7kΩ on both SCL and SDA | ||
| 9 | // - CN5 Pin 10 (PB8/SCL) and CN5 Pin 9 (PB9/SDA) | ||
| 10 | // | ||
| 11 | // Analog Discovery - Waveforms Setup: | ||
| 12 | // - Increase buffer size: Settings -> Device Manager -> Option 4 | ||
| 13 | // - Run Protocol Analyzer | ||
| 14 | // - Configure as I2C Slave at address 0x50 | ||
| 15 | // - Connect and configure DIO pins for SCL and SDA | ||
| 16 | // - Frequency: 100kHz - [✓] Clock Stretching | ||
| 17 | |||
| 18 | use defmt::*; | ||
| 19 | use embassy_executor::Spawner; | ||
| 20 | use embassy_stm32::i2c::{Config, I2c, Master}; | ||
| 21 | use embassy_stm32::mode::{Async, Blocking}; | ||
| 22 | use embassy_stm32::time::Hertz; | ||
| 23 | use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||
| 24 | use embassy_time::Timer; | ||
| 25 | use embedded_hal_1::i2c::Operation; | ||
| 26 | use {defmt_rtt as _, panic_probe as _}; | ||
| 27 | |||
| 28 | bind_interrupts!(struct Irqs { | ||
| 29 | I2C1 => i2c::EventInterruptHandler<peripherals::I2C1>, i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 30 | }); | ||
| 31 | |||
| 32 | #[embassy_executor::main] | ||
| 33 | async fn main(_spawner: Spawner) { | ||
| 34 | let p = embassy_stm32::init(Default::default()); | ||
| 35 | info!("Run stm32 I2C v2 Master Tests..."); | ||
| 36 | |||
| 37 | let mut i2c_peri = p.I2C1; | ||
| 38 | let mut scl = p.PB8; | ||
| 39 | let mut sda = p.PB9; | ||
| 40 | |||
| 41 | let mut config = Config::default(); | ||
| 42 | config.frequency = Hertz(100_000); | ||
| 43 | |||
| 44 | // I2C slave address for Analog Discovery or test EEPROM | ||
| 45 | let slave_addr = 0x50u8; | ||
| 46 | |||
| 47 | // Wait for slave device to be ready | ||
| 48 | Timer::after_millis(100).await; | ||
| 49 | |||
| 50 | // ========== BLOCKING DIRECT API TESTS ========== | ||
| 51 | info!("========== BLOCKING DIRECT API TESTS =========="); | ||
| 52 | { | ||
| 53 | let mut i2c = I2c::new_blocking(i2c_peri.reborrow(), scl.reborrow(), sda.reborrow(), config); | ||
| 54 | |||
| 55 | info!("=== Test 1: Direct blocking_write ==="); | ||
| 56 | test_blocking_write(&mut i2c, slave_addr); | ||
| 57 | |||
| 58 | info!("=== Test 2: Direct blocking_read ==="); | ||
| 59 | test_blocking_read(&mut i2c, slave_addr); | ||
| 60 | |||
| 61 | info!("=== Test 3: Direct blocking_write_read ==="); | ||
| 62 | test_blocking_write_read(&mut i2c, slave_addr); | ||
| 63 | |||
| 64 | info!("=== Test 4: Direct blocking_write_vectored ==="); | ||
| 65 | test_blocking_write_vectored(&mut i2c, slave_addr); | ||
| 66 | |||
| 67 | info!("=== Test 5: Large buffer (>255 bytes) ==="); | ||
| 68 | test_blocking_large_buffer(&mut i2c, slave_addr); | ||
| 69 | |||
| 70 | info!("Blocking direct API tests OK"); | ||
| 71 | } | ||
| 72 | |||
| 73 | Timer::after_millis(100).await; | ||
| 74 | |||
| 75 | // ========== BLOCKING TRANSACTION TESTS ========== | ||
| 76 | info!("========== BLOCKING TRANSACTION TESTS =========="); | ||
| 77 | { | ||
| 78 | let mut i2c = I2c::new_blocking(i2c_peri.reborrow(), scl.reborrow(), sda.reborrow(), config); | ||
| 79 | |||
| 80 | info!("=== Test 6: Consecutive Writes (Should Merge) ==="); | ||
| 81 | test_consecutive_writes_blocking(&mut i2c, slave_addr); | ||
| 82 | |||
| 83 | info!("=== Test 7: Consecutive Reads (Should Merge) ==="); | ||
| 84 | test_consecutive_reads_blocking(&mut i2c, slave_addr); | ||
| 85 | |||
| 86 | info!("=== Test 8: Write then Read (RESTART) ==="); | ||
| 87 | test_write_then_read_blocking(&mut i2c, slave_addr); | ||
| 88 | |||
| 89 | info!("=== Test 9: Read then Write (RESTART) ==="); | ||
| 90 | test_read_then_write_blocking(&mut i2c, slave_addr); | ||
| 91 | |||
| 92 | info!("=== Test 10: Complex Mixed Sequence ==="); | ||
| 93 | test_mixed_sequence_blocking(&mut i2c, slave_addr); | ||
| 94 | |||
| 95 | info!("=== Test 11: Single Operations ==="); | ||
| 96 | test_single_operations_blocking(&mut i2c, slave_addr); | ||
| 97 | |||
| 98 | info!("Blocking transaction tests OK"); | ||
| 99 | } | ||
| 100 | |||
| 101 | Timer::after_millis(100).await; | ||
| 102 | |||
| 103 | // ========== ASYNC TESTS (DMA) ========== | ||
| 104 | info!("========== ASYNC TESTS (DMA) =========="); | ||
| 105 | { | ||
| 106 | let tx_dma = p.DMA1_CH2; | ||
| 107 | let rx_dma = p.DMA1_CH3; | ||
| 108 | |||
| 109 | let mut i2c = I2c::new(i2c_peri, scl, sda, Irqs, tx_dma, rx_dma, config); | ||
| 110 | |||
| 111 | // Direct API tests (reusing same I2C instance) | ||
| 112 | info!("=== Direct API Test 1: write() ==="); | ||
| 113 | test_async_write(&mut i2c, slave_addr).await; | ||
| 114 | |||
| 115 | info!("=== Direct API Test 2: read() ==="); | ||
| 116 | test_async_read(&mut i2c, slave_addr).await; | ||
| 117 | |||
| 118 | info!("=== Direct API Test 3: write_read() ==="); | ||
| 119 | test_async_write_read(&mut i2c, slave_addr).await; | ||
| 120 | |||
| 121 | info!("=== Direct API Test 4: write_vectored() ==="); | ||
| 122 | test_async_write_vectored(&mut i2c, slave_addr).await; | ||
| 123 | |||
| 124 | info!("=== Direct API Test 5: Large buffer (>255 bytes) ==="); | ||
| 125 | test_async_large_buffer(&mut i2c, slave_addr).await; | ||
| 126 | |||
| 127 | info!("Async Direct API tests OK"); | ||
| 128 | |||
| 129 | // Transaction tests | ||
| 130 | info!("=== Transaction Test 6: Consecutive Writes (Should Merge) ==="); | ||
| 131 | test_consecutive_writes_async(&mut i2c, slave_addr).await; | ||
| 132 | |||
| 133 | info!("=== Transaction Test 7: Consecutive Reads (Should Merge) ==="); | ||
| 134 | test_consecutive_reads_async(&mut i2c, slave_addr).await; | ||
| 135 | |||
| 136 | info!("=== Transaction Test 8: Write then Read (RESTART) ==="); | ||
| 137 | test_write_then_read_async(&mut i2c, slave_addr).await; | ||
| 138 | |||
| 139 | info!("=== Transaction Test 9: Read then Write (RESTART) ==="); | ||
| 140 | test_read_then_write_async(&mut i2c, slave_addr).await; | ||
| 141 | |||
| 142 | info!("=== Transaction Test 10: Complex Mixed Sequence ==="); | ||
| 143 | test_mixed_sequence_async(&mut i2c, slave_addr).await; | ||
| 144 | |||
| 145 | info!("=== Transaction Test 11: Single Operations ==="); | ||
| 146 | test_single_operations_async(&mut i2c, slave_addr).await; | ||
| 147 | |||
| 148 | info!("Async transaction tests OK"); | ||
| 149 | } | ||
| 150 | |||
| 151 | info!("All tests OK"); | ||
| 152 | cortex_m::asm::bkpt(); | ||
| 153 | } | ||
| 154 | |||
| 155 | // ==================== BLOCKING DIRECT API TEST FUNCTIONS ==================== | ||
| 156 | |||
| 157 | fn test_blocking_write(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 158 | let write_data = [0x42, 0x43, 0x44, 0x45]; | ||
| 159 | |||
| 160 | match i2c.blocking_write(addr, &write_data) { | ||
| 161 | Ok(_) => info!("✓ blocking_write succeeded: {:02x}", write_data), | ||
| 162 | Err(e) => { | ||
| 163 | error!("✗ blocking_write failed: {:?}", e); | ||
| 164 | defmt::panic!("Test failed: blocking_write"); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | fn test_blocking_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 170 | let mut read_buf = [0u8; 8]; | ||
| 171 | |||
| 172 | match i2c.blocking_read(addr, &mut read_buf) { | ||
| 173 | Ok(_) => info!("✓ blocking_read succeeded: {:02x}", read_buf), | ||
| 174 | Err(e) => { | ||
| 175 | error!("✗ blocking_read failed: {:?}", e); | ||
| 176 | defmt::panic!("Test failed: blocking_read"); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | fn test_blocking_write_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 182 | let write_data = [0x50, 0x51]; | ||
| 183 | let mut read_buf = [0u8; 6]; | ||
| 184 | |||
| 185 | match i2c.blocking_write_read(addr, &write_data, &mut read_buf) { | ||
| 186 | Ok(_) => { | ||
| 187 | info!("✓ blocking_write_read succeeded"); | ||
| 188 | info!(" Written: {:02x}", write_data); | ||
| 189 | info!(" Read: {:02x}", read_buf); | ||
| 190 | } | ||
| 191 | Err(e) => { | ||
| 192 | error!("✗ blocking_write_read failed: {:?}", e); | ||
| 193 | defmt::panic!("Test failed: blocking_write_read"); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | fn test_blocking_write_vectored(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 199 | let buf1 = [0x60, 0x61, 0x62]; | ||
| 200 | let buf2 = [0x70, 0x71]; | ||
| 201 | let buf3 = [0x80, 0x81, 0x82, 0x83]; | ||
| 202 | let bufs = [&buf1[..], &buf2[..], &buf3[..]]; | ||
| 203 | |||
| 204 | match i2c.blocking_write_vectored(addr, &bufs) { | ||
| 205 | Ok(_) => info!("✓ blocking_write_vectored succeeded (9 bytes total)"), | ||
| 206 | Err(e) => { | ||
| 207 | error!("✗ blocking_write_vectored failed: {:?}", e); | ||
| 208 | defmt::panic!("Test failed: blocking_write_vectored"); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | fn test_blocking_large_buffer(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 214 | // Test with 300 bytes to verify RELOAD mechanism works (needs chunking at 255 bytes) | ||
| 215 | let mut write_buf = [0u8; 300]; | ||
| 216 | for (i, byte) in write_buf.iter_mut().enumerate() { | ||
| 217 | *byte = (i & 0xFF) as u8; | ||
| 218 | } | ||
| 219 | |||
| 220 | match i2c.blocking_write(addr, &write_buf) { | ||
| 221 | Ok(_) => info!("✓ Large buffer write succeeded (300 bytes, tests RELOAD)"), | ||
| 222 | Err(e) => { | ||
| 223 | error!("✗ Large buffer write failed: {:?}", e); | ||
| 224 | defmt::panic!("Test failed: large buffer write"); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | // Test large read | ||
| 229 | let mut read_buf = [0u8; 300]; | ||
| 230 | match i2c.blocking_read(addr, &mut read_buf) { | ||
| 231 | Ok(_) => info!("✓ Large buffer read succeeded (300 bytes, tests RELOAD)"), | ||
| 232 | Err(e) => { | ||
| 233 | error!("✗ Large buffer read failed: {:?}", e); | ||
| 234 | defmt::panic!("Test failed: large buffer read"); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // ==================== BLOCKING TRANSACTION TEST FUNCTIONS ==================== | ||
| 240 | |||
| 241 | fn test_consecutive_writes_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 242 | // Expected on bus: START, ADDR+W, data1, data2, data3, STOP | ||
| 243 | // NO intermediate RESTART/STOP between writes - they should be merged | ||
| 244 | let data1 = [0x10, 0x11, 0x12]; | ||
| 245 | let data2 = [0x20, 0x21]; | ||
| 246 | let data3 = [0x30, 0x31, 0x32, 0x33]; | ||
| 247 | |||
| 248 | let mut ops = [ | ||
| 249 | Operation::Write(&data1), | ||
| 250 | Operation::Write(&data2), | ||
| 251 | Operation::Write(&data3), | ||
| 252 | ]; | ||
| 253 | |||
| 254 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 255 | Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"), | ||
| 256 | Err(e) => { | ||
| 257 | error!("✗ Consecutive writes failed: {:?}", e); | ||
| 258 | defmt::panic!("Test failed: consecutive writes"); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | fn test_consecutive_reads_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 264 | // Expected on bus: START, ADDR+R, data1, data2, data3, NACK, STOP | ||
| 265 | // NO intermediate RESTART/STOP between reads - they should be merged | ||
| 266 | let mut buf1 = [0u8; 4]; | ||
| 267 | let mut buf2 = [0u8; 3]; | ||
| 268 | let mut buf3 = [0u8; 2]; | ||
| 269 | |||
| 270 | let mut ops = [ | ||
| 271 | Operation::Read(&mut buf1), | ||
| 272 | Operation::Read(&mut buf2), | ||
| 273 | Operation::Read(&mut buf3), | ||
| 274 | ]; | ||
| 275 | |||
| 276 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 277 | Ok(_) => { | ||
| 278 | info!("✓ Consecutive reads succeeded (merged 9 bytes)"); | ||
| 279 | info!(" buf1: {:02x}", buf1); | ||
| 280 | info!(" buf2: {:02x}", buf2); | ||
| 281 | info!(" buf3: {:02x}", buf3); | ||
| 282 | } | ||
| 283 | Err(e) => { | ||
| 284 | error!("✗ Consecutive reads failed: {:?}", e); | ||
| 285 | defmt::panic!("Test failed: consecutive reads"); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | fn test_write_then_read_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 291 | // Expected: START, ADDR+W, data, RESTART, ADDR+R, data, NACK, STOP | ||
| 292 | let write_data = [0xAA, 0xBB]; | ||
| 293 | let mut read_buf = [0u8; 4]; | ||
| 294 | |||
| 295 | let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)]; | ||
| 296 | |||
| 297 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 298 | Ok(_) => { | ||
| 299 | info!("✓ Write-then-read succeeded with RESTART"); | ||
| 300 | info!(" Written: {:02x}", write_data); | ||
| 301 | info!(" Read: {:02x}", read_buf); | ||
| 302 | } | ||
| 303 | Err(e) => { | ||
| 304 | error!("✗ Write-then-read failed: {:?}", e); | ||
| 305 | defmt::panic!("Test failed: write-then-read"); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | fn test_read_then_write_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 311 | // Expected: START, ADDR+R, data, NACK, RESTART, ADDR+W, data, STOP | ||
| 312 | let mut read_buf = [0u8; 3]; | ||
| 313 | let write_data = [0xCC, 0xDD, 0xEE]; | ||
| 314 | |||
| 315 | let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)]; | ||
| 316 | |||
| 317 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 318 | Ok(_) => { | ||
| 319 | info!("✓ Read-then-write succeeded with RESTART"); | ||
| 320 | info!(" Read: {:02x}", read_buf); | ||
| 321 | info!(" Written: {:02x}", write_data); | ||
| 322 | } | ||
| 323 | Err(e) => { | ||
| 324 | error!("✗ Read-then-write failed: {:?}", e); | ||
| 325 | defmt::panic!("Test failed: read-then-write"); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | fn test_mixed_sequence_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 331 | // Complex: W, W, R, R, W, R | ||
| 332 | // Groups: [W,W] RESTART [R,R] RESTART [W] RESTART [R] | ||
| 333 | let w1 = [0x01, 0x02]; | ||
| 334 | let w2 = [0x03, 0x04]; | ||
| 335 | let mut r1 = [0u8; 2]; | ||
| 336 | let mut r2 = [0u8; 2]; | ||
| 337 | let w3 = [0x05]; | ||
| 338 | let mut r3 = [0u8; 1]; | ||
| 339 | |||
| 340 | let mut ops = [ | ||
| 341 | Operation::Write(&w1), | ||
| 342 | Operation::Write(&w2), | ||
| 343 | Operation::Read(&mut r1), | ||
| 344 | Operation::Read(&mut r2), | ||
| 345 | Operation::Write(&w3), | ||
| 346 | Operation::Read(&mut r3), | ||
| 347 | ]; | ||
| 348 | |||
| 349 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 350 | Ok(_) => { | ||
| 351 | info!("✓ Mixed sequence succeeded"); | ||
| 352 | info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]"); | ||
| 353 | } | ||
| 354 | Err(e) => { | ||
| 355 | error!("✗ Mixed sequence failed: {:?}", e); | ||
| 356 | defmt::panic!("Test failed: mixed sequence"); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | fn test_single_operations_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) { | ||
| 362 | // Test single write | ||
| 363 | let write_data = [0xFF]; | ||
| 364 | let mut ops = [Operation::Write(&write_data)]; | ||
| 365 | |||
| 366 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 367 | Ok(_) => info!("✓ Single write succeeded"), | ||
| 368 | Err(e) => { | ||
| 369 | error!("✗ Single write failed: {:?}", e); | ||
| 370 | defmt::panic!("Test failed: single write"); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | // Test single read | ||
| 375 | let mut read_buf = [0u8; 1]; | ||
| 376 | let mut ops = [Operation::Read(&mut read_buf)]; | ||
| 377 | |||
| 378 | match i2c.blocking_transaction(addr, &mut ops) { | ||
| 379 | Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]), | ||
| 380 | Err(e) => { | ||
| 381 | error!("✗ Single read failed: {:?}", e); | ||
| 382 | defmt::panic!("Test failed: single read"); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | // ==================== ASYNC DIRECT API TEST FUNCTIONS ==================== | ||
| 388 | |||
| 389 | async fn test_async_write(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 390 | let write_data = [0x42, 0x43, 0x44, 0x45]; | ||
| 391 | |||
| 392 | match i2c.write(addr, &write_data).await { | ||
| 393 | Ok(_) => info!("✓ async write succeeded: {:02x}", write_data), | ||
| 394 | Err(e) => { | ||
| 395 | error!("✗ async write failed: {:?}", e); | ||
| 396 | defmt::panic!("Test failed: async write"); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | async fn test_async_read(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 402 | let mut read_buf = [0u8; 8]; | ||
| 403 | |||
| 404 | match i2c.read(addr, &mut read_buf).await { | ||
| 405 | Ok(_) => info!("✓ async read succeeded: {:02x}", read_buf), | ||
| 406 | Err(e) => { | ||
| 407 | error!("✗ async read failed: {:?}", e); | ||
| 408 | defmt::panic!("Test failed: async read"); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | async fn test_async_write_read(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 414 | let write_data = [0x50, 0x51]; | ||
| 415 | let mut read_buf = [0u8; 6]; | ||
| 416 | |||
| 417 | match i2c.write_read(addr, &write_data, &mut read_buf).await { | ||
| 418 | Ok(_) => { | ||
| 419 | info!("✓ async write_read succeeded"); | ||
| 420 | info!(" Written: {:02x}", write_data); | ||
| 421 | info!(" Read: {:02x}", read_buf); | ||
| 422 | } | ||
| 423 | Err(e) => { | ||
| 424 | error!("✗ async write_read failed: {:?}", e); | ||
| 425 | defmt::panic!("Test failed: async write_read"); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | async fn test_async_write_vectored(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 431 | let buf1 = [0x60, 0x61, 0x62]; | ||
| 432 | let buf2 = [0x70, 0x71]; | ||
| 433 | let buf3 = [0x80, 0x81, 0x82, 0x83]; | ||
| 434 | let bufs = [&buf1[..], &buf2[..], &buf3[..]]; | ||
| 435 | |||
| 436 | match i2c.write_vectored(addr.into(), &bufs).await { | ||
| 437 | Ok(_) => info!("✓ async write_vectored succeeded (9 bytes total)"), | ||
| 438 | Err(e) => { | ||
| 439 | error!("✗ async write_vectored failed: {:?}", e); | ||
| 440 | defmt::panic!("Test failed: async write_vectored"); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 | async fn test_async_large_buffer(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 446 | // Test with 300 bytes to verify RELOAD mechanism works with DMA (needs chunking at 255 bytes) | ||
| 447 | let mut write_buf = [0u8; 300]; | ||
| 448 | for (i, byte) in write_buf.iter_mut().enumerate() { | ||
| 449 | *byte = (i & 0xFF) as u8; | ||
| 450 | } | ||
| 451 | |||
| 452 | match i2c.write(addr, &write_buf).await { | ||
| 453 | Ok(_) => info!("✓ Large buffer async write succeeded (300 bytes, tests RELOAD with DMA)"), | ||
| 454 | Err(e) => { | ||
| 455 | error!("✗ Large buffer async write failed: {:?}", e); | ||
| 456 | defmt::panic!("Test failed: large buffer async write"); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | // Test large read | ||
| 461 | let mut read_buf = [0u8; 300]; | ||
| 462 | match i2c.read(addr, &mut read_buf).await { | ||
| 463 | Ok(_) => info!("✓ Large buffer async read succeeded (300 bytes, tests RELOAD with DMA)"), | ||
| 464 | Err(e) => { | ||
| 465 | error!("✗ Large buffer async read failed: {:?}", e); | ||
| 466 | defmt::panic!("Test failed: large buffer async read"); | ||
| 467 | } | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | // ==================== ASYNC TRANSACTION TEST FUNCTIONS ==================== | ||
| 472 | |||
| 473 | async fn test_consecutive_writes_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 474 | let data1 = [0x10, 0x11, 0x12]; | ||
| 475 | let data2 = [0x20, 0x21]; | ||
| 476 | let data3 = [0x30, 0x31, 0x32, 0x33]; | ||
| 477 | |||
| 478 | let mut ops = [ | ||
| 479 | Operation::Write(&data1), | ||
| 480 | Operation::Write(&data2), | ||
| 481 | Operation::Write(&data3), | ||
| 482 | ]; | ||
| 483 | |||
| 484 | match i2c.transaction(addr, &mut ops).await { | ||
| 485 | Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"), | ||
| 486 | Err(e) => { | ||
| 487 | error!("✗ Consecutive writes failed: {:?}", e); | ||
| 488 | defmt::panic!("Test failed: consecutive writes"); | ||
| 489 | } | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | async fn test_consecutive_reads_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 494 | let mut buf1 = [0u8; 4]; | ||
| 495 | let mut buf2 = [0u8; 3]; | ||
| 496 | let mut buf3 = [0u8; 2]; | ||
| 497 | |||
| 498 | let mut ops = [ | ||
| 499 | Operation::Read(&mut buf1), | ||
| 500 | Operation::Read(&mut buf2), | ||
| 501 | Operation::Read(&mut buf3), | ||
| 502 | ]; | ||
| 503 | |||
| 504 | match i2c.transaction(addr, &mut ops).await { | ||
| 505 | Ok(_) => { | ||
| 506 | info!("✓ Consecutive reads succeeded (merged 9 bytes)"); | ||
| 507 | info!(" buf1: {:02x}", buf1); | ||
| 508 | info!(" buf2: {:02x}", buf2); | ||
| 509 | info!(" buf3: {:02x}", buf3); | ||
| 510 | } | ||
| 511 | Err(e) => { | ||
| 512 | error!("✗ Consecutive reads failed: {:?}", e); | ||
| 513 | defmt::panic!("Test failed: consecutive reads"); | ||
| 514 | } | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | async fn test_write_then_read_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 519 | let write_data = [0xAA, 0xBB]; | ||
| 520 | let mut read_buf = [0u8; 4]; | ||
| 521 | |||
| 522 | let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)]; | ||
| 523 | |||
| 524 | match i2c.transaction(addr, &mut ops).await { | ||
| 525 | Ok(_) => { | ||
| 526 | info!("✓ Write-then-read succeeded with RESTART"); | ||
| 527 | info!(" Written: {:02x}", write_data); | ||
| 528 | info!(" Read: {:02x}", read_buf); | ||
| 529 | } | ||
| 530 | Err(e) => { | ||
| 531 | error!("✗ Write-then-read failed: {:?}", e); | ||
| 532 | defmt::panic!("Test failed: write-then-read"); | ||
| 533 | } | ||
| 534 | } | ||
| 535 | } | ||
| 536 | |||
| 537 | async fn test_read_then_write_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 538 | let mut read_buf = [0u8; 3]; | ||
| 539 | let write_data = [0xCC, 0xDD, 0xEE]; | ||
| 540 | |||
| 541 | let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)]; | ||
| 542 | |||
| 543 | match i2c.transaction(addr, &mut ops).await { | ||
| 544 | Ok(_) => { | ||
| 545 | info!("✓ Read-then-write succeeded with RESTART"); | ||
| 546 | info!(" Read: {:02x}", read_buf); | ||
| 547 | info!(" Written: {:02x}", write_data); | ||
| 548 | } | ||
| 549 | Err(e) => { | ||
| 550 | error!("✗ Read-then-write failed: {:?}", e); | ||
| 551 | defmt::panic!("Test failed: read-then-write"); | ||
| 552 | } | ||
| 553 | } | ||
| 554 | } | ||
| 555 | |||
| 556 | async fn test_mixed_sequence_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 557 | let w1 = [0x01, 0x02]; | ||
| 558 | let w2 = [0x03, 0x04]; | ||
| 559 | let mut r1 = [0u8; 2]; | ||
| 560 | let mut r2 = [0u8; 2]; | ||
| 561 | let w3 = [0x05]; | ||
| 562 | let mut r3 = [0u8; 1]; | ||
| 563 | |||
| 564 | let mut ops = [ | ||
| 565 | Operation::Write(&w1), | ||
| 566 | Operation::Write(&w2), | ||
| 567 | Operation::Read(&mut r1), | ||
| 568 | Operation::Read(&mut r2), | ||
| 569 | Operation::Write(&w3), | ||
| 570 | Operation::Read(&mut r3), | ||
| 571 | ]; | ||
| 572 | |||
| 573 | match i2c.transaction(addr, &mut ops).await { | ||
| 574 | Ok(_) => { | ||
| 575 | info!("✓ Mixed sequence succeeded"); | ||
| 576 | info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]"); | ||
| 577 | } | ||
| 578 | Err(e) => { | ||
| 579 | error!("✗ Mixed sequence failed: {:?}", e); | ||
| 580 | defmt::panic!("Test failed: mixed sequence"); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | async fn test_single_operations_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) { | ||
| 586 | // Test single write | ||
| 587 | let write_data = [0xFF]; | ||
| 588 | let mut ops = [Operation::Write(&write_data)]; | ||
| 589 | |||
| 590 | match i2c.transaction(addr, &mut ops).await { | ||
| 591 | Ok(_) => info!("✓ Single write succeeded"), | ||
| 592 | Err(e) => { | ||
| 593 | error!("✗ Single write failed: {:?}", e); | ||
| 594 | defmt::panic!("Test failed: single write"); | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 598 | // Test single read | ||
| 599 | let mut read_buf = [0u8; 1]; | ||
| 600 | let mut ops = [Operation::Read(&mut read_buf)]; | ||
| 601 | |||
| 602 | match i2c.transaction(addr, &mut ops).await { | ||
| 603 | Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]), | ||
| 604 | Err(e) => { | ||
| 605 | error!("✗ Single read failed: {:?}", e); | ||
| 606 | defmt::panic!("Test failed: single read"); | ||
| 607 | } | ||
| 608 | } | ||
| 609 | } | ||
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index b5244afc8..9a8dc5685 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs | |||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn USART1() { | 115 | unsafe fn USART1() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn USART2() { | 120 | unsafe fn USART2() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index dcb58796b..5714b149a 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f1-examples" | 3 | name = "embassy-stm32f1-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs index 541ff159e..2451aee3d 100644 --- a/examples/stm32f1/src/bin/adc.rs +++ b/examples/stm32f1/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::Adc; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_stm32::peripherals::ADC1; | 7 | use embassy_stm32::peripherals::ADC1; |
| 8 | use embassy_stm32::{adc, bind_interrupts}; | 8 | use embassy_stm32::{adc, bind_interrupts}; |
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 22 | let mut pin = p.PB1; | 22 | let mut pin = p.PB1; |
| 23 | 23 | ||
| 24 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 25 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; |
| 26 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 27 | // From http://www.st.com/resource/en/datasheet/CD00161566.pdf | 27 | // From http://www.st.com/resource/en/datasheet/CD00161566.pdf |
| 28 | // 5.3.4 Embedded reference voltage | 28 | // 5.3.4 Embedded reference voltage |
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; |
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 37 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 38 | } | 38 | } |
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs index ad0c8a5a5..cbe13b206 100644 --- a/examples/stm32f1/src/bin/can.rs +++ b/examples/stm32f1/src/bin/can.rs | |||
| @@ -5,11 +5,11 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::can::frame::Envelope; | 6 | use embassy_stm32::can::frame::Envelope; |
| 7 | use embassy_stm32::can::{ | 7 | use embassy_stm32::can::{ |
| 8 | filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, | 8 | Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, |
| 9 | TxInterruptHandler, | 9 | TxInterruptHandler, filter, |
| 10 | }; | 10 | }; |
| 11 | use embassy_stm32::peripherals::CAN; | 11 | use embassy_stm32::peripherals::CAN; |
| 12 | use embassy_stm32::{bind_interrupts, Config}; | 12 | use embassy_stm32::{Config, bind_interrupts}; |
| 13 | use static_cell::StaticCell; | 13 | use static_cell::StaticCell; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs index b5b26938d..6232d8c17 100644 --- a/examples/stm32f1/src/bin/input_capture.rs +++ b/examples/stm32f1/src/bin/input_capture.rs | |||
| @@ -7,7 +7,7 @@ use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; | |||
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; | 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; |
| 9 | use embassy_stm32::timer::{self, Channel}; | 9 | use embassy_stm32::timer::{self, Channel}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, Peri}; | 10 | use embassy_stm32::{Peri, bind_interrupts, peripherals}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index 9ae747018..136c5c555 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; | 6 | use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; |
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::pwm_input::PwmInput; | 8 | use embassy_stm32::timer::pwm_input::PwmInput; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; | 9 | use embassy_stm32::{Peri, bind_interrupts, peripherals, timer}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs index 77ec307b9..5ff54a521 100644 --- a/examples/stm32f1/src/bin/usb_serial.rs +++ b/examples/stm32f1/src/bin/usb_serial.rs | |||
| @@ -7,11 +7,11 @@ use embassy_futures::join::join; | |||
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 9 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use embassy_usb::Builder; | ||
| 12 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 13 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 14 | use embassy_usb::Builder; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | 17 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 498c20d84..f726018c3 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f2-examples" | 3 | name = "embassy-stm32f2-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs index e39e2daec..4418bf502 100644 --- a/examples/stm32f2/src/bin/pll.rs +++ b/examples/stm32f2/src/bin/pll.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::time::Hertz; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::time::Hertz; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 23025ef0b..4349e8055 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f3-examples" | 3 | name = "embassy-stm32f3-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs index a54d03212..643f499ed 100644 --- a/examples/stm32f3/src/bin/button_events.rs +++ b/examples/stm32f3/src/bin/button_events.rs | |||
| @@ -11,13 +11,19 @@ | |||
| 11 | 11 | ||
| 12 | use defmt::*; | 12 | use defmt::*; |
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_stm32::exti::ExtiInput; | 14 | use embassy_stm32::exti::{self, ExtiInput}; |
| 15 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 15 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 16 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 16 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 17 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 17 | use embassy_sync::channel::Channel; | 18 | use embassy_sync::channel::Channel; |
| 18 | use embassy_time::{with_timeout, Duration, Timer}; | 19 | use embassy_time::{Duration, Timer, with_timeout}; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 21 | ||
| 22 | bind_interrupts!( | ||
| 23 | pub struct Irqs{ | ||
| 24 | EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>; | ||
| 25 | }); | ||
| 26 | |||
| 21 | struct Leds<'a> { | 27 | struct Leds<'a> { |
| 22 | leds: [Output<'a>; 8], | 28 | leds: [Output<'a>; 8], |
| 23 | direction: i8, | 29 | direction: i8, |
| @@ -99,7 +105,7 @@ static CHANNEL: Channel<ThreadModeRawMutex, ButtonEvent, 4> = Channel::new(); | |||
| 99 | #[embassy_executor::main] | 105 | #[embassy_executor::main] |
| 100 | async fn main(spawner: Spawner) { | 106 | async fn main(spawner: Spawner) { |
| 101 | let p = embassy_stm32::init(Default::default()); | 107 | let p = embassy_stm32::init(Default::default()); |
| 102 | let button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down); | 108 | let button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down, Irqs); |
| 103 | info!("Press the USER button..."); | 109 | info!("Press the USER button..."); |
| 104 | let leds = [ | 110 | let leds = [ |
| 105 | Output::new(p.PE9, Level::Low, Speed::Low), | 111 | Output::new(p.PE9, Level::Low, Speed::Low), |
diff --git a/examples/stm32f3/src/bin/button_exti.rs b/examples/stm32f3/src/bin/button_exti.rs index a55530e0e..1df4735ca 100644 --- a/examples/stm32f3/src/bin/button_exti.rs +++ b/examples/stm32f3/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index 2f2ffdea2..8375e0e8e 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs | |||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn UART4() { | 115 | unsafe fn UART4() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn UART5() { | 120 | unsafe fn UART5() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs index 5760f2c1c..58b801c36 100644 --- a/examples/stm32f3/src/bin/usb_serial.rs +++ b/examples/stm32f3/src/bin/usb_serial.rs | |||
| @@ -7,11 +7,11 @@ use embassy_futures::join::join; | |||
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 9 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use embassy_usb::Builder; | ||
| 12 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 13 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 14 | use embassy_usb::Builder; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | 17 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 3495b118c..cf22633dd 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f334-examples" | 3 | name = "embassy-stm32f334-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs index 0528a9637..486f160ec 100644 --- a/examples/stm32f334/src/bin/adc.rs +++ b/examples/stm32f334/src/bin/adc.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::adc::{Adc, SampleTime}; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_stm32::peripherals::ADC1; | 7 | use embassy_stm32::peripherals::ADC1; |
| 8 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 9 | use embassy_stm32::{adc, bind_interrupts, Config}; | 9 | use embassy_stm32::{Config, adc, bind_interrupts}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| @@ -40,24 +40,22 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 40 | 40 | ||
| 41 | let mut adc = Adc::new(p.ADC1, Irqs); | 41 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 42 | 42 | ||
| 43 | adc.set_sample_time(SampleTime::CYCLES601_5); | ||
| 44 | |||
| 45 | info!("enable vrefint..."); | 43 | info!("enable vrefint..."); |
| 46 | 44 | ||
| 47 | let mut vrefint = adc.enable_vref(); | 45 | let mut vrefint = adc.enable_vref(); |
| 48 | let mut temperature = adc.enable_temperature(); | 46 | let mut temperature = adc.enable_temperature(); |
| 49 | 47 | ||
| 50 | loop { | 48 | loop { |
| 51 | let vref = adc.read(&mut vrefint).await; | 49 | let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; |
| 52 | info!("read vref: {} (should be {})", vref, vrefint.value()); | 50 | info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); |
| 53 | 51 | ||
| 54 | let temp = adc.read(&mut temperature).await; | 52 | let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; |
| 55 | info!("read temperature: {}", temp); | 53 | info!("read temperature: {}", temp); |
| 56 | 54 | ||
| 57 | let pin = adc.read(&mut p.PA0).await; | 55 | let pin = adc.read(&mut p.PA0, SampleTime::CYCLES601_5).await; |
| 58 | info!("read pin: {}", pin); | 56 | info!("read pin: {}", pin); |
| 59 | 57 | ||
| 60 | let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; | 58 | let pin_mv = (pin as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; |
| 61 | info!("computed pin mv: {}", pin_mv); | 59 | info!("computed pin mv: {}", pin_mv); |
| 62 | 60 | ||
| 63 | Timer::after_millis(500).await; | 61 | Timer::after_millis(500).await; |
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index c344935d7..9555fd35d 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs | |||
| @@ -7,7 +7,7 @@ use embassy_stm32::adc::{Adc, SampleTime}; | |||
| 7 | use embassy_stm32::opamp::OpAmp; | 7 | use embassy_stm32::opamp::OpAmp; |
| 8 | use embassy_stm32::peripherals::ADC2; | 8 | use embassy_stm32::peripherals::ADC2; |
| 9 | use embassy_stm32::time::mhz; | 9 | use embassy_stm32::time::mhz; |
| 10 | use embassy_stm32::{adc, bind_interrupts, Config}; | 10 | use embassy_stm32::{Config, adc, bind_interrupts}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| @@ -42,8 +42,6 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 42 | let mut adc = Adc::new(p.ADC2, Irqs); | 42 | let mut adc = Adc::new(p.ADC2, Irqs); |
| 43 | let mut opamp = OpAmp::new(p.OPAMP2); | 43 | let mut opamp = OpAmp::new(p.OPAMP2); |
| 44 | 44 | ||
| 45 | adc.set_sample_time(SampleTime::CYCLES601_5); | ||
| 46 | |||
| 47 | info!("enable vrefint..."); | 45 | info!("enable vrefint..."); |
| 48 | 46 | ||
| 49 | let mut vrefint = adc.enable_vref(); | 47 | let mut vrefint = adc.enable_vref(); |
| @@ -51,16 +49,16 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 51 | let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); | 49 | let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); |
| 52 | 50 | ||
| 53 | loop { | 51 | loop { |
| 54 | let vref = adc.read(&mut vrefint).await; | 52 | let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; |
| 55 | info!("read vref: {} (should be {})", vref, vrefint.value()); | 53 | info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); |
| 56 | 54 | ||
| 57 | let temp = adc.read(&mut temperature).await; | 55 | let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; |
| 58 | info!("read temperature: {}", temp); | 56 | info!("read temperature: {}", temp); |
| 59 | 57 | ||
| 60 | let buffer = adc.read(&mut buffer).await; | 58 | let buffer = adc.read(&mut buffer, SampleTime::CYCLES601_5).await; |
| 61 | info!("read buffer: {}", buffer); | 59 | info!("read buffer: {}", buffer); |
| 62 | 60 | ||
| 63 | let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; | 61 | let pin_mv = (buffer as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; |
| 64 | info!("computed pin mv: {}", pin_mv); | 62 | info!("computed pin mv: {}", pin_mv); |
| 65 | 63 | ||
| 66 | Timer::after_millis(500).await; | 64 | Timer::after_millis(500).await; |
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs index 2b0686121..68a61ae22 100644 --- a/examples/stm32f334/src/bin/pwm.rs +++ b/examples/stm32f334/src/bin/pwm.rs | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Config; | ||
| 6 | use embassy_stm32::hrtim::*; | 7 | use embassy_stm32::hrtim::*; |
| 7 | use embassy_stm32::time::{khz, mhz}; | 8 | use embassy_stm32::time::{khz, mhz}; |
| 8 | use embassy_stm32::Config; | ||
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index fb5f86aac..b4555045a 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f4-examples" | 3 | name = "embassy-stm32f4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -32,7 +32,7 @@ critical-section = "1.1" | |||
| 32 | nb = "1.0.0" | 32 | nb = "1.0.0" |
| 33 | embedded-storage = "0.3.1" | 33 | embedded-storage = "0.3.1" |
| 34 | micromath = "2.0.0" | 34 | micromath = "2.0.0" |
| 35 | usbd-hid = "0.8.1" | 35 | usbd-hid = "0.9.0" |
| 36 | static_cell = "2" | 36 | static_cell = "2" |
| 37 | chrono = { version = "^0.4", default-features = false} | 37 | chrono = { version = "^0.4", default-features = false} |
| 38 | 38 | ||
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs index 423d29225..694e85657 100644 --- a/examples/stm32f4/src/bin/adc.rs +++ b/examples/stm32f4/src/bin/adc.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; | 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::adc::{Adc, Temperature, VrefInt}; | 7 | use embassy_stm32::adc::{Adc, SampleTime, Temperature, VrefInt}; |
| 8 | use embassy_time::{Delay, Timer}; | 8 | use embassy_time::{Delay, Timer}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||
| 14 | info!("Hello World!"); | 14 | info!("Hello World!"); |
| 15 | 15 | ||
| 16 | let mut delay = Delay; | 16 | let mut delay = Delay; |
| 17 | let mut adc = Adc::new(p.ADC1); | 17 | let mut adc = Adc::new_with_config(p.ADC1, Default::default()); |
| 18 | let mut pin = p.PC1; | 18 | let mut pin = p.PC1; |
| 19 | 19 | ||
| 20 | let mut vrefint = adc.enable_vrefint(); | 20 | let mut vrefint = adc.enable_vrefint(); |
| @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | // Startup delay can be combined to the maximum of either | 23 | // Startup delay can be combined to the maximum of either |
| 24 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); | 24 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); |
| 25 | 25 | ||
| 26 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 26 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 27 | 27 | ||
| 28 | let convert_to_millivolts = |sample| { | 28 | let convert_to_millivolts = |sample| { |
| 29 | // From http://www.st.com/resource/en/datasheet/DM00071990.pdf | 29 | // From http://www.st.com/resource/en/datasheet/DM00071990.pdf |
| @@ -50,16 +50,16 @@ async fn main(_spawner: Spawner) { | |||
| 50 | 50 | ||
| 51 | loop { | 51 | loop { |
| 52 | // Read pin | 52 | // Read pin |
| 53 | let v = adc.blocking_read(&mut pin); | 53 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); |
| 54 | info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); | 54 | info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); |
| 55 | 55 | ||
| 56 | // Read internal temperature | 56 | // Read internal temperature |
| 57 | let v = adc.blocking_read(&mut temp); | 57 | let v = adc.blocking_read(&mut temp, SampleTime::CYCLES112); |
| 58 | let celcius = convert_to_celcius(v); | 58 | let celcius = convert_to_celcius(v); |
| 59 | info!("Internal temp: {} ({} C)", v, celcius); | 59 | info!("Internal temp: {} ({} C)", v, celcius); |
| 60 | 60 | ||
| 61 | // Read internal voltage reference | 61 | // Read internal voltage reference |
| 62 | let v = adc.blocking_read(&mut vrefint); | 62 | let v = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 63 | info!("VrefInt: {}", v); | 63 | info!("VrefInt: {}", v); |
| 64 | 64 | ||
| 65 | Timer::after_millis(100).await; | 65 | Timer::after_millis(100).await; |
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs index 2ec48640e..d61b1b2eb 100644 --- a/examples/stm32f4/src/bin/adc_dma.rs +++ b/examples/stm32f4/src/bin/adc_dma.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | use cortex_m::singleton; | 3 | use cortex_m::singleton; |
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, RingBufferedAdc, SampleTime, Sequence}; | ||
| 7 | use embassy_stm32::Peripherals; | 6 | use embassy_stm32::Peripherals; |
| 7 | use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, RingBufferedAdc, SampleTime}; | ||
| 8 | use embassy_time::Instant; | 8 | use embassy_time::Instant; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -15,21 +15,34 @@ async fn main(spawner: Spawner) { | |||
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn adc_task(mut p: Peripherals) { | 18 | async fn adc_task(p: Peripherals) { |
| 19 | const ADC_BUF_SIZE: usize = 1024; | 19 | const ADC_BUF_SIZE: usize = 1024; |
| 20 | let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); | 20 | let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); |
| 21 | let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); | 21 | let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); |
| 22 | 22 | ||
| 23 | let adc = Adc::new(p.ADC1); | 23 | let adc = Adc::new_with_config(p.ADC1, Default::default()); |
| 24 | let adc2 = Adc::new(p.ADC2); | 24 | let adc2 = Adc::new_with_config(p.ADC2, Default::default()); |
| 25 | 25 | ||
| 26 | let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_data); | 26 | let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered( |
| 27 | let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(p.DMA2_CH2, adc_data2); | 27 | p.DMA2_CH0, |
| 28 | 28 | adc_data, | |
| 29 | adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112); | 29 | [ |
| 30 | adc.set_sample_sequence(Sequence::Two, &mut p.PA2, SampleTime::CYCLES112); | 30 | (p.PA0.degrade_adc(), SampleTime::CYCLES112), |
| 31 | adc2.set_sample_sequence(Sequence::One, &mut p.PA1, SampleTime::CYCLES112); | 31 | (p.PA2.degrade_adc(), SampleTime::CYCLES112), |
| 32 | adc2.set_sample_sequence(Sequence::Two, &mut p.PA3, SampleTime::CYCLES112); | 32 | ] |
| 33 | .into_iter(), | ||
| 34 | RegularConversionMode::Continuous, | ||
| 35 | ); | ||
| 36 | let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered( | ||
| 37 | p.DMA2_CH2, | ||
| 38 | adc_data2, | ||
| 39 | [ | ||
| 40 | (p.PA1.degrade_adc(), SampleTime::CYCLES112), | ||
| 41 | (p.PA3.degrade_adc(), SampleTime::CYCLES112), | ||
| 42 | ] | ||
| 43 | .into_iter(), | ||
| 44 | RegularConversionMode::Continuous, | ||
| 45 | ); | ||
| 33 | 46 | ||
| 34 | // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around | 47 | // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around |
| 35 | // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of | 48 | // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of |
diff --git a/examples/stm32f4/src/bin/button_exti.rs b/examples/stm32f4/src/bin/button_exti.rs index 2a546dac5..e7e1549a8 100644 --- a/examples/stm32f4/src/bin/button_exti.rs +++ b/examples/stm32f4/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index f41a60529..8dfa0916d 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -5,11 +5,11 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 9 | use embassy_stm32::peripherals::ETH; | 9 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; |
| 10 | use embassy_stm32::rng::Rng; | 10 | use embassy_stm32::rng::Rng; |
| 11 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 12 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use embedded_io_async::Write; | 14 | use embedded_io_async::Write; |
| 15 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| @@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs { | |||
| 20 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; | 20 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; |
| 21 | }); | 21 | }); |
| 22 | 22 | ||
| 23 | type Device = Ethernet<'static, ETH, GenericPhy>; | 23 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 24 | 24 | ||
| 25 | #[embassy_executor::task] | 25 | #[embassy_executor::task] |
| 26 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 26 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -67,16 +67,16 @@ async fn main(spawner: Spawner) -> ! { | |||
| 67 | p.ETH, | 67 | p.ETH, |
| 68 | Irqs, | 68 | Irqs, |
| 69 | p.PA1, | 69 | p.PA1, |
| 70 | p.PA2, | ||
| 71 | p.PC1, | ||
| 72 | p.PA7, | 70 | p.PA7, |
| 73 | p.PC4, | 71 | p.PC4, |
| 74 | p.PC5, | 72 | p.PC5, |
| 75 | p.PG13, | 73 | p.PG13, |
| 76 | p.PB13, | 74 | p.PB13, |
| 77 | p.PG11, | 75 | p.PG11, |
| 78 | GenericPhy::new_auto(), | ||
| 79 | mac_addr, | 76 | mac_addr, |
| 77 | p.ETH_SMA, | ||
| 78 | p.PA2, | ||
| 79 | p.PC1, | ||
| 80 | ); | 80 | ); |
| 81 | 81 | ||
| 82 | let config = embassy_net::Config::dhcpv4(Default::default()); | 82 | let config = embassy_net::Config::dhcpv4(Default::default()); |
diff --git a/examples/stm32f4/src/bin/eth_compliance_test.rs b/examples/stm32f4/src/bin/eth_compliance_test.rs index 52f9d57f6..dc5d7dbb6 100644 --- a/examples/stm32f4/src/bin/eth_compliance_test.rs +++ b/examples/stm32f4/src/bin/eth_compliance_test.rs | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, StationManagement}; | 6 | use embassy_stm32::eth::{Ethernet, PacketQueue, StationManagement}; |
| 7 | use embassy_stm32::time::Hertz; | 7 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use static_cell::StaticCell; | 10 | use static_cell::StaticCell; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -43,27 +43,27 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 43 | 43 | ||
| 44 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 44 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 45 | 45 | ||
| 46 | const PHY_ADDR: u8 = 0; | ||
| 47 | static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); | 46 | static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); |
| 48 | let mut device = Ethernet::new( | 47 | let mut device = Ethernet::new( |
| 49 | PACKETS.init(PacketQueue::<4, 4>::new()), | 48 | PACKETS.init(PacketQueue::<4, 4>::new()), |
| 50 | p.ETH, | 49 | p.ETH, |
| 51 | Irqs, | 50 | Irqs, |
| 52 | p.PA1, | 51 | p.PA1, |
| 53 | p.PA2, | ||
| 54 | p.PC1, | ||
| 55 | p.PA7, | 52 | p.PA7, |
| 56 | p.PC4, | 53 | p.PC4, |
| 57 | p.PC5, | 54 | p.PC5, |
| 58 | p.PG13, | 55 | p.PG13, |
| 59 | p.PB13, | 56 | p.PB13, |
| 60 | p.PG11, | 57 | p.PG11, |
| 61 | GenericPhy::new(PHY_ADDR), | ||
| 62 | mac_addr, | 58 | mac_addr, |
| 59 | p.ETH_SMA, | ||
| 60 | p.PA2, | ||
| 61 | p.PC1, | ||
| 63 | ); | 62 | ); |
| 64 | 63 | ||
| 65 | let sm = device.station_management(); | 64 | let sm = device.phy_mut().station_management(); |
| 66 | 65 | ||
| 66 | const PHY_ADDR: u8 = 0; | ||
| 67 | // Just an example. Exact register settings depend on the specific PHY and test. | 67 | // Just an example. Exact register settings depend on the specific PHY and test. |
| 68 | sm.smi_write(PHY_ADDR, 0, 0x2100); | 68 | sm.smi_write(PHY_ADDR, 0, 0x2100); |
| 69 | sm.smi_write(PHY_ADDR, 11, 0xA000); | 69 | sm.smi_write(PHY_ADDR, 11, 0xA000); |
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs index 7ce3bfe75..e274d2a66 100644 --- a/examples/stm32f4/src/bin/eth_w5500.rs +++ b/examples/stm32f4/src/bin/eth_w5500.rs | |||
| @@ -7,13 +7,14 @@ use embassy_net::tcp::TcpSocket; | |||
| 7 | use embassy_net::{Ipv4Address, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_net_wiznet::chip::W5500; | 8 | use embassy_net_wiznet::chip::W5500; |
| 9 | use embassy_net_wiznet::{Device, Runner, State}; | 9 | use embassy_net_wiznet::{Device, Runner, State}; |
| 10 | use embassy_stm32::exti::ExtiInput; | 10 | use embassy_stm32::exti::{self, ExtiInput}; |
| 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 11 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 12 | use embassy_stm32::mode::Async; | 12 | use embassy_stm32::mode::Async; |
| 13 | use embassy_stm32::rng::Rng; | 13 | use embassy_stm32::rng::Rng; |
| 14 | use embassy_stm32::spi::Spi; | 14 | use embassy_stm32::spi::Spi; |
| 15 | use embassy_stm32::spi::mode::Master; | ||
| 15 | use embassy_stm32::time::Hertz; | 16 | use embassy_stm32::time::Hertz; |
| 16 | use embassy_stm32::{bind_interrupts, peripherals, rng, spi, Config}; | 17 | use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, rng, spi}; |
| 17 | use embassy_time::{Delay, Timer}; | 18 | use embassy_time::{Delay, Timer}; |
| 18 | use embedded_hal_bus::spi::ExclusiveDevice; | 19 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 19 | use embedded_io_async::Write; | 20 | use embedded_io_async::Write; |
| @@ -22,9 +23,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 22 | 23 | ||
| 23 | bind_interrupts!(struct Irqs { | 24 | bind_interrupts!(struct Irqs { |
| 24 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; | 25 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; |
| 26 | EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>; | ||
| 25 | }); | 27 | }); |
| 26 | 28 | ||
| 27 | type EthernetSPI = ExclusiveDevice<Spi<'static, Async>, Output<'static>, Delay>; | 29 | type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>; |
| 28 | #[embassy_executor::task] | 30 | #[embassy_executor::task] |
| 29 | async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { | 31 | async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { |
| 30 | runner.run().await | 32 | runner.run().await |
| @@ -74,7 +76,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 74 | let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); | 76 | let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); |
| 75 | let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); | 77 | let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); |
| 76 | 78 | ||
| 77 | let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); | 79 | let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up, Irqs); |
| 78 | let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); | 80 | let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); |
| 79 | 81 | ||
| 80 | let mac_addr = [0x02, 234, 3, 4, 82, 231]; | 82 | let mac_addr = [0x02, 234, 3, 4, 82, 231]; |
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index 2feb9de09..14f029747 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs | |||
| @@ -5,7 +5,7 @@ use defmt::{info, unwrap}; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::flash::{Flash, InterruptHandler}; | 6 | use embassy_stm32::flash::{Flash, InterruptHandler}; |
| 7 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; |
| 8 | use embassy_stm32::{bind_interrupts, Peri}; | 8 | use embassy_stm32::{Peri, bind_interrupts}; |
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
diff --git a/examples/stm32f4/src/bin/i2c_slave_async.rs b/examples/stm32f4/src/bin/i2c_slave_async.rs new file mode 100644 index 000000000..5065bcdd8 --- /dev/null +++ b/examples/stm32f4/src/bin/i2c_slave_async.rs | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | //! I2C slave example using async operations with DMA | ||
| 2 | //! | ||
| 3 | //! This example demonstrates DMA-accelerated I2C slave operations, | ||
| 4 | //! which provide better performance and lower CPU overhead for | ||
| 5 | //! high-frequency I2C transactions. | ||
| 6 | |||
| 7 | #![no_std] | ||
| 8 | #![no_main] | ||
| 9 | |||
| 10 | use defmt::{error, info}; | ||
| 11 | use embassy_executor::Spawner; | ||
| 12 | use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind}; | ||
| 13 | use embassy_stm32::time::Hertz; | ||
| 14 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 15 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||
| 16 | use embassy_sync::mutex::Mutex; | ||
| 17 | use embassy_time::{Duration, Timer}; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | pub const I2C_SLAVE_ADDR: u8 = 0x42; | ||
| 21 | pub const BUFFER_SIZE: usize = 8; | ||
| 22 | static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]); | ||
| 23 | |||
| 24 | bind_interrupts!(struct Irqs { | ||
| 25 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; | ||
| 26 | I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 27 | }); | ||
| 28 | |||
| 29 | #[embassy_executor::main] | ||
| 30 | async fn main(spawner: Spawner) { | ||
| 31 | let p = embassy_stm32::init(Default::default()); | ||
| 32 | |||
| 33 | // Configure I2C | ||
| 34 | let mut i2c_config = i2c::Config::default(); | ||
| 35 | i2c_config.sda_pullup = false; | ||
| 36 | i2c_config.scl_pullup = false; | ||
| 37 | i2c_config.frequency = Hertz(100_000); // 100kHz I2C speed | ||
| 38 | |||
| 39 | // Initialize I2C as master first | ||
| 40 | let i2c_master = I2c::new( | ||
| 41 | p.I2C1, p.PB8, // SCL | ||
| 42 | p.PB9, // SDA | ||
| 43 | Irqs, p.DMA1_CH6, // TX DMA | ||
| 44 | p.DMA1_CH0, // RX DMA | ||
| 45 | i2c_config, | ||
| 46 | ); | ||
| 47 | |||
| 48 | // Convert to MultiMaster mode | ||
| 49 | let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR); | ||
| 50 | let i2c_slave = i2c_master.into_slave_multimaster(slave_config); | ||
| 51 | |||
| 52 | spawner.spawn(i2c_slave_task(i2c_slave).unwrap()); | ||
| 53 | } | ||
| 54 | |||
| 55 | #[embassy_executor::task] | ||
| 56 | pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Async, i2c::mode::MultiMaster>) { | ||
| 57 | info!("Async I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR); | ||
| 58 | |||
| 59 | loop { | ||
| 60 | match i2c_slave.listen().await { | ||
| 61 | Ok(SlaveCommand { | ||
| 62 | kind: SlaveCommandKind::Write, | ||
| 63 | address, | ||
| 64 | }) => { | ||
| 65 | let addr_val = match address { | ||
| 66 | Address::SevenBit(addr) => addr, | ||
| 67 | Address::TenBit(addr) => (addr & 0xFF) as u8, | ||
| 68 | }; | ||
| 69 | |||
| 70 | info!("I2C: Received write command - Address 0x{:02X}", addr_val); | ||
| 71 | |||
| 72 | let mut data_buffer = I2C_BUFFER.lock().await; | ||
| 73 | |||
| 74 | match i2c_slave.respond_to_write(&mut *data_buffer).await { | ||
| 75 | Ok(_) => { | ||
| 76 | info!( | ||
| 77 | "I2C: Data received - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}", | ||
| 78 | data_buffer[0], | ||
| 79 | data_buffer[1], | ||
| 80 | data_buffer[2], | ||
| 81 | data_buffer[3], | ||
| 82 | data_buffer[4], | ||
| 83 | data_buffer[5], | ||
| 84 | data_buffer[6], | ||
| 85 | data_buffer[7] | ||
| 86 | ); | ||
| 87 | } | ||
| 88 | Err(e) => { | ||
| 89 | error!("I2C: Write error: {}", format_i2c_error(&e)); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | Ok(SlaveCommand { | ||
| 95 | kind: SlaveCommandKind::Read, | ||
| 96 | address, | ||
| 97 | }) => { | ||
| 98 | let addr_val = match address { | ||
| 99 | Address::SevenBit(addr) => addr, | ||
| 100 | Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit | ||
| 101 | }; | ||
| 102 | |||
| 103 | info!("I2C: Received read command - Address 0x{:02X}", addr_val); | ||
| 104 | |||
| 105 | let data_buffer = I2C_BUFFER.lock().await; | ||
| 106 | |||
| 107 | match i2c_slave.respond_to_read(&data_buffer[..BUFFER_SIZE]).await { | ||
| 108 | Ok(_) => { | ||
| 109 | info!("I2C: Responded to read command"); | ||
| 110 | } | ||
| 111 | Err(e) => { | ||
| 112 | error!("I2C: Read error: {}", format_i2c_error(&e)); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | Err(e) => { | ||
| 118 | error!("I2C: Listen error: {}", format_i2c_error(&e)); | ||
| 119 | Timer::after(Duration::from_millis(100)).await; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str { | ||
| 126 | match e { | ||
| 127 | embassy_stm32::i2c::Error::Bus => "Bus", | ||
| 128 | embassy_stm32::i2c::Error::Arbitration => "Arbitration", | ||
| 129 | embassy_stm32::i2c::Error::Nack => "Nack", | ||
| 130 | embassy_stm32::i2c::Error::Timeout => "Timeout", | ||
| 131 | embassy_stm32::i2c::Error::Crc => "Crc", | ||
| 132 | embassy_stm32::i2c::Error::Overrun => "Overrun", | ||
| 133 | embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer", | ||
| 134 | } | ||
| 135 | } | ||
diff --git a/examples/stm32f4/src/bin/i2c_slave_blocking.rs b/examples/stm32f4/src/bin/i2c_slave_blocking.rs new file mode 100644 index 000000000..ee06d4ac4 --- /dev/null +++ b/examples/stm32f4/src/bin/i2c_slave_blocking.rs | |||
| @@ -0,0 +1,132 @@ | |||
| 1 | //! Complete I2C slave example using blocking operations | ||
| 2 | //! | ||
| 3 | //! This example shows how to set up an STM32F4 as an I2C slave device | ||
| 4 | //! that can handle both read and write transactions from master devices. | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use defmt::{error, info}; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind}; | ||
| 12 | use embassy_stm32::time::Hertz; | ||
| 13 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 14 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | ||
| 15 | use embassy_sync::mutex::Mutex; | ||
| 16 | use embassy_time::{Duration, Timer}; | ||
| 17 | use {defmt_rtt as _, panic_probe as _}; | ||
| 18 | |||
| 19 | pub const I2C_SLAVE_ADDR: u8 = 0x42; | ||
| 20 | pub const BUFFER_SIZE: usize = 8; | ||
| 21 | static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]); | ||
| 22 | |||
| 23 | bind_interrupts!(struct Irqs { | ||
| 24 | I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; | ||
| 25 | I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>; | ||
| 26 | }); | ||
| 27 | |||
| 28 | #[embassy_executor::main] | ||
| 29 | async fn main(spawner: Spawner) { | ||
| 30 | let p = embassy_stm32::init(Default::default()); | ||
| 31 | |||
| 32 | // Configure I2C | ||
| 33 | let mut i2c_config = i2c::Config::default(); | ||
| 34 | i2c_config.sda_pullup = false; | ||
| 35 | i2c_config.scl_pullup = false; | ||
| 36 | i2c_config.frequency = Hertz(100_000); | ||
| 37 | i2c_config.timeout = embassy_time::Duration::from_millis(30000); | ||
| 38 | |||
| 39 | // Initialize I2C as master first | ||
| 40 | let i2c_master = I2c::new_blocking( | ||
| 41 | p.I2C1, p.PB8, // SCL | ||
| 42 | p.PB9, // SDA | ||
| 43 | i2c_config, | ||
| 44 | ); | ||
| 45 | |||
| 46 | // Convert to slave+master mode | ||
| 47 | let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR); | ||
| 48 | let i2c_slave = i2c_master.into_slave_multimaster(slave_config); | ||
| 49 | |||
| 50 | spawner.spawn(i2c_slave_task(i2c_slave).unwrap()); | ||
| 51 | } | ||
| 52 | |||
| 53 | #[embassy_executor::task] | ||
| 54 | pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Blocking, i2c::mode::MultiMaster>) { | ||
| 55 | info!("Blocking I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR); | ||
| 56 | |||
| 57 | loop { | ||
| 58 | match i2c_slave.blocking_listen() { | ||
| 59 | Ok(SlaveCommand { | ||
| 60 | kind: SlaveCommandKind::Write, | ||
| 61 | address, | ||
| 62 | }) => { | ||
| 63 | let addr_val = match address { | ||
| 64 | Address::SevenBit(addr) => addr, | ||
| 65 | Address::TenBit(addr) => (addr & 0xFF) as u8, | ||
| 66 | }; | ||
| 67 | |||
| 68 | info!("I2C: Received write command - Address 0x{:02X}", addr_val); | ||
| 69 | let mut data_buffer = I2C_BUFFER.lock().await; | ||
| 70 | |||
| 71 | match i2c_slave.blocking_respond_to_write(&mut *data_buffer) { | ||
| 72 | Ok(bytes_received) => { | ||
| 73 | info!( | ||
| 74 | "I2C: Received {} bytes - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}", | ||
| 75 | bytes_received, | ||
| 76 | data_buffer[0], | ||
| 77 | data_buffer[1], | ||
| 78 | data_buffer[2], | ||
| 79 | data_buffer[3], | ||
| 80 | data_buffer[4], | ||
| 81 | data_buffer[5], | ||
| 82 | data_buffer[6], | ||
| 83 | data_buffer[7] | ||
| 84 | ); | ||
| 85 | } | ||
| 86 | Err(e) => { | ||
| 87 | error!("I2C: Write error: {}", format_i2c_error(&e)); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | Ok(SlaveCommand { | ||
| 93 | kind: SlaveCommandKind::Read, | ||
| 94 | address, | ||
| 95 | }) => { | ||
| 96 | let addr_val = match address { | ||
| 97 | Address::SevenBit(addr) => addr, | ||
| 98 | Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit | ||
| 99 | }; | ||
| 100 | |||
| 101 | info!("I2C: Received read command - Address 0x{:02X}", addr_val); | ||
| 102 | let data_buffer = I2C_BUFFER.lock().await; | ||
| 103 | |||
| 104 | match i2c_slave.blocking_respond_to_read(&data_buffer[..BUFFER_SIZE]) { | ||
| 105 | Ok(bytes_sent) => { | ||
| 106 | info!("I2C: Responded to read - {} bytes sent", bytes_sent); | ||
| 107 | } | ||
| 108 | Err(e) => { | ||
| 109 | error!("I2C: Read error: {}", format_i2c_error(&e)); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | Err(e) => { | ||
| 115 | error!("I2C: Listen error: {}", format_i2c_error(&e)); | ||
| 116 | Timer::after(Duration::from_millis(100)).await; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str { | ||
| 123 | match e { | ||
| 124 | embassy_stm32::i2c::Error::Bus => "Bus", | ||
| 125 | embassy_stm32::i2c::Error::Arbitration => "Arbitration", | ||
| 126 | embassy_stm32::i2c::Error::Nack => "Nack", | ||
| 127 | embassy_stm32::i2c::Error::Timeout => "Timeout", | ||
| 128 | embassy_stm32::i2c::Error::Crc => "Crc", | ||
| 129 | embassy_stm32::i2c::Error::Overrun => "Overrun", | ||
| 130 | embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer", | ||
| 131 | } | ||
| 132 | } | ||
diff --git a/examples/stm32f4/src/bin/input_capture.rs b/examples/stm32f4/src/bin/input_capture.rs index 9998c4733..3ff96584d 100644 --- a/examples/stm32f4/src/bin/input_capture.rs +++ b/examples/stm32f4/src/bin/input_capture.rs | |||
| @@ -7,7 +7,7 @@ use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | |||
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; | 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; |
| 9 | use embassy_stm32::timer::{self, Channel}; | 9 | use embassy_stm32::timer::{self, Channel}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, Peri}; | 10 | use embassy_stm32::{Peri, bind_interrupts, peripherals}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs index eb7bb6261..a2e229770 100644 --- a/examples/stm32f4/src/bin/mco.rs +++ b/examples/stm32f4/src/bin/mco.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoPrescaler}; | 7 | use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoConfig, McoPrescaler}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -13,8 +13,20 @@ async fn main(_spawner: Spawner) { | |||
| 13 | let p = embassy_stm32::init(Default::default()); | 13 | let p = embassy_stm32::init(Default::default()); |
| 14 | info!("Hello World!"); | 14 | info!("Hello World!"); |
| 15 | 15 | ||
| 16 | let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV1); | 16 | let config_mco1 = { |
| 17 | let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, McoPrescaler::DIV4); | 17 | let mut config = McoConfig::default(); |
| 18 | config.prescaler = McoPrescaler::DIV1; | ||
| 19 | config | ||
| 20 | }; | ||
| 21 | |||
| 22 | let config_mco2 = { | ||
| 23 | let mut config = McoConfig::default(); | ||
| 24 | config.prescaler = McoPrescaler::DIV4; | ||
| 25 | config | ||
| 26 | }; | ||
| 27 | |||
| 28 | let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, config_mco1); | ||
| 29 | let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, config_mco2); | ||
| 18 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); | 30 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); |
| 19 | 31 | ||
| 20 | loop { | 32 | loop { |
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 2f2ffdea2..8375e0e8e 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs | |||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn UART4() { | 115 | unsafe fn UART4() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn UART5() { | 120 | unsafe fn UART5() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs index c981f1a76..5e39a06f5 100644 --- a/examples/stm32f4/src/bin/pwm_complementary.rs +++ b/examples/stm32f4/src/bin/pwm_complementary.rs | |||
| @@ -5,9 +5,9 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::OutputType; | 6 | use embassy_stm32::gpio::OutputType; |
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::Channel; | ||
| 8 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; | 9 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; |
| 9 | use embassy_stm32::timer::simple_pwm::PwmPin; | 10 | use embassy_stm32::timer::simple_pwm::PwmPin; |
| 10 | use embassy_stm32::timer::Channel; | ||
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| @@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | ); | 33 | ); |
| 34 | 34 | ||
| 35 | let max = pwm.get_max_duty(); | 35 | let max = pwm.get_max_duty(); |
| 36 | pwm.set_dead_time(max / 1024); | 36 | pwm.set_dead_time((max / 1024) as u16); |
| 37 | 37 | ||
| 38 | pwm.enable(Channel::Ch1); | 38 | pwm.enable(Channel::Ch1); |
| 39 | 39 | ||
diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index e8bfa524f..d8ea56a34 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; |
| 7 | use embassy_stm32::time::khz; | 7 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::pwm_input::PwmInput; | 8 | use embassy_stm32::timer::pwm_input::PwmInput; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; | 9 | use embassy_stm32::{Peri, bind_interrupts, peripherals, timer}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index 82d8a37ba..5ff705ca2 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 8 | use embassy_stm32::Config; | 7 | use embassy_stm32::Config; |
| 8 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) { | |||
| 21 | .and_hms_opt(10, 30, 15) | 21 | .and_hms_opt(10, 30, 15) |
| 22 | .unwrap(); | 22 | .unwrap(); |
| 23 | 23 | ||
| 24 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 24 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 25 | 25 | ||
| 26 | rtc.set_datetime(now.into()).expect("datetime not set"); | 26 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| 27 | 27 | ||
| 28 | loop { | 28 | loop { |
| 29 | let now: NaiveDateTime = rtc.now().unwrap().into(); | 29 | let now: NaiveDateTime = time_provider.now().unwrap().into(); |
| 30 | 30 | ||
| 31 | info!("{}", now.and_utc().timestamp()); | 31 | info!("{}", now.and_utc().timestamp()); |
| 32 | 32 | ||
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs index e97b63925..098fd6986 100644 --- a/examples/stm32f4/src/bin/sdmmc.rs +++ b/examples/stm32f4/src/bin/sdmmc.rs | |||
| @@ -3,9 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; | 6 | use embassy_stm32::sdmmc::Sdmmc; |
| 7 | use embassy_stm32::time::{mhz, Hertz}; | 7 | use embassy_stm32::sdmmc::sd::{CmdBlock, DataBlock, StorageDevice}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; | 8 | use embassy_stm32::time::{Hertz, mhz}; |
| 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 11 | ||
| 11 | /// This is a safeguard to not overwrite any data on the SD card. | 12 | /// This is a safeguard to not overwrite any data on the SD card. |
| @@ -57,31 +58,24 @@ async fn main(_spawner: Spawner) { | |||
| 57 | // Should print 400kHz for initialization | 58 | // Should print 400kHz for initialization |
| 58 | info!("Configured clock: {}", sdmmc.clock().0); | 59 | info!("Configured clock: {}", sdmmc.clock().0); |
| 59 | 60 | ||
| 60 | let mut err = None; | 61 | let mut cmd_block = CmdBlock::new(); |
| 61 | loop { | 62 | |
| 62 | match sdmmc.init_sd_card(mhz(24)).await { | 63 | let mut storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(24)) |
| 63 | Ok(_) => break, | 64 | .await |
| 64 | Err(e) => { | 65 | .unwrap(); |
| 65 | if err != Some(e) { | ||
| 66 | info!("waiting for card error, retrying: {:?}", e); | ||
| 67 | err = Some(e); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | 66 | ||
| 73 | let card = unwrap!(sdmmc.card()); | 67 | let card = storage.card(); |
| 74 | 68 | ||
| 75 | info!("Card: {:#?}", Debug2Format(card)); | 69 | info!("Card: {:#?}", Debug2Format(&card)); |
| 76 | info!("Clock: {}", sdmmc.clock()); | 70 | info!("Clock: {}", storage.sdmmc.clock()); |
| 77 | 71 | ||
| 78 | // Arbitrary block index | 72 | // Arbitrary block index |
| 79 | let block_idx = 16; | 73 | let block_idx = 16; |
| 80 | 74 | ||
| 81 | // SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware. | 75 | // SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware. |
| 82 | let mut block = DataBlock([0u8; 512]); | 76 | let mut block = DataBlock::new(); |
| 83 | 77 | ||
| 84 | sdmmc.read_block(block_idx, &mut block).await.unwrap(); | 78 | storage.read_block(block_idx, &mut block).await.unwrap(); |
| 85 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); | 79 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); |
| 86 | 80 | ||
| 87 | if !ALLOW_WRITES { | 81 | if !ALLOW_WRITES { |
| @@ -91,17 +85,17 @@ async fn main(_spawner: Spawner) { | |||
| 91 | 85 | ||
| 92 | info!("Filling block with 0x55"); | 86 | info!("Filling block with 0x55"); |
| 93 | block.fill(0x55); | 87 | block.fill(0x55); |
| 94 | sdmmc.write_block(block_idx, &block).await.unwrap(); | 88 | storage.write_block(block_idx, &block).await.unwrap(); |
| 95 | info!("Write done"); | 89 | info!("Write done"); |
| 96 | 90 | ||
| 97 | sdmmc.read_block(block_idx, &mut block).await.unwrap(); | 91 | storage.read_block(block_idx, &mut block).await.unwrap(); |
| 98 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); | 92 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); |
| 99 | 93 | ||
| 100 | info!("Filling block with 0xAA"); | 94 | info!("Filling block with 0xAA"); |
| 101 | block.fill(0xAA); | 95 | block.fill(0xAA); |
| 102 | sdmmc.write_block(block_idx, &block).await.unwrap(); | 96 | storage.write_block(block_idx, &block).await.unwrap(); |
| 103 | info!("Write done"); | 97 | info!("Write done"); |
| 104 | 98 | ||
| 105 | sdmmc.read_block(block_idx, &mut block).await.unwrap(); | 99 | storage.read_block(block_idx, &mut block).await.unwrap(); |
| 106 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); | 100 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); |
| 107 | } | 101 | } |
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index 7abbe8719..a5e625edd 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs | |||
| @@ -3,12 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::StackResources; | 6 | use embassy_net::StackResources; |
| 7 | use embassy_net::tcp::TcpSocket; | ||
| 8 | use embassy_stm32::rng::{self, Rng}; | 8 | use embassy_stm32::rng::{self, Rng}; |
| 9 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 10 | use embassy_stm32::usb::Driver; | 10 | use embassy_stm32::usb::Driver; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 11 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 12 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; | 12 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; |
| 13 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 13 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 14 | use embassy_usb::{Builder, UsbDevice}; | 14 | use embassy_usb::{Builder, UsbDevice}; |
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs index d6b4a9bc9..2d834dcf7 100644 --- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs +++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,17 +1,19 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 9 | use embassy_stm32::exti::ExtiInput; | 9 | use embassy_stm32::exti::{self, ExtiInput}; |
| 10 | use embassy_stm32::gpio::Pull; | 10 | use embassy_stm32::gpio::Pull; |
| 11 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::usb::Driver; | 12 | use embassy_stm32::usb::Driver; |
| 13 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 13 | use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, usb}; |
| 14 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 14 | use embassy_usb::class::hid::{ |
| 15 | HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 15 | use embassy_usb::control::OutResponse; | 17 | use embassy_usb::control::OutResponse; |
| 16 | use embassy_usb::{Builder, Handler}; | 18 | use embassy_usb::{Builder, Handler}; |
| 17 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 19 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -19,8 +21,11 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 19 | 21 | ||
| 20 | bind_interrupts!(struct Irqs { | 22 | bind_interrupts!(struct Irqs { |
| 21 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; | 23 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; |
| 24 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 22 | }); | 25 | }); |
| 23 | 26 | ||
| 27 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 28 | |||
| 24 | // If you are trying this and your USB device doesn't connect, the most | 29 | // If you are trying this and your USB device doesn't connect, the most |
| 25 | // common issues are the RCC config and vbus_detection | 30 | // common issues are the RCC config and vbus_detection |
| 26 | // | 31 | // |
| @@ -70,6 +75,10 @@ async fn main(_spawner: Spawner) { | |||
| 70 | config.serial_number = Some("12345678"); | 75 | config.serial_number = Some("12345678"); |
| 71 | config.max_power = 100; | 76 | config.max_power = 100; |
| 72 | config.max_packet_size_0 = 64; | 77 | config.max_packet_size_0 = 64; |
| 78 | config.composite_with_iads = false; | ||
| 79 | config.device_class = 0; | ||
| 80 | config.device_sub_class = 0; | ||
| 81 | config.device_protocol = 0; | ||
| 73 | 82 | ||
| 74 | // Create embassy-usb DeviceBuilder using the driver and config. | 83 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 75 | // It needs some buffers for building the descriptors. | 84 | // It needs some buffers for building the descriptors. |
| @@ -101,6 +110,8 @@ async fn main(_spawner: Spawner) { | |||
| 101 | request_handler: None, | 110 | request_handler: None, |
| 102 | poll_ms: 60, | 111 | poll_ms: 60, |
| 103 | max_packet_size: 8, | 112 | max_packet_size: 8, |
| 113 | hid_subclass: HidSubclass::Boot, | ||
| 114 | hid_boot_protocol: HidBootProtocol::Keyboard, | ||
| 104 | }; | 115 | }; |
| 105 | 116 | ||
| 106 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | 117 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| @@ -113,7 +124,7 @@ async fn main(_spawner: Spawner) { | |||
| 113 | 124 | ||
| 114 | let (reader, mut writer) = hid.split(); | 125 | let (reader, mut writer) = hid.split(); |
| 115 | 126 | ||
| 116 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 127 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 117 | 128 | ||
| 118 | // Do stuff with the class! | 129 | // Do stuff with the class! |
| 119 | let in_fut = async { | 130 | let in_fut = async { |
| @@ -121,32 +132,46 @@ async fn main(_spawner: Spawner) { | |||
| 121 | button.wait_for_rising_edge().await; | 132 | button.wait_for_rising_edge().await; |
| 122 | // signal_pin.wait_for_high().await; | 133 | // signal_pin.wait_for_high().await; |
| 123 | info!("Button pressed!"); | 134 | info!("Button pressed!"); |
| 124 | // Create a report with the A key pressed. (no shift modifier) | 135 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 125 | let report = KeyboardReport { | 136 | match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await { |
| 126 | keycodes: [4, 0, 0, 0, 0, 0], | 137 | Ok(()) => {} |
| 127 | leds: 0, | 138 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 128 | modifier: 0, | 139 | }; |
| 129 | reserved: 0, | 140 | } else { |
| 130 | }; | 141 | // Create a report with the A key pressed. (no shift modifier) |
| 131 | // Send the report. | 142 | let report = KeyboardReport { |
| 132 | match writer.write_serialize(&report).await { | 143 | keycodes: [4, 0, 0, 0, 0, 0], |
| 133 | Ok(()) => {} | 144 | leds: 0, |
| 134 | Err(e) => warn!("Failed to send report: {:?}", e), | 145 | modifier: 0, |
| 135 | }; | 146 | reserved: 0, |
| 147 | }; | ||
| 148 | // Send the report. | ||
| 149 | match writer.write_serialize(&report).await { | ||
| 150 | Ok(()) => {} | ||
| 151 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 152 | }; | ||
| 153 | } | ||
| 136 | 154 | ||
| 137 | button.wait_for_falling_edge().await; | 155 | button.wait_for_falling_edge().await; |
| 138 | // signal_pin.wait_for_low().await; | 156 | // signal_pin.wait_for_low().await; |
| 139 | info!("Button released!"); | 157 | info!("Button released!"); |
| 140 | let report = KeyboardReport { | 158 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 141 | keycodes: [0, 0, 0, 0, 0, 0], | 159 | match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await { |
| 142 | leds: 0, | 160 | Ok(()) => {} |
| 143 | modifier: 0, | 161 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 144 | reserved: 0, | 162 | }; |
| 145 | }; | 163 | } else { |
| 146 | match writer.write_serialize(&report).await { | 164 | let report = KeyboardReport { |
| 147 | Ok(()) => {} | 165 | keycodes: [0, 0, 0, 0, 0, 0], |
| 148 | Err(e) => warn!("Failed to send report: {:?}", e), | 166 | leds: 0, |
| 149 | }; | 167 | modifier: 0, |
| 168 | reserved: 0, | ||
| 169 | }; | ||
| 170 | match writer.write_serialize(&report).await { | ||
| 171 | Ok(()) => {} | ||
| 172 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 173 | }; | ||
| 174 | } | ||
| 150 | } | 175 | } |
| 151 | }; | 176 | }; |
| 152 | 177 | ||
| @@ -172,6 +197,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 172 | OutResponse::Accepted | 197 | OutResponse::Accepted |
| 173 | } | 198 | } |
| 174 | 199 | ||
| 200 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 201 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 202 | info!("The current HID protocol mode is: {}", protocol); | ||
| 203 | protocol | ||
| 204 | } | ||
| 205 | |||
| 206 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 207 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 208 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 209 | OutResponse::Accepted | ||
| 210 | } | ||
| 211 | |||
| 175 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 212 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 176 | info!("Set idle rate for {:?} to {:?}", id, dur); | 213 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 177 | } | 214 | } |
diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs index badb65e98..e83d01f88 100644 --- a/examples/stm32f4/src/bin/usb_hid_mouse.rs +++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs | |||
| @@ -1,16 +1,20 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::usb::Driver; | 10 | use embassy_stm32::usb::Driver; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 11 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 11 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | ||
| 12 | use embassy_usb::control::OutResponse; | ||
| 13 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 14 | use embassy_usb::class::hid::{ | ||
| 15 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 16 | }; | ||
| 17 | use embassy_usb::control::OutResponse; | ||
| 14 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 19 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 20 | ||
| @@ -18,6 +22,8 @@ bind_interrupts!(struct Irqs { | |||
| 18 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; | 22 | OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; |
| 19 | }); | 23 | }); |
| 20 | 24 | ||
| 25 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 26 | |||
| 21 | // If you are trying this and your USB device doesn't connect, the most | 27 | // If you are trying this and your USB device doesn't connect, the most |
| 22 | // common issues are the RCC config and vbus_detection | 28 | // common issues are the RCC config and vbus_detection |
| 23 | // | 29 | // |
| @@ -65,6 +71,10 @@ async fn main(_spawner: Spawner) { | |||
| 65 | config.manufacturer = Some("Embassy"); | 71 | config.manufacturer = Some("Embassy"); |
| 66 | config.product = Some("HID mouse example"); | 72 | config.product = Some("HID mouse example"); |
| 67 | config.serial_number = Some("12345678"); | 73 | config.serial_number = Some("12345678"); |
| 74 | config.composite_with_iads = false; | ||
| 75 | config.device_class = 0; | ||
| 76 | config.device_sub_class = 0; | ||
| 77 | config.device_protocol = 0; | ||
| 68 | 78 | ||
| 69 | // Create embassy-usb DeviceBuilder using the driver and config. | 79 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 70 | // It needs some buffers for building the descriptors. | 80 | // It needs some buffers for building the descriptors. |
| @@ -91,6 +101,8 @@ async fn main(_spawner: Spawner) { | |||
| 91 | request_handler: Some(&mut request_handler), | 101 | request_handler: Some(&mut request_handler), |
| 92 | poll_ms: 60, | 102 | poll_ms: 60, |
| 93 | max_packet_size: 8, | 103 | max_packet_size: 8, |
| 104 | hid_subclass: HidSubclass::Boot, | ||
| 105 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 94 | }; | 106 | }; |
| 95 | 107 | ||
| 96 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); | 108 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| @@ -108,16 +120,26 @@ async fn main(_spawner: Spawner) { | |||
| 108 | Timer::after_millis(500).await; | 120 | Timer::after_millis(500).await; |
| 109 | 121 | ||
| 110 | y = -y; | 122 | y = -y; |
| 111 | let report = MouseReport { | 123 | |
| 112 | buttons: 0, | 124 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 113 | x: 0, | 125 | let buttons = 0u8; |
| 114 | y, | 126 | let x = 0i8; |
| 115 | wheel: 0, | 127 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 116 | pan: 0, | 128 | Ok(()) => {} |
| 117 | }; | 129 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 118 | match writer.write_serialize(&report).await { | 130 | } |
| 119 | Ok(()) => {} | 131 | } else { |
| 120 | Err(e) => warn!("Failed to send report: {:?}", e), | 132 | let report = MouseReport { |
| 133 | buttons: 0, | ||
| 134 | x: 0, | ||
| 135 | y, | ||
| 136 | wheel: 0, | ||
| 137 | pan: 0, | ||
| 138 | }; | ||
| 139 | match writer.write_serialize(&report).await { | ||
| 140 | Ok(()) => {} | ||
| 141 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 142 | } | ||
| 121 | } | 143 | } |
| 122 | } | 144 | } |
| 123 | }; | 145 | }; |
| @@ -140,6 +162,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 140 | OutResponse::Accepted | 162 | OutResponse::Accepted |
| 141 | } | 163 | } |
| 142 | 164 | ||
| 165 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 166 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 167 | info!("The current HID protocol mode is: {}", protocol); | ||
| 168 | protocol | ||
| 169 | } | ||
| 170 | |||
| 171 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 172 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 173 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 174 | OutResponse::Accepted | ||
| 175 | } | ||
| 176 | |||
| 143 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 177 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 144 | info!("Set idle rate for {:?} to {:?}", id, dur); | 178 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 145 | } | 179 | } |
diff --git a/examples/stm32f4/src/bin/usb_raw.rs b/examples/stm32f4/src/bin/usb_raw.rs index bbbcc082b..511f0b281 100644 --- a/examples/stm32f4/src/bin/usb_raw.rs +++ b/examples/stm32f4/src/bin/usb_raw.rs | |||
| @@ -53,7 +53,7 @@ use defmt::*; | |||
| 53 | use embassy_executor::Spawner; | 53 | use embassy_executor::Spawner; |
| 54 | use embassy_stm32::time::Hertz; | 54 | use embassy_stm32::time::Hertz; |
| 55 | use embassy_stm32::usb::Driver; | 55 | use embassy_stm32::usb::Driver; |
| 56 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 56 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 57 | use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType}; | 57 | use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType}; |
| 58 | use embassy_usb::msos::{self, windows_version}; | 58 | use embassy_usb::msos::{self, windows_version}; |
| 59 | use embassy_usb::types::InterfaceNumber; | 59 | use embassy_usb::types::InterfaceNumber; |
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs index e62b2d8d6..2e81e0a59 100644 --- a/examples/stm32f4/src/bin/usb_serial.rs +++ b/examples/stm32f4/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::time::Hertz; | 7 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32f4/src/bin/usb_uac_speaker.rs b/examples/stm32f4/src/bin/usb_uac_speaker.rs index 79bd2d914..b92f4531e 100644 --- a/examples/stm32f4/src/bin/usb_uac_speaker.rs +++ b/examples/stm32f4/src/bin/usb_uac_speaker.rs | |||
| @@ -6,9 +6,9 @@ use core::cell::{Cell, RefCell}; | |||
| 6 | use defmt::{panic, *}; | 6 | use defmt::{panic, *}; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::{bind_interrupts, interrupt, peripherals, timer, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, timer, usb}; |
| 10 | use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | ||
| 11 | use embassy_sync::blocking_mutex::Mutex; | 10 | use embassy_sync::blocking_mutex::Mutex; |
| 11 | use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | ||
| 12 | use embassy_sync::signal::Signal; | 12 | use embassy_sync::signal::Signal; |
| 13 | use embassy_sync::zerocopy_channel; | 13 | use embassy_sync::zerocopy_channel; |
| 14 | use embassy_usb::class::uac1; | 14 | use embassy_usb::class::uac1; |
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs index 5153e1cfd..4e556f0d4 100644 --- a/examples/stm32f4/src/bin/ws2812_pwm.rs +++ b/examples/stm32f4/src/bin/ws2812_pwm.rs | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | use embassy_executor::Spawner; | 15 | use embassy_executor::Spawner; |
| 16 | use embassy_stm32::gpio::OutputType; | 16 | use embassy_stm32::gpio::OutputType; |
| 17 | use embassy_stm32::time::khz; | 17 | use embassy_stm32::time::khz; |
| 18 | use embassy_stm32::timer::Channel; | ||
| 18 | use embassy_stm32::timer::low_level::CountingMode; | 19 | use embassy_stm32::timer::low_level::CountingMode; |
| 19 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 20 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 20 | use embassy_stm32::timer::Channel; | ||
| 21 | use embassy_time::{Duration, Ticker, Timer}; | 21 | use embassy_time::{Duration, Ticker, Timer}; |
| 22 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {defmt_rtt as _, panic_probe as _}; |
| 23 | 23 | ||
| @@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) { | |||
| 61 | // construct ws2812 non-return-to-zero (NRZ) code bit by bit | 61 | // construct ws2812 non-return-to-zero (NRZ) code bit by bit |
| 62 | // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low | 62 | // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low |
| 63 | 63 | ||
| 64 | let max_duty = ws2812_pwm.max_duty_cycle(); | 64 | let max_duty = ws2812_pwm.max_duty_cycle() as u16; |
| 65 | let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing | 65 | let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing |
| 66 | let n1 = 2 * n0; // ws2812 Bit 1 high level timing | 66 | let n1 = 2 * n0; // ws2812 Bit 1 high level timing |
| 67 | 67 | ||
diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index f1d0e411a..5216e19b4 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f469-examples" | 3 | name = "embassy-stm32f469-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32f469/src/bin/dsi_bsp.rs b/examples/stm32f469/src/bin/dsi_bsp.rs index 3a24d5dcf..7ba4da72b 100644 --- a/examples/stm32f469/src/bin/dsi_bsp.rs +++ b/examples/stm32f469/src/bin/dsi_bsp.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dsihost::{blocking_delay_ms, DsiHost, PacketType}; | 6 | use embassy_stm32::dsihost::{DsiHost, PacketType}; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::ltdc::Ltdc; | 8 | use embassy_stm32::ltdc::Ltdc; |
| 9 | use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1}; | 9 | use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1}; |
| @@ -13,7 +13,7 @@ use embassy_stm32::rcc::{ | |||
| 13 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk, | 13 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk, |
| 14 | }; | 14 | }; |
| 15 | use embassy_stm32::time::mhz; | 15 | use embassy_stm32::time::mhz; |
| 16 | use embassy_time::Timer; | 16 | use embassy_time::{Duration, Timer, block_for}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
| 19 | enum _Orientation { | 19 | enum _Orientation { |
| @@ -211,7 +211,7 @@ async fn main(_spawner: Spawner) { | |||
| 211 | const HORIZONTAL_SYNC_ACTIVE: u16 = 4; // ((HSA as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; | 211 | const HORIZONTAL_SYNC_ACTIVE: u16 = 4; // ((HSA as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; |
| 212 | const HORIZONTAL_BACK_PORCH: u16 = 77; //((HBP as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32) as u16; | 212 | const HORIZONTAL_BACK_PORCH: u16 = 77; //((HBP as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32) as u16; |
| 213 | const HORIZONTAL_LINE: u16 = 1982; //(((HACT + HSA + HBP + HFP) as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; /* Value depending on display orientation choice portrait/landscape */ | 213 | const HORIZONTAL_LINE: u16 = 1982; //(((HACT + HSA + HBP + HFP) as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; /* Value depending on display orientation choice portrait/landscape */ |
| 214 | // FIXME: Make depend on orientation | 214 | // FIXME: Make depend on orientation |
| 215 | const VERTICAL_SYNC_ACTIVE: u16 = VSA; | 215 | const VERTICAL_SYNC_ACTIVE: u16 = VSA; |
| 216 | const VERTICAL_BACK_PORCH: u16 = VBP; | 216 | const VERTICAL_BACK_PORCH: u16 = VBP; |
| 217 | const VERTICAL_FRONT_PORCH: u16 = VFP; | 217 | const VERTICAL_FRONT_PORCH: u16 = VFP; |
| @@ -444,7 +444,7 @@ async fn main(_spawner: Spawner) { | |||
| 444 | dsi.enable_wrapper_dsi(); | 444 | dsi.enable_wrapper_dsi(); |
| 445 | 445 | ||
| 446 | // First, delay 120 ms (reason unknown, STM32 Cube Example does it) | 446 | // First, delay 120 ms (reason unknown, STM32 Cube Example does it) |
| 447 | blocking_delay_ms(120); | 447 | block_for(Duration::from_millis(120)); |
| 448 | 448 | ||
| 449 | // 1 to 26 | 449 | // 1 to 26 |
| 450 | dsi.write_cmd(0, NT35510_WRITES_0[0], &NT35510_WRITES_0[1..]).unwrap(); | 450 | dsi.write_cmd(0, NT35510_WRITES_0[0], &NT35510_WRITES_0[1..]).unwrap(); |
| @@ -480,7 +480,7 @@ async fn main(_spawner: Spawner) { | |||
| 480 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); | 480 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); |
| 481 | 481 | ||
| 482 | // Add a delay, otherwise MADCTL not taken | 482 | // Add a delay, otherwise MADCTL not taken |
| 483 | blocking_delay_ms(200); | 483 | block_for(Duration::from_millis(200)); |
| 484 | 484 | ||
| 485 | // Configure orientation as landscape | 485 | // Configure orientation as landscape |
| 486 | dsi.write_cmd(0, NT35510_MADCTL_LANDSCAPE[0], &NT35510_MADCTL_LANDSCAPE[1..]) | 486 | dsi.write_cmd(0, NT35510_MADCTL_LANDSCAPE[0], &NT35510_MADCTL_LANDSCAPE[1..]) |
| @@ -494,7 +494,7 @@ async fn main(_spawner: Spawner) { | |||
| 494 | dsi.write_cmd(0, NT35510_WRITES_27[0], &NT35510_WRITES_27[1..]).unwrap(); | 494 | dsi.write_cmd(0, NT35510_WRITES_27[0], &NT35510_WRITES_27[1..]).unwrap(); |
| 495 | 495 | ||
| 496 | // Wait for sleep out exit | 496 | // Wait for sleep out exit |
| 497 | blocking_delay_ms(120); | 497 | block_for(Duration::from_millis(120)); |
| 498 | 498 | ||
| 499 | // Configure COLOR_CODING | 499 | // Configure COLOR_CODING |
| 500 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); | 500 | dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); |
| @@ -590,7 +590,7 @@ async fn main(_spawner: Spawner) { | |||
| 590 | //LTDC->SRCR = LTDC_SRCR_IMR; | 590 | //LTDC->SRCR = LTDC_SRCR_IMR; |
| 591 | LTDC.srcr().modify(|w| w.set_imr(Imr::RELOAD)); | 591 | LTDC.srcr().modify(|w| w.set_imr(Imr::RELOAD)); |
| 592 | 592 | ||
| 593 | blocking_delay_ms(5000); | 593 | block_for(Duration::from_millis(5000)); |
| 594 | 594 | ||
| 595 | const READ_SIZE: u16 = 1; | 595 | const READ_SIZE: u16 = 1; |
| 596 | let mut data = [1u8; READ_SIZE as usize]; | 596 | let mut data = [1u8; READ_SIZE as usize]; |
| @@ -606,7 +606,7 @@ async fn main(_spawner: Spawner) { | |||
| 606 | .unwrap(); | 606 | .unwrap(); |
| 607 | info!("Display ID3: {:#04x}", data); | 607 | info!("Display ID3: {:#04x}", data); |
| 608 | 608 | ||
| 609 | blocking_delay_ms(500); | 609 | block_for(Duration::from_millis(500)); |
| 610 | 610 | ||
| 611 | info!("Config done, start blinking LED"); | 611 | info!("Config done, start blinking LED"); |
| 612 | loop { | 612 | loop { |
| @@ -658,7 +658,7 @@ const NT35510_RASET_LANDSCAPE: &[u8] = &[NT35510_CMD_RASET, 0x00, 0x00, 0x01, 0x | |||
| 658 | 658 | ||
| 659 | const NT35510_WRITES_26: &[u8] = &[NT35510_CMD_TEEON, 0x00]; // Tear on | 659 | const NT35510_WRITES_26: &[u8] = &[NT35510_CMD_TEEON, 0x00]; // Tear on |
| 660 | const NT35510_WRITES_27: &[u8] = &[NT35510_CMD_SLPOUT, 0x00]; // Sleep out | 660 | const NT35510_WRITES_27: &[u8] = &[NT35510_CMD_SLPOUT, 0x00]; // Sleep out |
| 661 | // 28,29 missing | 661 | // 28,29 missing |
| 662 | const NT35510_WRITES_30: &[u8] = &[NT35510_CMD_DISPON, 0x00]; // Display on | 662 | const NT35510_WRITES_30: &[u8] = &[NT35510_CMD_DISPON, 0x00]; // Display on |
| 663 | 663 | ||
| 664 | const NT35510_WRITES_31: &[u8] = &[NT35510_CMD_WRDISBV, 0x7F]; | 664 | const NT35510_WRITES_31: &[u8] = &[NT35510_CMD_WRDISBV, 0x7F]; |
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 5d7763334..565277394 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32f7-examples" | 3 | name = "embassy-stm32f7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs index 6689e3b5d..0f226d34e 100644 --- a/examples/stm32f7/src/bin/adc.rs +++ b/examples/stm32f7/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::Adc; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let mut pin = p.PA3; | 16 | let mut pin = p.PA3; |
| 17 | 17 | ||
| 18 | let mut vrefint = adc.enable_vrefint(); | 18 | let mut vrefint = adc.enable_vrefint(); |
| 19 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 19 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 20 | let convert_to_millivolts = |sample| { | 20 | let convert_to_millivolts = |sample| { |
| 21 | // From http://www.st.com/resource/en/datasheet/DM00273119.pdf | 21 | // From http://www.st.com/resource/en/datasheet/DM00273119.pdf |
| 22 | // 6.3.27 Reference voltage | 22 | // 6.3.27 Reference voltage |
| @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | loop { | 28 | loop { |
| 29 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); |
| 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 31 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 32 | } | 32 | } |
diff --git a/examples/stm32f7/src/bin/button_exti.rs b/examples/stm32f7/src/bin/button_exti.rs index 2a546dac5..e7e1549a8 100644 --- a/examples/stm32f7/src/bin/button_exti.rs +++ b/examples/stm32f7/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index 9a91ac814..2f3f6db84 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::num::{NonZeroU16, NonZeroU8}; | 4 | use core::num::{NonZeroU8, NonZeroU16}; |
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs index a31e9b4f2..9ccef0b82 100644 --- a/examples/stm32f7/src/bin/cryp.rs +++ b/examples/stm32f7/src/bin/cryp.rs | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use aes_gcm::Aes128Gcm; | ||
| 4 | use aes_gcm::aead::heapless::Vec; | 5 | use aes_gcm::aead::heapless::Vec; |
| 5 | use aes_gcm::aead::{AeadInPlace, KeyInit}; | 6 | use aes_gcm::aead::{AeadInPlace, KeyInit}; |
| 6 | use aes_gcm::Aes128Gcm; | ||
| 7 | use defmt::info; | 7 | use defmt::info; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::cryp::{self, *}; | 9 | use embassy_stm32::cryp::{self, *}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, Config}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals}; |
| 11 | use embassy_time::Instant; | 11 | use embassy_time::Instant; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index b13b7bdda..8613376b8 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -5,11 +5,11 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 9 | use embassy_stm32::peripherals::ETH; | 9 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; |
| 10 | use embassy_stm32::rng::Rng; | 10 | use embassy_stm32::rng::Rng; |
| 11 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 12 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use embedded_io_async::Write; | 14 | use embedded_io_async::Write; |
| 15 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| @@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs { | |||
| 20 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; | 20 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; |
| 21 | }); | 21 | }); |
| 22 | 22 | ||
| 23 | type Device = Ethernet<'static, ETH, GenericPhy>; | 23 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 24 | 24 | ||
| 25 | #[embassy_executor::task] | 25 | #[embassy_executor::task] |
| 26 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 26 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -67,16 +67,16 @@ async fn main(spawner: Spawner) -> ! { | |||
| 67 | p.ETH, | 67 | p.ETH, |
| 68 | Irqs, | 68 | Irqs, |
| 69 | p.PA1, | 69 | p.PA1, |
| 70 | p.PA2, | ||
| 71 | p.PC1, | ||
| 72 | p.PA7, | 70 | p.PA7, |
| 73 | p.PC4, | 71 | p.PC4, |
| 74 | p.PC5, | 72 | p.PC5, |
| 75 | p.PG13, | 73 | p.PG13, |
| 76 | p.PB13, | 74 | p.PB13, |
| 77 | p.PG11, | 75 | p.PG11, |
| 78 | GenericPhy::new_auto(), | ||
| 79 | mac_addr, | 76 | mac_addr, |
| 77 | p.ETH_SMA, | ||
| 78 | p.PA2, | ||
| 79 | p.PC1, | ||
| 80 | ); | 80 | ); |
| 81 | 81 | ||
| 82 | let config = embassy_net::Config::dhcpv4(Default::default()); | 82 | let config = embassy_net::Config::dhcpv4(Default::default()); |
diff --git a/examples/stm32f7/src/bin/hash.rs b/examples/stm32f7/src/bin/hash.rs index c2d1a7158..4fd465df6 100644 --- a/examples/stm32f7/src/bin/hash.rs +++ b/examples/stm32f7/src/bin/hash.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::hash::*; | 6 | use embassy_stm32::hash::*; |
| 7 | use embassy_stm32::{bind_interrupts, hash, peripherals, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, hash, peripherals}; |
| 8 | use embassy_time::Instant; | 8 | use embassy_time::Instant; |
| 9 | use hmac::{Hmac, Mac}; | 9 | use hmac::{Hmac, Mac}; |
| 10 | use sha2::{Digest, Sha256}; | 10 | use sha2::{Digest, Sha256}; |
diff --git a/examples/stm32f7/src/bin/pwm.rs b/examples/stm32f7/src/bin/pwm.rs new file mode 100644 index 000000000..b071eb597 --- /dev/null +++ b/examples/stm32f7/src/bin/pwm.rs | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::gpio::OutputType; | ||
| 8 | use embassy_stm32::time::{Hertz, mhz}; | ||
| 9 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | // If you are trying this and your USB device doesn't connect, the most | ||
| 14 | // common issues are the RCC config and vbus_detection | ||
| 15 | // | ||
| 16 | // See https://embassy.dev/book/#_the_usb_examples_are_not_working_on_my_board_is_there_anything_else_i_need_to_configure | ||
| 17 | // for more information. | ||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | info!("Hello World!"); | ||
| 21 | |||
| 22 | let mut config = Config::default(); | ||
| 23 | { | ||
| 24 | use embassy_stm32::rcc::*; | ||
| 25 | config.rcc.hse = Some(Hse { | ||
| 26 | freq: Hertz(8_000_000), | ||
| 27 | mode: HseMode::Bypass, | ||
| 28 | }); | ||
| 29 | config.rcc.pll_src = PllSource::HSE; | ||
| 30 | config.rcc.pll = Some(Pll { | ||
| 31 | prediv: PllPreDiv::DIV4, | ||
| 32 | mul: PllMul::MUL200, | ||
| 33 | divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 200 / 2 = 200Mhz | ||
| 34 | divq: Some(PllQDiv::DIV4), // 8mhz / 4 * 200 / 4 = 100Mhz | ||
| 35 | divr: None, | ||
| 36 | }); | ||
| 37 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 38 | config.rcc.apb1_pre = APBPrescaler::DIV4; | ||
| 39 | config.rcc.apb2_pre = APBPrescaler::DIV2; | ||
| 40 | config.rcc.sys = Sysclk::PLL1_P; | ||
| 41 | } | ||
| 42 | let p = embassy_stm32::init(config); | ||
| 43 | let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull); | ||
| 44 | let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, mhz(1), Default::default()); | ||
| 45 | let mut ch1 = pwm.ch1(); | ||
| 46 | ch1.enable(); | ||
| 47 | |||
| 48 | info!("PWM initialized"); | ||
| 49 | info!("PWM max duty {}", ch1.max_duty_cycle()); | ||
| 50 | |||
| 51 | loop { | ||
| 52 | ch1.set_duty_cycle_fully_off(); | ||
| 53 | Timer::after_millis(300).await; | ||
| 54 | ch1.set_duty_cycle_fraction(1, 4); | ||
| 55 | Timer::after_millis(300).await; | ||
| 56 | ch1.set_duty_cycle_fraction(1, 2); | ||
| 57 | Timer::after_millis(300).await; | ||
| 58 | ch1.set_duty_cycle(ch1.max_duty_cycle() - 1); | ||
| 59 | Timer::after_millis(300).await; | ||
| 60 | } | ||
| 61 | } | ||
diff --git a/examples/stm32f7/src/bin/pwm_ringbuffer.rs b/examples/stm32f7/src/bin/pwm_ringbuffer.rs new file mode 100644 index 000000000..4d191ac13 --- /dev/null +++ b/examples/stm32f7/src/bin/pwm_ringbuffer.rs | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::gpio::OutputType; | ||
| 8 | use embassy_stm32::time::mhz; | ||
| 9 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | // If you are trying this and your USB device doesn't connect, the most | ||
| 14 | // common issues are the RCC config and vbus_detection | ||
| 15 | // | ||
| 16 | // See https://embassy.dev/book/#_the_usb_examples_are_not_working_on_my_board_is_there_anything_else_i_need_to_configure | ||
| 17 | // for more information. | ||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | info!("PWM Ring Buffer Example"); | ||
| 21 | |||
| 22 | let mut config = Config::default(); | ||
| 23 | { | ||
| 24 | use embassy_stm32::rcc::*; | ||
| 25 | use embassy_stm32::time::Hertz; | ||
| 26 | config.rcc.hse = Some(Hse { | ||
| 27 | freq: Hertz(8_000_000), | ||
| 28 | mode: HseMode::Bypass, | ||
| 29 | }); | ||
| 30 | config.rcc.pll_src = PllSource::HSE; | ||
| 31 | config.rcc.pll = Some(Pll { | ||
| 32 | prediv: PllPreDiv::DIV4, | ||
| 33 | mul: PllMul::MUL200, | ||
| 34 | divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 200 / 2 = 200Mhz | ||
| 35 | divq: Some(PllQDiv::DIV4), // 8mhz / 4 * 200 / 4 = 100Mhz | ||
| 36 | divr: None, | ||
| 37 | }); | ||
| 38 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 39 | config.rcc.apb1_pre = APBPrescaler::DIV4; | ||
| 40 | config.rcc.apb2_pre = APBPrescaler::DIV2; | ||
| 41 | config.rcc.sys = Sysclk::PLL1_P; | ||
| 42 | } | ||
| 43 | let p = embassy_stm32::init(config); | ||
| 44 | |||
| 45 | // Initialize PWM on TIM1 | ||
| 46 | let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull); | ||
| 47 | let ch2_pin = PwmPin::new(p.PE11, OutputType::PushPull); | ||
| 48 | let mut pwm = SimplePwm::new( | ||
| 49 | p.TIM1, | ||
| 50 | Some(ch1_pin), | ||
| 51 | Some(ch2_pin), | ||
| 52 | None, | ||
| 53 | None, | ||
| 54 | mhz(1), | ||
| 55 | Default::default(), | ||
| 56 | ); | ||
| 57 | |||
| 58 | // Use channel 1 for static PWM at 50% | ||
| 59 | let mut ch1 = pwm.ch1(); | ||
| 60 | ch1.enable(); | ||
| 61 | ch1.set_duty_cycle_fraction(1, 2); | ||
| 62 | info!("Channel 1 (PE9/D6): Static 50% duty cycle"); | ||
| 63 | |||
| 64 | // Get max duty from channel 1 before converting channel 2 | ||
| 65 | let max_duty = ch1.max_duty_cycle(); | ||
| 66 | info!("PWM max duty: {}", max_duty); | ||
| 67 | |||
| 68 | // Create a DMA ring buffer for channel 2 | ||
| 69 | const BUFFER_SIZE: usize = 128; | ||
| 70 | static mut DMA_BUFFER: [u16; BUFFER_SIZE] = [0u16; BUFFER_SIZE]; | ||
| 71 | let dma_buffer = unsafe { &mut *core::ptr::addr_of_mut!(DMA_BUFFER) }; | ||
| 72 | |||
| 73 | // Pre-fill buffer with initial sine wave using lookup table approach | ||
| 74 | for i in 0..BUFFER_SIZE { | ||
| 75 | // Simple sine approximation using triangle wave | ||
| 76 | let phase = (i * 256) / BUFFER_SIZE; | ||
| 77 | let sine_approx = if phase < 128 { | ||
| 78 | phase as u16 * 2 | ||
| 79 | } else { | ||
| 80 | (255 - phase) as u16 * 2 | ||
| 81 | }; | ||
| 82 | dma_buffer[i] = (sine_approx as u32 * max_duty as u32 / 256) as u16; | ||
| 83 | } | ||
| 84 | |||
| 85 | // Convert channel 2 to ring-buffered PWM | ||
| 86 | let mut ring_pwm = pwm.ch1().into_ring_buffered_channel(p.DMA2_CH5, dma_buffer); | ||
| 87 | |||
| 88 | info!("Ring buffer capacity: {}", ring_pwm.capacity()); | ||
| 89 | |||
| 90 | // Pre-write some initial data to the buffer before starting | ||
| 91 | info!("Pre-writing initial waveform data..."); | ||
| 92 | |||
| 93 | ring_pwm.write(&[0; BUFFER_SIZE]).unwrap(); | ||
| 94 | |||
| 95 | // Enable the PWM channel output | ||
| 96 | ring_pwm.enable(); | ||
| 97 | |||
| 98 | // Start the DMA ring buffer | ||
| 99 | ring_pwm.start(); | ||
| 100 | info!("Channel 2 (PE11/D5): Ring buffered sine wave started"); | ||
| 101 | |||
| 102 | // Give DMA time to start consuming | ||
| 103 | Timer::after_millis(10).await; | ||
| 104 | |||
| 105 | // Continuously update the waveform | ||
| 106 | let mut phase: f32 = 0.0; | ||
| 107 | let mut amplitude: f32 = 1.0; | ||
| 108 | let mut amplitude_direction = -0.05; | ||
| 109 | |||
| 110 | loop { | ||
| 111 | // Generate new waveform data with varying amplitude | ||
| 112 | let mut new_data = [0u16; 32]; | ||
| 113 | for i in 0..new_data.len() { | ||
| 114 | // Triangle wave approximation for sine | ||
| 115 | let pos = ((i as u32 + phase as u32) * 4) % 256; | ||
| 116 | let sine_approx = if pos < 128 { | ||
| 117 | pos as u16 * 2 | ||
| 118 | } else { | ||
| 119 | (255 - pos) as u16 * 2 | ||
| 120 | }; | ||
| 121 | let scaled = (sine_approx as u32 * (amplitude * 256.0) as u32) / (256 * 256); | ||
| 122 | new_data[i] = ((scaled * max_duty as u32) / 256) as u16; | ||
| 123 | } | ||
| 124 | |||
| 125 | // Write new data to the ring buffer | ||
| 126 | match ring_pwm.write_exact(&new_data).await { | ||
| 127 | Ok(_remaining) => {} | ||
| 128 | Err(e) => { | ||
| 129 | info!("Write error: {:?}", e); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | // Update phase for animation effect | ||
| 134 | phase += 2.0; | ||
| 135 | if phase >= 64.0 { | ||
| 136 | phase = 0.0; | ||
| 137 | } | ||
| 138 | |||
| 139 | // Vary amplitude for breathing effect | ||
| 140 | amplitude += amplitude_direction; | ||
| 141 | if amplitude <= 0.2 || amplitude >= 1.0 { | ||
| 142 | amplitude_direction = -amplitude_direction; | ||
| 143 | } | ||
| 144 | |||
| 145 | // Log buffer status periodically | ||
| 146 | if (phase as u32) % 10 == 0 { | ||
| 147 | match ring_pwm.len() { | ||
| 148 | Ok(len) => info!("Ring buffer fill: {}/{}", len, ring_pwm.capacity()), | ||
| 149 | Err(_) => info!("Error reading buffer length"), | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs index 80652b865..e8ef3ad81 100644 --- a/examples/stm32f7/src/bin/qspi.rs +++ b/examples/stm32f7/src/bin/qspi.rs | |||
| @@ -4,11 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config as StmCfg; | ||
| 7 | use embassy_stm32::mode::Async; | 8 | use embassy_stm32::mode::Async; |
| 8 | use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *}; | 9 | use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *}; |
| 9 | use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig}; | 10 | use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig}; |
| 10 | use embassy_stm32::time::mhz; | 11 | use embassy_stm32::time::mhz; |
| 11 | use embassy_stm32::Config as StmCfg; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | const MEMORY_PAGE_SIZE: usize = 256; | 14 | const MEMORY_PAGE_SIZE: usize = 256; |
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs index 787bef25e..e5d261d89 100644 --- a/examples/stm32f7/src/bin/sdmmc.rs +++ b/examples/stm32f7/src/bin/sdmmc.rs | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::sdmmc::Sdmmc; | 6 | use embassy_stm32::sdmmc::Sdmmc; |
| 7 | use embassy_stm32::time::{mhz, Hertz}; | 7 | use embassy_stm32::sdmmc::sd::{CmdBlock, StorageDevice}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; | 8 | use embassy_stm32::time::{Hertz, mhz}; |
| 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 11 | ||
| 11 | bind_interrupts!(struct Irqs { | 12 | bind_interrupts!(struct Irqs { |
| @@ -54,9 +55,13 @@ async fn main(_spawner: Spawner) { | |||
| 54 | // Should print 400kHz for initialization | 55 | // Should print 400kHz for initialization |
| 55 | info!("Configured clock: {}", sdmmc.clock().0); | 56 | info!("Configured clock: {}", sdmmc.clock().0); |
| 56 | 57 | ||
| 57 | unwrap!(sdmmc.init_sd_card(mhz(25)).await); | 58 | let mut cmd_block = CmdBlock::new(); |
| 58 | 59 | ||
| 59 | let card = unwrap!(sdmmc.card()); | 60 | let storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(25)) |
| 61 | .await | ||
| 62 | .unwrap(); | ||
| 60 | 63 | ||
| 61 | info!("Card: {:#?}", Debug2Format(card)); | 64 | let card = storage.card(); |
| 65 | |||
| 66 | info!("Card: {:#?}", Debug2Format(&card)); | ||
| 62 | } | 67 | } |
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs index 349012888..9a30b2c20 100644 --- a/examples/stm32f7/src/bin/usb_serial.rs +++ b/examples/stm32f7/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::time::Hertz; | 7 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 1c9451469..16f28500d 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32g0-examples" | 3 | name = "embassy-stm32g0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs index 7d8653ef2..972e43b55 100644 --- a/examples/stm32g0/src/bin/adc.rs +++ b/examples/stm32g0/src/bin/adc.rs | |||
| @@ -13,11 +13,10 @@ async fn main(_spawner: Spawner) { | |||
| 13 | info!("Hello World!"); | 13 | info!("Hello World!"); |
| 14 | 14 | ||
| 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); | 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 16 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 17 | let mut pin = p.PA1; | 16 | let mut pin = p.PA1; |
| 18 | 17 | ||
| 19 | let mut vrefint = adc.enable_vrefint(); | 18 | let mut vrefint = adc.enable_vrefint(); |
| 20 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 19 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 21 | let convert_to_millivolts = |sample| { | 20 | let convert_to_millivolts = |sample| { |
| 22 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 21 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 23 | // 6.3.3 Embedded internal reference voltage | 22 | // 6.3.3 Embedded internal reference voltage |
| @@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 27 | }; | 26 | }; |
| 28 | 27 | ||
| 29 | loop { | 28 | loop { |
| 30 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 31 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 32 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 33 | } | 32 | } |
diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs index 834d1cd4a..aa8b1771b 100644 --- a/examples/stm32g0/src/bin/adc_oversampling.rs +++ b/examples/stm32g0/src/bin/adc_oversampling.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::adc::{Adc, Clock, Ovsr, Ovss, Presc, SampleTime}; | 10 | use embassy_stm32::adc::{Adc, AdcConfig, Clock, Ovsr, Ovss, Presc, SampleTime}; |
| 11 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| @@ -16,16 +16,17 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let p = embassy_stm32::init(Default::default()); | 16 | let p = embassy_stm32::init(Default::default()); |
| 17 | info!("Adc oversample test"); | 17 | info!("Adc oversample test"); |
| 18 | 18 | ||
| 19 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); | 19 | let mut config = AdcConfig::default(); |
| 20 | adc.set_sample_time(SampleTime::CYCLES1_5); | 20 | config.clock = Some(Clock::Async { div: Presc::DIV1 }); |
| 21 | let mut pin = p.PA1; | 21 | config.oversampling_ratio = Some(Ovsr::MUL16); |
| 22 | config.oversampling_shift = Some(Ovss::NO_SHIFT); | ||
| 23 | config.oversampling_enable = Some(true); | ||
| 22 | 24 | ||
| 23 | adc.set_oversampling_ratio(Ovsr::MUL16); | 25 | let mut adc = Adc::new_with_config(p.ADC1, config); |
| 24 | adc.set_oversampling_shift(Ovss::NO_SHIFT); | 26 | let mut pin = p.PA1; |
| 25 | adc.oversampling_enable(true); | ||
| 26 | 27 | ||
| 27 | loop { | 28 | loop { |
| 28 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES1_5); |
| 29 | info!("--> {} ", v); //max 65520 = 0xFFF0 | 30 | info!("--> {} ", v); //max 65520 = 0xFFF0 |
| 30 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 31 | } | 32 | } |
diff --git a/examples/stm32g0/src/bin/button_exti.rs b/examples/stm32g0/src/bin/button_exti.rs index 34a08bbc6..9d54479da 100644 --- a/examples/stm32g0/src/bin/button_exti.rs +++ b/examples/stm32g0/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32g0/src/bin/hf_timer.rs b/examples/stm32g0/src/bin/hf_timer.rs index 705905f01..88ee7ea86 100644 --- a/examples/stm32g0/src/bin/hf_timer.rs +++ b/examples/stm32g0/src/bin/hf_timer.rs | |||
| @@ -3,12 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Config as PeripheralConfig; | ||
| 6 | use embassy_stm32::gpio::OutputType; | 7 | use embassy_stm32::gpio::OutputType; |
| 7 | use embassy_stm32::time::khz; | 8 | use embassy_stm32::time::khz; |
| 9 | use embassy_stm32::timer::Channel; | ||
| 8 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; | 10 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; |
| 9 | use embassy_stm32::timer::simple_pwm::PwmPin; | 11 | use embassy_stm32::timer::simple_pwm::PwmPin; |
| 10 | use embassy_stm32::timer::Channel; | ||
| 11 | use embassy_stm32::Config as PeripheralConfig; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | #[embassy_executor::main] | 14 | #[embassy_executor::main] |
diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs index 5501a6941..ca3e8eb41 100644 --- a/examples/stm32g0/src/bin/input_capture.rs +++ b/examples/stm32g0/src/bin/input_capture.rs | |||
| @@ -13,10 +13,10 @@ use defmt::*; | |||
| 13 | use embassy_executor::Spawner; | 13 | use embassy_executor::Spawner; |
| 14 | use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed}; | 14 | use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed}; |
| 15 | use embassy_stm32::time::khz; | 15 | use embassy_stm32::time::khz; |
| 16 | use embassy_stm32::timer::Channel; | ||
| 16 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; | 17 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; |
| 17 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 18 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 18 | use embassy_stm32::timer::Channel; | 19 | use embassy_stm32::{Peri, bind_interrupts, peripherals, timer}; |
| 19 | use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; | ||
| 20 | use embassy_time::Timer; | 20 | use embassy_time::Timer; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 22 | 22 | ||
diff --git a/examples/stm32g0/src/bin/onewire_ds18b20.rs b/examples/stm32g0/src/bin/onewire_ds18b20.rs index 62f8711a6..43ecca8c4 100644 --- a/examples/stm32g0/src/bin/onewire_ds18b20.rs +++ b/examples/stm32g0/src/bin/onewire_ds18b20.rs | |||
| @@ -267,7 +267,7 @@ where | |||
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | match Self::crc8(&data) == 0 { | 269 | match Self::crc8(&data) == 0 { |
| 270 | true => Ok(((data[1] as u16) << 8 | data[0] as u16) as f32 / 16.), | 270 | true => Ok(((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.), |
| 271 | false => Err(()), | 271 | false => Err(()), |
| 272 | } | 272 | } |
| 273 | } | 273 | } |
diff --git a/examples/stm32g0/src/bin/pwm_complementary.rs b/examples/stm32g0/src/bin/pwm_complementary.rs index dbd9194c9..9856dd953 100644 --- a/examples/stm32g0/src/bin/pwm_complementary.rs +++ b/examples/stm32g0/src/bin/pwm_complementary.rs | |||
| @@ -17,9 +17,9 @@ use defmt::info; | |||
| 17 | use embassy_executor::Spawner; | 17 | use embassy_executor::Spawner; |
| 18 | use embassy_stm32::gpio::OutputType; | 18 | use embassy_stm32::gpio::OutputType; |
| 19 | use embassy_stm32::time::khz; | 19 | use embassy_stm32::time::khz; |
| 20 | use embassy_stm32::timer::Channel; | ||
| 20 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; | 21 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; |
| 21 | use embassy_stm32::timer::simple_pwm::PwmPin; | 22 | use embassy_stm32::timer::simple_pwm::PwmPin; |
| 22 | use embassy_stm32::timer::Channel; | ||
| 23 | use {defmt_rtt as _, panic_probe as _}; | 23 | use {defmt_rtt as _, panic_probe as _}; |
| 24 | 24 | ||
| 25 | #[embassy_executor::main] | 25 | #[embassy_executor::main] |
diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs index 72aa07c03..5da19e077 100644 --- a/examples/stm32g0/src/bin/pwm_input.rs +++ b/examples/stm32g0/src/bin/pwm_input.rs | |||
| @@ -14,7 +14,7 @@ use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed}; | |||
| 14 | use embassy_stm32::time::khz; | 14 | use embassy_stm32::time::khz; |
| 15 | use embassy_stm32::timer::pwm_input::PwmInput; | 15 | use embassy_stm32::timer::pwm_input::PwmInput; |
| 16 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 16 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 17 | use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; | 17 | use embassy_stm32::{Peri, bind_interrupts, peripherals, timer}; |
| 18 | use embassy_time::Timer; | 18 | use embassy_time::Timer; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 19 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 20 | ||
diff --git a/examples/stm32g0/src/bin/rtc.rs b/examples/stm32g0/src/bin/rtc.rs index 50fb6398e..d8b58de22 100644 --- a/examples/stm32g0/src/bin/rtc.rs +++ b/examples/stm32g0/src/bin/rtc.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -17,12 +17,12 @@ async fn main(_spawner: Spawner) { | |||
| 17 | 17 | ||
| 18 | let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0); | 18 | let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0); |
| 19 | 19 | ||
| 20 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 20 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 21 | 21 | ||
| 22 | rtc.set_datetime(now.unwrap()).expect("datetime not set"); | 22 | rtc.set_datetime(now.unwrap()).expect("datetime not set"); |
| 23 | 23 | ||
| 24 | loop { | 24 | loop { |
| 25 | let now: DateTime = rtc.now().unwrap().into(); | 25 | let now: DateTime = time_provider.now().unwrap().into(); |
| 26 | 26 | ||
| 27 | info!("{}:{}:{}", now.hour(), now.minute(), now.second()); | 27 | info!("{}:{}:{}", now.hour(), now.minute(), now.second()); |
| 28 | 28 | ||
diff --git a/examples/stm32g0/src/bin/usb_serial.rs b/examples/stm32g0/src/bin/usb_serial.rs index 162dfd86b..7dab393ac 100644 --- a/examples/stm32g0/src/bin/usb_serial.rs +++ b/examples/stm32g0/src/bin/usb_serial.rs | |||
| @@ -5,10 +5,10 @@ use defmt::{panic, *}; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::{Driver, Instance}; | 7 | use embassy_stm32::usb::{Driver, Instance}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 9 | use embassy_usb::Builder; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 102960980..d1c19582b 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32g4-examples" | 3 | name = "embassy-stm32g4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -7,13 +7,13 @@ publish = false | |||
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | # Change stm32g491re to your chip name, if necessary. | 9 | # Change stm32g491re to your chip name, if necessary. |
| 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } | 10 | embassy-stm32 = { path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } |
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | 15 | embassy-futures = { path = "../../embassy-futures" } |
| 16 | usbd-hid = "0.8.1" | 16 | usbd-hid = "0.9.0" |
| 17 | 17 | ||
| 18 | defmt = "1.0.1" | 18 | defmt = "1.0.1" |
| 19 | defmt-rtt = "1.0.0" | 19 | defmt-rtt = "1.0.0" |
| @@ -25,6 +25,7 @@ embedded-can = { version = "0.4" } | |||
| 25 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | 25 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 26 | heapless = { version = "0.8", default-features = false } | 26 | heapless = { version = "0.8", default-features = false } |
| 27 | static_cell = "2.0.0" | 27 | static_cell = "2.0.0" |
| 28 | critical-section = "1.1" | ||
| 28 | 29 | ||
| 29 | [profile.release] | 30 | [profile.release] |
| 30 | debug = 2 | 31 | debug = 2 |
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index adca846d8..2149e0748 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -28,12 +28,16 @@ async fn main(_spawner: Spawner) { | |||
| 28 | let mut p = embassy_stm32::init(config); | 28 | let mut p = embassy_stm32::init(config); |
| 29 | info!("Hello World!"); | 29 | info!("Hello World!"); |
| 30 | 30 | ||
| 31 | let mut adc = Adc::new(p.ADC2); | 31 | let mut adc = Adc::new(p.ADC2, Default::default()); |
| 32 | adc.set_sample_time(SampleTime::CYCLES24_5); | 32 | |
| 33 | let mut adc_temp = Adc::new(p.ADC1, Default::default()); | ||
| 34 | let mut temperature = adc_temp.enable_temperature(); | ||
| 33 | 35 | ||
| 34 | loop { | 36 | loop { |
| 35 | let measured = adc.blocking_read(&mut p.PA7); | 37 | let measured = adc.blocking_read(&mut p.PA7, SampleTime::CYCLES24_5); |
| 38 | let temperature = adc_temp.blocking_read(&mut temperature, SampleTime::CYCLES24_5); | ||
| 36 | info!("measured: {}", measured); | 39 | info!("measured: {}", measured); |
| 40 | info!("temperature: {}", temperature); | ||
| 37 | Timer::after_millis(500).await; | 41 | Timer::after_millis(500).await; |
| 38 | } | 42 | } |
| 39 | } | 43 | } |
diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs index 78d071d45..6dedf88d6 100644 --- a/examples/stm32g4/src/bin/adc_differential.rs +++ b/examples/stm32g4/src/bin/adc_differential.rs | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | use defmt::*; | 9 | use defmt::*; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 12 | use embassy_stm32::Config; | 11 | use embassy_stm32::Config; |
| 12 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| @@ -30,17 +30,16 @@ async fn main(_spawner: Spawner) { | |||
| 30 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; | 30 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; |
| 31 | config.rcc.sys = Sysclk::PLL1_R; | 31 | config.rcc.sys = Sysclk::PLL1_R; |
| 32 | } | 32 | } |
| 33 | let mut p = embassy_stm32::init(config); | 33 | let p = embassy_stm32::init(config); |
| 34 | 34 | ||
| 35 | let mut adc = Adc::new(p.ADC1); | 35 | let mut adc = Adc::new(p.ADC1, Default::default()); |
| 36 | adc.set_sample_time(SampleTime::CYCLES247_5); | 36 | let mut differential_channel = (p.PA0, p.PA1); |
| 37 | adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 | ||
| 38 | 37 | ||
| 39 | // can also use | 38 | // can also use |
| 40 | // adc.set_differential_channel(1, true); | 39 | // adc.set_differential_channel(1, true); |
| 41 | info!("adc initialized"); | 40 | info!("adc initialized"); |
| 42 | loop { | 41 | loop { |
| 43 | let measured = adc.blocking_read(&mut p.PA0); | 42 | let measured = adc.blocking_read(&mut differential_channel, SampleTime::CYCLES247_5); |
| 44 | info!("data: {}", measured); | 43 | info!("data: {}", measured); |
| 45 | Timer::after_millis(500).await; | 44 | Timer::after_millis(500).await; |
| 46 | } | 45 | } |
diff --git a/examples/stm32g4/src/bin/adc_dma.rs b/examples/stm32g4/src/bin/adc_dma.rs index 202704085..478b6b2ca 100644 --- a/examples/stm32g4/src/bin/adc_dma.rs +++ b/examples/stm32g4/src/bin/adc_dma.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -12,7 +12,7 @@ static mut DMA_BUF: [u16; 2] = [0; 2]; | |||
| 12 | 12 | ||
| 13 | #[embassy_executor::main] | 13 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 14 | async fn main(_spawner: Spawner) { |
| 15 | let mut read_buffer = unsafe { &mut DMA_BUF[..] }; | 15 | let read_buffer = unsafe { &mut DMA_BUF[..] }; |
| 16 | 16 | ||
| 17 | let mut config = Config::default(); | 17 | let mut config = Config::default(); |
| 18 | { | 18 | { |
| @@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | 33 | ||
| 34 | info!("Hello World!"); | 34 | info!("Hello World!"); |
| 35 | 35 | ||
| 36 | let mut adc = Adc::new(p.ADC1); | 36 | let mut adc = Adc::new(p.ADC1, Default::default()); |
| 37 | 37 | ||
| 38 | let mut dma = p.DMA1_CH1; | 38 | let mut dma = p.DMA1_CH1; |
| 39 | let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); | 39 | let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); |
| @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) { | |||
| 47 | (&mut pa0, SampleTime::CYCLES247_5), | 47 | (&mut pa0, SampleTime::CYCLES247_5), |
| 48 | ] | 48 | ] |
| 49 | .into_iter(), | 49 | .into_iter(), |
| 50 | &mut read_buffer, | 50 | read_buffer, |
| 51 | ) | 51 | ) |
| 52 | .await; | 52 | .await; |
| 53 | 53 | ||
diff --git a/examples/stm32g4/src/bin/adc_injected_and_regular.rs b/examples/stm32g4/src/bin/adc_injected_and_regular.rs new file mode 100644 index 000000000..1e97fa925 --- /dev/null +++ b/examples/stm32g4/src/bin/adc_injected_and_regular.rs | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | //! adc injected and regular conversions | ||
| 2 | //! | ||
| 3 | //! This example both regular and injected ADC conversions at the same time | ||
| 4 | //! p:pa0 n:pa2 | ||
| 5 | |||
| 6 | #![no_std] | ||
| 7 | #![no_main] | ||
| 8 | |||
| 9 | use core::cell::RefCell; | ||
| 10 | |||
| 11 | use defmt::info; | ||
| 12 | use embassy_stm32::adc::{ | ||
| 13 | Adc, AdcChannel as _, ConversionTrigger, Exten, InjectedAdc, RegularConversionMode, SampleTime, | ||
| 14 | }; | ||
| 15 | use embassy_stm32::interrupt::typelevel::{ADC1_2, Interrupt}; | ||
| 16 | use embassy_stm32::peripherals::ADC1; | ||
| 17 | use embassy_stm32::time::Hertz; | ||
| 18 | use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, Mms2}; | ||
| 19 | use embassy_stm32::timer::low_level::CountingMode; | ||
| 20 | use embassy_stm32::{Config, interrupt}; | ||
| 21 | use embassy_sync::blocking_mutex::CriticalSectionMutex; | ||
| 22 | use {defmt_rtt as _, panic_probe as _}; | ||
| 23 | |||
| 24 | static ADC1_HANDLE: CriticalSectionMutex<RefCell<Option<InjectedAdc<ADC1, 1>>>> = | ||
| 25 | CriticalSectionMutex::new(RefCell::new(None)); | ||
| 26 | |||
| 27 | /// This example showcases how to use both regular ADC conversions with DMA and injected ADC | ||
| 28 | /// conversions with ADC interrupt simultaneously. Both conversion types can be configured with | ||
| 29 | /// different triggers and thanks to DMA it is possible to use the measurements in different task | ||
| 30 | /// without needing to access the ADC peripheral. | ||
| 31 | /// | ||
| 32 | /// If you don't need both regular and injected conversions the example code can easily be reworked | ||
| 33 | /// to only include one of the ADC conversion types. | ||
| 34 | #[embassy_executor::main] | ||
| 35 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 36 | // See Table 166 and 167 in RM0440 Rev 9 for ADC1/2 External triggers | ||
| 37 | // Note: Regular and Injected channels use different tables!! | ||
| 38 | const ADC1_INJECTED_TRIGGER_TIM1_TRGO2: u8 = 8; | ||
| 39 | const ADC1_REGULAR_TRIGGER_TIM1_TRGO2: u8 = 10; | ||
| 40 | |||
| 41 | // --- RCC config --- | ||
| 42 | let mut config = Config::default(); | ||
| 43 | { | ||
| 44 | use embassy_stm32::rcc::*; | ||
| 45 | config.rcc.pll = Some(Pll { | ||
| 46 | source: PllSource::HSI, | ||
| 47 | prediv: PllPreDiv::DIV4, | ||
| 48 | mul: PllMul::MUL85, | ||
| 49 | divp: None, | ||
| 50 | divq: None, | ||
| 51 | divr: Some(PllRDiv::DIV2), | ||
| 52 | }); | ||
| 53 | config.rcc.mux.adc12sel = mux::Adcsel::SYS; | ||
| 54 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 55 | } | ||
| 56 | let p = embassy_stm32::init(config); | ||
| 57 | |||
| 58 | // In this example we use tim1_trgo2 event to trigger the ADC conversions | ||
| 59 | let tim1 = p.TIM1; | ||
| 60 | let pwm_freq = 1; | ||
| 61 | let mut pwm = ComplementaryPwm::new( | ||
| 62 | tim1, | ||
| 63 | None, | ||
| 64 | None, | ||
| 65 | None, | ||
| 66 | None, | ||
| 67 | None, | ||
| 68 | None, | ||
| 69 | None, | ||
| 70 | None, | ||
| 71 | Hertz::hz(pwm_freq), | ||
| 72 | CountingMode::EdgeAlignedUp, | ||
| 73 | ); | ||
| 74 | pwm.set_master_output_enable(false); | ||
| 75 | // Mms2 is used to configure which timer event that is connected to tim1_trgo2. | ||
| 76 | // In this case we use the update event of the timer. | ||
| 77 | pwm.set_mms2(Mms2::UPDATE); | ||
| 78 | |||
| 79 | // Configure regular conversions with DMA | ||
| 80 | let adc1 = Adc::new(p.ADC1, Default::default()); | ||
| 81 | |||
| 82 | let vrefint_channel = adc1.enable_vrefint().degrade_adc(); | ||
| 83 | let pa0 = p.PC1.degrade_adc(); | ||
| 84 | let regular_sequence = [ | ||
| 85 | (vrefint_channel, SampleTime::CYCLES247_5), | ||
| 86 | (pa0, SampleTime::CYCLES247_5), | ||
| 87 | ] | ||
| 88 | .into_iter(); | ||
| 89 | |||
| 90 | // Configurations of Injected ADC measurements | ||
| 91 | let pa2 = p.PA2.degrade_adc(); | ||
| 92 | let injected_sequence = [(pa2, SampleTime::CYCLES247_5)]; | ||
| 93 | |||
| 94 | // Configure DMA for retrieving regular ADC measurements | ||
| 95 | let dma1_ch1 = p.DMA1_CH1; | ||
| 96 | // Using buffer of double size means the half-full interrupts will generate at the expected rate | ||
| 97 | let mut readings = [0u16; 4]; | ||
| 98 | |||
| 99 | let injected_trigger = ConversionTrigger { | ||
| 100 | channel: ADC1_INJECTED_TRIGGER_TIM1_TRGO2, | ||
| 101 | edge: Exten::RISING_EDGE, | ||
| 102 | }; | ||
| 103 | let regular_trigger = ConversionTrigger { | ||
| 104 | channel: ADC1_REGULAR_TRIGGER_TIM1_TRGO2, | ||
| 105 | edge: Exten::RISING_EDGE, | ||
| 106 | }; | ||
| 107 | |||
| 108 | let (mut ring_buffered_adc, injected_adc) = adc1.into_ring_buffered_and_injected( | ||
| 109 | dma1_ch1, | ||
| 110 | &mut readings, | ||
| 111 | regular_sequence, | ||
| 112 | RegularConversionMode::Triggered(regular_trigger), | ||
| 113 | injected_sequence, | ||
| 114 | injected_trigger, | ||
| 115 | true, | ||
| 116 | ); | ||
| 117 | |||
| 118 | // Store ADC globally to allow access from ADC interrupt | ||
| 119 | critical_section::with(|cs| { | ||
| 120 | ADC1_HANDLE.borrow(cs).replace(Some(injected_adc)); | ||
| 121 | }); | ||
| 122 | // Enable interrupt for ADC1_2 | ||
| 123 | unsafe { ADC1_2::enable() }; | ||
| 124 | |||
| 125 | // Main loop for reading regular ADC measurements periodically | ||
| 126 | let mut data = [0u16; 2]; | ||
| 127 | loop { | ||
| 128 | { | ||
| 129 | match ring_buffered_adc.read(&mut data).await { | ||
| 130 | Ok(n) => { | ||
| 131 | defmt::info!("Regular ADC reading, VrefInt: {}, PA0: {}", data[0], data[1]); | ||
| 132 | defmt::info!("Remaining samples: {}", n,); | ||
| 133 | } | ||
| 134 | Err(e) => { | ||
| 135 | defmt::error!("DMA error: {:?}", e); | ||
| 136 | ring_buffered_adc.clear(); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /// Use ADC1_2 interrupt to retrieve injected ADC measurements | ||
| 144 | /// Interrupt must be unsafe as hardware can invoke it any-time. Critical sections ensure safety | ||
| 145 | /// within the interrupt. | ||
| 146 | #[interrupt] | ||
| 147 | unsafe fn ADC1_2() { | ||
| 148 | critical_section::with(|cs| { | ||
| 149 | if let Some(injected_adc) = ADC1_HANDLE.borrow(cs).borrow_mut().as_mut() { | ||
| 150 | let injected_data = injected_adc.read_injected_samples(); | ||
| 151 | info!("Injected reading of PA2: {}", injected_data[0]); | ||
| 152 | } | ||
| 153 | }); | ||
| 154 | } | ||
diff --git a/examples/stm32g4/src/bin/adc_oversampling.rs b/examples/stm32g4/src/bin/adc_oversampling.rs index d31eb20f8..87ffea4be 100644 --- a/examples/stm32g4/src/bin/adc_oversampling.rs +++ b/examples/stm32g4/src/bin/adc_oversampling.rs | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::adc::vals::{Rovsm, Trovs}; | ||
| 11 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 12 | use embassy_stm32::Config; | 10 | use embassy_stm32::Config; |
| 11 | use embassy_stm32::adc::vals::{Rovsm, Trovs}; | ||
| 12 | use embassy_stm32::adc::{Adc, AdcConfig, SampleTime}; | ||
| 13 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| @@ -32,8 +32,8 @@ async fn main(_spawner: Spawner) { | |||
| 32 | } | 32 | } |
| 33 | let mut p = embassy_stm32::init(config); | 33 | let mut p = embassy_stm32::init(config); |
| 34 | 34 | ||
| 35 | let mut adc = Adc::new(p.ADC1); | 35 | let mut config = AdcConfig::default(); |
| 36 | adc.set_sample_time(SampleTime::CYCLES6_5); | 36 | |
| 37 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf | 37 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf |
| 38 | // page652 Oversampler | 38 | // page652 Oversampler |
| 39 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation | 39 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation |
| @@ -45,12 +45,14 @@ async fn main(_spawner: Spawner) { | |||
| 45 | // 0x05 oversampling ratio X64 | 45 | // 0x05 oversampling ratio X64 |
| 46 | // 0x06 oversampling ratio X128 | 46 | // 0x06 oversampling ratio X128 |
| 47 | // 0x07 oversampling ratio X256 | 47 | // 0x07 oversampling ratio X256 |
| 48 | adc.set_oversampling_ratio(0x03); // ratio X3 | 48 | config.oversampling_ratio = Some(0x03); // ratio X3 |
| 49 | adc.set_oversampling_shift(0b0000); // no shift | 49 | config.oversampling_shift = Some(0b0000); // no shift |
| 50 | adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); | 50 | config.oversampling_mode = Some((Rovsm::RESUMED, Trovs::AUTOMATIC, true)); |
| 51 | |||
| 52 | let mut adc = Adc::new(p.ADC1, config); | ||
| 51 | 53 | ||
| 52 | loop { | 54 | loop { |
| 53 | let measured = adc.blocking_read(&mut p.PA0); | 55 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES6_5); |
| 54 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 | 56 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 |
| 55 | Timer::after_millis(500).await; | 57 | Timer::after_millis(500).await; |
| 56 | } | 58 | } |
diff --git a/examples/stm32g4/src/bin/button_exti.rs b/examples/stm32g4/src/bin/button_exti.rs index 2a546dac5..e7e1549a8 100644 --- a/examples/stm32g4/src/bin/button_exti.rs +++ b/examples/stm32g4/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 90004f874..7ff7bd7b4 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs | |||
| @@ -4,7 +4,7 @@ use defmt::*; | |||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_stm32::peripherals::*; | 5 | use embassy_stm32::peripherals::*; |
| 6 | use embassy_stm32::time::Hertz; | 6 | use embassy_stm32::time::Hertz; |
| 7 | use embassy_stm32::{bind_interrupts, can, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, can}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use static_cell::StaticCell; | 9 | use static_cell::StaticCell; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/stm32g4/src/bin/usb_c_pd.rs b/examples/stm32g4/src/bin/usb_c_pd.rs index 2e87d3931..b23984b3a 100644 --- a/examples/stm32g4/src/bin/usb_c_pd.rs +++ b/examples/stm32g4/src/bin/usb_c_pd.rs | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::{error, info, Format}; | 4 | use defmt::{Format, error, info}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; | 6 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; |
| 7 | use embassy_stm32::{bind_interrupts, peripherals, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, peripherals}; |
| 8 | use embassy_time::{with_timeout, Duration}; | 8 | use embassy_time::{Duration, with_timeout}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | 11 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index 9f66f0c53..a62da6d97 100644 --- a/examples/stm32g4/src/bin/usb_serial.rs +++ b/examples/stm32g4/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::time::Hertz; | 7 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::usb::{self, Driver, Instance}; | 8 | use embassy_stm32::usb::{self, Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 66680c027..512186c3d 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h5-examples" | 3 | name = "embassy-stm32h5-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 29 | heapless = { version = "0.8", default-features = false } | 29 | heapless = { version = "0.8", default-features = false } |
| 30 | critical-section = "1.1" | 30 | critical-section = "1.1" |
| 31 | micromath = "2.0.0" | 31 | micromath = "2.0.0" |
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.4.0" |
| 33 | embedded-storage = "0.3.1" | 33 | embedded-storage = "0.3.1" |
| 34 | static_cell = "2" | 34 | static_cell = "2" |
| 35 | 35 | ||
diff --git a/examples/stm32h5/src/bin/adc.rs b/examples/stm32h5/src/bin/adc.rs index c5d508ece..c919b1a95 100644 --- a/examples/stm32h5/src/bin/adc.rs +++ b/examples/stm32h5/src/bin/adc.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -45,14 +45,12 @@ async fn main(_spawner: Spawner) { | |||
| 45 | 45 | ||
| 46 | let mut adc = Adc::new(p.ADC1); | 46 | let mut adc = Adc::new(p.ADC1); |
| 47 | 47 | ||
| 48 | adc.set_sample_time(SampleTime::CYCLES24_5); | ||
| 49 | |||
| 50 | let mut vrefint_channel = adc.enable_vrefint(); | 48 | let mut vrefint_channel = adc.enable_vrefint(); |
| 51 | 49 | ||
| 52 | loop { | 50 | loop { |
| 53 | let vrefint = adc.blocking_read(&mut vrefint_channel); | 51 | let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES24_5); |
| 54 | info!("vrefint: {}", vrefint); | 52 | info!("vrefint: {}", vrefint); |
| 55 | let measured = adc.blocking_read(&mut p.PA0); | 53 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES24_5); |
| 56 | info!("measured: {}", measured); | 54 | info!("measured: {}", measured); |
| 57 | Timer::after_millis(500).await; | 55 | Timer::after_millis(500).await; |
| 58 | } | 56 | } |
diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs index fb9fcbc5c..e625e3a34 100644 --- a/examples/stm32h5/src/bin/adc_dma.rs +++ b/examples/stm32h5/src/bin/adc_dma.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; | 6 | use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; |
| 7 | use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; | 7 | use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; |
| 8 | use embassy_stm32::{Config, Peri}; | 8 | use embassy_stm32::{Config, Peri}; |
| 9 | use embassy_time::Instant; | 9 | use embassy_time::{Duration, Instant, Ticker}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
| @@ -66,7 +66,7 @@ async fn adc2_task( | |||
| 66 | adc_task(adc, dma, pin1, pin2).await; | 66 | adc_task(adc, dma, pin1, pin2).await; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | async fn adc_task<'a, T: adc::Instance>( | 69 | async fn adc_task<'a, T: adc::DefaultInstance>( |
| 70 | adc: Peri<'a, T>, | 70 | adc: Peri<'a, T>, |
| 71 | mut dma: Peri<'a, impl RxDma<T>>, | 71 | mut dma: Peri<'a, impl RxDma<T>>, |
| 72 | pin1: impl AdcChannel<T>, | 72 | pin1: impl AdcChannel<T>, |
| @@ -76,6 +76,9 @@ async fn adc_task<'a, T: adc::Instance>( | |||
| 76 | let mut pin1 = pin1.degrade_adc(); | 76 | let mut pin1 = pin1.degrade_adc(); |
| 77 | let mut pin2 = pin2.degrade_adc(); | 77 | let mut pin2 = pin2.degrade_adc(); |
| 78 | 78 | ||
| 79 | info!("adc init"); | ||
| 80 | |||
| 81 | let mut ticker = Ticker::every(Duration::from_millis(500)); | ||
| 79 | let mut tic = Instant::now(); | 82 | let mut tic = Instant::now(); |
| 80 | let mut buffer = [0u16; 512]; | 83 | let mut buffer = [0u16; 512]; |
| 81 | loop { | 84 | loop { |
| @@ -84,11 +87,13 @@ async fn adc_task<'a, T: adc::Instance>( | |||
| 84 | adc.read( | 87 | adc.read( |
| 85 | dma.reborrow(), | 88 | dma.reborrow(), |
| 86 | [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), | 89 | [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), |
| 87 | &mut buffer, | 90 | &mut buffer[0..2], |
| 88 | ) | 91 | ) |
| 89 | .await; | 92 | .await; |
| 90 | let toc = Instant::now(); | 93 | let toc = Instant::now(); |
| 91 | info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); | 94 | info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); |
| 92 | tic = toc; | 95 | tic = toc; |
| 96 | |||
| 97 | ticker.next().await; | ||
| 93 | } | 98 | } |
| 94 | } | 99 | } |
diff --git a/examples/stm32h5/src/bin/backup_sram.rs b/examples/stm32h5/src/bin/backup_sram.rs new file mode 100644 index 000000000..f8db1853e --- /dev/null +++ b/examples/stm32h5/src/bin/backup_sram.rs | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::backup_sram::BackupMemory; | ||
| 8 | use embassy_time::Timer; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async fn main(_spawner: Spawner) { | ||
| 13 | let mut config = Config::default(); | ||
| 14 | config.rcc.ls.enable_backup_sram = true; | ||
| 15 | |||
| 16 | let p = embassy_stm32::init(config); | ||
| 17 | info!("Started!"); | ||
| 18 | |||
| 19 | let (bytes, status) = BackupMemory::new(p.BKPSRAM); | ||
| 20 | |||
| 21 | match status { | ||
| 22 | false => info!("BKPSRAM just enabled"), | ||
| 23 | true => info!("BKPSRAM already enabled"), | ||
| 24 | } | ||
| 25 | |||
| 26 | loop { | ||
| 27 | info!("byte0: {}", bytes[0]); | ||
| 28 | bytes[0] = bytes[0].wrapping_add(1); | ||
| 29 | Timer::after_millis(500).await; | ||
| 30 | } | ||
| 31 | } | ||
diff --git a/examples/stm32h5/src/bin/button_exti.rs b/examples/stm32h5/src/bin/button_exti.rs index 2a546dac5..220f89228 100644 --- a/examples/stm32h5/src/bin/button_exti.rs +++ b/examples/stm32h5/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs index 194239d47..b1923547e 100644 --- a/examples/stm32h5/src/bin/can.rs +++ b/examples/stm32h5/src/bin/can.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::peripherals::*; | 6 | use embassy_stm32::peripherals::*; |
| 7 | use embassy_stm32::{bind_interrupts, can, rcc, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, can, rcc}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
diff --git a/examples/stm32h5/src/bin/dts.rs b/examples/stm32h5/src/bin/dts.rs index 8c18fafea..7c856b5b3 100644 --- a/examples/stm32h5/src/bin/dts.rs +++ b/examples/stm32h5/src/bin/dts.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::dts::{Dts, InterruptHandler, SampleTime}; | 6 | use embassy_stm32::dts::{Dts, InterruptHandler, SampleTime}; |
| 7 | use embassy_stm32::peripherals::DTS; | 7 | use embassy_stm32::peripherals::DTS; |
| 8 | use embassy_stm32::rcc::frequency; | 8 | use embassy_stm32::rcc::frequency; |
| 9 | use embassy_stm32::{bind_interrupts, dts, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, dts}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index a84fe358b..6a3afb2d1 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -5,14 +5,14 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 9 | use embassy_stm32::peripherals::ETH; | 9 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; |
| 10 | use embassy_stm32::rcc::{ | 10 | use embassy_stm32::rcc::{ |
| 11 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | 11 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, |
| 12 | }; | 12 | }; |
| 13 | use embassy_stm32::rng::Rng; | 13 | use embassy_stm32::rng::Rng; |
| 14 | use embassy_stm32::time::Hertz; | 14 | use embassy_stm32::time::Hertz; |
| 15 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 15 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 16 | use embassy_time::Timer; | 16 | use embassy_time::Timer; |
| 17 | use embedded_io_async::Write; | 17 | use embedded_io_async::Write; |
| 18 | use static_cell::StaticCell; | 18 | use static_cell::StaticCell; |
| @@ -23,7 +23,7 @@ bind_interrupts!(struct Irqs { | |||
| 23 | RNG => rng::InterruptHandler<peripherals::RNG>; | 23 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 24 | }); | 24 | }); |
| 25 | 25 | ||
| 26 | type Device = Ethernet<'static, ETH, GenericPhy>; | 26 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 27 | 27 | ||
| 28 | #[embassy_executor::task] | 28 | #[embassy_executor::task] |
| 29 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 29 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -70,16 +70,16 @@ async fn main(spawner: Spawner) -> ! { | |||
| 70 | p.ETH, | 70 | p.ETH, |
| 71 | Irqs, | 71 | Irqs, |
| 72 | p.PA1, | 72 | p.PA1, |
| 73 | p.PA2, | ||
| 74 | p.PC1, | ||
| 75 | p.PA7, | 73 | p.PA7, |
| 76 | p.PC4, | 74 | p.PC4, |
| 77 | p.PC5, | 75 | p.PC5, |
| 78 | p.PG13, | 76 | p.PG13, |
| 79 | p.PB15, | 77 | p.PB15, |
| 80 | p.PG11, | 78 | p.PG11, |
| 81 | GenericPhy::new_auto(), | ||
| 82 | mac_addr, | 79 | mac_addr, |
| 80 | p.ETH_SMA, | ||
| 81 | p.PA2, | ||
| 82 | p.PC1, | ||
| 83 | ); | 83 | ); |
| 84 | 84 | ||
| 85 | let config = embassy_net::Config::dhcpv4(Default::default()); | 85 | let config = embassy_net::Config::dhcpv4(Default::default()); |
diff --git a/examples/stm32h5/src/bin/mco.rs b/examples/stm32h5/src/bin/mco.rs new file mode 100644 index 000000000..1137ba25c --- /dev/null +++ b/examples/stm32h5/src/bin/mco.rs | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::gpio::Speed; | ||
| 7 | use embassy_stm32::rcc::{Mco, Mco2Source, McoConfig}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | #[embassy_executor::main] | ||
| 11 | async fn main(_spawner: Spawner) { | ||
| 12 | let p = embassy_stm32::init(Default::default()); | ||
| 13 | |||
| 14 | /* Default "VeryHigh" drive strength and prescaler DIV1 */ | ||
| 15 | // let _mco = Mco::new(p.MCO2, p.PC9, Mco2Source::SYS, McoConfig::default()); | ||
| 16 | |||
| 17 | /* Choose Speed::Low drive strength */ | ||
| 18 | let config = { | ||
| 19 | let mut config = McoConfig::default(); | ||
| 20 | config.speed = Speed::Low; | ||
| 21 | config | ||
| 22 | }; | ||
| 23 | |||
| 24 | let _mco = Mco::new(p.MCO2, p.PC9, Mco2Source::SYS, config); | ||
| 25 | |||
| 26 | info!("Clock out with low drive strength set on Master Clock Out 2 pin as AF on PC9"); | ||
| 27 | |||
| 28 | loop {} | ||
| 29 | } | ||
diff --git a/examples/stm32h5/src/bin/sai.rs b/examples/stm32h5/src/bin/sai.rs index 0e182f9cf..6632a7f98 100644 --- a/examples/stm32h5/src/bin/sai.rs +++ b/examples/stm32h5/src/bin/sai.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::{sai, Config}; | 6 | use embassy_stm32::{Config, sai}; |
| 7 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 8 | ||
| 9 | #[embassy_executor::main] | 9 | #[embassy_executor::main] |
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs index 3c4f49f64..8d5456b80 100644 --- a/examples/stm32h5/src/bin/stop.rs +++ b/examples/stm32h5/src/bin/stop.rs | |||
| @@ -7,22 +7,12 @@ | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; | 9 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; |
| 10 | use embassy_stm32::low_power::Executor; | ||
| 11 | use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; | 10 | use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; |
| 12 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 11 | use embassy_stm32::{Config, Peri, low_power}; |
| 13 | use embassy_stm32::{Config, Peri}; | ||
| 14 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 15 | use static_cell::StaticCell; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 14 | ||
| 18 | #[cortex_m_rt::entry] | 15 | #[embassy_executor::main(executor = "low_power::Executor")] |
| 19 | fn main() -> ! { | ||
| 20 | Executor::take().run(|spawner| { | ||
| 21 | spawner.spawn(unwrap!(async_main(spawner))); | ||
| 22 | }) | ||
| 23 | } | ||
| 24 | |||
| 25 | #[embassy_executor::task] | ||
| 26 | async fn async_main(spawner: Spawner) { | 16 | async fn async_main(spawner: Spawner) { |
| 27 | defmt::info!("Program Start"); | 17 | defmt::info!("Program Start"); |
| 28 | 18 | ||
| @@ -37,12 +27,6 @@ async fn async_main(spawner: Spawner) { | |||
| 37 | // config.enable_debug_during_sleep = false; | 27 | // config.enable_debug_during_sleep = false; |
| 38 | let p = embassy_stm32::init(config); | 28 | let p = embassy_stm32::init(config); |
| 39 | 29 | ||
| 40 | // give the RTC to the executor... | ||
| 41 | let rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 42 | static RTC: StaticCell<Rtc> = StaticCell::new(); | ||
| 43 | let rtc = RTC.init(rtc); | ||
| 44 | embassy_stm32::low_power::stop_with_rtc(rtc); | ||
| 45 | |||
| 46 | spawner.spawn(unwrap!(blinky(p.PB4.into()))); | 30 | spawner.spawn(unwrap!(blinky(p.PB4.into()))); |
| 47 | spawner.spawn(unwrap!(timeout())); | 31 | spawner.spawn(unwrap!(timeout())); |
| 48 | } | 32 | } |
diff --git a/examples/stm32h5/src/bin/usb_c_pd.rs b/examples/stm32h5/src/bin/usb_c_pd.rs index acb03e498..ab6efff32 100644 --- a/examples/stm32h5/src/bin/usb_c_pd.rs +++ b/examples/stm32h5/src/bin/usb_c_pd.rs | |||
| @@ -3,12 +3,12 @@ | |||
| 3 | #![no_std] | 3 | #![no_std] |
| 4 | #![no_main] | 4 | #![no_main] |
| 5 | 5 | ||
| 6 | use defmt::{error, info, Format}; | 6 | use defmt::{Format, error, info}; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::gpio::Output; | 8 | use embassy_stm32::gpio::Output; |
| 9 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; | 9 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, Config}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals}; |
| 11 | use embassy_time::{with_timeout, Duration}; | 11 | use embassy_time::{Duration, with_timeout}; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index e8f536133..f72851ed7 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::time::Hertz; | 7 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h5/src/bin/usb_uac_speaker.rs b/examples/stm32h5/src/bin/usb_uac_speaker.rs index 86873cabd..f75b1fd8a 100644 --- a/examples/stm32h5/src/bin/usb_uac_speaker.rs +++ b/examples/stm32h5/src/bin/usb_uac_speaker.rs | |||
| @@ -6,9 +6,9 @@ use core::cell::{Cell, RefCell}; | |||
| 6 | use defmt::{panic, *}; | 6 | use defmt::{panic, *}; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::{bind_interrupts, interrupt, peripherals, timer, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, timer, usb}; |
| 10 | use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | ||
| 11 | use embassy_sync::blocking_mutex::Mutex; | 10 | use embassy_sync::blocking_mutex::Mutex; |
| 11 | use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | ||
| 12 | use embassy_sync::signal::Signal; | 12 | use embassy_sync::signal::Signal; |
| 13 | use embassy_sync::zerocopy_channel; | 13 | use embassy_sync::zerocopy_channel; |
| 14 | use embassy_usb::class::uac1; | 14 | use embassy_usb::class::uac1; |
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 9a2080013..09b734054 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h7-examples" | 3 | name = "embassy-stm32h7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 30 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 31 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | stm32-fmc = "0.3.0" | 33 | stm32-fmc = "0.4.0" |
| 34 | embedded-storage = "0.3.1" | 34 | embedded-storage = "0.3.1" |
| 35 | static_cell = "2" | 35 | static_cell = "2" |
| 36 | chrono = { version = "^0.4", default-features = false } | 36 | chrono = { version = "^0.4", default-features = false } |
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index 98504ddf6..fc45541bf 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -46,14 +46,12 @@ async fn main(_spawner: Spawner) { | |||
| 46 | 46 | ||
| 47 | let mut adc = Adc::new(p.ADC3); | 47 | let mut adc = Adc::new(p.ADC3); |
| 48 | 48 | ||
| 49 | adc.set_sample_time(SampleTime::CYCLES32_5); | ||
| 50 | |||
| 51 | let mut vrefint_channel = adc.enable_vrefint(); | 49 | let mut vrefint_channel = adc.enable_vrefint(); |
| 52 | 50 | ||
| 53 | loop { | 51 | loop { |
| 54 | let vrefint = adc.blocking_read(&mut vrefint_channel); | 52 | let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES32_5); |
| 55 | info!("vrefint: {}", vrefint); | 53 | info!("vrefint: {}", vrefint); |
| 56 | let measured = adc.blocking_read(&mut p.PC0); | 54 | let measured = adc.blocking_read(&mut p.PC0, SampleTime::CYCLES32_5); |
| 57 | info!("measured: {}", measured); | 55 | info!("measured: {}", measured); |
| 58 | Timer::after_millis(500).await; | 56 | Timer::after_millis(500).await; |
| 59 | } | 57 | } |
diff --git a/examples/stm32h7/src/bin/adc_dma.rs b/examples/stm32h7/src/bin/adc_dma.rs index f06b5d06e..cedb32e47 100644 --- a/examples/stm32h7/src/bin/adc_dma.rs +++ b/examples/stm32h7/src/bin/adc_dma.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; | ||
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
diff --git a/examples/stm32h7/src/bin/button_exti.rs b/examples/stm32h7/src/bin/button_exti.rs index 2a546dac5..e7e1549a8 100644 --- a/examples/stm32h7/src/bin/button_exti.rs +++ b/examples/stm32h7/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 8f2e265d6..c593d5e0b 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs | |||
| @@ -5,8 +5,8 @@ use embassy_executor::Spawner; | |||
| 5 | use embassy_stm32::dcmi::{self, *}; | 5 | use embassy_stm32::dcmi::{self, *}; |
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::i2c::I2c; | 7 | use embassy_stm32::i2c::I2c; |
| 8 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; | 8 | use embassy_stm32::rcc::{Mco, Mco1Source, McoConfig, McoPrescaler}; |
| 9 | use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, i2c, peripherals}; |
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use ov7725::*; | 11 | use ov7725::*; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -48,7 +48,14 @@ async fn main(_spawner: Spawner) { | |||
| 48 | let p = embassy_stm32::init(config); | 48 | let p = embassy_stm32::init(config); |
| 49 | 49 | ||
| 50 | defmt::info!("Hello World!"); | 50 | defmt::info!("Hello World!"); |
| 51 | let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); | 51 | |
| 52 | let mco_config = { | ||
| 53 | let mut config = McoConfig::default(); | ||
| 54 | config.prescaler = McoPrescaler::DIV3; | ||
| 55 | config | ||
| 56 | }; | ||
| 57 | |||
| 58 | let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, mco_config); | ||
| 52 | 59 | ||
| 53 | let mut led = Output::new(p.PE3, Level::High, Speed::Low); | 60 | let mut led = Output::new(p.PE3, Level::High, Speed::Low); |
| 54 | let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); | 61 | let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); |
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs index 0af11ef3e..49830f9b7 100644 --- a/examples/stm32h7/src/bin/can.rs +++ b/examples/stm32h7/src/bin/can.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::peripherals::*; | 6 | use embassy_stm32::peripherals::*; |
| 7 | use embassy_stm32::{bind_interrupts, can, rcc, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, can, rcc}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs index 27df80336..fa22837c5 100644 --- a/examples/stm32h7/src/bin/dac.rs +++ b/examples/stm32h7/src/bin/dac.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_stm32::dac::{DacCh1, Value}; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::dac::{DacCh1, Value}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| 10 | #[entry] | 10 | #[entry] |
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index df37e9d78..9ccefa761 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Peri; | ||
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 7 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::mode::Async; | 8 | use embassy_stm32::mode::Async; |
| 8 | use embassy_stm32::pac::timer::vals::Mms; | 9 | use embassy_stm32::pac::timer::vals::Mms; |
| @@ -10,7 +11,6 @@ use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; | |||
| 10 | use embassy_stm32::rcc::frequency; | 11 | use embassy_stm32::rcc::frequency; |
| 11 | use embassy_stm32::time::Hertz; | 12 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::timer::low_level::Timer; | 13 | use embassy_stm32::timer::low_level::Timer; |
| 13 | use embassy_stm32::Peri; | ||
| 14 | use micromath::F32Ext; | 14 | use micromath::F32Ext; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 6c215362d..09915799b 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -5,10 +5,10 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | 6 | use embassy_net::tcp::TcpSocket; |
| 7 | use embassy_net::{Ipv4Address, StackResources}; | 7 | use embassy_net::{Ipv4Address, StackResources}; |
| 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 9 | use embassy_stm32::peripherals::ETH; | 9 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; |
| 10 | use embassy_stm32::rng::Rng; | 10 | use embassy_stm32::rng::Rng; |
| 11 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 11 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use embedded_io_async::Write; | 13 | use embedded_io_async::Write; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| @@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs { | |||
| 19 | RNG => rng::InterruptHandler<peripherals::RNG>; | 19 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 20 | }); | 20 | }); |
| 21 | 21 | ||
| 22 | type Device = Ethernet<'static, ETH, GenericPhy>; | 22 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 23 | 23 | ||
| 24 | #[embassy_executor::task] | 24 | #[embassy_executor::task] |
| 25 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 25 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -69,16 +69,16 @@ async fn main(spawner: Spawner) -> ! { | |||
| 69 | p.ETH, | 69 | p.ETH, |
| 70 | Irqs, | 70 | Irqs, |
| 71 | p.PA1, // ref_clk | 71 | p.PA1, // ref_clk |
| 72 | p.PA2, // mdio | ||
| 73 | p.PC1, // eth_mdc | ||
| 74 | p.PA7, // CRS_DV: Carrier Sense | 72 | p.PA7, // CRS_DV: Carrier Sense |
| 75 | p.PC4, // RX_D0: Received Bit 0 | 73 | p.PC4, // RX_D0: Received Bit 0 |
| 76 | p.PC5, // RX_D1: Received Bit 1 | 74 | p.PC5, // RX_D1: Received Bit 1 |
| 77 | p.PG13, // TX_D0: Transmit Bit 0 | 75 | p.PG13, // TX_D0: Transmit Bit 0 |
| 78 | p.PB13, // TX_D1: Transmit Bit 1 | 76 | p.PB13, // TX_D1: Transmit Bit 1 |
| 79 | p.PG11, // TX_EN: Transmit Enable | 77 | p.PG11, // TX_EN: Transmit Enable |
| 80 | GenericPhy::new_auto(), | ||
| 81 | mac_addr, | 78 | mac_addr, |
| 79 | p.ETH_SMA, | ||
| 80 | p.PA2, // mdio | ||
| 81 | p.PC1, // mdc | ||
| 82 | ); | 82 | ); |
| 83 | 83 | ||
| 84 | let config = embassy_net::Config::dhcpv4(Default::default()); | 84 | let config = embassy_net::Config::dhcpv4(Default::default()); |
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 10ac57fc9..189c99686 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -5,12 +5,12 @@ use core::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; | ||
| 9 | use embassy_net::StackResources; | 8 | use embassy_net::StackResources; |
| 10 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 9 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; |
| 11 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 11 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; | ||
| 12 | use embassy_stm32::rng::Rng; | 12 | use embassy_stm32::rng::Rng; |
| 13 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 13 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 15 | use embedded_io_async::Write; | 15 | use embedded_io_async::Write; |
| 16 | use embedded_nal_async::TcpConnect; | 16 | use embedded_nal_async::TcpConnect; |
| @@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs { | |||
| 22 | RNG => rng::InterruptHandler<peripherals::RNG>; | 22 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 23 | }); | 23 | }); |
| 24 | 24 | ||
| 25 | type Device = Ethernet<'static, ETH, GenericPhy>; | 25 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -71,16 +71,16 @@ async fn main(spawner: Spawner) -> ! { | |||
| 71 | p.ETH, | 71 | p.ETH, |
| 72 | Irqs, | 72 | Irqs, |
| 73 | p.PA1, | 73 | p.PA1, |
| 74 | p.PA2, | ||
| 75 | p.PC1, | ||
| 76 | p.PA7, | 74 | p.PA7, |
| 77 | p.PC4, | 75 | p.PC4, |
| 78 | p.PC5, | 76 | p.PC5, |
| 79 | p.PG13, | 77 | p.PG13, |
| 80 | p.PB13, | 78 | p.PB13, |
| 81 | p.PG11, | 79 | p.PG11, |
| 82 | GenericPhy::new_auto(), | ||
| 83 | mac_addr, | 80 | mac_addr, |
| 81 | p.ETH_SMA, | ||
| 82 | p.PA2, | ||
| 83 | p.PC1, | ||
| 84 | ); | 84 | ); |
| 85 | 85 | ||
| 86 | let config = embassy_net::Config::dhcpv4(Default::default()); | 86 | let config = embassy_net::Config::dhcpv4(Default::default()); |
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs index c6a108471..92c823567 100644 --- a/examples/stm32h7/src/bin/eth_client_mii.rs +++ b/examples/stm32h7/src/bin/eth_client_mii.rs | |||
| @@ -5,12 +5,12 @@ use core::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; | ||
| 9 | use embassy_net::StackResources; | 8 | use embassy_net::StackResources; |
| 10 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 9 | use embassy_net::tcp::client::{TcpClient, TcpClientState}; |
| 11 | use embassy_stm32::peripherals::ETH; | 10 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 11 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; | ||
| 12 | use embassy_stm32::rng::Rng; | 12 | use embassy_stm32::rng::Rng; |
| 13 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 13 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 15 | use embedded_io_async::Write; | 15 | use embedded_io_async::Write; |
| 16 | use embedded_nal_async::TcpConnect; | 16 | use embedded_nal_async::TcpConnect; |
| @@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs { | |||
| 22 | RNG => rng::InterruptHandler<peripherals::RNG>; | 22 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 23 | }); | 23 | }); |
| 24 | 24 | ||
| 25 | type Device = Ethernet<'static, ETH, GenericPhy>; | 25 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 26 | 26 | ||
| 27 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 28 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -72,8 +72,6 @@ async fn main(spawner: Spawner) -> ! { | |||
| 72 | Irqs, | 72 | Irqs, |
| 73 | p.PA1, | 73 | p.PA1, |
| 74 | p.PC3, | 74 | p.PC3, |
| 75 | p.PA2, | ||
| 76 | p.PC1, | ||
| 77 | p.PA7, | 75 | p.PA7, |
| 78 | p.PC4, | 76 | p.PC4, |
| 79 | p.PC5, | 77 | p.PC5, |
| @@ -84,8 +82,10 @@ async fn main(spawner: Spawner) -> ! { | |||
| 84 | p.PC2, | 82 | p.PC2, |
| 85 | p.PE2, | 83 | p.PE2, |
| 86 | p.PG11, | 84 | p.PG11, |
| 87 | GenericPhy::new_auto(), | ||
| 88 | mac_addr, | 85 | mac_addr, |
| 86 | p.ETH_SMA, | ||
| 87 | p.PA2, | ||
| 88 | p.PC1, | ||
| 89 | ); | 89 | ); |
| 90 | info!("Device created"); | 90 | info!("Device created"); |
| 91 | 91 | ||
diff --git a/examples/stm32h7/src/bin/flash_async.rs b/examples/stm32h7/src/bin/flash_async.rs new file mode 100644 index 000000000..96d1936f3 --- /dev/null +++ b/examples/stm32h7/src/bin/flash_async.rs | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{info, unwrap}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::flash::{Flash, InterruptHandler}; | ||
| 7 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; | ||
| 8 | use embassy_stm32::{Peri, bind_interrupts}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | FLASH => InterruptHandler; | ||
| 14 | }); | ||
| 15 | |||
| 16 | #[embassy_executor::main] | ||
| 17 | async fn main(spawner: Spawner) { | ||
| 18 | let p = embassy_stm32::init(Default::default()); | ||
| 19 | info!("Hello Flash!"); | ||
| 20 | |||
| 21 | let mut f = Flash::new(p.FLASH, Irqs); | ||
| 22 | |||
| 23 | // Led should blink uninterrupted during ~2sec erase operation | ||
| 24 | spawner.spawn(blinky(p.PB14.into()).unwrap()); | ||
| 25 | |||
| 26 | // Test on bank 2 in order not to stall CPU. | ||
| 27 | test_flash(&mut f, 1024 * 1024, 128 * 1024).await; | ||
| 28 | } | ||
| 29 | |||
| 30 | #[embassy_executor::task] | ||
| 31 | async fn blinky(p: Peri<'static, AnyPin>) { | ||
| 32 | let mut led = Output::new(p, Level::High, Speed::Low); | ||
| 33 | |||
| 34 | loop { | ||
| 35 | info!("high"); | ||
| 36 | led.set_high(); | ||
| 37 | Timer::after_millis(300).await; | ||
| 38 | |||
| 39 | info!("low"); | ||
| 40 | led.set_low(); | ||
| 41 | Timer::after_millis(300).await; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | ||
| 46 | info!("Testing offset: {=u32:#X}, size: {=u32:#X}", offset, size); | ||
| 47 | |||
| 48 | info!("Reading..."); | ||
| 49 | let mut buf = [0u8; 32]; | ||
| 50 | unwrap!(f.blocking_read(offset, &mut buf)); | ||
| 51 | info!("Read: {=[u8]:x}", buf); | ||
| 52 | |||
| 53 | info!("Erasing..."); | ||
| 54 | unwrap!(f.erase(offset, offset + size).await); | ||
| 55 | |||
| 56 | info!("Reading..."); | ||
| 57 | let mut buf = [0u8; 32]; | ||
| 58 | unwrap!(f.blocking_read(offset, &mut buf)); | ||
| 59 | info!("Read after erase: {=[u8]:x}", buf); | ||
| 60 | |||
| 61 | info!("Writing..."); | ||
| 62 | unwrap!( | ||
| 63 | f.write( | ||
| 64 | offset, | ||
| 65 | &[ | ||
| 66 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, | ||
| 67 | 29, 30, 31, 32 | ||
| 68 | ] | ||
| 69 | ) | ||
| 70 | .await | ||
| 71 | ); | ||
| 72 | |||
| 73 | info!("Reading..."); | ||
| 74 | let mut buf = [0u8; 32]; | ||
| 75 | unwrap!(f.blocking_read(offset, &mut buf)); | ||
| 76 | info!("Read: {=[u8]:x}", buf); | ||
| 77 | assert_eq!( | ||
| 78 | &buf[..], | ||
| 79 | &[ | ||
| 80 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | ||
| 81 | 30, 31, 32 | ||
| 82 | ] | ||
| 83 | ); | ||
| 84 | } | ||
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs index 5e5e6ccc8..b65d50443 100644 --- a/examples/stm32h7/src/bin/fmc.rs +++ b/examples/stm32h7/src/bin/fmc.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::fmc::Fmc; | ||
| 7 | use embassy_stm32::Config; | 6 | use embassy_stm32::Config; |
| 7 | use embassy_stm32::fmc::Fmc; | ||
| 8 | use embassy_time::{Delay, Timer}; | 8 | use embassy_time::{Delay, Timer}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 9e45d845f..08ff812f2 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs | |||
| @@ -9,8 +9,8 @@ use embassy_executor::Spawner; | |||
| 9 | use embassy_stm32::i2c::{self, I2c}; | 9 | use embassy_stm32::i2c::{self, I2c}; |
| 10 | use embassy_stm32::mode::Async; | 10 | use embassy_stm32::mode::Async; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals}; | 11 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 12 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 13 | use embassy_sync::blocking_mutex::NoopMutex; | 12 | use embassy_sync::blocking_mutex::NoopMutex; |
| 13 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 14 | use embassy_time::{Duration, Timer}; | 14 | use embassy_time::{Duration, Timer}; |
| 15 | use embedded_hal_1::i2c::I2c as _; | 15 | use embedded_hal_1::i2c::I2c as _; |
| 16 | use static_cell::StaticCell; | 16 | use static_cell::StaticCell; |
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 12abb8693..f17fb2aaa 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed}; | 6 | use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed}; |
| 7 | use embassy_stm32::time::{khz, Hertz}; | 7 | use embassy_stm32::time::{Hertz, khz}; |
| 8 | use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; | 8 | use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; |
| 9 | use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin}; | 9 | use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin}; |
| 10 | use embassy_stm32::{Config, Peri}; | 10 | use embassy_stm32::{Config, Peri}; |
diff --git a/examples/stm32h7/src/bin/mco.rs b/examples/stm32h7/src/bin/mco.rs index a6ee27625..cafcb90f6 100644 --- a/examples/stm32h7/src/bin/mco.rs +++ b/examples/stm32h7/src/bin/mco.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; | 7 | use embassy_stm32::rcc::{Mco, Mco1Source, McoConfig, McoPrescaler}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -15,7 +15,13 @@ async fn main(_spawner: Spawner) { | |||
| 15 | 15 | ||
| 16 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); | 16 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); |
| 17 | 17 | ||
| 18 | let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8); | 18 | let config = { |
| 19 | let mut config = McoConfig::default(); | ||
| 20 | config.prescaler = McoPrescaler::DIV8; | ||
| 21 | config | ||
| 22 | }; | ||
| 23 | |||
| 24 | let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, config); | ||
| 19 | 25 | ||
| 20 | loop { | 26 | loop { |
| 21 | info!("high"); | 27 | info!("high"); |
diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index 2f2ffdea2..8375e0e8e 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs | |||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn UART4() { | 115 | unsafe fn UART4() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn UART5() { | 120 | unsafe fn UART5() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index 73b43be69..ffd117580 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs | |||
| @@ -3,10 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Config; | ||
| 6 | use embassy_stm32::gpio::OutputType; | 7 | use embassy_stm32::gpio::OutputType; |
| 7 | use embassy_stm32::time::khz; | 8 | use embassy_stm32::time::khz; |
| 8 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 9 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32h7/src/bin/rng.rs b/examples/stm32h7/src/bin/rng.rs index a9ef7200d..489747678 100644 --- a/examples/stm32h7/src/bin/rng.rs +++ b/examples/stm32h7/src/bin/rng.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rng::Rng; | 6 | use embassy_stm32::rng::Rng; |
| 7 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| 10 | bind_interrupts!(struct Irqs { | 10 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs index 0adb48877..965716d23 100644 --- a/examples/stm32h7/src/bin/rtc.rs +++ b/examples/stm32h7/src/bin/rtc.rs | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::LsConfig; | 8 | use embassy_stm32::rcc::LsConfig; |
| 8 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | .and_hms_opt(10, 30, 15) | 23 | .and_hms_opt(10, 30, 15) |
| 24 | .unwrap(); | 24 | .unwrap(); |
| 25 | 25 | ||
| 26 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 26 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 27 | info!("Got RTC! {:?}", now.and_utc().timestamp()); | 27 | info!("Got RTC! {:?}", now.and_utc().timestamp()); |
| 28 | 28 | ||
| 29 | rtc.set_datetime(now.into()).expect("datetime not set"); | 29 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| @@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) { | |||
| 31 | // In reality the delay would be much longer | 31 | // In reality the delay would be much longer |
| 32 | Timer::after_millis(20000).await; | 32 | Timer::after_millis(20000).await; |
| 33 | 33 | ||
| 34 | let then: NaiveDateTime = rtc.now().unwrap().into(); | 34 | let then: NaiveDateTime = time_provider.now().unwrap().into(); |
| 35 | info!("Got RTC! {:?}", then.and_utc().timestamp()); | 35 | info!("Got RTC! {:?}", then.and_utc().timestamp()); |
| 36 | } | 36 | } |
diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs index 847b70c85..0300f83bf 100644 --- a/examples/stm32h7/src/bin/sai.rs +++ b/examples/stm32h7/src/bin/sai.rs | |||
| @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { | |||
| 63 | tx_config.tx_rx = TxRx::Transmitter; | 63 | tx_config.tx_rx = TxRx::Transmitter; |
| 64 | tx_config.sync_output = true; | 64 | tx_config.sync_output = true; |
| 65 | tx_config.clock_strobe = ClockStrobe::Falling; | 65 | tx_config.clock_strobe = ClockStrobe::Falling; |
| 66 | tx_config.master_clock_divider = Some(mclk_div); | 66 | tx_config.master_clock_divider = mclk_div; |
| 67 | tx_config.stereo_mono = StereoMono::Stereo; | 67 | tx_config.stereo_mono = StereoMono::Stereo; |
| 68 | tx_config.data_size = DataSize::Data24; | 68 | tx_config.data_size = DataSize::Data24; |
| 69 | tx_config.bit_order = BitOrder::MsbFirst; | 69 | tx_config.bit_order = BitOrder::MsbFirst; |
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs index 96840d8ff..f2e5bedeb 100644 --- a/examples/stm32h7/src/bin/sdmmc.rs +++ b/examples/stm32h7/src/bin/sdmmc.rs | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::sdmmc::Sdmmc; | 6 | use embassy_stm32::sdmmc::Sdmmc; |
| 7 | use embassy_stm32::sdmmc::sd::{CmdBlock, StorageDevice}; | ||
| 7 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 11 | ||
| 11 | bind_interrupts!(struct Irqs { | 12 | bind_interrupts!(struct Irqs { |
| @@ -13,7 +14,7 @@ bind_interrupts!(struct Irqs { | |||
| 13 | }); | 14 | }); |
| 14 | 15 | ||
| 15 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) -> ! { | 17 | async fn main(_spawner: Spawner) { |
| 17 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 18 | { | 19 | { |
| 19 | use embassy_stm32::rcc::*; | 20 | use embassy_stm32::rcc::*; |
| @@ -53,11 +54,13 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 53 | // Should print 400kHz for initialization | 54 | // Should print 400kHz for initialization |
| 54 | info!("Configured clock: {}", sdmmc.clock().0); | 55 | info!("Configured clock: {}", sdmmc.clock().0); |
| 55 | 56 | ||
| 56 | unwrap!(sdmmc.init_sd_card(mhz(25)).await); | 57 | let mut cmd_block = CmdBlock::new(); |
| 57 | 58 | ||
| 58 | let card = unwrap!(sdmmc.card()); | 59 | let storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(25)) |
| 60 | .await | ||
| 61 | .unwrap(); | ||
| 59 | 62 | ||
| 60 | info!("Card: {:#?}", Debug2Format(card)); | 63 | let card = storage.card(); |
| 61 | 64 | ||
| 62 | loop {} | 65 | info!("Card: {:#?}", Debug2Format(&card)); |
| 63 | } | 66 | } |
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index dce30a4a7..f7ab20cdd 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs | |||
| @@ -9,13 +9,13 @@ use defmt::*; | |||
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_stm32::mode::Blocking; | 10 | use embassy_stm32::mode::Blocking; |
| 11 | use embassy_stm32::time::mhz; | 11 | use embassy_stm32::time::mhz; |
| 12 | use embassy_stm32::{spi, Config}; | 12 | use embassy_stm32::{Config, spi}; |
| 13 | use heapless::String; | 13 | use heapless::String; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); | 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); |
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs index 828f687b8..cd9d6c789 100644 --- a/examples/stm32h7/src/bin/spi_bdma.rs +++ b/examples/stm32h7/src/bin/spi_bdma.rs | |||
| @@ -9,7 +9,7 @@ use defmt::*; | |||
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_stm32::mode::Async; | 10 | use embassy_stm32::mode::Async; |
| 11 | use embassy_stm32::time::mhz; | 11 | use embassy_stm32::time::mhz; |
| 12 | use embassy_stm32::{spi, Config}; | 12 | use embassy_stm32::{Config, spi}; |
| 13 | use grounded::uninit::GroundedArrayCell; | 13 | use grounded::uninit::GroundedArrayCell; |
| 14 | use heapless::String; | 14 | use heapless::String; |
| 15 | use static_cell::StaticCell; | 15 | use static_cell::StaticCell; |
| @@ -20,7 +20,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 20 | static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); | 20 | static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); |
| 21 | 21 | ||
| 22 | #[embassy_executor::task] | 22 | #[embassy_executor::task] |
| 23 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 23 | async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) { |
| 24 | let (read_buffer, write_buffer) = unsafe { | 24 | let (read_buffer, write_buffer) = unsafe { |
| 25 | let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); | 25 | let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); |
| 26 | ram.initialize_all_copied(0); | 26 | ram.initialize_all_copied(0); |
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 2197fabce..3d3c2f43e 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs | |||
| @@ -9,13 +9,13 @@ use defmt::*; | |||
| 9 | use embassy_executor::Executor; | 9 | use embassy_executor::Executor; |
| 10 | use embassy_stm32::mode::Async; | 10 | use embassy_stm32::mode::Async; |
| 11 | use embassy_stm32::time::mhz; | 11 | use embassy_stm32::time::mhz; |
| 12 | use embassy_stm32::{spi, Config}; | 12 | use embassy_stm32::{Config, spi}; |
| 13 | use heapless::String; | 13 | use heapless::String; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | let mut read = [0; 128]; | 21 | let mut read = [0; 128]; |
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs index 50bb964da..d0470101b 100644 --- a/examples/stm32h7/src/bin/usb_serial.rs +++ b/examples/stm32h7/src/bin/usb_serial.rs | |||
| @@ -5,10 +5,10 @@ use defmt::{panic, *}; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::{Driver, Instance}; | 7 | use embassy_stm32::usb::{Driver, Instance}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 9 | use embassy_usb::Builder; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index 7e4ccc528..93a5109e2 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h723-examples" | 3 | name = "embassy-stm32h723-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs index b75a03ae8..959e2aa18 100644 --- a/examples/stm32h723/src/bin/spdifrx.rs +++ b/examples/stm32h723/src/bin/spdifrx.rs | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::{info, trace}; | 8 | use defmt::{info, trace}; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_futures::select::{select, Either}; | 10 | use embassy_futures::select::{Either, select}; |
| 11 | use embassy_stm32::spdifrx::{self, Spdifrx}; | 11 | use embassy_stm32::spdifrx::{self, Spdifrx}; |
| 12 | use embassy_stm32::{bind_interrupts, peripherals, sai, Peri}; | 12 | use embassy_stm32::{Peri, bind_interrupts, peripherals, sai}; |
| 13 | use grounded::uninit::GroundedArrayCell; | 13 | use grounded::uninit::GroundedArrayCell; |
| 14 | use hal::sai::*; | 14 | use hal::sai::*; |
| 15 | use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; | 15 | use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; |
| @@ -167,8 +167,7 @@ fn new_sai_transmitter<'d>( | |||
| 167 | sai_config.slot_count = hal::sai::word::U4(CHANNEL_COUNT as u8); | 167 | sai_config.slot_count = hal::sai::word::U4(CHANNEL_COUNT as u8); |
| 168 | sai_config.slot_enable = 0xFFFF; // All slots | 168 | sai_config.slot_enable = 0xFFFF; // All slots |
| 169 | sai_config.data_size = sai::DataSize::Data32; | 169 | sai_config.data_size = sai::DataSize::Data32; |
| 170 | sai_config.frame_length = (CHANNEL_COUNT * 32) as u8; | 170 | sai_config.frame_length = (CHANNEL_COUNT * 32) as u16; |
| 171 | sai_config.master_clock_divider = None; | ||
| 172 | 171 | ||
| 173 | let (sub_block_tx, _) = hal::sai::split_subblocks(sai); | 172 | let (sub_block_tx, _) = hal::sai::split_subblocks(sai); |
| 174 | Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) | 173 | Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) |
diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 22b7ad96a..1ad2eeb2e 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h735-examples" | 3 | name = "embassy-stm32h735-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32h735/src/bin/ltdc.rs b/examples/stm32h735/src/bin/ltdc.rs index 8a99f745d..f042e04c2 100644 --- a/examples/stm32h735/src/bin/ltdc.rs +++ b/examples/stm32h735/src/bin/ltdc.rs | |||
| @@ -15,14 +15,14 @@ use embassy_stm32::gpio::{Level, Output, Speed}; | |||
| 15 | use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge}; | 15 | use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge}; |
| 16 | use embassy_stm32::{bind_interrupts, peripherals}; | 16 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 17 | use embassy_time::{Duration, Timer}; | 17 | use embassy_time::{Duration, Timer}; |
| 18 | use embedded_graphics::Pixel; | ||
| 18 | use embedded_graphics::draw_target::DrawTarget; | 19 | use embedded_graphics::draw_target::DrawTarget; |
| 19 | use embedded_graphics::geometry::{OriginDimensions, Point, Size}; | 20 | use embedded_graphics::geometry::{OriginDimensions, Point, Size}; |
| 20 | use embedded_graphics::image::Image; | 21 | use embedded_graphics::image::Image; |
| 21 | use embedded_graphics::pixelcolor::raw::RawU24; | ||
| 22 | use embedded_graphics::pixelcolor::Rgb888; | 22 | use embedded_graphics::pixelcolor::Rgb888; |
| 23 | use embedded_graphics::pixelcolor::raw::RawU24; | ||
| 23 | use embedded_graphics::prelude::*; | 24 | use embedded_graphics::prelude::*; |
| 24 | use embedded_graphics::primitives::Rectangle; | 25 | use embedded_graphics::primitives::Rectangle; |
| 25 | use embedded_graphics::Pixel; | ||
| 26 | use heapless::{Entry, FnvIndexMap}; | 26 | use heapless::{Entry, FnvIndexMap}; |
| 27 | use tinybmp::Bmp; | 27 | use tinybmp::Bmp; |
| 28 | use {defmt_rtt as _, panic_probe as _}; | 28 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index c76340b5f..9b5e5d93d 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h742-examples" | 3 | name = "embassy-stm32h742-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32h742/src/bin/qspi.rs b/examples/stm32h742/src/bin/qspi.rs index 9e79d7089..a88c8f249 100644 --- a/examples/stm32h742/src/bin/qspi.rs +++ b/examples/stm32h742/src/bin/qspi.rs | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config as StmCfg; | ||
| 7 | use embassy_stm32::mode::Blocking; | 8 | use embassy_stm32::mode::Blocking; |
| 8 | use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *}; | 9 | use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *}; |
| 9 | use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig}; | 10 | use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig}; |
| 10 | use embassy_stm32::Config as StmCfg; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | const MEMORY_PAGE_SIZE: usize = 256; | 13 | const MEMORY_PAGE_SIZE: usize = 256; |
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index c73f9df79..d69f0228e 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h755cm4-examples" | 3 | name = "embassy-stm32h755cm4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 30 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 31 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | stm32-fmc = "0.3.0" | 33 | stm32-fmc = "0.4.0" |
| 34 | embedded-storage = "0.3.1" | 34 | embedded-storage = "0.3.1" |
| 35 | static_cell = "2" | 35 | static_cell = "2" |
| 36 | chrono = { version = "^0.4", default-features = false } | 36 | chrono = { version = "^0.4", default-features = false } |
diff --git a/examples/stm32h755cm4/src/bin/blinky.rs b/examples/stm32h755cm4/src/bin/blinky.rs index 39112c1f5..0ee3c68dc 100644 --- a/examples/stm32h755cm4/src/bin/blinky.rs +++ b/examples/stm32h755cm4/src/bin/blinky.rs | |||
| @@ -5,8 +5,8 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 9 | use embassy_stm32::SharedData; | 8 | use embassy_stm32::SharedData; |
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index f584e31e9..c0db8cdd3 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs | |||
| @@ -85,7 +85,7 @@ mod shared { | |||
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | #[link_section = ".ram_d3"] | 88 | #[unsafe(link_section = ".ram_d3")] |
| 89 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); | 89 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| @@ -93,13 +93,13 @@ use core::mem::MaybeUninit; | |||
| 93 | 93 | ||
| 94 | use defmt::*; | 94 | use defmt::*; |
| 95 | use embassy_executor::Spawner; | 95 | use embassy_executor::Spawner; |
| 96 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 97 | use embassy_stm32::SharedData; | 96 | use embassy_stm32::SharedData; |
| 97 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 98 | use embassy_time::Timer; | 98 | use embassy_time::Timer; |
| 99 | use shared::SHARED_LED_STATE; | 99 | use shared::SHARED_LED_STATE; |
| 100 | use {defmt_rtt as _, panic_probe as _}; | 100 | use {defmt_rtt as _, panic_probe as _}; |
| 101 | 101 | ||
| 102 | #[link_section = ".ram_d3"] | 102 | #[unsafe(link_section = ".ram_d3")] |
| 103 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | 103 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); |
| 104 | 104 | ||
| 105 | /// Task that continuously blinks the red LED as a heartbeat indicator | 105 | /// Task that continuously blinks the red LED as a heartbeat indicator |
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index c34d4e45c..f4e1e53b7 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h755cm7-examples" | 3 | name = "embassy-stm32h755cm7-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 30 | heapless = { version = "0.8", default-features = false } | 30 | heapless = { version = "0.8", default-features = false } |
| 31 | critical-section = "1.1" | 31 | critical-section = "1.1" |
| 32 | micromath = "2.0.0" | 32 | micromath = "2.0.0" |
| 33 | stm32-fmc = "0.3.0" | 33 | stm32-fmc = "0.4.0" |
| 34 | embedded-storage = "0.3.1" | 34 | embedded-storage = "0.3.1" |
| 35 | static_cell = "2" | 35 | static_cell = "2" |
| 36 | chrono = { version = "^0.4", default-features = false } | 36 | chrono = { version = "^0.4", default-features = false } |
diff --git a/examples/stm32h755cm7/src/bin/blinky.rs b/examples/stm32h755cm7/src/bin/blinky.rs index b30bf4de8..e8f5a1c43 100644 --- a/examples/stm32h755cm7/src/bin/blinky.rs +++ b/examples/stm32h755cm7/src/bin/blinky.rs | |||
| @@ -5,8 +5,8 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 9 | use embassy_stm32::SharedData; | 8 | use embassy_stm32::SharedData; |
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index a4e1b5ff4..3df0b26d7 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs | |||
| @@ -97,7 +97,7 @@ mod shared { | |||
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | #[link_section = ".ram_d3"] | 100 | #[unsafe(link_section = ".ram_d3")] |
| 101 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); | 101 | pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); |
| 102 | 102 | ||
| 103 | // Memory region constants for MPU configuration | 103 | // Memory region constants for MPU configuration |
| @@ -106,7 +106,7 @@ mod shared { | |||
| 106 | pub const SRAM4_REGION_NUMBER: u8 = 0; | 106 | pub const SRAM4_REGION_NUMBER: u8 = 0; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | #[link_section = ".ram_d3"] | 109 | #[unsafe(link_section = ".ram_d3")] |
| 110 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | 110 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); |
| 111 | 111 | ||
| 112 | /// Configure MPU to make SRAM4 region non-cacheable | 112 | /// Configure MPU to make SRAM4 region non-cacheable |
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 1917749c5..0509d394d 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h7b0-examples" | 3 | name = "embassy-stm32h7b0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 29 | heapless = { version = "0.8", default-features = false } | 29 | heapless = { version = "0.8", default-features = false } |
| 30 | critical-section = "1.1" | 30 | critical-section = "1.1" |
| 31 | micromath = "2.0.0" | 31 | micromath = "2.0.0" |
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.4.0" |
| 33 | embedded-storage = "0.3.1" | 33 | embedded-storage = "0.3.1" |
| 34 | static_cell = "2" | 34 | static_cell = "2" |
| 35 | chrono = { version = "^0.4", default-features = false } | 35 | chrono = { version = "^0.4", default-features = false } |
diff --git a/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs b/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs index dffb740a9..865062f4b 100644 --- a/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs +++ b/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | use defmt::info; | 6 | use defmt::info; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::Config; | ||
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | 9 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 9 | use embassy_stm32::mode::Blocking; | 10 | use embassy_stm32::mode::Blocking; |
| 10 | use embassy_stm32::ospi::{ | 11 | use embassy_stm32::ospi::{ |
| @@ -12,7 +13,6 @@ use embassy_stm32::ospi::{ | |||
| 12 | OspiWidth, TransferConfig, WrapSize, | 13 | OspiWidth, TransferConfig, WrapSize, |
| 13 | }; | 14 | }; |
| 14 | use embassy_stm32::time::Hertz; | 15 | use embassy_stm32::time::Hertz; |
| 15 | use embassy_stm32::Config; | ||
| 16 | use embassy_time::Timer; | 16 | use embassy_time::Timer; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index bfe59b68d..ab525ad91 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32h7rs-examples" | 3 | name = "embassy-stm32h7rs-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 29 | heapless = { version = "0.8", default-features = false } | 29 | heapless = { version = "0.8", default-features = false } |
| 30 | critical-section = "1.1" | 30 | critical-section = "1.1" |
| 31 | micromath = "2.0.0" | 31 | micromath = "2.0.0" |
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.4.0" |
| 33 | embedded-storage = "0.3.1" | 33 | embedded-storage = "0.3.1" |
| 34 | static_cell = "2" | 34 | static_cell = "2" |
| 35 | chrono = { version = "^0.4", default-features = false } | 35 | chrono = { version = "^0.4", default-features = false } |
diff --git a/examples/stm32h7rs/src/bin/blinky.rs b/examples/stm32h7rs/src/bin/blinky.rs index 5fd50fb15..4c0864ff6 100644 --- a/examples/stm32h7rs/src/bin/blinky.rs +++ b/examples/stm32h7rs/src/bin/blinky.rs | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Config; | ||
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::time::Hertz; | 8 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::Config; | ||
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
diff --git a/examples/stm32h7rs/src/bin/button_exti.rs b/examples/stm32h7rs/src/bin/button_exti.rs index 34a08bbc6..d63290d42 100644 --- a/examples/stm32h7rs/src/bin/button_exti.rs +++ b/examples/stm32h7rs/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32h7rs/src/bin/can.rs b/examples/stm32h7rs/src/bin/can.rs index 0af11ef3e..49830f9b7 100644 --- a/examples/stm32h7rs/src/bin/can.rs +++ b/examples/stm32h7rs/src/bin/can.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::peripherals::*; | 6 | use embassy_stm32::peripherals::*; |
| 7 | use embassy_stm32::{bind_interrupts, can, rcc, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, can, rcc}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs index 67f541564..8e07d0a67 100644 --- a/examples/stm32h7rs/src/bin/eth.rs +++ b/examples/stm32h7rs/src/bin/eth.rs | |||
| @@ -5,10 +5,10 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | 6 | use embassy_net::udp::{PacketMetadata, UdpSocket}; |
| 7 | use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; | 7 | use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; |
| 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; | 8 | use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma}; |
| 9 | use embassy_stm32::peripherals::ETH; | 9 | use embassy_stm32::peripherals::{ETH, ETH_SMA}; |
| 10 | use embassy_stm32::rng::Rng; | 10 | use embassy_stm32::rng::Rng; |
| 11 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 11 | use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng}; |
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use heapless::Vec; | 13 | use heapless::Vec; |
| 14 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| @@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs { | |||
| 19 | RNG => rng::InterruptHandler<peripherals::RNG>; | 19 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 20 | }); | 20 | }); |
| 21 | 21 | ||
| 22 | type Device = Ethernet<'static, ETH, GenericPhy>; | 22 | type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>; |
| 23 | 23 | ||
| 24 | #[embassy_executor::task] | 24 | #[embassy_executor::task] |
| 25 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { | 25 | async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { |
| @@ -69,16 +69,16 @@ async fn main(spawner: Spawner) -> ! { | |||
| 69 | p.ETH, | 69 | p.ETH, |
| 70 | Irqs, | 70 | Irqs, |
| 71 | p.PB6, | 71 | p.PB6, |
| 72 | p.PA2, | ||
| 73 | p.PG6, | ||
| 74 | p.PA7, | 72 | p.PA7, |
| 75 | p.PG4, | 73 | p.PG4, |
| 76 | p.PG5, | 74 | p.PG5, |
| 77 | p.PG13, | 75 | p.PG13, |
| 78 | p.PG12, | 76 | p.PG12, |
| 79 | p.PG11, | 77 | p.PG11, |
| 80 | GenericPhy::new(0), | ||
| 81 | mac_addr, | 78 | mac_addr, |
| 79 | p.ETH_SMA, | ||
| 80 | p.PA2, | ||
| 81 | p.PG6, | ||
| 82 | ); | 82 | ); |
| 83 | 83 | ||
| 84 | // Have to use UDP w/ static config to fit in internal flash | 84 | // Have to use UDP w/ static config to fit in internal flash |
diff --git a/examples/stm32h7rs/src/bin/mco.rs b/examples/stm32h7rs/src/bin/mco.rs index a6ee27625..cafcb90f6 100644 --- a/examples/stm32h7rs/src/bin/mco.rs +++ b/examples/stm32h7rs/src/bin/mco.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; | 7 | use embassy_stm32::rcc::{Mco, Mco1Source, McoConfig, McoPrescaler}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -15,7 +15,13 @@ async fn main(_spawner: Spawner) { | |||
| 15 | 15 | ||
| 16 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); | 16 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); |
| 17 | 17 | ||
| 18 | let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8); | 18 | let config = { |
| 19 | let mut config = McoConfig::default(); | ||
| 20 | config.prescaler = McoPrescaler::DIV8; | ||
| 21 | config | ||
| 22 | }; | ||
| 23 | |||
| 24 | let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, config); | ||
| 19 | 25 | ||
| 20 | loop { | 26 | loop { |
| 21 | info!("high"); | 27 | info!("high"); |
diff --git a/examples/stm32h7rs/src/bin/multiprio.rs b/examples/stm32h7rs/src/bin/multiprio.rs index 2f2ffdea2..8375e0e8e 100644 --- a/examples/stm32h7rs/src/bin/multiprio.rs +++ b/examples/stm32h7rs/src/bin/multiprio.rs | |||
| @@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new(); | |||
| 113 | 113 | ||
| 114 | #[interrupt] | 114 | #[interrupt] |
| 115 | unsafe fn UART4() { | 115 | unsafe fn UART4() { |
| 116 | EXECUTOR_HIGH.on_interrupt() | 116 | unsafe { EXECUTOR_HIGH.on_interrupt() } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #[interrupt] | 119 | #[interrupt] |
| 120 | unsafe fn UART5() { | 120 | unsafe fn UART5() { |
| 121 | EXECUTOR_MED.on_interrupt() | 121 | unsafe { EXECUTOR_MED.on_interrupt() } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #[entry] | 124 | #[entry] |
diff --git a/examples/stm32h7rs/src/bin/rng.rs b/examples/stm32h7rs/src/bin/rng.rs index a9ef7200d..489747678 100644 --- a/examples/stm32h7rs/src/bin/rng.rs +++ b/examples/stm32h7rs/src/bin/rng.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rng::Rng; | 6 | use embassy_stm32::rng::Rng; |
| 7 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 7 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| 10 | bind_interrupts!(struct Irqs { | 10 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h7rs/src/bin/rtc.rs b/examples/stm32h7rs/src/bin/rtc.rs index 0adb48877..965716d23 100644 --- a/examples/stm32h7rs/src/bin/rtc.rs +++ b/examples/stm32h7rs/src/bin/rtc.rs | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::LsConfig; | 8 | use embassy_stm32::rcc::LsConfig; |
| 8 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | .and_hms_opt(10, 30, 15) | 23 | .and_hms_opt(10, 30, 15) |
| 24 | .unwrap(); | 24 | .unwrap(); |
| 25 | 25 | ||
| 26 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 26 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 27 | info!("Got RTC! {:?}", now.and_utc().timestamp()); | 27 | info!("Got RTC! {:?}", now.and_utc().timestamp()); |
| 28 | 28 | ||
| 29 | rtc.set_datetime(now.into()).expect("datetime not set"); | 29 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| @@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) { | |||
| 31 | // In reality the delay would be much longer | 31 | // In reality the delay would be much longer |
| 32 | Timer::after_millis(20000).await; | 32 | Timer::after_millis(20000).await; |
| 33 | 33 | ||
| 34 | let then: NaiveDateTime = rtc.now().unwrap().into(); | 34 | let then: NaiveDateTime = time_provider.now().unwrap().into(); |
| 35 | info!("Got RTC! {:?}", then.and_utc().timestamp()); | 35 | info!("Got RTC! {:?}", then.and_utc().timestamp()); |
| 36 | } | 36 | } |
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs index 8c280fdae..3253304eb 100644 --- a/examples/stm32h7rs/src/bin/spi.rs +++ b/examples/stm32h7rs/src/bin/spi.rs | |||
| @@ -15,7 +15,7 @@ use static_cell::StaticCell; | |||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); | 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); |
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs index 3fa69fd15..ca644c6a8 100644 --- a/examples/stm32h7rs/src/bin/spi_dma.rs +++ b/examples/stm32h7rs/src/bin/spi_dma.rs | |||
| @@ -15,7 +15,7 @@ use static_cell::StaticCell; | |||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | let mut read = [0; 128]; | 21 | let mut read = [0; 128]; |
diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs index 23abc3e2f..3e295dd51 100644 --- a/examples/stm32h7rs/src/bin/usb_serial.rs +++ b/examples/stm32h7rs/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::time::Hertz; | 7 | use embassy_stm32::time::Hertz; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs index 4c1b450b4..d91ae9de0 100644 --- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs +++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs | |||
| @@ -8,6 +8,7 @@ use core::cmp::min; | |||
| 8 | 8 | ||
| 9 | use defmt::info; | 9 | use defmt::info; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::Config; | ||
| 11 | use embassy_stm32::gpio::{Level, Output, Speed}; | 12 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 12 | use embassy_stm32::mode::Blocking; | 13 | use embassy_stm32::mode::Blocking; |
| 13 | use embassy_stm32::time::Hertz; | 14 | use embassy_stm32::time::Hertz; |
| @@ -15,7 +16,6 @@ use embassy_stm32::xspi::{ | |||
| 15 | AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, Instance, MemorySize, MemoryType, TransferConfig, | 16 | AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, Instance, MemorySize, MemoryType, TransferConfig, |
| 16 | WrapSize, Xspi, XspiWidth, | 17 | WrapSize, Xspi, XspiWidth, |
| 17 | }; | 18 | }; |
| 18 | use embassy_stm32::Config; | ||
| 19 | use embassy_time::Timer; | 19 | use embassy_time::Timer; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 21 | ||
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index d42cdac15..a9c71d655 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32l0-examples" | 3 | name = "embassy-stm32l0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs index 9dd09bc45..83be74ed9 100644 --- a/examples/stm32l0/src/bin/adc.rs +++ b/examples/stm32l0/src/bin/adc.rs | |||
| @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1, Irqs); | 21 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 22 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 23 | let mut pin = p.PA1; | 22 | let mut pin = p.PA1; |
| 24 | 23 | ||
| 25 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 26 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES79_5).await; |
| 27 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 28 | // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf |
| 29 | // 6.3.3 Embedded internal reference voltage | 28 | // 6.3.3 Embedded internal reference voltage |
| @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | loop { | 34 | loop { |
| 36 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES79_5).await; |
| 37 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 38 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 39 | } | 38 | } |
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs index 4945da7ce..a118c7a5a 100644 --- a/examples/stm32l0/src/bin/button_exti.rs +++ b/examples/stm32l0/src/bin/button_exti.rs | |||
| @@ -3,17 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::Config; | 8 | use embassy_stm32::{Config, bind_interrupts, interrupt}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI2_3 => exti::InterruptHandler<interrupt::typelevel::EXTI2_3>; | ||
| 14 | }); | ||
| 15 | |||
| 11 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 13 | let config = Config::default(); | 18 | let config = Config::default(); |
| 14 | let p = embassy_stm32::init(config); | 19 | let p = embassy_stm32::init(config); |
| 15 | 20 | ||
| 16 | let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs); |
| 17 | 22 | ||
| 18 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 19 | 24 | ||
diff --git a/examples/stm32l0/src/bin/dds.rs b/examples/stm32l0/src/bin/dds.rs index eaa7a61a8..d8f9020d4 100644 --- a/examples/stm32l0/src/bin/dds.rs +++ b/examples/stm32l0/src/bin/dds.rs | |||
| @@ -12,7 +12,7 @@ use embassy_stm32::time::hz; | |||
| 12 | use embassy_stm32::timer::low_level::{Timer as LLTimer, *}; | 12 | use embassy_stm32::timer::low_level::{Timer as LLTimer, *}; |
| 13 | use embassy_stm32::timer::simple_pwm::PwmPin; | 13 | use embassy_stm32::timer::simple_pwm::PwmPin; |
| 14 | use embassy_stm32::timer::{Ch3, Channel}; | 14 | use embassy_stm32::timer::{Ch3, Channel}; |
| 15 | use embassy_stm32::{interrupt, pac, Config}; | 15 | use embassy_stm32::{Config, interrupt, pac}; |
| 16 | use panic_probe as _; | 16 | use panic_probe as _; |
| 17 | 17 | ||
| 18 | const DDS_SINE_DATA: [u8; 256] = [ | 18 | const DDS_SINE_DATA: [u8; 256] = [ |
diff --git a/examples/stm32l0/src/bin/eeprom.rs b/examples/stm32l0/src/bin/eeprom.rs index 370246644..a33088f36 100644 --- a/examples/stm32l0/src/bin/eeprom.rs +++ b/examples/stm32l0/src/bin/eeprom.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::{info, unwrap}; | 4 | use defmt::{info, unwrap}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; | 6 | use embassy_stm32::flash::{EEPROM_BASE, EEPROM_SIZE, Flash}; |
| 7 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 8 | ||
| 9 | #[embassy_executor::main] | 9 | #[embassy_executor::main] |
diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs index 6385e3c8f..8e8fe0240 100644 --- a/examples/stm32l0/src/bin/raw_spawn.rs +++ b/examples/stm32l0/src/bin/raw_spawn.rs | |||
| @@ -5,8 +5,8 @@ use core::mem; | |||
| 5 | 5 | ||
| 6 | use cortex_m_rt::entry; | 6 | use cortex_m_rt::entry; |
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::raw::TaskStorage; | ||
| 9 | use embassy_executor::Executor; | 8 | use embassy_executor::Executor; |
| 9 | use embassy_executor::raw::TaskStorage; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use static_cell::StaticCell; | 11 | use static_cell::StaticCell; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -48,5 +48,5 @@ fn main() -> ! { | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | unsafe fn make_static<T>(t: &T) -> &'static T { | 50 | unsafe fn make_static<T>(t: &T) -> &'static T { |
| 51 | mem::transmute(t) | 51 | unsafe { mem::transmute(t) } |
| 52 | } | 52 | } |
diff --git a/examples/stm32l0/src/bin/usb_serial.rs b/examples/stm32l0/src/bin/usb_serial.rs index fdb1aeb59..612082f29 100644 --- a/examples/stm32l0/src/bin/usb_serial.rs +++ b/examples/stm32l0/src/bin/usb_serial.rs | |||
| @@ -6,9 +6,9 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::{self, Driver, Instance}; | 7 | use embassy_stm32::usb::{self, Driver, Instance}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals}; | 8 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 9 | use embassy_usb::Builder; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 76ceade9c..7f6b31ed5 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32l1-examples" | 3 | name = "embassy-stm32l1-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32l1/src/bin/eeprom.rs b/examples/stm32l1/src/bin/eeprom.rs index 370246644..a33088f36 100644 --- a/examples/stm32l1/src/bin/eeprom.rs +++ b/examples/stm32l1/src/bin/eeprom.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::{info, unwrap}; | 4 | use defmt::{info, unwrap}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; | 6 | use embassy_stm32::flash::{EEPROM_BASE, EEPROM_SIZE, Flash}; |
| 7 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 8 | ||
| 9 | #[embassy_executor::main] | 9 | #[embassy_executor::main] |
diff --git a/examples/stm32l1/src/bin/usb_serial.rs b/examples/stm32l1/src/bin/usb_serial.rs index a35f1d7a7..c54d37f9d 100644 --- a/examples/stm32l1/src/bin/usb_serial.rs +++ b/examples/stm32l1/src/bin/usb_serial.rs | |||
| @@ -6,9 +6,9 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::{self, Driver, Instance}; | 7 | use embassy_stm32::usb::{self, Driver, Instance}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals}; | 8 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 9 | use embassy_usb::Builder; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 1b7f15b1d..936472199 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32l4-examples" | 3 | name = "embassy-stm32l4-examples" |
| 4 | version = "0.1.1" | 4 | version = "0.1.1" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index c557ac6d7..42766a5e3 100644 --- a/examples/stm32l4/src/bin/adc.rs +++ b/examples/stm32l4/src/bin/adc.rs | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc::{Adc, Resolution}; | ||
| 6 | use embassy_stm32::Config; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 8 | ||
| 9 | #[cortex_m_rt::entry] | 9 | #[cortex_m_rt::entry] |
| @@ -17,13 +17,16 @@ fn main() -> ! { | |||
| 17 | } | 17 | } |
| 18 | let p = embassy_stm32::init(config); | 18 | let p = embassy_stm32::init(config); |
| 19 | 19 | ||
| 20 | let mut adc = Adc::new(p.ADC1); | 20 | let mut config = AdcConfig::default(); |
| 21 | config.resolution = Some(Resolution::BITS8); | ||
| 22 | |||
| 23 | let mut adc = Adc::new_with_config(p.ADC1, config); | ||
| 21 | //adc.enable_vref(); | 24 | //adc.enable_vref(); |
| 22 | adc.set_resolution(Resolution::BITS8); | 25 | |
| 23 | let mut channel = p.PC0; | 26 | let mut channel = p.PC0; |
| 24 | 27 | ||
| 25 | loop { | 28 | loop { |
| 26 | let v = adc.blocking_read(&mut channel); | 29 | let v = adc.blocking_read(&mut channel, SampleTime::from_bits(0)); |
| 27 | info!("--> {}", v); | 30 | info!("--> {}", v); |
| 28 | } | 31 | } |
| 29 | } | 32 | } |
diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs new file mode 100644 index 000000000..550da95a4 --- /dev/null +++ b/examples/stm32l4/src/bin/adc_dma.rs | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, SampleTime}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | ||
| 9 | |||
| 10 | const DMA_BUF_LEN: usize = 512; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | info!("Hello World!"); | ||
| 15 | |||
| 16 | let mut config = Config::default(); | ||
| 17 | { | ||
| 18 | use embassy_stm32::rcc::*; | ||
| 19 | config.rcc.mux.adcsel = mux::Adcsel::SYS; | ||
| 20 | } | ||
| 21 | let p = embassy_stm32::init(config); | ||
| 22 | |||
| 23 | let adc = Adc::new(p.ADC1); | ||
| 24 | let adc_pin0 = p.PA0.degrade_adc(); | ||
| 25 | let adc_pin1 = p.PA1.degrade_adc(); | ||
| 26 | let mut adc_dma_buf = [0u16; DMA_BUF_LEN]; | ||
| 27 | let mut measurements = [0u16; DMA_BUF_LEN / 2]; | ||
| 28 | let mut ring_buffered_adc = adc.into_ring_buffered( | ||
| 29 | p.DMA1_CH1, | ||
| 30 | &mut adc_dma_buf, | ||
| 31 | [(adc_pin0, SampleTime::CYCLES640_5), (adc_pin1, SampleTime::CYCLES640_5)].into_iter(), | ||
| 32 | RegularConversionMode::Continuous, | ||
| 33 | ); | ||
| 34 | |||
| 35 | info!("starting measurement loop"); | ||
| 36 | loop { | ||
| 37 | match ring_buffered_adc.read(&mut measurements).await { | ||
| 38 | Ok(_) => { | ||
| 39 | //note: originally there was a print here showing all the samples, | ||
| 40 | //but even that takes too much time and would cause adc overruns | ||
| 41 | info!("adc1 first 10 samples: {}", measurements[0..10]); | ||
| 42 | } | ||
| 43 | Err(e) => { | ||
| 44 | warn!("Error: {:?}", e); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
diff --git a/examples/stm32l4/src/bin/button_exti.rs b/examples/stm32l4/src/bin/button_exti.rs index 34a08bbc6..c84b11dab 100644 --- a/examples/stm32l4/src/bin/button_exti.rs +++ b/examples/stm32l4/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32l4/src/bin/can.rs b/examples/stm32l4/src/bin/can.rs index 3c4cdac24..bd361417e 100644 --- a/examples/stm32l4/src/bin/can.rs +++ b/examples/stm32l4/src/bin/can.rs | |||
| @@ -8,7 +8,7 @@ use embassy_stm32::can::{ | |||
| 8 | Can, Fifo, Frame, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, | 8 | Can, Fifo, Frame, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, |
| 9 | }; | 9 | }; |
| 10 | use embassy_stm32::peripherals::CAN1; | 10 | use embassy_stm32::peripherals::CAN1; |
| 11 | use embassy_stm32::{bind_interrupts, Config}; | 11 | use embassy_stm32::{Config, bind_interrupts}; |
| 12 | use embassy_time::Timer; | 12 | use embassy_time::Timer; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index 44edec728..bfdf858c5 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Peri; | ||
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 7 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::mode::Async; | 8 | use embassy_stm32::mode::Async; |
| 8 | use embassy_stm32::pac::timer::vals::Mms; | 9 | use embassy_stm32::pac::timer::vals::Mms; |
| @@ -10,7 +11,6 @@ use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; | |||
| 10 | use embassy_stm32::rcc::frequency; | 11 | use embassy_stm32::rcc::frequency; |
| 11 | use embassy_stm32::time::Hertz; | 12 | use embassy_stm32::time::Hertz; |
| 12 | use embassy_stm32::timer::low_level::Timer; | 13 | use embassy_stm32::timer::low_level::Timer; |
| 13 | use embassy_stm32::Peri; | ||
| 14 | use micromath::F32Ext; | 14 | use micromath::F32Ext; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
diff --git a/examples/stm32l4/src/bin/mco.rs b/examples/stm32l4/src/bin/mco.rs index 36c002952..4cdeaa440 100644 --- a/examples/stm32l4/src/bin/mco.rs +++ b/examples/stm32l4/src/bin/mco.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 7 | use embassy_stm32::rcc::{Mco, McoPrescaler, McoSource}; | 7 | use embassy_stm32::rcc::{Mco, McoConfig, McoPrescaler, McoSource}; |
| 8 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -13,7 +13,13 @@ async fn main(_spawner: Spawner) { | |||
| 13 | let p = embassy_stm32::init(Default::default()); | 13 | let p = embassy_stm32::init(Default::default()); |
| 14 | info!("Hello World!"); | 14 | info!("Hello World!"); |
| 15 | 15 | ||
| 16 | let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI, McoPrescaler::DIV1); | 16 | let config = { |
| 17 | let mut config = McoConfig::default(); | ||
| 18 | config.prescaler = McoPrescaler::DIV1; | ||
| 19 | config | ||
| 20 | }; | ||
| 21 | |||
| 22 | let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI, config); | ||
| 17 | 23 | ||
| 18 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); | 24 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); |
| 19 | 25 | ||
diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs index 14d0e3c1e..4d9f83ad8 100644 --- a/examples/stm32l4/src/bin/rng.rs +++ b/examples/stm32l4/src/bin/rng.rs | |||
| @@ -5,7 +5,7 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk}; | 6 | use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk}; |
| 7 | use embassy_stm32::rng::Rng; | 7 | use embassy_stm32::rng::Rng; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | 11 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index f554f0f78..8b92075cc 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 8 | use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 8 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| @@ -39,7 +39,7 @@ async fn main(_spawner: Spawner) { | |||
| 39 | .and_hms_opt(10, 30, 15) | 39 | .and_hms_opt(10, 30, 15) |
| 40 | .unwrap(); | 40 | .unwrap(); |
| 41 | 41 | ||
| 42 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 42 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 43 | info!("Got RTC! {:?}", now.and_utc().timestamp()); | 43 | info!("Got RTC! {:?}", now.and_utc().timestamp()); |
| 44 | 44 | ||
| 45 | rtc.set_datetime(now.into()).expect("datetime not set"); | 45 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| @@ -47,6 +47,6 @@ async fn main(_spawner: Spawner) { | |||
| 47 | // In reality the delay would be much longer | 47 | // In reality the delay would be much longer |
| 48 | Timer::after_millis(20000).await; | 48 | Timer::after_millis(20000).await; |
| 49 | 49 | ||
| 50 | let then: NaiveDateTime = rtc.now().unwrap().into(); | 50 | let then: NaiveDateTime = time_provider.now().unwrap().into(); |
| 51 | info!("Got RTC! {:?}", then.and_utc().timestamp()); | 51 | info!("Got RTC! {:?}", then.and_utc().timestamp()); |
| 52 | } | 52 | } |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 24efe526f..8f2510cdc 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -16,21 +16,23 @@ | |||
| 16 | use core::marker::PhantomData; | 16 | use core::marker::PhantomData; |
| 17 | use core::sync::atomic::{AtomicI32, Ordering}; | 17 | use core::sync::atomic::{AtomicI32, Ordering}; |
| 18 | 18 | ||
| 19 | use defmt::{error, info, println, unwrap, Format}; | 19 | use defmt::{Format, error, info, println, unwrap}; |
| 20 | use defmt_rtt as _; // global logger | 20 | use defmt_rtt as _; // global logger |
| 21 | use embassy_executor::Spawner; | 21 | use embassy_executor::Spawner; |
| 22 | use embassy_futures::select::{select, Either}; | 22 | use embassy_futures::select::{Either, select}; |
| 23 | use embassy_futures::yield_now; | 23 | use embassy_futures::yield_now; |
| 24 | use embassy_net::tcp::TcpSocket; | 24 | use embassy_net::tcp::TcpSocket; |
| 25 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4}; | 25 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4}; |
| 26 | use embassy_net_adin1110::{Device, Runner, ADIN1110}; | 26 | use embassy_net_adin1110::{ADIN1110, Device, Runner}; |
| 27 | use embassy_stm32::exti::ExtiInput; | ||
| 27 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | 28 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; |
| 28 | use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; | 29 | use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; |
| 29 | use embassy_stm32::mode::Async; | 30 | use embassy_stm32::mode::Async; |
| 30 | use embassy_stm32::rng::{self, Rng}; | 31 | use embassy_stm32::rng::{self, Rng}; |
| 32 | use embassy_stm32::spi::mode::Master; | ||
| 31 | use embassy_stm32::spi::{Config as SPI_Config, Spi}; | 33 | use embassy_stm32::spi::{Config as SPI_Config, Spi}; |
| 32 | use embassy_stm32::time::Hertz; | 34 | use embassy_stm32::time::Hertz; |
| 33 | use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; | 35 | use embassy_stm32::{bind_interrupts, exti, interrupt, pac, peripherals}; |
| 34 | use embassy_time::{Delay, Duration, Ticker, Timer}; | 36 | use embassy_time::{Delay, Duration, Ticker, Timer}; |
| 35 | use embedded_hal_async::i2c::I2c as I2cBus; | 37 | use embedded_hal_async::i2c::I2c as I2cBus; |
| 36 | use embedded_hal_bus::spi::ExclusiveDevice; | 38 | use embedded_hal_bus::spi::ExclusiveDevice; |
| @@ -44,6 +46,7 @@ bind_interrupts!(struct Irqs { | |||
| 44 | I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>; | 46 | I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>; |
| 45 | I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>; | 47 | I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>; |
| 46 | RNG => rng::InterruptHandler<peripherals::RNG>; | 48 | RNG => rng::InterruptHandler<peripherals::RNG>; |
| 49 | EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>; | ||
| 47 | }); | 50 | }); |
| 48 | 51 | ||
| 49 | // Basic settings | 52 | // Basic settings |
| @@ -54,7 +57,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 5), 24) | |||
| 54 | // Listen port for the webserver | 57 | // Listen port for the webserver |
| 55 | const HTTP_LISTEN_PORT: u16 = 80; | 58 | const HTTP_LISTEN_PORT: u16 = 80; |
| 56 | 59 | ||
| 57 | pub type SpeSpi = Spi<'static, Async>; | 60 | pub type SpeSpi = Spi<'static, Async, Master>; |
| 58 | pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; | 61 | pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; |
| 59 | pub type SpeInt = exti::ExtiInput<'static>; | 62 | pub type SpeInt = exti::ExtiInput<'static>; |
| 60 | pub type SpeRst = Output<'static>; | 63 | pub type SpeRst = Output<'static>; |
| @@ -124,7 +127,7 @@ async fn main(spawner: Spawner) { | |||
| 124 | let spe_cfg1 = Input::new(dp.PC9, Pull::None); | 127 | let spe_cfg1 = Input::new(dp.PC9, Pull::None); |
| 125 | let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low); | 128 | let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low); |
| 126 | 129 | ||
| 127 | let spe_int = exti::ExtiInput::new(dp.PB11, dp.EXTI11, Pull::None); | 130 | let spe_int = ExtiInput::new(dp.PB11, dp.EXTI11, Pull::None, Irqs); |
| 128 | 131 | ||
| 129 | let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High); | 132 | let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High); |
| 130 | let spe_spi_sclk = dp.PB13; | 133 | let spe_spi_sclk = dp.PB13; |
| @@ -159,7 +162,9 @@ async fn main(spawner: Spawner) { | |||
| 159 | 162 | ||
| 160 | // Check the SPI mode selected with the "HW CFG" dip-switch | 163 | // Check the SPI mode selected with the "HW CFG" dip-switch |
| 161 | if !cfg1_spi_mode { | 164 | if !cfg1_spi_mode { |
| 162 | error!("Driver doesn´t support SPI Protolcol \"OPEN Alliance\".\nplease use the \"Generic SPI\"! Turn On \"HW CFG\": \"SPI_CFG1\""); | 165 | error!( |
| 166 | "Driver doesn´t support SPI Protolcol \"OPEN Alliance\".\nplease use the \"Generic SPI\"! Turn On \"HW CFG\": \"SPI_CFG1\"" | ||
| 167 | ); | ||
| 163 | loop { | 168 | loop { |
| 164 | led_uc2_red.toggle(); | 169 | led_uc2_red.toggle(); |
| 165 | Timer::after(Duration::from_hz(10)).await; | 170 | Timer::after(Duration::from_hz(10)).await; |
diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs index 946a759b1..970a0c608 100644 --- a/examples/stm32l4/src/bin/spi_dma.rs +++ b/examples/stm32l4/src/bin/spi_dma.rs | |||
| @@ -34,8 +34,8 @@ async fn main(_spawner: Spawner) { | |||
| 34 | info!("waiting for ready"); | 34 | info!("waiting for ready"); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | let write = [0x0A; 10]; | 37 | let write = [0x0Au8; 10]; |
| 38 | let mut read = [0; 10]; | 38 | let mut read = [0u8; 10]; |
| 39 | cs.set_low(); | 39 | cs.set_low(); |
| 40 | spi.transfer(&mut read, &write).await.ok(); | 40 | spi.transfer(&mut read, &write).await.ok(); |
| 41 | cs.set_high(); | 41 | cs.set_high(); |
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs index af90e297e..17cd107f6 100644 --- a/examples/stm32l4/src/bin/usb_serial.rs +++ b/examples/stm32l4/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use panic_probe as _; | 13 | use panic_probe as _; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index f173c651e..14f41992d 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32l432-examples" | 3 | name = "embassy-stm32l432-examples" |
| 4 | version = "0.1.1" | 4 | version = "0.1.1" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 9999300b8..586b00836 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32l5-examples" | 3 | name = "embassy-stm32l5-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -14,7 +14,7 @@ embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["de | |||
| 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } | 15 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } |
| 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } |
| 17 | usbd-hid = "0.8.1" | 17 | usbd-hid = "0.9.0" |
| 18 | 18 | ||
| 19 | defmt = "1.0.1" | 19 | defmt = "1.0.1" |
| 20 | defmt-rtt = "1.0.0" | 20 | defmt-rtt = "1.0.0" |
diff --git a/examples/stm32l5/src/bin/button_exti.rs b/examples/stm32l5/src/bin/button_exti.rs index e6639d22b..225a7b3fd 100644 --- a/examples/stm32l5/src/bin/button_exti.rs +++ b/examples/stm32l5/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs index 0a644e73d..d6302e106 100644 --- a/examples/stm32l5/src/bin/rng.rs +++ b/examples/stm32l5/src/bin/rng.rs | |||
| @@ -5,7 +5,7 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllRDiv, PllSource, Sysclk}; | 6 | use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllRDiv, PllSource, Sysclk}; |
| 7 | use embassy_stm32::rng::Rng; | 7 | use embassy_stm32::rng::Rng; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | 11 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs index c34053190..fde804fb7 100644 --- a/examples/stm32l5/src/bin/stop.rs +++ b/examples/stm32l5/src/bin/stop.rs | |||
| @@ -4,22 +4,12 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; | 6 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; |
| 7 | use embassy_stm32::low_power::Executor; | ||
| 8 | use embassy_stm32::rcc::LsConfig; | 7 | use embassy_stm32::rcc::LsConfig; |
| 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 8 | use embassy_stm32::{Config, Peri, low_power}; |
| 10 | use embassy_stm32::{Config, Peri}; | ||
| 11 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 12 | use static_cell::StaticCell; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 11 | ||
| 15 | #[cortex_m_rt::entry] | 12 | #[embassy_executor::main(executor = "low_power::Executor")] |
| 16 | fn main() -> ! { | ||
| 17 | Executor::take().run(|spawner| { | ||
| 18 | spawner.spawn(unwrap!(async_main(spawner))); | ||
| 19 | }) | ||
| 20 | } | ||
| 21 | |||
| 22 | #[embassy_executor::task] | ||
| 23 | async fn async_main(spawner: Spawner) { | 13 | async fn async_main(spawner: Spawner) { |
| 24 | let mut config = Config::default(); | 14 | let mut config = Config::default(); |
| 25 | config.rcc.ls = LsConfig::default_lsi(); | 15 | config.rcc.ls = LsConfig::default_lsi(); |
| @@ -28,12 +18,6 @@ async fn async_main(spawner: Spawner) { | |||
| 28 | // config.enable_debug_during_sleep = false; | 18 | // config.enable_debug_during_sleep = false; |
| 29 | let p = embassy_stm32::init(config); | 19 | let p = embassy_stm32::init(config); |
| 30 | 20 | ||
| 31 | // give the RTC to the executor... | ||
| 32 | let rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 33 | static RTC: StaticCell<Rtc> = StaticCell::new(); | ||
| 34 | let rtc = RTC.init(rtc); | ||
| 35 | embassy_stm32::low_power::stop_with_rtc(rtc); | ||
| 36 | |||
| 37 | spawner.spawn(unwrap!(blinky(p.PC7.into()))); | 21 | spawner.spawn(unwrap!(blinky(p.PC7.into()))); |
| 38 | spawner.spawn(unwrap!(timeout())); | 22 | spawner.spawn(unwrap!(timeout())); |
| 39 | } | 23 | } |
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 25aa9ef69..d2cbeb550 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::StackResources; | 6 | use embassy_net::StackResources; |
| 7 | use embassy_net::tcp::TcpSocket; | ||
| 8 | use embassy_stm32::rng::Rng; | 8 | use embassy_stm32::rng::Rng; |
| 9 | use embassy_stm32::usb::Driver; | 9 | use embassy_stm32::usb::Driver; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng, usb}; |
| 11 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; | 11 | use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; |
| 12 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 12 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 13 | use embassy_usb::{Builder, UsbDevice}; | 13 | use embassy_usb::{Builder, UsbDevice}; |
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index 3f8c52b82..d8f2de941 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs | |||
| @@ -1,15 +1,19 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::Driver; | 9 | use embassy_stm32::usb::Driver; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 10 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 9 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 10 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | ||
| 11 | use embassy_usb::control::OutResponse; | ||
| 12 | use embassy_usb::Builder; | 12 | use embassy_usb::Builder; |
| 13 | use embassy_usb::class::hid::{ | ||
| 14 | HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State, | ||
| 15 | }; | ||
| 16 | use embassy_usb::control::OutResponse; | ||
| 13 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 17 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 19 | ||
| @@ -17,6 +21,8 @@ bind_interrupts!(struct Irqs { | |||
| 17 | USB_FS => usb::InterruptHandler<peripherals::USB>; | 21 | USB_FS => usb::InterruptHandler<peripherals::USB>; |
| 18 | }); | 22 | }); |
| 19 | 23 | ||
| 24 | static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); | ||
| 25 | |||
| 20 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 21 | async fn main(_spawner: Spawner) { | 27 | async fn main(_spawner: Spawner) { |
| 22 | let mut config = Config::default(); | 28 | let mut config = Config::default(); |
| @@ -48,6 +54,10 @@ async fn main(_spawner: Spawner) { | |||
| 48 | config.serial_number = Some("12345678"); | 54 | config.serial_number = Some("12345678"); |
| 49 | config.max_power = 100; | 55 | config.max_power = 100; |
| 50 | config.max_packet_size_0 = 64; | 56 | config.max_packet_size_0 = 64; |
| 57 | config.composite_with_iads = false; | ||
| 58 | config.device_class = 0; | ||
| 59 | config.device_sub_class = 0; | ||
| 60 | config.device_protocol = 0; | ||
| 51 | 61 | ||
| 52 | // Create embassy-usb DeviceBuilder using the driver and config. | 62 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 53 | // It needs some buffers for building the descriptors. | 63 | // It needs some buffers for building the descriptors. |
| @@ -73,6 +83,8 @@ async fn main(_spawner: Spawner) { | |||
| 73 | request_handler: Some(&mut request_handler), | 83 | request_handler: Some(&mut request_handler), |
| 74 | poll_ms: 60, | 84 | poll_ms: 60, |
| 75 | max_packet_size: 8, | 85 | max_packet_size: 8, |
| 86 | hid_subclass: HidSubclass::Boot, | ||
| 87 | hid_boot_protocol: HidBootProtocol::Mouse, | ||
| 76 | }; | 88 | }; |
| 77 | 89 | ||
| 78 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); | 90 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| @@ -90,16 +102,26 @@ async fn main(_spawner: Spawner) { | |||
| 90 | Timer::after_millis(500).await; | 102 | Timer::after_millis(500).await; |
| 91 | 103 | ||
| 92 | y = -y; | 104 | y = -y; |
| 93 | let report = MouseReport { | 105 | |
| 94 | buttons: 0, | 106 | if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 { |
| 95 | x: 0, | 107 | let buttons = 0u8; |
| 96 | y, | 108 | let x = 0i8; |
| 97 | wheel: 0, | 109 | match writer.write(&[buttons, x as u8, y as u8]).await { |
| 98 | pan: 0, | 110 | Ok(()) => {} |
| 99 | }; | 111 | Err(e) => warn!("Failed to send boot report: {:?}", e), |
| 100 | match writer.write_serialize(&report).await { | 112 | } |
| 101 | Ok(()) => {} | 113 | } else { |
| 102 | Err(e) => warn!("Failed to send report: {:?}", e), | 114 | let report = MouseReport { |
| 115 | buttons: 0, | ||
| 116 | x: 0, | ||
| 117 | y, | ||
| 118 | wheel: 0, | ||
| 119 | pan: 0, | ||
| 120 | }; | ||
| 121 | match writer.write_serialize(&report).await { | ||
| 122 | Ok(()) => {} | ||
| 123 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 124 | } | ||
| 103 | } | 125 | } |
| 104 | } | 126 | } |
| 105 | }; | 127 | }; |
| @@ -122,6 +144,18 @@ impl RequestHandler for MyRequestHandler { | |||
| 122 | OutResponse::Accepted | 144 | OutResponse::Accepted |
| 123 | } | 145 | } |
| 124 | 146 | ||
| 147 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 148 | let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed)); | ||
| 149 | info!("The current HID protocol mode is: {}", protocol); | ||
| 150 | protocol | ||
| 151 | } | ||
| 152 | |||
| 153 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 154 | info!("Switching to HID protocol mode: {}", protocol); | ||
| 155 | HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed); | ||
| 156 | OutResponse::Accepted | ||
| 157 | } | ||
| 158 | |||
| 125 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { | 159 | fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { |
| 126 | info!("Set idle rate for {:?} to {:?}", id, dur); | 160 | info!("Set idle rate for {:?} to {:?}", id, dur); |
| 127 | } | 161 | } |
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs index a64bda31b..4f77fc1d7 100644 --- a/examples/stm32l5/src/bin/usb_serial.rs +++ b/examples/stm32l5/src/bin/usb_serial.rs | |||
| @@ -5,10 +5,10 @@ use defmt::{panic, *}; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::{Driver, Instance}; | 7 | use embassy_stm32::usb::{Driver, Instance}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 9 | use embassy_usb::Builder; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32n6/.cargo/config.toml b/examples/stm32n6/.cargo/config.toml new file mode 100644 index 000000000..2fdd70649 --- /dev/null +++ b/examples/stm32n6/.cargo/config.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [target.thumbv8m.main-none-eabihf] | ||
| 2 | runner = 'probe-rs run --chip STM32N657' | ||
| 3 | |||
| 4 | [build] | ||
| 5 | target = "thumbv8m.main-none-eabihf" | ||
| 6 | |||
| 7 | [env] | ||
| 8 | DEFMT_LOG = "trace" | ||
diff --git a/examples/stm32n6/Cargo.toml b/examples/stm32n6/Cargo.toml new file mode 100644 index 000000000..5ad5b97ce --- /dev/null +++ b/examples/stm32n6/Cargo.toml | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2021" | ||
| 3 | name = "embassy-stm32n6-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | # Change stm32h563zi to your chip name, if necessary. | ||
| 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32n657x0", "time-driver-any", "exti", "unstable-pac"] } | ||
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | ||
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||
| 14 | embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } | ||
| 15 | embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } | ||
| 16 | embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } | ||
| 17 | |||
| 18 | defmt = "1.0.1" | ||
| 19 | defmt-rtt = "1.0.0" | ||
| 20 | |||
| 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 22 | cortex-m-rt = "0.7.0" | ||
| 23 | embedded-hal = "0.2.6" | ||
| 24 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | ||
| 25 | embedded-hal-async = { version = "1.0" } | ||
| 26 | embedded-io-async = { version = "0.6.1" } | ||
| 27 | embedded-nal-async = "0.8.0" | ||
| 28 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 29 | heapless = { version = "0.8", default-features = false } | ||
| 30 | critical-section = "1.1" | ||
| 31 | micromath = "2.0.0" | ||
| 32 | stm32-fmc = "0.3.0" | ||
| 33 | embedded-storage = "0.3.1" | ||
| 34 | static_cell = "2" | ||
| 35 | hmac = "0.12.1" | ||
| 36 | sha2 = { version = "0.10.9", default-features = false } | ||
| 37 | |||
| 38 | |||
| 39 | # cargo build/run | ||
| 40 | [profile.dev] | ||
| 41 | codegen-units = 1 | ||
| 42 | debug = 2 | ||
| 43 | debug-assertions = true # <- | ||
| 44 | incremental = false | ||
| 45 | opt-level = 3 # <- | ||
| 46 | overflow-checks = true # <- | ||
| 47 | |||
| 48 | # cargo test | ||
| 49 | [profile.test] | ||
| 50 | codegen-units = 1 | ||
| 51 | debug = 2 | ||
| 52 | debug-assertions = true # <- | ||
| 53 | incremental = false | ||
| 54 | opt-level = 3 # <- | ||
| 55 | overflow-checks = true # <- | ||
| 56 | |||
| 57 | # cargo build/run --release | ||
| 58 | [profile.release] | ||
| 59 | codegen-units = 1 | ||
| 60 | debug = 2 | ||
| 61 | debug-assertions = false # <- | ||
| 62 | incremental = false | ||
| 63 | lto = 'fat' | ||
| 64 | opt-level = 3 # <- | ||
| 65 | overflow-checks = false # <- | ||
| 66 | |||
| 67 | # cargo test --release | ||
| 68 | [profile.bench] | ||
| 69 | codegen-units = 1 | ||
| 70 | debug = 2 | ||
| 71 | debug-assertions = false # <- | ||
| 72 | incremental = false | ||
| 73 | lto = 'fat' | ||
| 74 | opt-level = 3 # <- | ||
| 75 | overflow-checks = false # <- | ||
| 76 | |||
| 77 | [package.metadata.embassy] | ||
| 78 | build = [ | ||
| 79 | { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32n6" } | ||
| 80 | ] | ||
diff --git a/examples/stm32n6/build.rs b/examples/stm32n6/build.rs new file mode 100644 index 000000000..8cd32d7ed --- /dev/null +++ b/examples/stm32n6/build.rs | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | fn main() { | ||
| 2 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 3 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 4 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 5 | } | ||
diff --git a/examples/stm32n6/memory.x b/examples/stm32n6/memory.x new file mode 100644 index 000000000..59f127adc --- /dev/null +++ b/examples/stm32n6/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x34180400, LENGTH = 255K | ||
| 4 | RAM : ORIGIN = 0x341C0000, LENGTH = 256K | ||
| 5 | } | ||
diff --git a/examples/stm32n6/src/bin/blinky.rs b/examples/stm32n6/src/bin/blinky.rs new file mode 100644 index 000000000..a8baf16af --- /dev/null +++ b/examples/stm32n6/src/bin/blinky.rs | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::exti::{self, ExtiInput}; | ||
| 7 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | ||
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | bind_interrupts!( | ||
| 13 | pub struct Irqs{ | ||
| 14 | EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>; | ||
| 15 | }); | ||
| 16 | |||
| 17 | #[embassy_executor::task] | ||
| 18 | async fn button_task(mut p: ExtiInput<'static>) { | ||
| 19 | loop { | ||
| 20 | p.wait_for_any_edge().await; | ||
| 21 | info!("button pressed!"); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | #[embassy_executor::main] | ||
| 26 | async fn main(spawner: Spawner) { | ||
| 27 | let p = embassy_stm32::init(Default::default()); | ||
| 28 | info!("Hello World!"); | ||
| 29 | |||
| 30 | let mut led = Output::new(p.PG10, Level::High, Speed::Low); | ||
| 31 | let button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); | ||
| 32 | |||
| 33 | spawner.spawn(button_task(button).unwrap()); | ||
| 34 | |||
| 35 | loop { | ||
| 36 | led.set_high(); | ||
| 37 | Timer::after_millis(500).await; | ||
| 38 | |||
| 39 | led.set_low(); | ||
| 40 | Timer::after_millis(500).await; | ||
| 41 | } | ||
| 42 | } | ||
diff --git a/examples/stm32n6/src/bin/crc.rs b/examples/stm32n6/src/bin/crc.rs new file mode 100644 index 000000000..d1b545d5b --- /dev/null +++ b/examples/stm32n6/src/bin/crc.rs | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::crc::{Config, Crc, InputReverseConfig, PolySize}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_stm32::init(Default::default()); | ||
| 12 | info!("Hello World!"); | ||
| 13 | |||
| 14 | // Setup for: https://crccalc.com/?crc=Life, it never dieWomen are my favorite guy&method=crc32&datatype=ascii&outtype=0 | ||
| 15 | let mut crc = Crc::new( | ||
| 16 | p.CRC, | ||
| 17 | unwrap!(Config::new( | ||
| 18 | InputReverseConfig::Byte, | ||
| 19 | true, | ||
| 20 | PolySize::Width32, | ||
| 21 | 0xFFFFFFFF, | ||
| 22 | 0x04C11DB7 | ||
| 23 | )), | ||
| 24 | ); | ||
| 25 | |||
| 26 | let output = crc.feed_bytes(b"Life, it never die\nWomen are my favorite guy") ^ 0xFFFFFFFF; | ||
| 27 | |||
| 28 | defmt::assert_eq!(output, 0x33F0E26B); | ||
| 29 | |||
| 30 | cortex_m::asm::bkpt(); | ||
| 31 | } | ||
diff --git a/examples/stm32n6/src/bin/hash.rs b/examples/stm32n6/src/bin/hash.rs new file mode 100644 index 000000000..9f248318f --- /dev/null +++ b/examples/stm32n6/src/bin/hash.rs | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::hash::*; | ||
| 7 | use embassy_stm32::{Config, bind_interrupts, hash, peripherals}; | ||
| 8 | use embassy_time::Instant; | ||
| 9 | use hmac::{Hmac, Mac}; | ||
| 10 | use sha2::{Digest, Sha256}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | type HmacSha256 = Hmac<Sha256>; | ||
| 14 | |||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | HASH => hash::InterruptHandler<peripherals::HASH>; | ||
| 17 | }); | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(_spawner: Spawner) -> ! { | ||
| 21 | let config = Config::default(); | ||
| 22 | let p = embassy_stm32::init(config); | ||
| 23 | |||
| 24 | let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; | ||
| 25 | let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; | ||
| 26 | |||
| 27 | let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs); | ||
| 28 | |||
| 29 | let hw_start_time = Instant::now(); | ||
| 30 | |||
| 31 | // Compute a digest in hardware. | ||
| 32 | let mut context = hw_hasher.start(Algorithm::SHA256, DataType::Width8, None); | ||
| 33 | hw_hasher.update_blocking(&mut context, test_1); | ||
| 34 | hw_hasher.update_blocking(&mut context, test_2); | ||
| 35 | let mut hw_digest: [u8; 32] = [0; 32]; | ||
| 36 | hw_hasher.finish_blocking(context, &mut hw_digest); | ||
| 37 | |||
| 38 | let hw_end_time = Instant::now(); | ||
| 39 | let hw_execution_time = hw_end_time - hw_start_time; | ||
| 40 | |||
| 41 | let sw_start_time = Instant::now(); | ||
| 42 | |||
| 43 | // Compute a digest in software. | ||
| 44 | let mut sw_hasher = Sha256::new(); | ||
| 45 | sw_hasher.update(test_1); | ||
| 46 | sw_hasher.update(test_2); | ||
| 47 | let sw_digest = sw_hasher.finalize(); | ||
| 48 | |||
| 49 | let sw_end_time = Instant::now(); | ||
| 50 | let sw_execution_time = sw_end_time - sw_start_time; | ||
| 51 | |||
| 52 | info!("Hardware Digest: {:?}", hw_digest); | ||
| 53 | info!("Software Digest: {:?}", sw_digest[..]); | ||
| 54 | info!("Hardware Execution Time: {:?}", hw_execution_time); | ||
| 55 | info!("Software Execution Time: {:?}", sw_execution_time); | ||
| 56 | assert_eq!(hw_digest, sw_digest[..]); | ||
| 57 | |||
| 58 | let hmac_key: [u8; 64] = [0x55; 64]; | ||
| 59 | |||
| 60 | // Compute HMAC in hardware. | ||
| 61 | let mut sha256hmac_context = hw_hasher.start(Algorithm::SHA256, DataType::Width8, Some(&hmac_key)); | ||
| 62 | hw_hasher.update_blocking(&mut sha256hmac_context, test_1); | ||
| 63 | hw_hasher.update_blocking(&mut sha256hmac_context, test_2); | ||
| 64 | let mut hw_hmac: [u8; 32] = [0; 32]; | ||
| 65 | hw_hasher.finish_blocking(sha256hmac_context, &mut hw_hmac); | ||
| 66 | |||
| 67 | // Compute HMAC in software. | ||
| 68 | let mut sw_mac = HmacSha256::new_from_slice(&hmac_key).unwrap(); | ||
| 69 | sw_mac.update(test_1); | ||
| 70 | sw_mac.update(test_2); | ||
| 71 | let sw_hmac = sw_mac.finalize().into_bytes(); | ||
| 72 | |||
| 73 | info!("Hardware HMAC: {:?}", hw_hmac); | ||
| 74 | info!("Software HMAC: {:?}", sw_hmac[..]); | ||
| 75 | assert_eq!(hw_hmac, sw_hmac[..]); | ||
| 76 | |||
| 77 | loop {} | ||
| 78 | } | ||
diff --git a/examples/stm32u0/.cargo/config.toml b/examples/stm32u0/.cargo/config.toml index 688347084..e9212cacb 100644 --- a/examples/stm32u0/.cargo/config.toml +++ b/examples/stm32u0/.cargo/config.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace stm32u083rctx with your chip as listed in `probe-rs chip list` | 2 | # replace stm32u083mctx with your chip as listed in `probe-rs chip list` |
| 3 | runner = "probe-rs run --chip stm32u083rctx" | 3 | runner = "probe-rs run --chip stm32u083mctx" |
| 4 | 4 | ||
| 5 | [build] | 5 | [build] |
| 6 | target = "thumbv6m-none-eabi" | 6 | target = "thumbv6m-none-eabi" |
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 9318414a5..8cc894cb3 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32u0-examples" | 3 | name = "embassy-stm32u0-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | # Change stm32u083rc to your chip name, if necessary. | 9 | # Change stm32u083mc to your chip name, if necessary. |
| 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083mc", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| @@ -19,9 +19,7 @@ defmt-rtt = "1.0.0" | |||
| 19 | 19 | ||
| 20 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 20 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 21 | cortex-m-rt = "0.7.0" |
| 22 | embedded-hal = "0.2.6" | ||
| 23 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | 22 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } |
| 24 | heapless = { version = "0.8", default-features = false } | ||
| 25 | 23 | ||
| 26 | micromath = "2.0.0" | 24 | micromath = "2.0.0" |
| 27 | chrono = { version = "0.4.38", default-features = false } | 25 | chrono = { version = "0.4.38", default-features = false } |
diff --git a/examples/stm32u0/src/bin/adc.rs b/examples/stm32u0/src/bin/adc.rs index c8252e4e1..53bd37303 100644 --- a/examples/stm32u0/src/bin/adc.rs +++ b/examples/stm32u0/src/bin/adc.rs | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc::{Adc, Resolution}; | ||
| 6 | use embassy_stm32::Config; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime}; | ||
| 7 | use embassy_time::Duration; | 7 | use embassy_time::Duration; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -18,12 +18,13 @@ fn main() -> ! { | |||
| 18 | } | 18 | } |
| 19 | let p = embassy_stm32::init(config); | 19 | let p = embassy_stm32::init(config); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1); | 21 | let mut config = AdcConfig::default(); |
| 22 | adc.set_resolution(Resolution::BITS8); | 22 | config.resolution = Some(Resolution::BITS8); |
| 23 | let mut adc = Adc::new_with_config(p.ADC1, config); | ||
| 23 | let mut channel = p.PC0; | 24 | let mut channel = p.PC0; |
| 24 | 25 | ||
| 25 | loop { | 26 | loop { |
| 26 | let v = adc.blocking_read(&mut channel); | 27 | let v = adc.blocking_read(&mut channel, SampleTime::CYCLES12_5); |
| 27 | info!("--> {}", v); | 28 | info!("--> {}", v); |
| 28 | embassy_time::block_for(Duration::from_millis(200)); | 29 | embassy_time::block_for(Duration::from_millis(200)); |
| 29 | } | 30 | } |
diff --git a/examples/stm32u0/src/bin/button_exti.rs b/examples/stm32u0/src/bin/button_exti.rs index 34a08bbc6..9d54479da 100644 --- a/examples/stm32u0/src/bin/button_exti.rs +++ b/examples/stm32u0/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32u0/src/bin/lcd.rs b/examples/stm32u0/src/bin/lcd.rs new file mode 100644 index 000000000..2b34d4ef1 --- /dev/null +++ b/examples/stm32u0/src/bin/lcd.rs | |||
| @@ -0,0 +1,412 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::lcd::{Bias, BlinkFreq, BlinkSelector, Config, Duty, Lcd, LcdPin}; | ||
| 7 | use embassy_stm32::peripherals::LCD; | ||
| 8 | use embassy_stm32::time::Hertz; | ||
| 9 | use embassy_time::Duration; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let mut config = embassy_stm32::Config::default(); | ||
| 15 | // The RTC clock = the LCD clock and must be running | ||
| 16 | { | ||
| 17 | use embassy_stm32::rcc::*; | ||
| 18 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 19 | config.rcc.hsi = true; | ||
| 20 | config.rcc.pll = Some(Pll { | ||
| 21 | source: PllSource::HSI, // 16 MHz | ||
| 22 | prediv: PllPreDiv::DIV1, | ||
| 23 | mul: PllMul::MUL7, // 16 * 7 = 112 MHz | ||
| 24 | divp: None, | ||
| 25 | divq: None, | ||
| 26 | divr: Some(PllRDiv::DIV2), // 112 / 2 = 56 MHz | ||
| 27 | }); | ||
| 28 | config.rcc.ls = LsConfig::default_lsi(); | ||
| 29 | } | ||
| 30 | |||
| 31 | let p = embassy_stm32::init(config); | ||
| 32 | info!("Hello World!"); | ||
| 33 | |||
| 34 | let mut config = Config::default(); | ||
| 35 | config.bias = Bias::Third; | ||
| 36 | config.duty = Duty::Quarter; | ||
| 37 | config.target_fps = Hertz(100); | ||
| 38 | |||
| 39 | let mut lcd = Lcd::new( | ||
| 40 | p.LCD, | ||
| 41 | config, | ||
| 42 | p.PC3, | ||
| 43 | [ | ||
| 44 | LcdPin::new_com(p.PA8), | ||
| 45 | LcdPin::new_com(p.PA9), | ||
| 46 | LcdPin::new_com(p.PA10), | ||
| 47 | LcdPin::new_seg(p.PB1), | ||
| 48 | LcdPin::new_com(p.PB9), | ||
| 49 | LcdPin::new_seg(p.PB11), | ||
| 50 | LcdPin::new_seg(p.PB14), | ||
| 51 | LcdPin::new_seg(p.PB15), | ||
| 52 | LcdPin::new_seg(p.PC4), | ||
| 53 | LcdPin::new_seg(p.PC5), | ||
| 54 | LcdPin::new_seg(p.PC6), | ||
| 55 | LcdPin::new_seg(p.PC8), | ||
| 56 | LcdPin::new_seg(p.PC9), | ||
| 57 | LcdPin::new_seg(p.PC10), | ||
| 58 | LcdPin::new_seg(p.PC11), | ||
| 59 | LcdPin::new_seg(p.PD8), | ||
| 60 | LcdPin::new_seg(p.PD9), | ||
| 61 | LcdPin::new_seg(p.PD12), | ||
| 62 | LcdPin::new_seg(p.PD13), | ||
| 63 | LcdPin::new_seg(p.PD0), | ||
| 64 | LcdPin::new_seg(p.PD1), | ||
| 65 | LcdPin::new_seg(p.PD3), | ||
| 66 | LcdPin::new_seg(p.PD4), | ||
| 67 | LcdPin::new_seg(p.PD5), | ||
| 68 | LcdPin::new_seg(p.PD6), | ||
| 69 | LcdPin::new_seg(p.PE7), | ||
| 70 | LcdPin::new_seg(p.PE8), | ||
| 71 | LcdPin::new_seg(p.PE9), | ||
| 72 | ], | ||
| 73 | ); | ||
| 74 | |||
| 75 | lcd.set_blink(BlinkSelector::All, BlinkFreq::Hz4); | ||
| 76 | { | ||
| 77 | let mut buffer = DisplayBuffer::new(); | ||
| 78 | for i in 0..4 { | ||
| 79 | buffer.write_colon(i); | ||
| 80 | buffer.write(&mut lcd); | ||
| 81 | embassy_time::Timer::after_millis(200).await; | ||
| 82 | buffer.write_dot(i); | ||
| 83 | buffer.write(&mut lcd); | ||
| 84 | embassy_time::Timer::after_millis(200).await; | ||
| 85 | } | ||
| 86 | for i in 0..4 { | ||
| 87 | buffer.write_bar(i); | ||
| 88 | buffer.write(&mut lcd); | ||
| 89 | embassy_time::Timer::after_millis(200).await; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | embassy_time::Timer::after_millis(1000).await; | ||
| 94 | |||
| 95 | lcd.set_blink(BlinkSelector::None, BlinkFreq::Hz4); | ||
| 96 | |||
| 97 | const MESSAGE: &str = "Hello embassy people. Hope you like this LCD demo :} "; | ||
| 98 | loop { | ||
| 99 | print_message(MESSAGE, &mut lcd, Duration::from_millis(250)).await; | ||
| 100 | print_message(characters::ALL_CHARS, &mut lcd, Duration::from_millis(500)).await; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | async fn print_message(message: &str, lcd: &mut Lcd<'_, LCD>, delay: Duration) { | ||
| 105 | let mut display_buffer = DisplayBuffer::new(); | ||
| 106 | |||
| 107 | let mut char_buffer = [' '; 6]; | ||
| 108 | for char in message.chars() { | ||
| 109 | char_buffer.copy_within(1.., 0); | ||
| 110 | char_buffer[5] = char; | ||
| 111 | |||
| 112 | display_buffer.clear(); | ||
| 113 | for (i, char) in char_buffer.iter().enumerate() { | ||
| 114 | display_buffer.write_char(i, *char); | ||
| 115 | } | ||
| 116 | display_buffer.write(lcd); | ||
| 117 | |||
| 118 | embassy_time::Timer::after(delay).await; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | /// Display layout for the U0-DK | ||
| 123 | mod display_layout { | ||
| 124 | // Character layout. There are 6 characters, left-to-right | ||
| 125 | // T | ||
| 126 | // ───────── | ||
| 127 | // │ N │ | ||
| 128 | // │ │ │ │ │ | ||
| 129 | // TL │ └┐ │ ┌┘ │ TR | ||
| 130 | // │NW│ │ │NE│ | ||
| 131 | // │ │ │ | ||
| 132 | // W─── ───E | ||
| 133 | // │ │ │ | ||
| 134 | // │SW│ │ │SE│ | ||
| 135 | // BL │ ┌┘ │ └┐ │ BR | ||
| 136 | // │ │ │ │ │ | ||
| 137 | // │ S │ | ||
| 138 | // ───────── | ||
| 139 | // B | ||
| 140 | |||
| 141 | pub const CHAR_N_COM: u8 = 3; | ||
| 142 | pub const CHAR_N_SEG: [u8; 6] = [39, 37, 35, 48, 26, 33]; | ||
| 143 | pub const CHAR_NW_COM: u8 = 3; | ||
| 144 | pub const CHAR_NW_SEG: [u8; 6] = [49, 38, 36, 34, 27, 24]; | ||
| 145 | pub const CHAR_W_COM: u8 = 0; | ||
| 146 | pub const CHAR_W_SEG: [u8; 6] = CHAR_NW_SEG; | ||
| 147 | pub const CHAR_SW_COM: u8 = 2; | ||
| 148 | pub const CHAR_SW_SEG: [u8; 6] = CHAR_NW_SEG; | ||
| 149 | pub const CHAR_S_COM: u8 = 2; | ||
| 150 | pub const CHAR_S_SEG: [u8; 6] = [22, 6, 46, 11, 15, 29]; | ||
| 151 | pub const CHAR_SE_COM: u8 = 3; | ||
| 152 | pub const CHAR_SE_SEG: [u8; 6] = CHAR_S_SEG; | ||
| 153 | pub const CHAR_E_COM: u8 = 0; | ||
| 154 | pub const CHAR_E_SEG: [u8; 6] = [23, 45, 47, 14, 28, 32]; | ||
| 155 | pub const CHAR_NE_COM: u8 = 2; | ||
| 156 | pub const CHAR_NE_SEG: [u8; 6] = CHAR_N_SEG; | ||
| 157 | pub const CHAR_T_COM: u8 = 1; | ||
| 158 | pub const CHAR_T_SEG: [u8; 6] = CHAR_N_SEG; | ||
| 159 | pub const CHAR_TL_COM: u8 = 1; | ||
| 160 | pub const CHAR_TL_SEG: [u8; 6] = CHAR_NW_SEG; | ||
| 161 | pub const CHAR_BL_COM: u8 = 0; | ||
| 162 | pub const CHAR_BL_SEG: [u8; 6] = CHAR_S_SEG; | ||
| 163 | pub const CHAR_B_COM: u8 = 1; | ||
| 164 | pub const CHAR_B_SEG: [u8; 6] = CHAR_S_SEG; | ||
| 165 | pub const CHAR_BR_COM: u8 = 1; | ||
| 166 | pub const CHAR_BR_SEG: [u8; 6] = CHAR_E_SEG; | ||
| 167 | pub const CHAR_TR_COM: u8 = 0; | ||
| 168 | pub const CHAR_TR_SEG: [u8; 6] = CHAR_N_SEG; | ||
| 169 | |||
| 170 | pub const COLON_COM: u8 = 2; | ||
| 171 | pub const COLON_SEG: [u8; 4] = [23, 45, 47, 14]; | ||
| 172 | pub const DOT_COM: u8 = 3; | ||
| 173 | pub const DOT_SEG: [u8; 4] = COLON_SEG; | ||
| 174 | /// COM + SEG, bar from top to bottom | ||
| 175 | pub const BAR: [(u8, u8); 4] = [(2, 28), (3, 28), (2, 32), (3, 32)]; | ||
| 176 | } | ||
| 177 | |||
| 178 | mod characters { | ||
| 179 | use super::CharSegment::{self, *}; | ||
| 180 | |||
| 181 | pub const CHAR_0: &[CharSegment] = &[T, TL, BL, B, BR, TR, NW, SE]; | ||
| 182 | pub const CHAR_1: &[CharSegment] = &[NE, TR, BR]; | ||
| 183 | pub const CHAR_2: &[CharSegment] = &[T, BL, B, TR, E, W]; | ||
| 184 | pub const CHAR_3: &[CharSegment] = &[T, B, BR, TR, E]; | ||
| 185 | pub const CHAR_4: &[CharSegment] = &[TL, BR, TR, E, W]; | ||
| 186 | pub const CHAR_5: &[CharSegment] = &[T, TL, B, BR, E, W]; | ||
| 187 | pub const CHAR_6: &[CharSegment] = &[T, TL, BL, B, BR, E, W]; | ||
| 188 | pub const CHAR_7: &[CharSegment] = &[T, NE, S]; | ||
| 189 | pub const CHAR_8: &[CharSegment] = &[T, TL, BL, B, BR, TR, E, W]; | ||
| 190 | pub const CHAR_9: &[CharSegment] = &[T, TL, BR, TR, E, W]; | ||
| 191 | |||
| 192 | pub const CHAR_COLON: &[CharSegment] = &[N, S]; | ||
| 193 | pub const CHAR_SEMICOLON: &[CharSegment] = &[N, SW]; | ||
| 194 | pub const CHAR_EQUALS: &[CharSegment] = &[E, W, B]; | ||
| 195 | pub const CHAR_SLASH: &[CharSegment] = &[SW, NE]; | ||
| 196 | pub const CHAR_BACKSLASH: &[CharSegment] = &[SE, NW]; | ||
| 197 | pub const CHAR_PLUS: &[CharSegment] = &[N, E, S, W]; | ||
| 198 | pub const CHAR_STAR: &[CharSegment] = &[NE, N, NW, SE, S, SW]; | ||
| 199 | pub const CHAR_QUOTE: &[CharSegment] = &[N]; | ||
| 200 | pub const CHAR_BACKTICK: &[CharSegment] = &[NW]; | ||
| 201 | pub const CHAR_DASH: &[CharSegment] = &[W, E]; | ||
| 202 | pub const CHAR_COMMA: &[CharSegment] = &[SW]; | ||
| 203 | pub const CHAR_DOT: &[CharSegment] = &[S]; | ||
| 204 | pub const CHAR_CURLYOPEN: &[CharSegment] = &[T, NW, W, SW, B]; | ||
| 205 | pub const CHAR_CURLYCLOSE: &[CharSegment] = &[T, NE, E, SE, B]; | ||
| 206 | pub const CHAR_AMPERSAND: &[CharSegment] = &[T, NE, NW, W, BL, B, SE]; | ||
| 207 | |||
| 208 | pub const CHAR_A: &[CharSegment] = &[T, TL, TR, E, W, BL, BR]; | ||
| 209 | pub const CHAR_B: &[CharSegment] = &[T, TR, BR, B, N, S, E]; | ||
| 210 | pub const CHAR_C: &[CharSegment] = &[T, TL, BL, B]; | ||
| 211 | pub const CHAR_D: &[CharSegment] = &[T, TR, BR, B, N, S]; | ||
| 212 | pub const CHAR_E: &[CharSegment] = &[T, TL, BL, B, W]; | ||
| 213 | pub const CHAR_F: &[CharSegment] = &[T, TL, BL, W]; | ||
| 214 | pub const CHAR_G: &[CharSegment] = &[T, TL, BL, B, BR, E]; | ||
| 215 | pub const CHAR_H: &[CharSegment] = &[TL, BL, E, W, TR, BR]; | ||
| 216 | pub const CHAR_I: &[CharSegment] = &[T, N, S, B]; | ||
| 217 | pub const CHAR_J: &[CharSegment] = &[TR, BR, B, BL]; | ||
| 218 | pub const CHAR_K: &[CharSegment] = &[TL, BL, W, NE, SE]; | ||
| 219 | pub const CHAR_L: &[CharSegment] = &[TL, BL, B]; | ||
| 220 | pub const CHAR_M: &[CharSegment] = &[BL, TL, NW, NE, TR, BR]; | ||
| 221 | pub const CHAR_N: &[CharSegment] = &[BL, TL, NW, SE, BR, TR]; | ||
| 222 | pub const CHAR_O: &[CharSegment] = &[T, TL, BL, B, BR, TR]; | ||
| 223 | pub const CHAR_P: &[CharSegment] = &[BL, TL, T, TR, E, W]; | ||
| 224 | pub const CHAR_Q: &[CharSegment] = &[T, TL, BL, B, BR, TR, SE]; | ||
| 225 | pub const CHAR_R: &[CharSegment] = &[BL, TL, T, TR, E, W, SE]; | ||
| 226 | pub const CHAR_S: &[CharSegment] = &[T, NW, E, BR, B]; | ||
| 227 | pub const CHAR_T: &[CharSegment] = &[T, N, S]; | ||
| 228 | pub const CHAR_U: &[CharSegment] = &[TL, BL, B, BR, TR]; | ||
| 229 | pub const CHAR_V: &[CharSegment] = &[TL, BL, SW, NE]; | ||
| 230 | pub const CHAR_W: &[CharSegment] = &[TL, BL, SW, SE, BR, TR]; | ||
| 231 | pub const CHAR_X: &[CharSegment] = &[NE, NW, SE, SW]; | ||
| 232 | pub const CHAR_Y: &[CharSegment] = &[NE, NW, S]; | ||
| 233 | pub const CHAR_Z: &[CharSegment] = &[T, NE, SW, B]; | ||
| 234 | |||
| 235 | pub const CHAR_UNKNOWN: &[CharSegment] = &[N, NW, W, SW, S, SE, E, NE, T, TL, BL, B, BR, TR]; | ||
| 236 | |||
| 237 | pub const ALL_CHARS: &str = | ||
| 238 | "0 1 2 3 4 5 6 7 8 9 : ; = / \\ + * ' ` - , . { } & A B C D E F G H I J K L M N O P Q R S T U V W X Y Z � "; | ||
| 239 | |||
| 240 | pub fn get_char_segments(val: char) -> &'static [CharSegment] { | ||
| 241 | match val { | ||
| 242 | val if val.is_whitespace() => &[], | ||
| 243 | |||
| 244 | '0' => CHAR_0, | ||
| 245 | '1' => CHAR_1, | ||
| 246 | '2' => CHAR_2, | ||
| 247 | '3' => CHAR_3, | ||
| 248 | '4' => CHAR_4, | ||
| 249 | '5' => CHAR_5, | ||
| 250 | '6' => CHAR_6, | ||
| 251 | '7' => CHAR_7, | ||
| 252 | '8' => CHAR_8, | ||
| 253 | '9' => CHAR_9, | ||
| 254 | |||
| 255 | ':' => CHAR_COLON, | ||
| 256 | ';' => CHAR_SEMICOLON, | ||
| 257 | '=' => CHAR_EQUALS, | ||
| 258 | '/' => CHAR_SLASH, | ||
| 259 | '\\' => CHAR_BACKSLASH, | ||
| 260 | '+' => CHAR_PLUS, | ||
| 261 | '*' => CHAR_STAR, | ||
| 262 | '\'' => CHAR_QUOTE, | ||
| 263 | '`' => CHAR_BACKTICK, | ||
| 264 | '-' => CHAR_DASH, | ||
| 265 | ',' => CHAR_COMMA, | ||
| 266 | '.' => CHAR_DOT, | ||
| 267 | '{' => CHAR_CURLYOPEN, | ||
| 268 | '}' => CHAR_CURLYCLOSE, | ||
| 269 | '&' => CHAR_AMPERSAND, | ||
| 270 | |||
| 271 | 'A' | 'a' => CHAR_A, | ||
| 272 | 'B' | 'b' => CHAR_B, | ||
| 273 | 'C' | 'c' => CHAR_C, | ||
| 274 | 'D' | 'd' => CHAR_D, | ||
| 275 | 'E' | 'e' => CHAR_E, | ||
| 276 | 'F' | 'f' => CHAR_F, | ||
| 277 | 'G' | 'g' => CHAR_G, | ||
| 278 | 'H' | 'h' => CHAR_H, | ||
| 279 | 'I' | 'i' => CHAR_I, | ||
| 280 | 'J' | 'j' => CHAR_J, | ||
| 281 | 'K' | 'k' => CHAR_K, | ||
| 282 | 'L' | 'l' => CHAR_L, | ||
| 283 | 'M' | 'm' => CHAR_M, | ||
| 284 | 'N' | 'n' => CHAR_N, | ||
| 285 | 'O' | 'o' => CHAR_O, | ||
| 286 | 'P' | 'p' => CHAR_P, | ||
| 287 | 'Q' | 'q' => CHAR_Q, | ||
| 288 | 'R' | 'r' => CHAR_R, | ||
| 289 | 'S' | 's' => CHAR_S, | ||
| 290 | 'T' | 't' => CHAR_T, | ||
| 291 | 'U' | 'u' => CHAR_U, | ||
| 292 | 'V' | 'v' => CHAR_V, | ||
| 293 | 'W' | 'w' => CHAR_W, | ||
| 294 | 'X' | 'x' => CHAR_X, | ||
| 295 | 'Y' | 'y' => CHAR_Y, | ||
| 296 | 'Z' | 'z' => CHAR_Z, | ||
| 297 | |||
| 298 | _ => CHAR_UNKNOWN, | ||
| 299 | } | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | pub struct DisplayBuffer { | ||
| 304 | pixels: [u64; 4], | ||
| 305 | } | ||
| 306 | |||
| 307 | impl DisplayBuffer { | ||
| 308 | pub const fn new() -> Self { | ||
| 309 | Self { pixels: [0; 4] } | ||
| 310 | } | ||
| 311 | |||
| 312 | pub fn clear(&mut self) { | ||
| 313 | *self = Self::new(); | ||
| 314 | } | ||
| 315 | |||
| 316 | fn write_char_segment(&mut self, index: usize, value: CharSegment) { | ||
| 317 | defmt::assert!(index < 6); | ||
| 318 | let (com, segments) = value.get_com_seg(); | ||
| 319 | self.pixels[com as usize] |= 1 << segments[index]; | ||
| 320 | } | ||
| 321 | |||
| 322 | pub fn write_char(&mut self, index: usize, val: char) { | ||
| 323 | let segments = characters::get_char_segments(val); | ||
| 324 | |||
| 325 | for segment in segments { | ||
| 326 | self.write_char_segment(index, *segment); | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | pub fn write(&self, lcd: &mut Lcd<'_, LCD>) { | ||
| 331 | lcd.write_com_segments(0, self.pixels[0]); | ||
| 332 | lcd.write_com_segments(1, self.pixels[1]); | ||
| 333 | lcd.write_com_segments(2, self.pixels[2]); | ||
| 334 | lcd.write_com_segments(3, self.pixels[3]); | ||
| 335 | lcd.submit_frame(); | ||
| 336 | } | ||
| 337 | |||
| 338 | pub fn write_colon(&mut self, index: usize) { | ||
| 339 | defmt::assert!(index < 4); | ||
| 340 | self.pixels[display_layout::COLON_COM as usize] |= 1 << display_layout::COLON_SEG[index]; | ||
| 341 | } | ||
| 342 | |||
| 343 | pub fn write_dot(&mut self, index: usize) { | ||
| 344 | defmt::assert!(index < 4); | ||
| 345 | self.pixels[display_layout::DOT_COM as usize] |= 1 << display_layout::DOT_SEG[index]; | ||
| 346 | } | ||
| 347 | |||
| 348 | pub fn write_bar(&mut self, index: usize) { | ||
| 349 | defmt::assert!(index < 4); | ||
| 350 | let (bar_com, bar_seg) = display_layout::BAR[index]; | ||
| 351 | self.pixels[bar_com as usize] |= 1 << bar_seg; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | impl Default for DisplayBuffer { | ||
| 356 | fn default() -> Self { | ||
| 357 | Self::new() | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | #[derive(Debug, Clone, Copy)] | ||
| 362 | enum CharSegment { | ||
| 363 | /// North | ||
| 364 | N, | ||
| 365 | /// North west | ||
| 366 | NW, | ||
| 367 | /// West | ||
| 368 | W, | ||
| 369 | /// South west | ||
| 370 | SW, | ||
| 371 | /// South | ||
| 372 | S, | ||
| 373 | /// South East | ||
| 374 | SE, | ||
| 375 | /// East | ||
| 376 | E, | ||
| 377 | /// North East | ||
| 378 | NE, | ||
| 379 | /// Top | ||
| 380 | T, | ||
| 381 | /// Top left | ||
| 382 | TL, | ||
| 383 | /// Bottom left | ||
| 384 | BL, | ||
| 385 | /// Bottom | ||
| 386 | B, | ||
| 387 | /// Bottom right | ||
| 388 | BR, | ||
| 389 | /// Top right | ||
| 390 | TR, | ||
| 391 | } | ||
| 392 | |||
| 393 | impl CharSegment { | ||
| 394 | fn get_com_seg(&self) -> (u8, [u8; 6]) { | ||
| 395 | match self { | ||
| 396 | CharSegment::N => (display_layout::CHAR_N_COM, display_layout::CHAR_N_SEG), | ||
| 397 | CharSegment::NW => (display_layout::CHAR_NW_COM, display_layout::CHAR_NW_SEG), | ||
| 398 | CharSegment::W => (display_layout::CHAR_W_COM, display_layout::CHAR_W_SEG), | ||
| 399 | CharSegment::SW => (display_layout::CHAR_SW_COM, display_layout::CHAR_SW_SEG), | ||
| 400 | CharSegment::S => (display_layout::CHAR_S_COM, display_layout::CHAR_S_SEG), | ||
| 401 | CharSegment::SE => (display_layout::CHAR_SE_COM, display_layout::CHAR_SE_SEG), | ||
| 402 | CharSegment::E => (display_layout::CHAR_E_COM, display_layout::CHAR_E_SEG), | ||
| 403 | CharSegment::NE => (display_layout::CHAR_NE_COM, display_layout::CHAR_NE_SEG), | ||
| 404 | CharSegment::T => (display_layout::CHAR_T_COM, display_layout::CHAR_T_SEG), | ||
| 405 | CharSegment::TL => (display_layout::CHAR_TL_COM, display_layout::CHAR_TL_SEG), | ||
| 406 | CharSegment::BL => (display_layout::CHAR_BL_COM, display_layout::CHAR_BL_SEG), | ||
| 407 | CharSegment::B => (display_layout::CHAR_B_COM, display_layout::CHAR_B_SEG), | ||
| 408 | CharSegment::BR => (display_layout::CHAR_BR_COM, display_layout::CHAR_BR_SEG), | ||
| 409 | CharSegment::TR => (display_layout::CHAR_TR_COM, display_layout::CHAR_TR_SEG), | ||
| 410 | } | ||
| 411 | } | ||
| 412 | } | ||
diff --git a/examples/stm32u0/src/bin/rng.rs b/examples/stm32u0/src/bin/rng.rs index 89445b042..07deda94c 100644 --- a/examples/stm32u0/src/bin/rng.rs +++ b/examples/stm32u0/src/bin/rng.rs | |||
| @@ -5,7 +5,7 @@ use defmt::*; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::rcc::mux::Clk48sel; | 6 | use embassy_stm32::rcc::mux::Clk48sel; |
| 7 | use embassy_stm32::rng::Rng; | 7 | use embassy_stm32::rng::Rng; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | 11 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32u0/src/bin/rtc.rs b/examples/stm32u0/src/bin/rtc.rs index 72fa0fde4..56d16ccf7 100644 --- a/examples/stm32u0/src/bin/rtc.rs +++ b/examples/stm32u0/src/bin/rtc.rs | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 8 | use embassy_stm32::Config; | 7 | use embassy_stm32::Config; |
| 8 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { | |||
| 36 | .and_hms_opt(10, 30, 15) | 36 | .and_hms_opt(10, 30, 15) |
| 37 | .unwrap(); | 37 | .unwrap(); |
| 38 | 38 | ||
| 39 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 39 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 40 | info!("Got RTC! {:?}", now.and_utc().timestamp()); | 40 | info!("Got RTC! {:?}", now.and_utc().timestamp()); |
| 41 | 41 | ||
| 42 | rtc.set_datetime(now.into()).expect("datetime not set"); | 42 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| @@ -44,6 +44,6 @@ async fn main(_spawner: Spawner) { | |||
| 44 | // In reality the delay would be much longer | 44 | // In reality the delay would be much longer |
| 45 | Timer::after_millis(20000).await; | 45 | Timer::after_millis(20000).await; |
| 46 | 46 | ||
| 47 | let then: NaiveDateTime = rtc.now().unwrap().into(); | 47 | let then: NaiveDateTime = time_provider.now().unwrap().into(); |
| 48 | info!("Got RTC! {:?}", then.and_utc().timestamp()); | 48 | info!("Got RTC! {:?}", then.and_utc().timestamp()); |
| 49 | } | 49 | } |
diff --git a/examples/stm32u0/src/bin/usb_serial.rs b/examples/stm32u0/src/bin/usb_serial.rs index 273f40643..77d0640f6 100644 --- a/examples/stm32u0/src/bin/usb_serial.rs +++ b/examples/stm32u0/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use panic_probe as _; | 13 | use panic_probe as _; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index f2ffe52c5..7a1e62406 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32u5-examples" | 3 | name = "embassy-stm32u5-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs index d2aa28087..4d2d93aa2 100644 --- a/examples/stm32u5/src/bin/adc.rs +++ b/examples/stm32u5/src/bin/adc.rs | |||
| @@ -2,8 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc; | 5 | use embassy_stm32::adc::{self, Adc, AdcChannel, AdcConfig, SampleTime, adc4}; |
| 6 | use embassy_stm32::adc::{adc4, AdcChannel}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 7 | ||
| 9 | #[embassy_executor::main] | 8 | #[embassy_executor::main] |
| @@ -13,56 +12,55 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 13 | let mut p = embassy_stm32::init(config); | 12 | let mut p = embassy_stm32::init(config); |
| 14 | 13 | ||
| 15 | // **** ADC1 init **** | 14 | // **** ADC1 init **** |
| 16 | let mut adc1 = adc::Adc::new(p.ADC1); | 15 | let mut config = AdcConfig::default(); |
| 16 | config.averaging = Some(adc::Averaging::Samples1024); | ||
| 17 | config.resolution = Some(adc::Resolution::BITS14); | ||
| 18 | let mut adc1 = Adc::new_with_config(p.ADC1, config); | ||
| 17 | let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5 | 19 | let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5 |
| 18 | let mut adc1_pin2 = p.PA2; // A1 | 20 | let mut adc1_pin2 = p.PA2; // A1 |
| 19 | adc1.set_resolution(adc::Resolution::BITS14); | ||
| 20 | adc1.set_averaging(adc::Averaging::Samples1024); | ||
| 21 | adc1.set_sample_time(adc::SampleTime::CYCLES160_5); | ||
| 22 | let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); | 21 | let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); |
| 23 | 22 | ||
| 24 | // **** ADC2 init **** | 23 | // **** ADC2 init **** |
| 25 | let mut adc2 = adc::Adc::new(p.ADC2); | 24 | let mut config = AdcConfig::default(); |
| 25 | config.averaging = Some(adc::Averaging::Samples1024); | ||
| 26 | config.resolution = Some(adc::Resolution::BITS14); | ||
| 27 | let mut adc2 = Adc::new_with_config(p.ADC2, config); | ||
| 26 | let mut adc2_pin1 = p.PC3; // A2 | 28 | let mut adc2_pin1 = p.PC3; // A2 |
| 27 | let mut adc2_pin2 = p.PB0; // A3 | 29 | let mut adc2_pin2 = p.PB0; // A3 |
| 28 | adc2.set_resolution(adc::Resolution::BITS14); | ||
| 29 | adc2.set_averaging(adc::Averaging::Samples1024); | ||
| 30 | adc2.set_sample_time(adc::SampleTime::CYCLES160_5); | ||
| 31 | let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); | 30 | let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); |
| 32 | 31 | ||
| 33 | // **** ADC4 init **** | 32 | // **** ADC4 init **** |
| 34 | let mut adc4 = adc4::Adc4::new(p.ADC4); | 33 | let mut adc4 = Adc::new_adc4(p.ADC4); |
| 35 | let mut adc4_pin1 = p.PC1; // A4 | 34 | let mut adc4_pin1 = p.PC1.degrade_adc(); // A4 |
| 36 | let mut adc4_pin2 = p.PC0; // A5 | 35 | let mut adc4_pin2 = p.PC0; // A5 |
| 37 | adc4.set_resolution(adc4::Resolution::BITS12); | 36 | adc4.set_resolution_adc4(adc4::Resolution::BITS12); |
| 38 | adc4.set_averaging(adc4::Averaging::Samples256); | 37 | adc4.set_averaging_adc4(adc4::Averaging::Samples256); |
| 39 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 40 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 38 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 41 | 39 | ||
| 42 | // **** ADC1 blocking read **** | 40 | // **** ADC1 blocking read **** |
| 43 | let raw: u16 = adc1.blocking_read(&mut adc1_pin1); | 41 | let raw: u16 = adc1.blocking_read(&mut adc1_pin1, SampleTime::CYCLES160_5); |
| 44 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; | 42 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; |
| 45 | info!("Read adc1 pin 1 {}", volt); | 43 | info!("Read adc1 pin 1 {}", volt); |
| 46 | 44 | ||
| 47 | let raw: u16 = adc1.blocking_read(&mut adc1_pin2); | 45 | let raw: u16 = adc1.blocking_read(&mut adc1_pin2, SampleTime::CYCLES160_5); |
| 48 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; | 46 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; |
| 49 | info!("Read adc1 pin 2 {}", volt); | 47 | info!("Read adc1 pin 2 {}", volt); |
| 50 | 48 | ||
| 51 | // **** ADC2 blocking read **** | 49 | // **** ADC2 blocking read **** |
| 52 | let raw: u16 = adc2.blocking_read(&mut adc2_pin1); | 50 | let raw: u16 = adc2.blocking_read(&mut adc2_pin1, SampleTime::CYCLES160_5); |
| 53 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; | 51 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; |
| 54 | info!("Read adc2 pin 1 {}", volt); | 52 | info!("Read adc2 pin 1 {}", volt); |
| 55 | 53 | ||
| 56 | let raw: u16 = adc2.blocking_read(&mut adc2_pin2); | 54 | let raw: u16 = adc2.blocking_read(&mut adc2_pin2, SampleTime::CYCLES160_5); |
| 57 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; | 55 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; |
| 58 | info!("Read adc2 pin 2 {}", volt); | 56 | info!("Read adc2 pin 2 {}", volt); |
| 59 | 57 | ||
| 60 | // **** ADC4 blocking read **** | 58 | // **** ADC4 blocking read **** |
| 61 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 59 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 62 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 60 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 63 | info!("Read adc4 pin 1 {}", volt); | 61 | info!("Read adc4 pin 1 {}", volt); |
| 64 | 62 | ||
| 65 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 63 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 66 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 64 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 67 | info!("Read adc4 pin 2 {}", volt); | 65 | info!("Read adc4 pin 2 {}", volt); |
| 68 | 66 | ||
| @@ -97,11 +95,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 97 | // The channels must be in ascending order and can't repeat for ADC4 | 95 | // The channels must be in ascending order and can't repeat for ADC4 |
| 98 | adc4.read( | 96 | adc4.read( |
| 99 | p.GPDMA1_CH1.reborrow(), | 97 | p.GPDMA1_CH1.reborrow(), |
| 100 | [&mut degraded42, &mut degraded41].into_iter(), | 98 | [ |
| 99 | (&mut degraded42, adc4::SampleTime::CYCLES1_5), | ||
| 100 | (&mut degraded41, adc4::SampleTime::CYCLES1_5), | ||
| 101 | ] | ||
| 102 | .into_iter(), | ||
| 101 | &mut measurements, | 103 | &mut measurements, |
| 102 | ) | 104 | ) |
| 103 | .await | 105 | .await; |
| 104 | .unwrap(); | ||
| 105 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | 106 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; |
| 106 | let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32; | 107 | let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32; |
| 107 | info!("Async read 4 pin 1 {}", volt1); | 108 | info!("Async read 4 pin 1 {}", volt1); |
diff --git a/examples/stm32u5/src/bin/ltdc.rs b/examples/stm32u5/src/bin/ltdc.rs index 46d1c120f..d1fddb679 100644 --- a/examples/stm32u5/src/bin/ltdc.rs +++ b/examples/stm32u5/src/bin/ltdc.rs | |||
| @@ -13,14 +13,14 @@ use embassy_stm32::gpio::{Level, Output, Speed}; | |||
| 13 | use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge}; | 13 | use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge}; |
| 14 | use embassy_stm32::{bind_interrupts, peripherals}; | 14 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use embedded_graphics::Pixel; | ||
| 16 | use embedded_graphics::draw_target::DrawTarget; | 17 | use embedded_graphics::draw_target::DrawTarget; |
| 17 | use embedded_graphics::geometry::{OriginDimensions, Point, Size}; | 18 | use embedded_graphics::geometry::{OriginDimensions, Point, Size}; |
| 18 | use embedded_graphics::image::Image; | 19 | use embedded_graphics::image::Image; |
| 19 | use embedded_graphics::pixelcolor::raw::RawU24; | ||
| 20 | use embedded_graphics::pixelcolor::Rgb888; | 20 | use embedded_graphics::pixelcolor::Rgb888; |
| 21 | use embedded_graphics::pixelcolor::raw::RawU24; | ||
| 21 | use embedded_graphics::prelude::*; | 22 | use embedded_graphics::prelude::*; |
| 22 | use embedded_graphics::primitives::Rectangle; | 23 | use embedded_graphics::primitives::Rectangle; |
| 23 | use embedded_graphics::Pixel; | ||
| 24 | use heapless::{Entry, FnvIndexMap}; | 24 | use heapless::{Entry, FnvIndexMap}; |
| 25 | use tinybmp::Bmp; | 25 | use tinybmp::Bmp; |
| 26 | use {defmt_rtt as _, panic_probe as _}; | 26 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -317,7 +317,7 @@ impl OriginDimensions for DoubleBuffer { | |||
| 317 | mod rcc_setup { | 317 | mod rcc_setup { |
| 318 | 318 | ||
| 319 | use embassy_stm32::time::Hertz; | 319 | use embassy_stm32::time::Hertz; |
| 320 | use embassy_stm32::{rcc, Config, Peripherals}; | 320 | use embassy_stm32::{Config, Peripherals, rcc}; |
| 321 | 321 | ||
| 322 | /// Sets up clocks for the stm32u5g9zj mcu | 322 | /// Sets up clocks for the stm32u5g9zj mcu |
| 323 | /// change this if you plan to use a different microcontroller | 323 | /// change this if you plan to use a different microcontroller |
diff --git a/examples/stm32u5/src/bin/usb_hs_serial.rs b/examples/stm32u5/src/bin/usb_hs_serial.rs index d37e7777b..c444d3479 100644 --- a/examples/stm32u5/src/bin/usb_hs_serial.rs +++ b/examples/stm32u5/src/bin/usb_hs_serial.rs | |||
| @@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use panic_probe as _; | 13 | use panic_probe as _; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs index ff7f4e5be..c0a768cbb 100644 --- a/examples/stm32u5/src/bin/usb_serial.rs +++ b/examples/stm32u5/src/bin/usb_serial.rs | |||
| @@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 8 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 10 | use embassy_usb::Builder; | ||
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 11 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 12 | use embassy_usb::Builder; | ||
| 13 | use panic_probe as _; | 13 | use panic_probe as _; |
| 14 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 7ab13c290..83f7cb56b 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32wb-examples" | 3 | name = "embassy-stm32wb-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| @@ -7,7 +7,7 @@ publish = false | |||
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | # Change stm32wb55rg to your chip name in both dependencies, if necessary. | 9 | # Change stm32wb55rg to your chip name in both dependencies, if necessary. |
| 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } | 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti", "low-power"] } |
| 11 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } | 11 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } |
| 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 13 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| @@ -26,8 +26,8 @@ static_cell = "2" | |||
| 26 | 26 | ||
| 27 | [features] | 27 | [features] |
| 28 | default = ["ble", "mac"] | 28 | default = ["ble", "mac"] |
| 29 | mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"] | 29 | mac = ["embassy-stm32-wpan/wb55_mac", "dep:embassy-net"] |
| 30 | ble = ["embassy-stm32-wpan/ble"] | 30 | ble = ["embassy-stm32-wpan/wb55_ble"] |
| 31 | 31 | ||
| 32 | [[bin]] | 32 | [[bin]] |
| 33 | name = "tl_mbox_ble" | 33 | name = "tl_mbox_ble" |
diff --git a/examples/stm32wb/src/bin/button_exti.rs b/examples/stm32wb/src/bin/button_exti.rs index 2871fd55f..3c58eb556 100644 --- a/examples/stm32wb/src/bin/button_exti.rs +++ b/examples/stm32wb/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI4 => exti::InterruptHandler<interrupt::typelevel::EXTI4>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC4, p.EXTI4, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC4, p.EXTI4, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index 3bd8b4a63..413b1ac8f 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs | |||
| @@ -8,15 +8,15 @@ use embassy_executor::Spawner; | |||
| 8 | use embassy_stm32::bind_interrupts; | 8 | use embassy_stm32::bind_interrupts; |
| 9 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 9 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 10 | use embassy_stm32::rcc::WPAN_DEFAULT; | 10 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 11 | use embassy_stm32_wpan::TlMbox; | ||
| 12 | use embassy_stm32_wpan::hci::BdAddr; | ||
| 11 | use embassy_stm32_wpan::hci::host::uart::UartHci; | 13 | use embassy_stm32_wpan::hci::host::uart::UartHci; |
| 12 | use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; | 14 | use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; |
| 13 | use embassy_stm32_wpan::hci::types::AdvertisingType; | 15 | use embassy_stm32_wpan::hci::types::AdvertisingType; |
| 14 | use embassy_stm32_wpan::hci::vendor::command::gap::{AdvertisingDataType, DiscoverableParameters, GapCommands, Role}; | 16 | use embassy_stm32_wpan::hci::vendor::command::gap::{AdvertisingDataType, DiscoverableParameters, GapCommands, Role}; |
| 15 | use embassy_stm32_wpan::hci::vendor::command::gatt::GattCommands; | 17 | use embassy_stm32_wpan::hci::vendor::command::gatt::GattCommands; |
| 16 | use embassy_stm32_wpan::hci::vendor::command::hal::{ConfigData, HalCommands, PowerLevel}; | 18 | use embassy_stm32_wpan::hci::vendor::command::hal::{ConfigData, HalCommands, PowerLevel}; |
| 17 | use embassy_stm32_wpan::hci::BdAddr; | ||
| 18 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; | 19 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; |
| 19 | use embassy_stm32_wpan::TlMbox; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 21 | ||
| 22 | bind_interrupts!(struct Irqs{ | 22 | bind_interrupts!(struct Irqs{ |
| @@ -57,126 +57,112 @@ async fn main(_spawner: Spawner) { | |||
| 57 | info!("Hello World!"); | 57 | info!("Hello World!"); |
| 58 | 58 | ||
| 59 | let config = Config::default(); | 59 | let config = Config::default(); |
| 60 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); | 60 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 61 | 61 | let mut sys = mbox.sys_subsystem; | |
| 62 | let sys_event = mbox.sys_subsystem.read().await; | 62 | let mut ble = mbox.ble_subsystem; |
| 63 | info!("sys event: {}", sys_event.payload()); | ||
| 64 | 63 | ||
| 65 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | 64 | let _ = sys.shci_c2_ble_init(Default::default()).await; |
| 66 | 65 | ||
| 67 | info!("resetting BLE..."); | 66 | info!("resetting BLE..."); |
| 68 | mbox.ble_subsystem.reset().await; | 67 | ble.reset().await; |
| 69 | let response = mbox.ble_subsystem.read().await.unwrap(); | 68 | let response = ble.read().await.unwrap(); |
| 70 | defmt::info!("{}", response); | 69 | defmt::info!("{}", response); |
| 71 | 70 | ||
| 72 | info!("config public address..."); | 71 | info!("config public address..."); |
| 73 | mbox.ble_subsystem | 72 | ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build()) |
| 74 | .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) | ||
| 75 | .await; | 73 | .await; |
| 76 | let response = mbox.ble_subsystem.read().await.unwrap(); | 74 | let response = ble.read().await.unwrap(); |
| 77 | defmt::info!("{}", response); | 75 | defmt::info!("{}", response); |
| 78 | 76 | ||
| 79 | info!("config random address..."); | 77 | info!("config random address..."); |
| 80 | mbox.ble_subsystem | 78 | ble.write_config_data(&ConfigData::random_address(get_random_addr()).build()) |
| 81 | .write_config_data(&ConfigData::random_address(get_random_addr()).build()) | ||
| 82 | .await; | 79 | .await; |
| 83 | let response = mbox.ble_subsystem.read().await.unwrap(); | 80 | let response = ble.read().await.unwrap(); |
| 84 | defmt::info!("{}", response); | 81 | defmt::info!("{}", response); |
| 85 | 82 | ||
| 86 | info!("config identity root..."); | 83 | info!("config identity root..."); |
| 87 | mbox.ble_subsystem | 84 | ble.write_config_data(&ConfigData::identity_root(&get_irk()).build()) |
| 88 | .write_config_data(&ConfigData::identity_root(&get_irk()).build()) | ||
| 89 | .await; | 85 | .await; |
| 90 | let response = mbox.ble_subsystem.read().await.unwrap(); | 86 | let response = ble.read().await.unwrap(); |
| 91 | defmt::info!("{}", response); | 87 | defmt::info!("{}", response); |
| 92 | 88 | ||
| 93 | info!("config encryption root..."); | 89 | info!("config encryption root..."); |
| 94 | mbox.ble_subsystem | 90 | ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build()) |
| 95 | .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) | ||
| 96 | .await; | 91 | .await; |
| 97 | let response = mbox.ble_subsystem.read().await.unwrap(); | 92 | let response = ble.read().await.unwrap(); |
| 98 | defmt::info!("{}", response); | 93 | defmt::info!("{}", response); |
| 99 | 94 | ||
| 100 | info!("config tx power level..."); | 95 | info!("config tx power level..."); |
| 101 | mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; | 96 | ble.set_tx_power_level(PowerLevel::ZerodBm).await; |
| 102 | let response = mbox.ble_subsystem.read().await.unwrap(); | 97 | let response = ble.read().await.unwrap(); |
| 103 | defmt::info!("{}", response); | 98 | defmt::info!("{}", response); |
| 104 | 99 | ||
| 105 | info!("GATT init..."); | 100 | info!("GATT init..."); |
| 106 | mbox.ble_subsystem.init_gatt().await; | 101 | ble.init_gatt().await; |
| 107 | let response = mbox.ble_subsystem.read().await.unwrap(); | 102 | let response = ble.read().await.unwrap(); |
| 108 | defmt::info!("{}", response); | 103 | defmt::info!("{}", response); |
| 109 | 104 | ||
| 110 | info!("GAP init..."); | 105 | info!("GAP init..."); |
| 111 | mbox.ble_subsystem | 106 | ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await; |
| 112 | .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) | 107 | let response = ble.read().await.unwrap(); |
| 113 | .await; | ||
| 114 | let response = mbox.ble_subsystem.read().await.unwrap(); | ||
| 115 | defmt::info!("{}", response); | 108 | defmt::info!("{}", response); |
| 116 | 109 | ||
| 117 | // info!("set scan response..."); | 110 | // info!("set scan response..."); |
| 118 | // mbox.ble_subsystem.le_set_scan_response_data(&[]).await.unwrap(); | 111 | // ble.le_set_scan_response_data(&[]).await.unwrap(); |
| 119 | // let response = mbox.ble_subsystem.read().await.unwrap(); | 112 | // let response = ble.read().await.unwrap(); |
| 120 | // defmt::info!("{}", response); | 113 | // defmt::info!("{}", response); |
| 121 | 114 | ||
| 122 | info!("set discoverable..."); | 115 | info!("set discoverable..."); |
| 123 | mbox.ble_subsystem | 116 | ble.set_discoverable(&DiscoverableParameters { |
| 124 | .set_discoverable(&DiscoverableParameters { | 117 | advertising_type: AdvertisingType::NonConnectableUndirected, |
| 125 | advertising_type: AdvertisingType::NonConnectableUndirected, | 118 | advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), |
| 126 | advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), | 119 | address_type: OwnAddressType::Public, |
| 127 | address_type: OwnAddressType::Public, | 120 | filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, |
| 128 | filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, | 121 | local_name: None, |
| 129 | local_name: None, | 122 | advertising_data: &[], |
| 130 | advertising_data: &[], | 123 | conn_interval: (None, None), |
| 131 | conn_interval: (None, None), | 124 | }) |
| 132 | }) | 125 | .await |
| 133 | .await | 126 | .unwrap(); |
| 134 | .unwrap(); | 127 | |
| 135 | 128 | let response = ble.read().await; | |
| 136 | let response = mbox.ble_subsystem.read().await; | ||
| 137 | defmt::info!("{}", response); | 129 | defmt::info!("{}", response); |
| 138 | 130 | ||
| 139 | // remove some advertisement to decrease the packet size | 131 | // remove some advertisement to decrease the packet size |
| 140 | info!("delete tx power ad type..."); | 132 | info!("delete tx power ad type..."); |
| 141 | mbox.ble_subsystem | 133 | ble.delete_ad_type(AdvertisingDataType::TxPowerLevel).await; |
| 142 | .delete_ad_type(AdvertisingDataType::TxPowerLevel) | 134 | let response = ble.read().await.unwrap(); |
| 143 | .await; | ||
| 144 | let response = mbox.ble_subsystem.read().await.unwrap(); | ||
| 145 | defmt::info!("{}", response); | 135 | defmt::info!("{}", response); |
| 146 | 136 | ||
| 147 | info!("delete conn interval ad type..."); | 137 | info!("delete conn interval ad type..."); |
| 148 | mbox.ble_subsystem | 138 | ble.delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval) |
| 149 | .delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval) | ||
| 150 | .await; | 139 | .await; |
| 151 | let response = mbox.ble_subsystem.read().await.unwrap(); | 140 | let response = ble.read().await.unwrap(); |
| 152 | defmt::info!("{}", response); | 141 | defmt::info!("{}", response); |
| 153 | 142 | ||
| 154 | info!("update advertising data..."); | 143 | info!("update advertising data..."); |
| 155 | mbox.ble_subsystem | 144 | ble.update_advertising_data(&eddystone_advertising_data()) |
| 156 | .update_advertising_data(&eddystone_advertising_data()) | ||
| 157 | .await | 145 | .await |
| 158 | .unwrap(); | 146 | .unwrap(); |
| 159 | let response = mbox.ble_subsystem.read().await.unwrap(); | 147 | let response = ble.read().await.unwrap(); |
| 160 | defmt::info!("{}", response); | 148 | defmt::info!("{}", response); |
| 161 | 149 | ||
| 162 | info!("update advertising data type..."); | 150 | info!("update advertising data type..."); |
| 163 | mbox.ble_subsystem | 151 | ble.update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe]) |
| 164 | .update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe]) | ||
| 165 | .await | 152 | .await |
| 166 | .unwrap(); | 153 | .unwrap(); |
| 167 | let response = mbox.ble_subsystem.read().await.unwrap(); | 154 | let response = ble.read().await.unwrap(); |
| 168 | defmt::info!("{}", response); | 155 | defmt::info!("{}", response); |
| 169 | 156 | ||
| 170 | info!("update advertising data flags..."); | 157 | info!("update advertising data flags..."); |
| 171 | mbox.ble_subsystem | 158 | ble.update_advertising_data(&[ |
| 172 | .update_advertising_data(&[ | 159 | 2, |
| 173 | 2, | 160 | AdvertisingDataType::Flags as u8, |
| 174 | AdvertisingDataType::Flags as u8, | 161 | (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support |
| 175 | (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support | 162 | ]) |
| 176 | ]) | 163 | .await |
| 177 | .await | 164 | .unwrap(); |
| 178 | .unwrap(); | 165 | let response = ble.read().await.unwrap(); |
| 179 | let response = mbox.ble_subsystem.read().await.unwrap(); | ||
| 180 | defmt::info!("{}", response); | 166 | defmt::info!("{}", response); |
| 181 | 167 | ||
| 182 | cortex_m::asm::wfi(); | 168 | cortex_m::asm::wfi(); |
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 5d927bc00..3484f1844 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs | |||
| @@ -8,6 +8,7 @@ use embassy_executor::Spawner; | |||
| 8 | use embassy_stm32::bind_interrupts; | 8 | use embassy_stm32::bind_interrupts; |
| 9 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 9 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 10 | use embassy_stm32::rcc::WPAN_DEFAULT; | 10 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 11 | use embassy_stm32_wpan::TlMbox; | ||
| 11 | use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; | 12 | use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; |
| 12 | use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; | 13 | use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; |
| 13 | use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; | 14 | use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; |
| @@ -28,7 +29,6 @@ use embassy_stm32_wpan::hci::{BdAddr, Event}; | |||
| 28 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; | 29 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; |
| 29 | use embassy_stm32_wpan::sub::ble::Ble; | 30 | use embassy_stm32_wpan::sub::ble::Ble; |
| 30 | use embassy_stm32_wpan::sub::mm; | 31 | use embassy_stm32_wpan::sub::mm; |
| 31 | use embassy_stm32_wpan::TlMbox; | ||
| 32 | use {defmt_rtt as _, panic_probe as _}; | 32 | use {defmt_rtt as _, panic_probe as _}; |
| 33 | 33 | ||
| 34 | bind_interrupts!(struct Irqs{ | 34 | bind_interrupts!(struct Irqs{ |
| @@ -69,92 +69,85 @@ async fn main(spawner: Spawner) { | |||
| 69 | info!("Hello World!"); | 69 | info!("Hello World!"); |
| 70 | 70 | ||
| 71 | let config = Config::default(); | 71 | let config = Config::default(); |
| 72 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); | 72 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 73 | let mut sys = mbox.sys_subsystem; | ||
| 74 | let mut ble = mbox.ble_subsystem; | ||
| 73 | 75 | ||
| 74 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); | 76 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 75 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 76 | info!("sys event: {}", sys_event.payload()); | ||
| 77 | 77 | ||
| 78 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | 78 | let _ = sys.shci_c2_ble_init(Default::default()).await; |
| 79 | 79 | ||
| 80 | info!("resetting BLE..."); | 80 | info!("resetting BLE..."); |
| 81 | mbox.ble_subsystem.reset().await; | 81 | ble.reset().await; |
| 82 | let response = mbox.ble_subsystem.read().await; | 82 | let response = ble.read().await; |
| 83 | defmt::debug!("{}", response); | 83 | defmt::debug!("{}", response); |
| 84 | 84 | ||
| 85 | info!("config public address..."); | 85 | info!("config public address..."); |
| 86 | mbox.ble_subsystem | 86 | ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build()) |
| 87 | .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) | ||
| 88 | .await; | 87 | .await; |
| 89 | let response = mbox.ble_subsystem.read().await; | 88 | let response = ble.read().await; |
| 90 | defmt::debug!("{}", response); | 89 | defmt::debug!("{}", response); |
| 91 | 90 | ||
| 92 | info!("config random address..."); | 91 | info!("config random address..."); |
| 93 | mbox.ble_subsystem | 92 | ble.write_config_data(&ConfigData::random_address(get_random_addr()).build()) |
| 94 | .write_config_data(&ConfigData::random_address(get_random_addr()).build()) | ||
| 95 | .await; | 93 | .await; |
| 96 | let response = mbox.ble_subsystem.read().await; | 94 | let response = ble.read().await; |
| 97 | defmt::debug!("{}", response); | 95 | defmt::debug!("{}", response); |
| 98 | 96 | ||
| 99 | info!("config identity root..."); | 97 | info!("config identity root..."); |
| 100 | mbox.ble_subsystem | 98 | ble.write_config_data(&ConfigData::identity_root(&get_irk()).build()) |
| 101 | .write_config_data(&ConfigData::identity_root(&get_irk()).build()) | ||
| 102 | .await; | 99 | .await; |
| 103 | let response = mbox.ble_subsystem.read().await; | 100 | let response = ble.read().await; |
| 104 | defmt::debug!("{}", response); | 101 | defmt::debug!("{}", response); |
| 105 | 102 | ||
| 106 | info!("config encryption root..."); | 103 | info!("config encryption root..."); |
| 107 | mbox.ble_subsystem | 104 | ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build()) |
| 108 | .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) | ||
| 109 | .await; | 105 | .await; |
| 110 | let response = mbox.ble_subsystem.read().await; | 106 | let response = ble.read().await; |
| 111 | defmt::debug!("{}", response); | 107 | defmt::debug!("{}", response); |
| 112 | 108 | ||
| 113 | info!("config tx power level..."); | 109 | info!("config tx power level..."); |
| 114 | mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; | 110 | ble.set_tx_power_level(PowerLevel::ZerodBm).await; |
| 115 | let response = mbox.ble_subsystem.read().await; | 111 | let response = ble.read().await; |
| 116 | defmt::debug!("{}", response); | 112 | defmt::debug!("{}", response); |
| 117 | 113 | ||
| 118 | info!("GATT init..."); | 114 | info!("GATT init..."); |
| 119 | mbox.ble_subsystem.init_gatt().await; | 115 | ble.init_gatt().await; |
| 120 | let response = mbox.ble_subsystem.read().await; | 116 | let response = ble.read().await; |
| 121 | defmt::debug!("{}", response); | 117 | defmt::debug!("{}", response); |
| 122 | 118 | ||
| 123 | info!("GAP init..."); | 119 | info!("GAP init..."); |
| 124 | mbox.ble_subsystem | 120 | ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await; |
| 125 | .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) | 121 | let response = ble.read().await; |
| 126 | .await; | ||
| 127 | let response = mbox.ble_subsystem.read().await; | ||
| 128 | defmt::debug!("{}", response); | 122 | defmt::debug!("{}", response); |
| 129 | 123 | ||
| 130 | info!("set IO capabilities..."); | 124 | info!("set IO capabilities..."); |
| 131 | mbox.ble_subsystem.set_io_capability(IoCapability::DisplayConfirm).await; | 125 | ble.set_io_capability(IoCapability::DisplayConfirm).await; |
| 132 | let response = mbox.ble_subsystem.read().await; | 126 | let response = ble.read().await; |
| 133 | defmt::debug!("{}", response); | 127 | defmt::debug!("{}", response); |
| 134 | 128 | ||
| 135 | info!("set authentication requirements..."); | 129 | info!("set authentication requirements..."); |
| 136 | mbox.ble_subsystem | 130 | ble.set_authentication_requirement(&AuthenticationRequirements { |
| 137 | .set_authentication_requirement(&AuthenticationRequirements { | 131 | bonding_required: false, |
| 138 | bonding_required: false, | 132 | keypress_notification_support: false, |
| 139 | keypress_notification_support: false, | 133 | mitm_protection_required: false, |
| 140 | mitm_protection_required: false, | 134 | encryption_key_size_range: (8, 16), |
| 141 | encryption_key_size_range: (8, 16), | 135 | fixed_pin: Pin::Requested, |
| 142 | fixed_pin: Pin::Requested, | 136 | identity_address_type: AddressType::Public, |
| 143 | identity_address_type: AddressType::Public, | 137 | secure_connection_support: SecureConnectionSupport::Optional, |
| 144 | secure_connection_support: SecureConnectionSupport::Optional, | 138 | }) |
| 145 | }) | 139 | .await |
| 146 | .await | 140 | .unwrap(); |
| 147 | .unwrap(); | 141 | let response = ble.read().await; |
| 148 | let response = mbox.ble_subsystem.read().await; | ||
| 149 | defmt::debug!("{}", response); | 142 | defmt::debug!("{}", response); |
| 150 | 143 | ||
| 151 | info!("set scan response data..."); | 144 | info!("set scan response data..."); |
| 152 | mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); | 145 | ble.le_set_scan_response_data(b"TXTX").await.unwrap(); |
| 153 | let response = mbox.ble_subsystem.read().await; | 146 | let response = ble.read().await; |
| 154 | defmt::debug!("{}", response); | 147 | defmt::debug!("{}", response); |
| 155 | 148 | ||
| 156 | defmt::info!("initializing services and characteristics..."); | 149 | defmt::info!("initializing services and characteristics..."); |
| 157 | let mut ble_context = init_gatt_services(&mut mbox.ble_subsystem).await.unwrap(); | 150 | let mut ble_context = init_gatt_services(&mut ble).await.unwrap(); |
| 158 | defmt::info!("{}", ble_context); | 151 | defmt::info!("{}", ble_context); |
| 159 | 152 | ||
| 160 | let discovery_params = DiscoverableParameters { | 153 | let discovery_params = DiscoverableParameters { |
| @@ -168,12 +161,12 @@ async fn main(spawner: Spawner) { | |||
| 168 | }; | 161 | }; |
| 169 | 162 | ||
| 170 | info!("set discoverable..."); | 163 | info!("set discoverable..."); |
| 171 | mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); | 164 | ble.set_discoverable(&discovery_params).await.unwrap(); |
| 172 | let response = mbox.ble_subsystem.read().await; | 165 | let response = ble.read().await; |
| 173 | defmt::debug!("{}", response); | 166 | defmt::debug!("{}", response); |
| 174 | 167 | ||
| 175 | loop { | 168 | loop { |
| 176 | let response = mbox.ble_subsystem.read().await; | 169 | let response = ble.read().await; |
| 177 | defmt::debug!("{}", response); | 170 | defmt::debug!("{}", response); |
| 178 | 171 | ||
| 179 | if let Ok(Packet::Event(event)) = response { | 172 | if let Ok(Packet::Event(event)) = response { |
| @@ -184,24 +177,23 @@ async fn main(spawner: Spawner) { | |||
| 184 | Event::DisconnectionComplete(_) => { | 177 | Event::DisconnectionComplete(_) => { |
| 185 | defmt::info!("disconnected"); | 178 | defmt::info!("disconnected"); |
| 186 | ble_context.is_subscribed = false; | 179 | ble_context.is_subscribed = false; |
| 187 | mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); | 180 | ble.set_discoverable(&discovery_params).await.unwrap(); |
| 188 | } | 181 | } |
| 189 | Event::Vendor(vendor_event) => match vendor_event { | 182 | Event::Vendor(vendor_event) => match vendor_event { |
| 190 | VendorEvent::AttReadPermitRequest(read_req) => { | 183 | VendorEvent::AttReadPermitRequest(read_req) => { |
| 191 | defmt::info!("read request received {}, allowing", read_req); | 184 | defmt::info!("read request received {}, allowing", read_req); |
| 192 | mbox.ble_subsystem.allow_read(read_req.conn_handle).await | 185 | ble.allow_read(read_req.conn_handle).await |
| 193 | } | 186 | } |
| 194 | VendorEvent::AttWritePermitRequest(write_req) => { | 187 | VendorEvent::AttWritePermitRequest(write_req) => { |
| 195 | defmt::info!("write request received {}, allowing", write_req); | 188 | defmt::info!("write request received {}, allowing", write_req); |
| 196 | mbox.ble_subsystem | 189 | ble.write_response(&WriteResponseParameters { |
| 197 | .write_response(&WriteResponseParameters { | 190 | conn_handle: write_req.conn_handle, |
| 198 | conn_handle: write_req.conn_handle, | 191 | attribute_handle: write_req.attribute_handle, |
| 199 | attribute_handle: write_req.attribute_handle, | 192 | status: Ok(()), |
| 200 | status: Ok(()), | 193 | value: write_req.value(), |
| 201 | value: write_req.value(), | 194 | }) |
| 202 | }) | 195 | .await |
| 203 | .await | 196 | .unwrap() |
| 204 | .unwrap() | ||
| 205 | } | 197 | } |
| 206 | VendorEvent::GattAttributeModified(attribute) => { | 198 | VendorEvent::GattAttributeModified(attribute) => { |
| 207 | defmt::info!("{}", ble_context); | 199 | defmt::info!("{}", ble_context); |
| @@ -224,7 +216,7 @@ async fn main(spawner: Spawner) { | |||
| 224 | } | 216 | } |
| 225 | 217 | ||
| 226 | #[embassy_executor::task] | 218 | #[embassy_executor::task] |
| 227 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 219 | async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { |
| 228 | memory_manager.run_queue().await; | 220 | memory_manager.run_queue().await; |
| 229 | } | 221 | } |
| 230 | 222 | ||
| @@ -285,7 +277,7 @@ pub struct CharHandles { | |||
| 285 | pub notify: AttributeHandle, | 277 | pub notify: AttributeHandle, |
| 286 | } | 278 | } |
| 287 | 279 | ||
| 288 | pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result<BleContext, ()> { | 280 | pub async fn init_gatt_services<'a>(ble_subsystem: &mut Ble<'a>) -> Result<BleContext, ()> { |
| 289 | let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?; | 281 | let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?; |
| 290 | 282 | ||
| 291 | let read = gatt_add_char( | 283 | let read = gatt_add_char( |
| @@ -322,7 +314,7 @@ pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result<BleContext, ( | |||
| 322 | }) | 314 | }) |
| 323 | } | 315 | } |
| 324 | 316 | ||
| 325 | async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result<AttributeHandle, ()> { | 317 | async fn gatt_add_service<'a>(ble_subsystem: &mut Ble<'a>, uuid: Uuid) -> Result<AttributeHandle, ()> { |
| 326 | ble_subsystem | 318 | ble_subsystem |
| 327 | .add_service(&AddServiceParameters { | 319 | .add_service(&AddServiceParameters { |
| 328 | uuid, | 320 | uuid, |
| @@ -348,8 +340,8 @@ async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result<Attribu | |||
| 348 | } | 340 | } |
| 349 | } | 341 | } |
| 350 | 342 | ||
| 351 | async fn gatt_add_char( | 343 | async fn gatt_add_char<'a>( |
| 352 | ble_subsystem: &mut Ble, | 344 | ble_subsystem: &mut Ble<'a>, |
| 353 | service_handle: AttributeHandle, | 345 | service_handle: AttributeHandle, |
| 354 | characteristic_uuid: Uuid, | 346 | characteristic_uuid: Uuid, |
| 355 | characteristic_properties: CharacteristicProperty, | 347 | characteristic_properties: CharacteristicProperty, |
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index ede6cf4b9..4bab6ea9f 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs | |||
| @@ -6,11 +6,11 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::bind_interrupts; | 6 | use embassy_stm32::bind_interrupts; |
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 8 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 9 | use embassy_stm32_wpan::TlMbox; | ||
| 9 | use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; | 10 | use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; |
| 10 | use embassy_stm32_wpan::mac::event::MacEvent; | 11 | use embassy_stm32_wpan::mac::event::MacEvent; |
| 11 | use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; | 12 | use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; |
| 12 | use embassy_stm32_wpan::sub::mm; | 13 | use embassy_stm32_wpan::sub::mm; |
| 13 | use embassy_stm32_wpan::TlMbox; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | bind_interrupts!(struct Irqs{ | 16 | bind_interrupts!(struct Irqs{ |
| @@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs{ | |||
| 19 | }); | 19 | }); |
| 20 | 20 | ||
| 21 | #[embassy_executor::task] | 21 | #[embassy_executor::task] |
| 22 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 22 | async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { |
| 23 | memory_manager.run_queue().await; | 23 | memory_manager.run_queue().await; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| @@ -54,74 +54,72 @@ async fn main(spawner: Spawner) { | |||
| 54 | info!("Hello World!"); | 54 | info!("Hello World!"); |
| 55 | 55 | ||
| 56 | let config = Config::default(); | 56 | let config = Config::default(); |
| 57 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 57 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 58 | let mut sys = mbox.sys_subsystem; | ||
| 58 | 59 | ||
| 59 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); | 60 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 60 | 61 | ||
| 61 | let sys_event = mbox.sys_subsystem.read().await; | 62 | let result = sys.shci_c2_mac_802_15_4_init().await; |
| 62 | info!("sys event: {}", sys_event.payload()); | ||
| 63 | |||
| 64 | core::mem::drop(sys_event); | ||
| 65 | |||
| 66 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 67 | info!("initialized mac: {}", result); | 63 | info!("initialized mac: {}", result); |
| 68 | 64 | ||
| 65 | let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split(); | ||
| 66 | |||
| 69 | info!("resetting"); | 67 | info!("resetting"); |
| 70 | mbox.mac_subsystem | 68 | mac_tx |
| 71 | .send_command(&ResetRequest { | 69 | .send_command(&ResetRequest { |
| 72 | set_default_pib: true, | 70 | set_default_pib: true, |
| 73 | ..Default::default() | 71 | ..Default::default() |
| 74 | }) | 72 | }) |
| 75 | .await | 73 | .await |
| 76 | .unwrap(); | 74 | .unwrap(); |
| 77 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 75 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 78 | 76 | ||
| 79 | info!("setting extended address"); | 77 | info!("setting extended address"); |
| 80 | let extended_address: u64 = 0xACDE480000000001; | 78 | let extended_address: u64 = 0xACDE480000000001; |
| 81 | mbox.mac_subsystem | 79 | mac_tx |
| 82 | .send_command(&SetRequest { | 80 | .send_command(&SetRequest { |
| 83 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | 81 | pib_attribute_ptr: &extended_address as *const _ as *const u8, |
| 84 | pib_attribute: PibId::ExtendedAddress, | 82 | pib_attribute: PibId::ExtendedAddress, |
| 85 | }) | 83 | }) |
| 86 | .await | 84 | .await |
| 87 | .unwrap(); | 85 | .unwrap(); |
| 88 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 86 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 89 | 87 | ||
| 90 | info!("setting short address"); | 88 | info!("setting short address"); |
| 91 | let short_address: u16 = 0x1122; | 89 | let short_address: u16 = 0x1122; |
| 92 | mbox.mac_subsystem | 90 | mac_tx |
| 93 | .send_command(&SetRequest { | 91 | .send_command(&SetRequest { |
| 94 | pib_attribute_ptr: &short_address as *const _ as *const u8, | 92 | pib_attribute_ptr: &short_address as *const _ as *const u8, |
| 95 | pib_attribute: PibId::ShortAddress, | 93 | pib_attribute: PibId::ShortAddress, |
| 96 | }) | 94 | }) |
| 97 | .await | 95 | .await |
| 98 | .unwrap(); | 96 | .unwrap(); |
| 99 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 97 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 100 | 98 | ||
| 101 | info!("setting association permit"); | 99 | info!("setting association permit"); |
| 102 | let association_permit: bool = true; | 100 | let association_permit: bool = true; |
| 103 | mbox.mac_subsystem | 101 | mac_tx |
| 104 | .send_command(&SetRequest { | 102 | .send_command(&SetRequest { |
| 105 | pib_attribute_ptr: &association_permit as *const _ as *const u8, | 103 | pib_attribute_ptr: &association_permit as *const _ as *const u8, |
| 106 | pib_attribute: PibId::AssociationPermit, | 104 | pib_attribute: PibId::AssociationPermit, |
| 107 | }) | 105 | }) |
| 108 | .await | 106 | .await |
| 109 | .unwrap(); | 107 | .unwrap(); |
| 110 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 108 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 111 | 109 | ||
| 112 | info!("setting TX power"); | 110 | info!("setting TX power"); |
| 113 | let transmit_power: i8 = 2; | 111 | let transmit_power: i8 = 2; |
| 114 | mbox.mac_subsystem | 112 | mac_tx |
| 115 | .send_command(&SetRequest { | 113 | .send_command(&SetRequest { |
| 116 | pib_attribute_ptr: &transmit_power as *const _ as *const u8, | 114 | pib_attribute_ptr: &transmit_power as *const _ as *const u8, |
| 117 | pib_attribute: PibId::TransmitPower, | 115 | pib_attribute: PibId::TransmitPower, |
| 118 | }) | 116 | }) |
| 119 | .await | 117 | .await |
| 120 | .unwrap(); | 118 | .unwrap(); |
| 121 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 119 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 122 | 120 | ||
| 123 | info!("starting FFD device"); | 121 | info!("starting FFD device"); |
| 124 | mbox.mac_subsystem | 122 | mac_tx |
| 125 | .send_command(&StartRequest { | 123 | .send_command(&StartRequest { |
| 126 | pan_id: PanId([0x1A, 0xAA]), | 124 | pan_id: PanId([0x1A, 0xAA]), |
| 127 | channel_number: MacChannel::Channel16, | 125 | channel_number: MacChannel::Channel16, |
| @@ -133,28 +131,27 @@ async fn main(spawner: Spawner) { | |||
| 133 | }) | 131 | }) |
| 134 | .await | 132 | .await |
| 135 | .unwrap(); | 133 | .unwrap(); |
| 136 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 134 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 137 | 135 | ||
| 138 | info!("setting RX on when idle"); | 136 | info!("setting RX on when idle"); |
| 139 | let rx_on_while_idle: bool = true; | 137 | let rx_on_while_idle: bool = true; |
| 140 | mbox.mac_subsystem | 138 | mac_tx |
| 141 | .send_command(&SetRequest { | 139 | .send_command(&SetRequest { |
| 142 | pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, | 140 | pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, |
| 143 | pib_attribute: PibId::RxOnWhenIdle, | 141 | pib_attribute: PibId::RxOnWhenIdle, |
| 144 | }) | 142 | }) |
| 145 | .await | 143 | .await |
| 146 | .unwrap(); | 144 | .unwrap(); |
| 147 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 145 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 148 | 146 | ||
| 149 | loop { | 147 | loop { |
| 150 | let evt = mbox.mac_subsystem.read().await; | 148 | let evt = mac_rx.read().await; |
| 151 | if let Ok(evt) = evt { | 149 | if let Ok(evt) = evt { |
| 152 | defmt::info!("parsed mac event"); | 150 | defmt::info!("parsed mac event"); |
| 153 | defmt::info!("{:#x}", evt); | 151 | defmt::info!("{:#x}", evt); |
| 154 | 152 | ||
| 155 | match evt { | 153 | match evt { |
| 156 | MacEvent::MlmeAssociateInd(association) => mbox | 154 | MacEvent::MlmeAssociateInd(association) => mac_tx |
| 157 | .mac_subsystem | ||
| 158 | .send_command(&AssociateResponse { | 155 | .send_command(&AssociateResponse { |
| 159 | device_address: association.device_address, | 156 | device_address: association.device_address, |
| 160 | assoc_short_address: [0x33, 0x44], | 157 | assoc_short_address: [0x33, 0x44], |
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index cc3b21e2e..b4789e3ee 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs | |||
| @@ -1,32 +1,44 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::net::Ipv6Addr; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | ||
| 9 | use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6}; | ||
| 6 | use embassy_stm32::bind_interrupts; | 10 | use embassy_stm32::bind_interrupts; |
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 11 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 12 | use embassy_stm32::peripherals::RNG; | ||
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 13 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 9 | use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; | 14 | use embassy_stm32::rng::InterruptHandler as RngInterruptHandler; |
| 10 | use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId}; | ||
| 11 | use embassy_stm32_wpan::mac::{self, Runner}; | ||
| 12 | use embassy_stm32_wpan::sub::mm; | ||
| 13 | use embassy_stm32_wpan::TlMbox; | 15 | use embassy_stm32_wpan::TlMbox; |
| 16 | use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; | ||
| 17 | use embassy_stm32_wpan::sub::mm; | ||
| 18 | use embassy_time::{Duration, Timer}; | ||
| 19 | use heapless::Vec; | ||
| 14 | use static_cell::StaticCell; | 20 | use static_cell::StaticCell; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 22 | ||
| 17 | bind_interrupts!(struct Irqs{ | 23 | bind_interrupts!(struct Irqs{ |
| 18 | IPCC_C1_RX => ReceiveInterruptHandler; | 24 | IPCC_C1_RX => ReceiveInterruptHandler; |
| 19 | IPCC_C1_TX => TransmitInterruptHandler; | 25 | IPCC_C1_TX => TransmitInterruptHandler; |
| 26 | RNG => RngInterruptHandler<RNG>; | ||
| 20 | }); | 27 | }); |
| 21 | 28 | ||
| 22 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| 23 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 30 | async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) -> ! { |
| 24 | memory_manager.run_queue().await; | 31 | memory_manager.run_queue().await |
| 25 | } | 32 | } |
| 26 | 33 | ||
| 27 | #[embassy_executor::task] | 34 | #[embassy_executor::task] |
| 28 | async fn run_mac(runner: &'static Runner<'static>) { | 35 | async fn run_mac(runner: &'static Runner<'static>) -> ! { |
| 29 | runner.run().await; | 36 | runner.run().await |
| 37 | } | ||
| 38 | |||
| 39 | #[embassy_executor::task] | ||
| 40 | async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> ! { | ||
| 41 | runner.run().await | ||
| 30 | } | 42 | } |
| 31 | 43 | ||
| 32 | #[embassy_executor::main] | 44 | #[embassy_executor::main] |
| @@ -60,118 +72,76 @@ async fn main(spawner: Spawner) { | |||
| 60 | info!("Hello World!"); | 72 | info!("Hello World!"); |
| 61 | 73 | ||
| 62 | let config = Config::default(); | 74 | let config = Config::default(); |
| 63 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 75 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 64 | 76 | ||
| 65 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); | 77 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 66 | 78 | ||
| 67 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 68 | info!("sys event: {}", sys_event.payload()); | ||
| 69 | |||
| 70 | core::mem::drop(sys_event); | ||
| 71 | |||
| 72 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | 79 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; |
| 73 | info!("initialized mac: {}", result); | 80 | info!("initialized mac: {}", result); |
| 74 | 81 | ||
| 75 | info!("resetting"); | 82 | static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new(); |
| 76 | mbox.mac_subsystem | ||
| 77 | .send_command(&ResetRequest { | ||
| 78 | set_default_pib: true, | ||
| 79 | ..Default::default() | ||
| 80 | }) | ||
| 81 | .await | ||
| 82 | .unwrap(); | ||
| 83 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 84 | |||
| 85 | info!("setting extended address"); | ||
| 86 | let extended_address: u64 = 0xACDE480000000001; | ||
| 87 | mbox.mac_subsystem | ||
| 88 | .send_command(&SetRequest { | ||
| 89 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | ||
| 90 | pib_attribute: PibId::ExtendedAddress, | ||
| 91 | }) | ||
| 92 | .await | ||
| 93 | .unwrap(); | ||
| 94 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 95 | |||
| 96 | info!("setting short address"); | ||
| 97 | let short_address: u16 = 0x1122; | ||
| 98 | mbox.mac_subsystem | ||
| 99 | .send_command(&SetRequest { | ||
| 100 | pib_attribute_ptr: &short_address as *const _ as *const u8, | ||
| 101 | pib_attribute: PibId::ShortAddress, | ||
| 102 | }) | ||
| 103 | .await | ||
| 104 | .unwrap(); | ||
| 105 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 106 | |||
| 107 | info!("setting association permit"); | ||
| 108 | let association_permit: bool = true; | ||
| 109 | mbox.mac_subsystem | ||
| 110 | .send_command(&SetRequest { | ||
| 111 | pib_attribute_ptr: &association_permit as *const _ as *const u8, | ||
| 112 | pib_attribute: PibId::AssociationPermit, | ||
| 113 | }) | ||
| 114 | .await | ||
| 115 | .unwrap(); | ||
| 116 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 117 | |||
| 118 | info!("setting TX power"); | ||
| 119 | let transmit_power: i8 = 2; | ||
| 120 | mbox.mac_subsystem | ||
| 121 | .send_command(&SetRequest { | ||
| 122 | pib_attribute_ptr: &transmit_power as *const _ as *const u8, | ||
| 123 | pib_attribute: PibId::TransmitPower, | ||
| 124 | }) | ||
| 125 | .await | ||
| 126 | .unwrap(); | ||
| 127 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 128 | |||
| 129 | info!("starting FFD device"); | ||
| 130 | mbox.mac_subsystem | ||
| 131 | .send_command(&StartRequest { | ||
| 132 | pan_id: PanId([0x1A, 0xAA]), | ||
| 133 | channel_number: MacChannel::Channel16, | ||
| 134 | beacon_order: 0x0F, | ||
| 135 | superframe_order: 0x0F, | ||
| 136 | pan_coordinator: true, | ||
| 137 | battery_life_extension: false, | ||
| 138 | ..Default::default() | ||
| 139 | }) | ||
| 140 | .await | ||
| 141 | .unwrap(); | ||
| 142 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 143 | |||
| 144 | info!("setting RX on when idle"); | ||
| 145 | let rx_on_while_idle: bool = true; | ||
| 146 | mbox.mac_subsystem | ||
| 147 | .send_command(&SetRequest { | ||
| 148 | pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, | ||
| 149 | pib_attribute: PibId::RxOnWhenIdle, | ||
| 150 | }) | ||
| 151 | .await | ||
| 152 | .unwrap(); | ||
| 153 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 154 | |||
| 155 | static TX1: StaticCell<[u8; 127]> = StaticCell::new(); | ||
| 156 | static TX2: StaticCell<[u8; 127]> = StaticCell::new(); | ||
| 157 | static TX3: StaticCell<[u8; 127]> = StaticCell::new(); | ||
| 158 | static TX4: StaticCell<[u8; 127]> = StaticCell::new(); | ||
| 159 | static TX5: StaticCell<[u8; 127]> = StaticCell::new(); | ||
| 160 | let tx_queue = [ | ||
| 161 | TX1.init([0u8; 127]), | ||
| 162 | TX2.init([0u8; 127]), | ||
| 163 | TX3.init([0u8; 127]), | ||
| 164 | TX4.init([0u8; 127]), | ||
| 165 | TX5.init([0u8; 127]), | ||
| 166 | ]; | ||
| 167 | |||
| 168 | static RUNNER: StaticCell<Runner> = StaticCell::new(); | 83 | static RUNNER: StaticCell<Runner> = StaticCell::new(); |
| 169 | let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue)); | 84 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); |
| 85 | |||
| 86 | let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem)); | ||
| 87 | |||
| 88 | let (driver, mac_runner, mut control) = Driver::new( | ||
| 89 | driver_state, | ||
| 90 | 0x1122u16.to_be_bytes().try_into().unwrap(), | ||
| 91 | 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), | ||
| 92 | ); | ||
| 93 | |||
| 94 | // TODO: rng does not work for some reason | ||
| 95 | // Generate random seed. | ||
| 96 | // let mut rng = Rng::new(p.RNG, Irqs); | ||
| 97 | let seed = [0; 8]; | ||
| 98 | // let _ = rng.async_fill_bytes(&mut seed).await; | ||
| 99 | let seed = u64::from_le_bytes(seed); | ||
| 100 | |||
| 101 | info!("seed generated"); | ||
| 102 | |||
| 103 | // Init network stack | ||
| 104 | let ipv6_addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); | ||
| 105 | |||
| 106 | let config = embassy_net::Config::ipv6_static(StaticConfigV6 { | ||
| 107 | address: Ipv6Cidr::new(ipv6_addr, 104), | ||
| 108 | gateway: None, | ||
| 109 | dns_servers: Vec::new(), | ||
| 110 | }); | ||
| 111 | |||
| 112 | let (stack, eth_runner) = embassy_net::new(driver, config, RESOURCES.init(StackResources::new()), seed); | ||
| 113 | |||
| 114 | // wpan runner | ||
| 115 | spawner.spawn(run_mac(RUNNER.init(mac_runner)).unwrap()); | ||
| 116 | |||
| 117 | // Launch network task | ||
| 118 | spawner.spawn(unwrap!(run_net(eth_runner))); | ||
| 119 | |||
| 120 | info!("Network task initialized"); | ||
| 121 | |||
| 122 | control.init_link([0x1A, 0xAA]).await; | ||
| 123 | |||
| 124 | // Ensure DHCP configuration is up before trying connect | ||
| 125 | stack.wait_config_up().await; | ||
| 126 | |||
| 127 | info!("Network up"); | ||
| 128 | |||
| 129 | // Then we can use it! | ||
| 130 | let mut rx_meta = [PacketMetadata::EMPTY]; | ||
| 131 | let mut rx_buffer = [0; 4096]; | ||
| 132 | let mut tx_meta = [PacketMetadata::EMPTY]; | ||
| 133 | let mut tx_buffer = [0; 4096]; | ||
| 134 | |||
| 135 | let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | ||
| 136 | |||
| 137 | let remote_endpoint = (Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2fb), 8000); | ||
| 138 | |||
| 139 | let send_buf = [0u8; 20]; | ||
| 170 | 140 | ||
| 171 | spawner.spawn(run_mac(runner).unwrap()); | 141 | socket.bind((ipv6_addr, 8000)).unwrap(); |
| 142 | socket.send_to(&send_buf, remote_endpoint).await.unwrap(); | ||
| 172 | 143 | ||
| 173 | let (driver, control) = mac::new(runner).await; | 144 | Timer::after(Duration::from_secs(2)).await; |
| 174 | 145 | ||
| 175 | let _ = driver; | 146 | cortex_m::asm::bkpt(); |
| 176 | let _ = control; | ||
| 177 | } | 147 | } |
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index d872104a8..dae3c5200 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs | |||
| @@ -6,13 +6,13 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::bind_interrupts; | 6 | use embassy_stm32::bind_interrupts; |
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 8 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 9 | use embassy_stm32_wpan::TlMbox; | ||
| 9 | use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; | 10 | use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; |
| 10 | use embassy_stm32_wpan::mac::event::MacEvent; | 11 | use embassy_stm32_wpan::mac::event::MacEvent; |
| 11 | use embassy_stm32_wpan::mac::typedefs::{ | 12 | use embassy_stm32_wpan::mac::typedefs::{ |
| 12 | AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, | 13 | AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, |
| 13 | }; | 14 | }; |
| 14 | use embassy_stm32_wpan::sub::mm; | 15 | use embassy_stm32_wpan::sub::mm; |
| 15 | use embassy_stm32_wpan::TlMbox; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | bind_interrupts!(struct Irqs{ | 18 | bind_interrupts!(struct Irqs{ |
| @@ -21,7 +21,7 @@ bind_interrupts!(struct Irqs{ | |||
| 21 | }); | 21 | }); |
| 22 | 22 | ||
| 23 | #[embassy_executor::task] | 23 | #[embassy_executor::task] |
| 24 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 24 | async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { |
| 25 | memory_manager.run_queue().await; | 25 | memory_manager.run_queue().await; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| @@ -56,41 +56,39 @@ async fn main(spawner: Spawner) { | |||
| 56 | info!("Hello World!"); | 56 | info!("Hello World!"); |
| 57 | 57 | ||
| 58 | let config = Config::default(); | 58 | let config = Config::default(); |
| 59 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 59 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 60 | let mut sys = mbox.sys_subsystem; | ||
| 60 | 61 | ||
| 61 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); | 62 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 62 | 63 | ||
| 63 | let sys_event = mbox.sys_subsystem.read().await; | 64 | let result = sys.shci_c2_mac_802_15_4_init().await; |
| 64 | info!("sys event: {}", sys_event.payload()); | ||
| 65 | |||
| 66 | core::mem::drop(sys_event); | ||
| 67 | |||
| 68 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 69 | info!("initialized mac: {}", result); | 65 | info!("initialized mac: {}", result); |
| 70 | 66 | ||
| 67 | let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split(); | ||
| 68 | |||
| 71 | info!("resetting"); | 69 | info!("resetting"); |
| 72 | mbox.mac_subsystem | 70 | mac_tx |
| 73 | .send_command(&ResetRequest { | 71 | .send_command(&ResetRequest { |
| 74 | set_default_pib: true, | 72 | set_default_pib: true, |
| 75 | ..Default::default() | 73 | ..Default::default() |
| 76 | }) | 74 | }) |
| 77 | .await | 75 | .await |
| 78 | .unwrap(); | 76 | .unwrap(); |
| 79 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 77 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 80 | 78 | ||
| 81 | info!("setting extended address"); | 79 | info!("setting extended address"); |
| 82 | let extended_address: u64 = 0xACDE480000000002; | 80 | let extended_address: u64 = 0xACDE480000000002; |
| 83 | mbox.mac_subsystem | 81 | mac_tx |
| 84 | .send_command(&SetRequest { | 82 | .send_command(&SetRequest { |
| 85 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | 83 | pib_attribute_ptr: &extended_address as *const _ as *const u8, |
| 86 | pib_attribute: PibId::ExtendedAddress, | 84 | pib_attribute: PibId::ExtendedAddress, |
| 87 | }) | 85 | }) |
| 88 | .await | 86 | .await |
| 89 | .unwrap(); | 87 | .unwrap(); |
| 90 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | 88 | defmt::info!("{:#x}", mac_rx.read().await.unwrap()); |
| 91 | 89 | ||
| 92 | info!("getting extended address"); | 90 | info!("getting extended address"); |
| 93 | mbox.mac_subsystem | 91 | mac_tx |
| 94 | .send_command(&GetRequest { | 92 | .send_command(&GetRequest { |
| 95 | pib_attribute: PibId::ExtendedAddress, | 93 | pib_attribute: PibId::ExtendedAddress, |
| 96 | ..Default::default() | 94 | ..Default::default() |
| @@ -99,7 +97,7 @@ async fn main(spawner: Spawner) { | |||
| 99 | .unwrap(); | 97 | .unwrap(); |
| 100 | 98 | ||
| 101 | { | 99 | { |
| 102 | let evt = mbox.mac_subsystem.read().await.unwrap(); | 100 | let evt = mac_rx.read().await.unwrap(); |
| 103 | info!("{:#x}", evt); | 101 | info!("{:#x}", evt); |
| 104 | 102 | ||
| 105 | if let MacEvent::MlmeGetCnf(evt) = evt { | 103 | if let MacEvent::MlmeGetCnf(evt) = evt { |
| @@ -125,9 +123,9 @@ async fn main(spawner: Spawner) { | |||
| 125 | key_index: 152, | 123 | key_index: 152, |
| 126 | }; | 124 | }; |
| 127 | info!("{}", a); | 125 | info!("{}", a); |
| 128 | mbox.mac_subsystem.send_command(&a).await.unwrap(); | 126 | mac_tx.send_command(&a).await.unwrap(); |
| 129 | let short_addr = { | 127 | let short_addr = { |
| 130 | let evt = mbox.mac_subsystem.read().await.unwrap(); | 128 | let evt = mac_rx.read().await.unwrap(); |
| 131 | info!("{:#x}", evt); | 129 | info!("{:#x}", evt); |
| 132 | 130 | ||
| 133 | if let MacEvent::MlmeAssociateCnf(conf) = evt { | 131 | if let MacEvent::MlmeAssociateCnf(conf) = evt { |
| @@ -138,7 +136,7 @@ async fn main(spawner: Spawner) { | |||
| 138 | }; | 136 | }; |
| 139 | 137 | ||
| 140 | info!("setting short address"); | 138 | info!("setting short address"); |
| 141 | mbox.mac_subsystem | 139 | mac_tx |
| 142 | .send_command(&SetRequest { | 140 | .send_command(&SetRequest { |
| 143 | pib_attribute_ptr: &short_addr as *const _ as *const u8, | 141 | pib_attribute_ptr: &short_addr as *const _ as *const u8, |
| 144 | pib_attribute: PibId::ShortAddress, | 142 | pib_attribute: PibId::ShortAddress, |
| @@ -146,13 +144,13 @@ async fn main(spawner: Spawner) { | |||
| 146 | .await | 144 | .await |
| 147 | .unwrap(); | 145 | .unwrap(); |
| 148 | { | 146 | { |
| 149 | let evt = mbox.mac_subsystem.read().await.unwrap(); | 147 | let evt = mac_rx.read().await.unwrap(); |
| 150 | info!("{:#x}", evt); | 148 | info!("{:#x}", evt); |
| 151 | } | 149 | } |
| 152 | 150 | ||
| 153 | info!("sending data"); | 151 | info!("sending data"); |
| 154 | let data = b"Hello from embassy!"; | 152 | let data = b"Hello from embassy!"; |
| 155 | mbox.mac_subsystem | 153 | mac_tx |
| 156 | .send_command( | 154 | .send_command( |
| 157 | DataRequest { | 155 | DataRequest { |
| 158 | src_addr_mode: AddressMode::Short, | 156 | src_addr_mode: AddressMode::Short, |
| @@ -170,12 +168,12 @@ async fn main(spawner: Spawner) { | |||
| 170 | .await | 168 | .await |
| 171 | .unwrap(); | 169 | .unwrap(); |
| 172 | { | 170 | { |
| 173 | let evt = mbox.mac_subsystem.read().await.unwrap(); | 171 | let evt = mac_rx.read().await.unwrap(); |
| 174 | info!("{:#x}", evt); | 172 | info!("{:#x}", evt); |
| 175 | } | 173 | } |
| 176 | 174 | ||
| 177 | loop { | 175 | loop { |
| 178 | match mbox.mac_subsystem.read().await { | 176 | match mac_rx.read().await { |
| 179 | Ok(evt) => info!("{:#x}", evt), | 177 | Ok(evt) => info!("{:#x}", evt), |
| 180 | _ => continue, | 178 | _ => continue, |
| 181 | }; | 179 | }; |
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 4e7f2304d..0902e28e8 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs | |||
| @@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) { | |||
| 46 | info!("Hello World!"); | 46 | info!("Hello World!"); |
| 47 | 47 | ||
| 48 | let config = Config::default(); | 48 | let config = Config::default(); |
| 49 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 49 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 50 | 50 | ||
| 51 | loop { | 51 | loop { |
| 52 | let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info(); | 52 | let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info(); |
diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index 72a4c18e6..763dc32cd 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs | |||
| @@ -7,6 +7,7 @@ use embassy_stm32::bind_interrupts; | |||
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 8 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 9 | use embassy_stm32_wpan::TlMbox; | 9 | use embassy_stm32_wpan::TlMbox; |
| 10 | use embassy_stm32_wpan::sub::mm; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 12 | ||
| 12 | bind_interrupts!(struct Irqs{ | 13 | bind_interrupts!(struct Irqs{ |
| @@ -14,8 +15,13 @@ bind_interrupts!(struct Irqs{ | |||
| 14 | IPCC_C1_TX => TransmitInterruptHandler; | 15 | IPCC_C1_TX => TransmitInterruptHandler; |
| 15 | }); | 16 | }); |
| 16 | 17 | ||
| 18 | #[embassy_executor::task] | ||
| 19 | async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { | ||
| 20 | memory_manager.run_queue().await; | ||
| 21 | } | ||
| 22 | |||
| 17 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 24 | async fn main(spawner: Spawner) { |
| 19 | /* | 25 | /* |
| 20 | How to make this work: | 26 | How to make this work: |
| 21 | 27 | ||
| @@ -45,18 +51,19 @@ async fn main(_spawner: Spawner) { | |||
| 45 | info!("Hello World!"); | 51 | info!("Hello World!"); |
| 46 | 52 | ||
| 47 | let config = Config::default(); | 53 | let config = Config::default(); |
| 48 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 54 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 55 | let mut sys = mbox.sys_subsystem; | ||
| 56 | let mut ble = mbox.ble_subsystem; | ||
| 49 | 57 | ||
| 50 | let sys_event = mbox.sys_subsystem.read().await; | 58 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 51 | info!("sys event: {}", sys_event.payload()); | ||
| 52 | 59 | ||
| 53 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | 60 | let _ = sys.shci_c2_ble_init(Default::default()).await; |
| 54 | 61 | ||
| 55 | info!("starting ble..."); | 62 | info!("starting ble..."); |
| 56 | mbox.ble_subsystem.tl_write(0x0c, &[]).await; | 63 | ble.tl_write(0x0c, &[]).await; |
| 57 | 64 | ||
| 58 | info!("waiting for ble..."); | 65 | info!("waiting for ble..."); |
| 59 | let ble_event = mbox.ble_subsystem.tl_read().await; | 66 | let ble_event = ble.tl_read().await; |
| 60 | 67 | ||
| 61 | info!("ble event: {}", ble_event.payload()); | 68 | info!("ble event: {}", ble_event.payload()); |
| 62 | 69 | ||
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index 95c73872b..235a48241 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs | |||
| @@ -6,8 +6,8 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::bind_interrupts; | 6 | use embassy_stm32::bind_interrupts; |
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 8 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 9 | use embassy_stm32_wpan::sub::mm; | ||
| 10 | use embassy_stm32_wpan::TlMbox; | 9 | use embassy_stm32_wpan::TlMbox; |
| 10 | use embassy_stm32_wpan::sub::mm; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | bind_interrupts!(struct Irqs{ | 13 | bind_interrupts!(struct Irqs{ |
| @@ -16,7 +16,7 @@ bind_interrupts!(struct Irqs{ | |||
| 16 | }); | 16 | }); |
| 17 | 17 | ||
| 18 | #[embassy_executor::task] | 18 | #[embassy_executor::task] |
| 19 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 19 | async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { |
| 20 | memory_manager.run_queue().await; | 20 | memory_manager.run_queue().await; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| @@ -51,16 +51,12 @@ async fn main(spawner: Spawner) { | |||
| 51 | info!("Hello World!"); | 51 | info!("Hello World!"); |
| 52 | 52 | ||
| 53 | let config = Config::default(); | 53 | let config = Config::default(); |
| 54 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 54 | let mbox = TlMbox::init(p.IPCC, Irqs, config).await; |
| 55 | let mut sys = mbox.sys_subsystem; | ||
| 55 | 56 | ||
| 56 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); | 57 | spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); |
| 57 | 58 | ||
| 58 | let sys_event = mbox.sys_subsystem.read().await; | 59 | let result = sys.shci_c2_mac_802_15_4_init().await; |
| 59 | info!("sys event: {}", sys_event.payload()); | ||
| 60 | |||
| 61 | core::mem::drop(sys_event); | ||
| 62 | |||
| 63 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 64 | info!("initialized mac: {}", result); | 60 | info!("initialized mac: {}", result); |
| 65 | 61 | ||
| 66 | // | 62 | // |
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index e1196614a..b10114420 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32wba-examples" | 3 | name = "embassy-stm32wba-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | publish = false | 6 | publish = false |
| 7 | 7 | ||
| 8 | [dependencies] | 8 | [dependencies] |
| 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } | 9 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] } |
| 10 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wba52cg"] } | ||
| 10 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } |
| 12 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| @@ -22,6 +23,11 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } | |||
| 22 | heapless = { version = "0.8", default-features = false } | 23 | heapless = { version = "0.8", default-features = false } |
| 23 | static_cell = "2" | 24 | static_cell = "2" |
| 24 | 25 | ||
| 26 | [features] | ||
| 27 | default = ["ble", "mac"] | ||
| 28 | mac = ["embassy-stm32-wpan/wba_mac", "dep:embassy-net"] | ||
| 29 | ble = ["embassy-stm32-wpan/wba_ble"] | ||
| 30 | |||
| 25 | [profile.release] | 31 | [profile.release] |
| 26 | debug = 2 | 32 | debug = 2 |
| 27 | 33 | ||
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs index a9651d57e..ade3f5d6a 100644 --- a/examples/stm32wba/src/bin/adc.rs +++ b/examples/stm32wba/src/bin/adc.rs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc::{adc4, AdcChannel}; | 5 | use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4}; |
| 6 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 7 | 7 | ||
| 8 | #[embassy_executor::main] | 8 | #[embassy_executor::main] |
| @@ -12,20 +12,20 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 12 | let mut p = embassy_stm32::init(config); | 12 | let mut p = embassy_stm32::init(config); |
| 13 | 13 | ||
| 14 | // **** ADC4 init **** | 14 | // **** ADC4 init **** |
| 15 | let mut adc4 = adc4::Adc4::new(p.ADC4); | 15 | let mut adc4 = Adc::new_adc4(p.ADC4); |
| 16 | let mut adc4_pin1 = p.PA0; // A4 | 16 | let mut adc4_pin1 = p.PA0; // A4 |
| 17 | let mut adc4_pin2 = p.PA1; // A5 | 17 | let mut adc4_pin2 = p.PA1; // A5 |
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | 18 | adc4.set_resolution_adc4(adc4::Resolution::BITS12); |
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | 19 | adc4.set_averaging_adc4(adc4::Averaging::Samples256); |
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | 20 | |
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 22 | 22 | ||
| 23 | // **** ADC4 blocking read **** | 23 | // **** ADC4 blocking read **** |
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; |
| 26 | info!("Read adc4 pin 1 {}", volt); | 26 | info!("Read adc4 pin 1 {}", volt); |
| 27 | 27 | ||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 30 | info!("Read adc4 pin 2 {}", volt); | 30 | info!("Read adc4 pin 2 {}", volt); |
| 31 | 31 | ||
| @@ -37,11 +37,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 37 | // The channels must be in ascending order and can't repeat for ADC4 | 37 | // The channels must be in ascending order and can't repeat for ADC4 |
| 38 | adc4.read( | 38 | adc4.read( |
| 39 | p.GPDMA1_CH1.reborrow(), | 39 | p.GPDMA1_CH1.reborrow(), |
| 40 | [&mut degraded42, &mut degraded41].into_iter(), | 40 | [ |
| 41 | (&mut degraded42, SampleTime::CYCLES12_5), | ||
| 42 | (&mut degraded41, SampleTime::CYCLES12_5), | ||
| 43 | ] | ||
| 44 | .into_iter(), | ||
| 41 | &mut measurements, | 45 | &mut measurements, |
| 42 | ) | 46 | ) |
| 43 | .await | 47 | .await; |
| 44 | .unwrap(); | ||
| 45 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | 48 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; |
| 46 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; | 49 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; |
| 47 | info!("Async read 4 pin 1 {}", volt1); | 50 | info!("Async read 4 pin 1 {}", volt1); |
diff --git a/examples/stm32wba/src/bin/button_exti.rs b/examples/stm32wba/src/bin/button_exti.rs index 34a08bbc6..d63290d42 100644 --- a/examples/stm32wba/src/bin/button_exti.rs +++ b/examples/stm32wba/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32wba/src/bin/mac_ffd.rs b/examples/stm32wba/src/bin/mac_ffd.rs new file mode 100644 index 000000000..b15fb3452 --- /dev/null +++ b/examples/stm32wba/src/bin/mac_ffd.rs | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::{Sysclk, mux}; | ||
| 8 | use embassy_stm32_wpan::bindings::mac::ST_MAC_callbacks_t; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | static _MAC_CALLBACKS: ST_MAC_callbacks_t = ST_MAC_callbacks_t { | ||
| 12 | mlmeAssociateCnfCb: None, // ST_MAC_MLMEAssociateCnfCbPtr, | ||
| 13 | mlmeAssociateIndCb: None, // ST_MAC_MLMEAssociateIndCbPtr, | ||
| 14 | mlmeBeaconNotifyIndCb: None, // ST_MAC_MLMEBeaconNotifyIndCbPtr, | ||
| 15 | mlmeCalibrateCnfCb: None, // ST_MAC_MLMECalibrateCnfCbPtr, | ||
| 16 | mlmeCommStatusIndCb: None, // ST_MAC_MLMECommStatusIndCbPtr, | ||
| 17 | mlmeDisassociateCnfCb: None, // ST_MAC_MLMEDisassociateCnfCbPtr, | ||
| 18 | mlmeDisassociateIndCb: None, // ST_MAC_MLMEDisassociateIndCbPtr, | ||
| 19 | mlmeDpsCnfCb: None, // ST_MAC_MLMEDpsCnfCbPtr, | ||
| 20 | mlmeDpsIndCb: None, // ST_MAC_MLMEDpsIndCbPtr, | ||
| 21 | mlmeGetCnfCb: None, // ST_MAC_MLMEGetCnfCbPtr, | ||
| 22 | mlmeGtsCnfCb: None, // ST_MAC_MLMEGtsCnfCbPtr, | ||
| 23 | mlmeGtsIndCb: None, // ST_MAC_MLMEGtsIndCbPtr, | ||
| 24 | mlmeOrphanIndCb: None, // ST_MAC_MLMEOrphanIndCbPtr, | ||
| 25 | mlmePollCnfCb: None, // ST_MAC_MLMEPollCnfCbPtr, | ||
| 26 | mlmeResetCnfCb: None, // ST_MAC_MLMEResetCnfCbPtr, | ||
| 27 | mlmeRxEnableCnfCb: None, // ST_MAC_MLMERxEnableCnfCbPtr, | ||
| 28 | mlmeScanCnfCb: None, // ST_MAC_MLMEScanCnfCbPtr, | ||
| 29 | mlmeSetCnfCb: None, // ST_MAC_MLMESetCnfCbPtr, | ||
| 30 | mlmeSoundingCnfCb: None, // ST_MAC_MLMESoundingCnfCbPtr, | ||
| 31 | mlmeStartCnfCb: None, // ST_MAC_MLMEStartCnfCbPtr, | ||
| 32 | mlmeSyncLossIndCb: None, // ST_MAC_MLMESyncLossIndCbPtr, | ||
| 33 | mcpsDataIndCb: None, // ST_MAC_MCPSDataIndCbPtr, | ||
| 34 | mcpsDataCnfCb: None, // ST_MAC_MCPSDataCnfCbPtr, | ||
| 35 | mcpsPurgeCnfCb: None, // ST_MAC_MCPSPurgeCnfCbPtr, | ||
| 36 | mlmePollIndCb: None, // ST_MAC_MLMEPollIndCbPtr, | ||
| 37 | mlmeBeaconReqIndCb: None, // ST_MAC_MLMEBeaconReqIndCbPtr, | ||
| 38 | mlmeBeaconCnfCb: None, // ST_MAC_MLMEBeaconCnfCbPtr, | ||
| 39 | mlmeGetPwrInfoTableCnfCb: None, // ST_MAC_MLMEGetPwrInfoTableCnfCbPtr, | ||
| 40 | mlmeSetPwrInfoTableCnfCb: None, // ST_MAC_MLMESetPwrInfoTableCnfCbPtr, | ||
| 41 | }; | ||
| 42 | |||
| 43 | #[embassy_executor::main] | ||
| 44 | async fn main(_spawner: Spawner) { | ||
| 45 | let mut config = Config::default(); | ||
| 46 | |||
| 47 | config.rcc.sys = Sysclk::HSI; | ||
| 48 | config.rcc.mux.rngsel = mux::Rngsel::HSI; | ||
| 49 | |||
| 50 | let _p = embassy_stm32::init(config); | ||
| 51 | info!("Hello World!"); | ||
| 52 | |||
| 53 | // let status = unsafe { ST_MAC_init(&_MAC_CALLBACKS as *const _ as *mut _) }; | ||
| 54 | // | ||
| 55 | // info!("mac init: {}", status); | ||
| 56 | |||
| 57 | cortex_m::asm::bkpt(); | ||
| 58 | } | ||
diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs index de690fda0..f20c77a7c 100644 --- a/examples/stm32wba/src/bin/pwm.rs +++ b/examples/stm32wba/src/bin/pwm.rs | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use defmt_rtt as _; // global logger | 5 | use defmt_rtt as _; // global logger |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::gpio::OutputType; | 8 | use embassy_stm32::gpio::OutputType; |
| 8 | use embassy_stm32::rcc::{ | 9 | use embassy_stm32::rcc::{ |
| 9 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | 10 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, |
| 10 | }; | 11 | }; |
| 11 | use embassy_stm32::time::khz; | 12 | use embassy_stm32::time::khz; |
| 12 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 13 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 13 | use embassy_stm32::Config; | ||
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 15 | use panic_probe as _; | 15 | use panic_probe as _; |
| 16 | 16 | ||
diff --git a/examples/stm32wba/src/bin/rtc.rs b/examples/stm32wba/src/bin/rtc.rs new file mode 100644 index 000000000..cef8501e0 --- /dev/null +++ b/examples/stm32wba/src/bin/rtc.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::*; | ||
| 8 | use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | pub fn pll_init(config: &mut Config) { | ||
| 13 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 14 | source: PllSource::HSI, | ||
| 15 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 16 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 17 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 18 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 19 | divq: None, | ||
| 20 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 21 | frac: Some(0), // Fractional part (enabled) | ||
| 22 | }); | ||
| 23 | |||
| 24 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 25 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 26 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 27 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 28 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 29 | |||
| 30 | // voltage scale for max performance | ||
| 31 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 32 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 33 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 34 | } | ||
| 35 | |||
| 36 | #[embassy_executor::main] | ||
| 37 | async fn main(_spawner: Spawner) { | ||
| 38 | let mut config = Config::default(); | ||
| 39 | |||
| 40 | pll_init(&mut config); | ||
| 41 | |||
| 42 | let p = embassy_stm32::init(config); | ||
| 43 | |||
| 44 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 45 | |||
| 46 | // Setting datetime | ||
| 47 | let initial_datetime = DateTime::from(1970, 1, 1, DayOfWeek::Thursday, 0, 00, 00, 0).unwrap(); | ||
| 48 | match rtc.0.set_datetime(initial_datetime) { | ||
| 49 | Ok(()) => info!("RTC set successfully."), | ||
| 50 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 51 | } | ||
| 52 | |||
| 53 | // Reading datetime every 1s | ||
| 54 | loop { | ||
| 55 | match rtc.1.now() { | ||
| 56 | Ok(result) => info!("{}", result), | ||
| 57 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 58 | } | ||
| 59 | |||
| 60 | Timer::after_millis(1000).await; | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index f98317846..04bb27cb0 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32wba6-examples" | 3 | name = "embassy-stm32wba6-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs index a9651d57e..51dcff57a 100644 --- a/examples/stm32wba6/src/bin/adc.rs +++ b/examples/stm32wba6/src/bin/adc.rs | |||
| @@ -2,30 +2,55 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc::{adc4, AdcChannel}; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4}; | ||
| 7 | use embassy_stm32::rcc::{ | ||
| 8 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | ||
| 9 | }; | ||
| 6 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 7 | 11 | ||
| 8 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
| 9 | async fn main(_spawner: embassy_executor::Spawner) { | 13 | async fn main(_spawner: embassy_executor::Spawner) { |
| 10 | let config = embassy_stm32::Config::default(); | 14 | let mut config = Config::default(); |
| 15 | // Fine-tune PLL1 dividers/multipliers | ||
| 16 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 17 | source: PllSource::HSI, | ||
| 18 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 19 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 20 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 21 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 22 | divq: None, | ||
| 23 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 24 | frac: Some(0), // Fractional part (enabled) | ||
| 25 | }); | ||
| 26 | |||
| 27 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 28 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 29 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 30 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 31 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 32 | |||
| 33 | // voltage scale for max performance | ||
| 34 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 35 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 36 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 11 | 37 | ||
| 12 | let mut p = embassy_stm32::init(config); | 38 | let mut p = embassy_stm32::init(config); |
| 13 | 39 | ||
| 14 | // **** ADC4 init **** | 40 | // **** ADC4 init **** |
| 15 | let mut adc4 = adc4::Adc4::new(p.ADC4); | 41 | let mut adc4 = Adc::new_adc4(p.ADC4); |
| 16 | let mut adc4_pin1 = p.PA0; // A4 | 42 | let mut adc4_pin1 = p.PA0; // A4 |
| 17 | let mut adc4_pin2 = p.PA1; // A5 | 43 | let mut adc4_pin2 = p.PA1; // A5 |
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | 44 | adc4.set_resolution_adc4(adc4::Resolution::BITS12); |
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | 45 | adc4.set_averaging_adc4(adc4::Averaging::Samples256); |
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 46 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 22 | 47 | ||
| 23 | // **** ADC4 blocking read **** | 48 | // **** ADC4 blocking read **** |
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 49 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | 50 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; |
| 26 | info!("Read adc4 pin 1 {}", volt); | 51 | info!("Read adc4 pin 1 {}", volt); |
| 27 | 52 | ||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 53 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 54 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 30 | info!("Read adc4 pin 2 {}", volt); | 55 | info!("Read adc4 pin 2 {}", volt); |
| 31 | 56 | ||
| @@ -37,11 +62,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 37 | // The channels must be in ascending order and can't repeat for ADC4 | 62 | // The channels must be in ascending order and can't repeat for ADC4 |
| 38 | adc4.read( | 63 | adc4.read( |
| 39 | p.GPDMA1_CH1.reborrow(), | 64 | p.GPDMA1_CH1.reborrow(), |
| 40 | [&mut degraded42, &mut degraded41].into_iter(), | 65 | [ |
| 66 | (&mut degraded42, SampleTime::CYCLES12_5), | ||
| 67 | (&mut degraded41, SampleTime::CYCLES12_5), | ||
| 68 | ] | ||
| 69 | .into_iter(), | ||
| 41 | &mut measurements, | 70 | &mut measurements, |
| 42 | ) | 71 | ) |
| 43 | .await | 72 | .await; |
| 44 | .unwrap(); | ||
| 45 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; | 73 | let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; |
| 46 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; | 74 | let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; |
| 47 | info!("Async read 4 pin 1 {}", volt1); | 75 | info!("Async read 4 pin 1 {}", volt1); |
diff --git a/examples/stm32wba6/src/bin/blinky.rs b/examples/stm32wba6/src/bin/blinky.rs index 0d803b257..95f3339b7 100644 --- a/examples/stm32wba6/src/bin/blinky.rs +++ b/examples/stm32wba6/src/bin/blinky.rs | |||
| @@ -3,16 +3,45 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::Config; | ||
| 6 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::rcc::{ | ||
| 9 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | ||
| 10 | }; | ||
| 7 | use embassy_time::Timer; | 11 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 13 | ||
| 10 | #[embassy_executor::main] | 14 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 15 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 16 | let mut config = Config::default(); |
| 17 | // Fine-tune PLL1 dividers/multipliers | ||
| 18 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 19 | source: PllSource::HSI, | ||
| 20 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 21 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 22 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 23 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 24 | divq: None, | ||
| 25 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 26 | frac: Some(0), // Fractional part (enabled) | ||
| 27 | }); | ||
| 28 | |||
| 29 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 30 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 31 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 32 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 33 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 34 | |||
| 35 | // voltage scale for max performance | ||
| 36 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 37 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 38 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 39 | |||
| 40 | let p = embassy_stm32::init(config); | ||
| 13 | info!("Hello World!"); | 41 | info!("Hello World!"); |
| 14 | 42 | ||
| 15 | let mut led = Output::new(p.PB4, Level::High, Speed::Low); | 43 | // LD2 - PC4 |
| 44 | let mut led = Output::new(p.PC4, Level::High, Speed::Low); | ||
| 16 | 45 | ||
| 17 | loop { | 46 | loop { |
| 18 | info!("high"); | 47 | info!("high"); |
diff --git a/examples/stm32wba6/src/bin/button_exti.rs b/examples/stm32wba6/src/bin/button_exti.rs index 34a08bbc6..d63290d42 100644 --- a/examples/stm32wba6/src/bin/button_exti.rs +++ b/examples/stm32wba6/src/bin/button_exti.rs | |||
| @@ -3,16 +3,22 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::exti::ExtiInput; | 6 | use embassy_stm32::exti::{self, ExtiInput}; |
| 7 | use embassy_stm32::gpio::Pull; | 7 | use embassy_stm32::gpio::Pull; |
| 8 | use embassy_stm32::{bind_interrupts, interrupt}; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 11 | bind_interrupts!( | ||
| 12 | pub struct Irqs{ | ||
| 13 | EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>; | ||
| 14 | }); | ||
| 15 | |||
| 10 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 11 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 12 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 14 | 20 | ||
| 15 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); | 21 | let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs); |
| 16 | 22 | ||
| 17 | info!("Press the USER button..."); | 23 | info!("Press the USER button..."); |
| 18 | 24 | ||
diff --git a/examples/stm32wba6/src/bin/pwm.rs b/examples/stm32wba6/src/bin/pwm.rs index 2c696834a..64ae01945 100644 --- a/examples/stm32wba6/src/bin/pwm.rs +++ b/examples/stm32wba6/src/bin/pwm.rs | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use defmt_rtt as _; // global logger | 5 | use defmt_rtt as _; // global logger |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::gpio::OutputType; | 8 | use embassy_stm32::gpio::OutputType; |
| 8 | use embassy_stm32::rcc::{ | 9 | use embassy_stm32::rcc::{ |
| 9 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | 10 | AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, |
| 10 | }; | 11 | }; |
| 11 | use embassy_stm32::time::khz; | 12 | use embassy_stm32::time::khz; |
| 12 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | 13 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; |
| 13 | use embassy_stm32::Config; | ||
| 14 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 15 | use panic_probe as _; | 15 | use panic_probe as _; |
| 16 | 16 | ||
diff --git a/examples/stm32wba6/src/bin/rtc.rs b/examples/stm32wba6/src/bin/rtc.rs new file mode 100644 index 000000000..cef8501e0 --- /dev/null +++ b/examples/stm32wba6/src/bin/rtc.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::*; | ||
| 8 | use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | pub fn pll_init(config: &mut Config) { | ||
| 13 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 14 | source: PllSource::HSI, | ||
| 15 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 16 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 17 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 18 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 19 | divq: None, | ||
| 20 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 21 | frac: Some(0), // Fractional part (enabled) | ||
| 22 | }); | ||
| 23 | |||
| 24 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 25 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 26 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 27 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 28 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 29 | |||
| 30 | // voltage scale for max performance | ||
| 31 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 32 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 33 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 34 | } | ||
| 35 | |||
| 36 | #[embassy_executor::main] | ||
| 37 | async fn main(_spawner: Spawner) { | ||
| 38 | let mut config = Config::default(); | ||
| 39 | |||
| 40 | pll_init(&mut config); | ||
| 41 | |||
| 42 | let p = embassy_stm32::init(config); | ||
| 43 | |||
| 44 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 45 | |||
| 46 | // Setting datetime | ||
| 47 | let initial_datetime = DateTime::from(1970, 1, 1, DayOfWeek::Thursday, 0, 00, 00, 0).unwrap(); | ||
| 48 | match rtc.0.set_datetime(initial_datetime) { | ||
| 49 | Ok(()) => info!("RTC set successfully."), | ||
| 50 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 51 | } | ||
| 52 | |||
| 53 | // Reading datetime every 1s | ||
| 54 | loop { | ||
| 55 | match rtc.1.now() { | ||
| 56 | Ok(result) => info!("{}", result), | ||
| 57 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 58 | } | ||
| 59 | |||
| 60 | Timer::after_millis(1000).await; | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/examples/stm32wba6/src/bin/usb_hs_serial.rs b/examples/stm32wba6/src/bin/usb_hs_serial.rs index 20bdeaac3..a60eeb480 100644 --- a/examples/stm32wba6/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba6/src/bin/usb_hs_serial.rs | |||
| @@ -5,10 +5,10 @@ use defmt::{panic, *}; | |||
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_stm32::usb::{Driver, Instance}; | 7 | use embassy_stm32::usb::{Driver, Instance}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; |
| 9 | use embassy_usb::Builder; | ||
| 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; |
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 825d25c0d..1754aa0b8 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-stm32wl-examples" | 3 | name = "embassy-stm32wl-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs index 118f02ae1..adabe0df8 100644 --- a/examples/stm32wl/src/bin/adc.rs +++ b/examples/stm32wl/src/bin/adc.rs | |||
| @@ -5,8 +5,8 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime}; | ||
| 9 | use embassy_stm32::SharedData; | 8 | use embassy_stm32::SharedData; |
| 9 | use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime}; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| @@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) { | |||
| 18 | info!("Hello World!"); | 18 | info!("Hello World!"); |
| 19 | 19 | ||
| 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); | 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); |
| 21 | adc.set_sample_time(SampleTime::CYCLES79_5); | 21 | |
| 22 | let mut pin = p.PB2; | 22 | let mut pin = p.PB2; |
| 23 | 23 | ||
| 24 | let mut vrefint = adc.enable_vrefint(); | 24 | let mut vrefint = adc.enable_vrefint(); |
| 25 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 25 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 26 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 28 | // 6.3.3 Embedded internal reference voltage | 28 | // 6.3.3 Embedded internal reference voltage |
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | let v = adc.blocking_read(&mut pin); | 35 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 37 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 38 | } | 38 | } |
diff --git a/examples/stm32wl/src/bin/blinky.rs b/examples/stm32wl/src/bin/blinky.rs index a2a90871d..f7f57e35c 100644 --- a/examples/stm32wl/src/bin/blinky.rs +++ b/examples/stm32wl/src/bin/blinky.rs | |||
| @@ -5,8 +5,8 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 9 | use embassy_stm32::SharedData; | 8 | use embassy_stm32::SharedData; |
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embassy_time::Timer; | 10 | use embassy_time::Timer; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
diff --git a/examples/stm32wl/src/bin/button.rs b/examples/stm32wl/src/bin/button.rs index 21bcd2ac6..07bc95ad7 100644 --- a/examples/stm32wl/src/bin/button.rs +++ b/examples/stm32wl/src/bin/button.rs | |||
| @@ -5,8 +5,8 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use cortex_m_rt::entry; | 6 | use cortex_m_rt::entry; |
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | ||
| 9 | use embassy_stm32::SharedData; | 8 | use embassy_stm32::SharedData; |
| 9 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | #[unsafe(link_section = ".shared_data")] | 12 | #[unsafe(link_section = ".shared_data")] |
diff --git a/examples/stm32wl/src/bin/button_exti.rs b/examples/stm32wl/src/bin/button_exti.rs index 0a8aece34..2bb39c709 100644 --- a/examples/stm32wl/src/bin/button_exti.rs +++ b/examples/stm32wl/src/bin/button_exti.rs | |||
| @@ -5,11 +5,16 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::exti::ExtiInput; | 8 | use embassy_stm32::exti::{self, ExtiInput}; |
| 9 | use embassy_stm32::gpio::Pull; | 9 | use embassy_stm32::gpio::Pull; |
| 10 | use embassy_stm32::SharedData; | 10 | use embassy_stm32::{SharedData, bind_interrupts, interrupt}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | bind_interrupts!( | ||
| 14 | pub struct Irqs{ | ||
| 15 | EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>; | ||
| 16 | }); | ||
| 17 | |||
| 13 | #[unsafe(link_section = ".shared_data")] | 18 | #[unsafe(link_section = ".shared_data")] |
| 14 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | 19 | static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); |
| 15 | 20 | ||
| @@ -18,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 18 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); | 23 | let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); |
| 19 | info!("Hello World!"); | 24 | info!("Hello World!"); |
| 20 | 25 | ||
| 21 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); | 26 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs); |
| 22 | 27 | ||
| 23 | info!("Press the USER button..."); | 28 | info!("Press the USER button..."); |
| 24 | 29 | ||
diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index 320a9723a..bc707820d 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs | |||
| @@ -5,8 +5,8 @@ use core::mem::MaybeUninit; | |||
| 5 | 5 | ||
| 6 | use defmt::{info, unwrap}; | 6 | use defmt::{info, unwrap}; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::flash::Flash; | ||
| 9 | use embassy_stm32::SharedData; | 8 | use embassy_stm32::SharedData; |
| 9 | use embassy_stm32::flash::Flash; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | #[unsafe(link_section = ".shared_data")] | 12 | #[unsafe(link_section = ".shared_data")] |
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 68b9d7d00..931f9819a 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs | |||
| @@ -7,7 +7,7 @@ use defmt::*; | |||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::rng::{self, Rng}; | 8 | use embassy_stm32::rng::{self, Rng}; |
| 9 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, SharedData}; | 10 | use embassy_stm32::{SharedData, bind_interrupts, peripherals}; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | bind_interrupts!(struct Irqs{ | 13 | bind_interrupts!(struct Irqs{ |
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index d3709120f..2185142c9 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs | |||
| @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { | |||
| 44 | .and_hms_opt(10, 30, 15) | 44 | .and_hms_opt(10, 30, 15) |
| 45 | .unwrap(); | 45 | .unwrap(); |
| 46 | 46 | ||
| 47 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 47 | let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default()); |
| 48 | info!("Got RTC! {:?}", now.and_utc().timestamp()); | 48 | info!("Got RTC! {:?}", now.and_utc().timestamp()); |
| 49 | 49 | ||
| 50 | rtc.set_datetime(now.into()).expect("datetime not set"); | 50 | rtc.set_datetime(now.into()).expect("datetime not set"); |
| @@ -52,6 +52,6 @@ async fn main(_spawner: Spawner) { | |||
| 52 | // In reality the delay would be much longer | 52 | // In reality the delay would be much longer |
| 53 | Timer::after_millis(20000).await; | 53 | Timer::after_millis(20000).await; |
| 54 | 54 | ||
| 55 | let then: NaiveDateTime = rtc.now().unwrap().into(); | 55 | let then: NaiveDateTime = time_provider.now().unwrap().into(); |
| 56 | info!("Got RTC! {:?}", then.and_utc().timestamp()); | 56 | info!("Got RTC! {:?}", then.and_utc().timestamp()); |
| 57 | } | 57 | } |
diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs index 505a85f47..829ea2de7 100644 --- a/examples/stm32wl/src/bin/uart_async.rs +++ b/examples/stm32wl/src/bin/uart_async.rs | |||
| @@ -6,7 +6,7 @@ use core::mem::MaybeUninit; | |||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::usart::{Config, InterruptHandler, Uart}; | 8 | use embassy_stm32::usart::{Config, InterruptHandler, Uart}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, SharedData}; | 9 | use embassy_stm32::{SharedData, bind_interrupts, peripherals}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | bind_interrupts!(struct Irqs{ | 12 | bind_interrupts!(struct Irqs{ |
diff --git a/examples/stm32wle5/.cargo/config.toml b/examples/stm32wle5/.cargo/config.toml new file mode 100644 index 000000000..0178d377c --- /dev/null +++ b/examples/stm32wle5/.cargo/config.toml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace your chip as listed in `probe-rs chip list` | ||
| 3 | runner = "probe-rs run --chip STM32WLE5JCIx --connect-under-reset" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv7em-none-eabi" | ||
| 7 | |||
| 8 | [env] | ||
| 9 | DEFMT_LOG = "info" | ||
diff --git a/examples/stm32wle5/Cargo.toml b/examples/stm32wle5/Cargo.toml new file mode 100644 index 000000000..f2fc4dd3d --- /dev/null +++ b/examples/stm32wle5/Cargo.toml | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | [package] | ||
| 2 | edition = "2024" | ||
| 3 | name = "embassy-stm32wl-examples" | ||
| 4 | version = "0.1.0" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | publish = false | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | # Change stm32wl55jc-cm4 to your chip name, if necessary. | ||
| 10 | embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wle5jc", "time-driver-any", "memory-x", "unstable-pac", "exti", "low-power"] } | ||
| 11 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | ||
| 12 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } | ||
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-1_000"] } | ||
| 14 | embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } | ||
| 15 | |||
| 16 | defmt = "1.0.1" | ||
| 17 | defmt-rtt = { version = "1.1.0", optional = true } | ||
| 18 | defmt-serial = { version = "0.10.0", optional = true } | ||
| 19 | |||
| 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| 21 | cortex-m-rt = "0.7.0" | ||
| 22 | embedded-hal = "1.0.0" | ||
| 23 | embedded-storage = "0.3.1" | ||
| 24 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } | ||
| 25 | static_cell = { version = "2.1.1", default-features = false } | ||
| 26 | |||
| 27 | [profile.release] | ||
| 28 | debug = 2 | ||
| 29 | |||
| 30 | [package.metadata.embassy] | ||
| 31 | build = [ | ||
| 32 | { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" } | ||
| 33 | ] | ||
| 34 | |||
| 35 | [features] | ||
| 36 | default = ["defmt-serial"] | ||
| 37 | defmt-rtt = ["dep:defmt-rtt"] | ||
| 38 | defmt-serial = ["dep:defmt-serial"] | ||
diff --git a/examples/stm32wle5/README.md b/examples/stm32wle5/README.md new file mode 100644 index 000000000..18c3b5071 --- /dev/null +++ b/examples/stm32wle5/README.md | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | # Low Power Examples for STM32WLEx family | ||
| 2 | |||
| 3 | Examples in this repo should work with [LoRa-E5 Dev Board](https://www.st.com/en/partner-products-and-services/lora-e5-development-kit.html) board. | ||
| 4 | |||
| 5 | ## Prerequsits | ||
| 6 | |||
| 7 | - Connect a usb serial adapter to LPUart1 (this is where ALL logging will go) | ||
| 8 | - Optional: Connect an amp meter that ran measure down to 0.1uA to the power test pins | ||
| 9 | - `cargo install defmt-print` so you can print log messahes from LPUart1 | ||
| 10 | |||
| 11 | ## Example Notes | ||
| 12 | |||
| 13 | All examples will set all pins to analog mode before configuring pins for the example, if any. This saves about 500uA!!!! | ||
| 14 | |||
| 15 | - the `adc` example will sleep in STOP1 betwen samples and the chip will only draw about 13uA while sleeping | ||
| 16 | - the `blinky` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping | ||
| 17 | - the `button_exti` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping | ||
| 18 | - the `i2c` examples will sleep in STOP1 between reads and the chip only draw about 10uA while sleeping | ||
| 19 | |||
| 20 | For each example you will need to start `defmt-print` with the example binary and the correct serial port in a seperate terminal. Example: | ||
| 21 | ``` | ||
| 22 | defmt-print -w -v -e target/thumbv7em-none-eabi/debug/<module-name> serial --path /dev/cu.usbserial-00000000 --baud 115200 | ||
| 23 | ``` | ||
| 24 | |||
| 25 | Run individual examples with | ||
| 26 | ``` | ||
| 27 | cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin <module-name> | ||
| 28 | ``` | ||
| 29 | for example | ||
| 30 | ``` | ||
| 31 | cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin blinky | ||
| 32 | ``` | ||
| 33 | |||
| 34 | You can also run them with with `run`. However in this case expect probe-rs to be disconnected as soon as flashing is done as all IO pins are set to analog input! | ||
| 35 | ``` | ||
| 36 | cargo run --bin blinky | ||
| 37 | ``` | ||
| 38 | |||
| 39 | ## Checklist before running examples | ||
| 40 | You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. | ||
| 41 | |||
| 42 | * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L432KCU6 it should be `probe-rs run --chip STM32L432KCUx`. (use `probe-rs chip list` to find your chip) | ||
| 43 | * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature. For example for L432KCU6 it should be `stm32l432kc`. Look in the `Cargo.toml` file of the `embassy-stm32` project to find the correct feature flag for your chip. | ||
| 44 | * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. | ||
| 45 | * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic | ||
| 46 | |||
| 47 | If you are unsure, please drop by the Embassy Matrix chat for support, and let us know: | ||
| 48 | |||
| 49 | * Which example you are trying to run | ||
| 50 | * Which chip and board you are using | ||
| 51 | |||
| 52 | Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org | ||
diff --git a/examples/stm32wle5/build.rs b/examples/stm32wle5/build.rs new file mode 100644 index 000000000..8cd32d7ed --- /dev/null +++ b/examples/stm32wle5/build.rs | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | fn main() { | ||
| 2 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 3 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 4 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 5 | } | ||
diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs new file mode 100644 index 000000000..8cc84ccdf --- /dev/null +++ b/examples/stm32wle5/src/bin/adc.rs | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | #[cfg(feature = "defmt-rtt")] | ||
| 6 | use defmt_rtt as _; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::adc::{Adc, SampleTime}; | ||
| 9 | use embassy_stm32::low_power; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use panic_probe as _; | ||
| 12 | use static_cell::StaticCell; | ||
| 13 | |||
| 14 | #[embassy_executor::main(executor = "low_power::Executor")] | ||
| 15 | async fn async_main(_spawner: Spawner) { | ||
| 16 | let mut config = embassy_stm32::Config::default(); | ||
| 17 | // enable HSI clock | ||
| 18 | config.rcc.hsi = true; | ||
| 19 | // enable LSI clock for RTC | ||
| 20 | config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi(); | ||
| 21 | config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M); | ||
| 22 | config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI; | ||
| 23 | // enable ADC with HSI clock | ||
| 24 | config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI; | ||
| 25 | #[cfg(feature = "defmt-serial")] | ||
| 26 | { | ||
| 27 | // disable debug during sleep to reduce power consumption since we are | ||
| 28 | // using defmt-serial on LPUART1. | ||
| 29 | config.enable_debug_during_sleep = false; | ||
| 30 | // if we are using defmt-serial on LPUART1, we need to use HSI for the clock | ||
| 31 | // so that its registers are preserved during STOP modes. | ||
| 32 | config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI; | ||
| 33 | } | ||
| 34 | // Initialize STM32WL peripherals (use default config like wio-e5-async example) | ||
| 35 | let p = embassy_stm32::init(config); | ||
| 36 | |||
| 37 | #[cfg(feature = "defmt-serial")] | ||
| 38 | { | ||
| 39 | use embassy_stm32::mode::Blocking; | ||
| 40 | use embassy_stm32::usart::Uart; | ||
| 41 | let config = embassy_stm32::usart::Config::default(); | ||
| 42 | let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!"); | ||
| 43 | static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new(); | ||
| 44 | defmt_serial::defmt_serial(SERIAL.init(uart)); | ||
| 45 | } | ||
| 46 | |||
| 47 | info!("Hello World!"); | ||
| 48 | |||
| 49 | let mut adc = Adc::new(p.ADC1); | ||
| 50 | let mut pin = p.PA10; | ||
| 51 | |||
| 52 | let mut vrefint = adc.enable_vrefint(); | ||
| 53 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); | ||
| 54 | let convert_to_millivolts = |sample| { | ||
| 55 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | ||
| 56 | // 6.3.3 Embedded internal reference voltage | ||
| 57 | const VREFINT_MV: u32 = 1212; // mV | ||
| 58 | |||
| 59 | (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16 | ||
| 60 | }; | ||
| 61 | |||
| 62 | loop { | ||
| 63 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); | ||
| 64 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | ||
| 65 | Timer::after_secs(1).await; | ||
| 66 | } | ||
| 67 | } | ||
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs new file mode 100644 index 000000000..3b7eb7761 --- /dev/null +++ b/examples/stm32wle5/src/bin/blinky.rs | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | #[cfg(feature = "defmt-rtt")] | ||
| 6 | use defmt_rtt as _; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 9 | use embassy_stm32::low_power; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use panic_probe as _; | ||
| 12 | use static_cell::StaticCell; | ||
| 13 | |||
| 14 | #[embassy_executor::main(executor = "low_power::Executor")] | ||
| 15 | async fn async_main(_spawner: Spawner) { | ||
| 16 | let mut config = embassy_stm32::Config::default(); | ||
| 17 | // enable HSI clock | ||
| 18 | config.rcc.hsi = true; | ||
| 19 | // enable LSI clock for RTC | ||
| 20 | config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi(); | ||
| 21 | config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M); | ||
| 22 | config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI; | ||
| 23 | #[cfg(feature = "defmt-serial")] | ||
| 24 | { | ||
| 25 | // disable debug during sleep to reduce power consumption since we are | ||
| 26 | // using defmt-serial on LPUART1. | ||
| 27 | config.enable_debug_during_sleep = false; | ||
| 28 | // if we are using defmt-serial on LPUART1, we need to use HSI for the clock | ||
| 29 | // so that its registers are preserved during STOP modes. | ||
| 30 | config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI; | ||
| 31 | } | ||
| 32 | // Initialize STM32WL peripherals (use default config like wio-e5-async example) | ||
| 33 | let p = embassy_stm32::init(config); | ||
| 34 | |||
| 35 | #[cfg(feature = "defmt-serial")] | ||
| 36 | { | ||
| 37 | use embassy_stm32::mode::Blocking; | ||
| 38 | use embassy_stm32::usart::Uart; | ||
| 39 | let config = embassy_stm32::usart::Config::default(); | ||
| 40 | let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!"); | ||
| 41 | static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new(); | ||
| 42 | defmt_serial::defmt_serial(SERIAL.init(uart)); | ||
| 43 | } | ||
| 44 | |||
| 45 | info!("Hello World!"); | ||
| 46 | |||
| 47 | let mut led = Output::new(p.PB5, Level::High, Speed::Low); | ||
| 48 | |||
| 49 | loop { | ||
| 50 | info!("low"); | ||
| 51 | led.set_low(); | ||
| 52 | Timer::after_millis(15000).await; | ||
| 53 | |||
| 54 | info!("high"); | ||
| 55 | led.set_high(); | ||
| 56 | Timer::after_millis(15000).await; | ||
| 57 | } | ||
| 58 | } | ||
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs new file mode 100644 index 000000000..9ffc39948 --- /dev/null +++ b/examples/stm32wle5/src/bin/button_exti.rs | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | #[cfg(feature = "defmt-rtt")] | ||
| 6 | use defmt_rtt as _; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::exti::{self, ExtiInput}; | ||
| 9 | use embassy_stm32::gpio::Pull; | ||
| 10 | use embassy_stm32::{bind_interrupts, interrupt, low_power}; | ||
| 11 | use panic_probe as _; | ||
| 12 | use static_cell::StaticCell; | ||
| 13 | |||
| 14 | bind_interrupts!( | ||
| 15 | pub struct Irqs{ | ||
| 16 | EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>; | ||
| 17 | }); | ||
| 18 | |||
| 19 | #[embassy_executor::main(executor = "low_power::Executor")] | ||
| 20 | async fn async_main(_spawner: Spawner) { | ||
| 21 | let mut config = embassy_stm32::Config::default(); | ||
| 22 | // enable HSI clock | ||
| 23 | config.rcc.hsi = true; | ||
| 24 | // enable LSI clock for RTC | ||
| 25 | config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi(); | ||
| 26 | config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M); | ||
| 27 | config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI; | ||
| 28 | // enable ADC with HSI clock | ||
| 29 | config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI; | ||
| 30 | #[cfg(feature = "defmt-serial")] | ||
| 31 | { | ||
| 32 | // disable debug during sleep to reduce power consumption since we are | ||
| 33 | // using defmt-serial on LPUART1. | ||
| 34 | config.enable_debug_during_sleep = false; | ||
| 35 | // if we are using defmt-serial on LPUART1, we need to use HSI for the clock | ||
| 36 | // so that its registers are preserved during STOP modes. | ||
| 37 | config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI; | ||
| 38 | } | ||
| 39 | // Initialize STM32WL peripherals (use default config like wio-e5-async example) | ||
| 40 | let p = embassy_stm32::init(config); | ||
| 41 | |||
| 42 | #[cfg(feature = "defmt-serial")] | ||
| 43 | { | ||
| 44 | use embassy_stm32::mode::Blocking; | ||
| 45 | use embassy_stm32::usart::Uart; | ||
| 46 | let config = embassy_stm32::usart::Config::default(); | ||
| 47 | let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!"); | ||
| 48 | static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new(); | ||
| 49 | defmt_serial::defmt_serial(SERIAL.init(uart)); | ||
| 50 | } | ||
| 51 | |||
| 52 | info!("Hello World!"); | ||
| 53 | |||
| 54 | let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs); | ||
| 55 | |||
| 56 | info!("Press the USER button..."); | ||
| 57 | |||
| 58 | loop { | ||
| 59 | button.wait_for_falling_edge().await; | ||
| 60 | info!("Pressed!"); | ||
| 61 | button.wait_for_rising_edge().await; | ||
| 62 | info!("Released!"); | ||
| 63 | } | ||
| 64 | } | ||
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs new file mode 100644 index 000000000..8e7a6e2d8 --- /dev/null +++ b/examples/stm32wle5/src/bin/i2c.rs | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | #[cfg(feature = "defmt-rtt")] | ||
| 6 | use defmt_rtt as _; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::i2c::I2c; | ||
| 9 | use embassy_stm32::time::Hertz; | ||
| 10 | use embassy_stm32::{bind_interrupts, i2c, low_power, peripherals}; | ||
| 11 | use embassy_time::{Duration, Timer}; | ||
| 12 | use panic_probe as _; | ||
| 13 | use static_cell::StaticCell; | ||
| 14 | |||
| 15 | bind_interrupts!(struct IrqsI2C{ | ||
| 16 | I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>; | ||
| 17 | I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>; | ||
| 18 | }); | ||
| 19 | |||
| 20 | #[embassy_executor::main(executor = "low_power::Executor")] | ||
| 21 | async fn async_main(_spawner: Spawner) { | ||
| 22 | let mut config = embassy_stm32::Config::default(); | ||
| 23 | // enable HSI clock | ||
| 24 | config.rcc.hsi = true; | ||
| 25 | // enable LSI clock for RTC | ||
| 26 | config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi(); | ||
| 27 | config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M); | ||
| 28 | config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI; | ||
| 29 | // enable ADC with HSI clock | ||
| 30 | config.rcc.mux.i2c2sel = embassy_stm32::pac::rcc::vals::I2c2sel::HSI; | ||
| 31 | #[cfg(feature = "defmt-serial")] | ||
| 32 | { | ||
| 33 | // disable debug during sleep to reduce power consumption since we are | ||
| 34 | // using defmt-serial on LPUART1. | ||
| 35 | config.enable_debug_during_sleep = false; | ||
| 36 | // if we are using defmt-serial on LPUART1, we need to use HSI for the clock | ||
| 37 | // so that its registers are preserved during STOP modes. | ||
| 38 | config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI; | ||
| 39 | } | ||
| 40 | // Initialize STM32WL peripherals (use default config like wio-e5-async example) | ||
| 41 | let p = embassy_stm32::init(config); | ||
| 42 | |||
| 43 | #[cfg(feature = "defmt-serial")] | ||
| 44 | { | ||
| 45 | use embassy_stm32::mode::Blocking; | ||
| 46 | use embassy_stm32::usart::Uart; | ||
| 47 | let config = embassy_stm32::usart::Config::default(); | ||
| 48 | let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!"); | ||
| 49 | static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new(); | ||
| 50 | defmt_serial::defmt_serial(SERIAL.init(uart)); | ||
| 51 | } | ||
| 52 | |||
| 53 | info!("Hello World!"); | ||
| 54 | let en3v3 = embassy_stm32::gpio::Output::new( | ||
| 55 | p.PA9, | ||
| 56 | embassy_stm32::gpio::Level::High, | ||
| 57 | embassy_stm32::gpio::Speed::High, | ||
| 58 | ); | ||
| 59 | core::mem::forget(en3v3); // keep the output pin enabled | ||
| 60 | |||
| 61 | let mut i2c = I2c::new(p.I2C2, p.PB15, p.PA15, IrqsI2C, p.DMA1_CH6, p.DMA1_CH7, { | ||
| 62 | let mut config = i2c::Config::default(); | ||
| 63 | config.frequency = Hertz::khz(100); | ||
| 64 | config.timeout = Duration::from_millis(1000); | ||
| 65 | config | ||
| 66 | }); | ||
| 67 | |||
| 68 | loop { | ||
| 69 | let mut buffer = [0; 2]; | ||
| 70 | // read the temperature register of the onboard lm75 | ||
| 71 | match i2c.read(0x48, &mut buffer).await { | ||
| 72 | Ok(_) => info!("--> {:?}", buffer), | ||
| 73 | Err(e) => info!("--> Error: {:?}", e), | ||
| 74 | } | ||
| 75 | Timer::after_secs(5).await; | ||
| 76 | } | ||
| 77 | } | ||
diff --git a/examples/stm32wle5/stm32wle5.code-workspace b/examples/stm32wle5/stm32wle5.code-workspace new file mode 100644 index 000000000..a7c4a0ebd --- /dev/null +++ b/examples/stm32wle5/stm32wle5.code-workspace | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | { | ||
| 2 | "folders": [ | ||
| 3 | { | ||
| 4 | "path": "." | ||
| 5 | } | ||
| 6 | ], | ||
| 7 | "settings": { | ||
| 8 | "rust-analyzer.cargo.target": "thumbv7em-none-eabi", | ||
| 9 | "rust-analyzer.cargo.allTargets": false, | ||
| 10 | "rust-analyzer.cargo.targetDir": "target/rust-analyzer", | ||
| 11 | "rust-analyzer.checkOnSave": true, | ||
| 12 | } | ||
| 13 | } | ||
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index e8897506c..79d50b584 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2024" |
| 3 | name = "embassy-wasm-example" | 3 | name = "embassy-wasm-example" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
