diff options
| author | sodo <[email protected]> | 2024-01-02 01:37:00 +0900 |
|---|---|---|
| committer | sodo <[email protected]> | 2024-01-02 13:34:22 +0900 |
| commit | 6ee153a3e2eec284c0d9d87f31801265c0604f74 (patch) | |
| tree | 8b801cbd15f9ad5052d5942c731e75736dc9d7eb /examples/stm32f4/src/bin | |
| parent | b7cd7952c890f585ff876c622482534e5d58d4a4 (diff) | |
| parent | 0be9b0599aaf2e425d76ec7852ff4b3535defddf (diff) | |
Merge remote-tracking branch 'origin'
Diffstat (limited to 'examples/stm32f4/src/bin')
31 files changed, 280 insertions, 52 deletions
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs index f19328727..699c29c05 100644 --- a/examples/stm32f4/src/bin/adc.rs +++ b/examples/stm32f4/src/bin/adc.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; | 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; |
| 6 | use defmt::*; | 5 | use defmt::*; |
diff --git a/examples/stm32f4/src/bin/blinky.rs b/examples/stm32f4/src/bin/blinky.rs index 4bfc5a50d..31cce8225 100644 --- a/examples/stm32f4/src/bin/blinky.rs +++ b/examples/stm32f4/src/bin/blinky.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/button.rs b/examples/stm32f4/src/bin/button.rs index b13e64531..ad30a56a2 100644 --- a/examples/stm32f4/src/bin/button.rs +++ b/examples/stm32f4/src/bin/button.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 6 | use defmt::*; | 5 | use defmt::*; |
| @@ -13,7 +12,7 @@ fn main() -> ! { | |||
| 13 | 12 | ||
| 14 | let p = embassy_stm32::init(Default::default()); | 13 | let p = embassy_stm32::init(Default::default()); |
| 15 | 14 | ||
| 16 | let button = Input::new(p.PC13, Pull::Down); | 15 | let mut button = Input::new(p.PC13, Pull::Down); |
| 17 | let mut led1 = Output::new(p.PB0, Level::High, Speed::Low); | 16 | let mut led1 = Output::new(p.PB0, Level::High, Speed::Low); |
| 18 | let _led2 = Output::new(p.PB7, Level::High, Speed::Low); | 17 | let _led2 = Output::new(p.PB7, Level::High, Speed::Low); |
| 19 | let mut led3 = Output::new(p.PB14, Level::High, Speed::Low); | 18 | let mut led3 = Output::new(p.PB14, Level::High, Speed::Low); |
diff --git a/examples/stm32f4/src/bin/button_exti.rs b/examples/stm32f4/src/bin/button_exti.rs index dfe587d41..67751187d 100644 --- a/examples/stm32f4/src/bin/button_exti.rs +++ b/examples/stm32f4/src/bin/button_exti.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/can.rs b/examples/stm32f4/src/bin/can.rs index 20ce4edce..d074b4265 100644 --- a/examples/stm32f4/src/bin/can.rs +++ b/examples/stm32f4/src/bin/can.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs index 8f14d6078..9c7754c4f 100644 --- a/examples/stm32f4/src/bin/dac.rs +++ b/examples/stm32f4/src/bin/dac.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 088d83c06..7f5c8fdb1 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| @@ -14,7 +13,7 @@ use embassy_stm32::time::Hertz; | |||
| 14 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 13 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; |
| 15 | use embassy_time::Timer; | 14 | use embassy_time::Timer; |
| 16 | use embedded_io_async::Write; | 15 | use embedded_io_async::Write; |
| 17 | use static_cell::make_static; | 16 | use static_cell::StaticCell; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 19 | 18 | ||
| 20 | bind_interrupts!(struct Irqs { | 19 | bind_interrupts!(struct Irqs { |
| @@ -63,8 +62,9 @@ async fn main(spawner: Spawner) -> ! { | |||
| 63 | 62 | ||
| 64 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | 63 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; |
| 65 | 64 | ||
| 65 | static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new(); | ||
| 66 | let device = Ethernet::new( | 66 | let device = Ethernet::new( |
| 67 | make_static!(PacketQueue::<16, 16>::new()), | 67 | PACKETS.init(PacketQueue::<16, 16>::new()), |
| 68 | p.ETH, | 68 | p.ETH, |
| 69 | Irqs, | 69 | Irqs, |
| 70 | p.PA1, | 70 | p.PA1, |
| @@ -88,11 +88,13 @@ async fn main(spawner: Spawner) -> ! { | |||
| 88 | //}); | 88 | //}); |
| 89 | 89 | ||
| 90 | // Init network stack | 90 | // Init network stack |
| 91 | let stack = &*make_static!(Stack::new( | 91 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); |
| 92 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | ||
| 93 | let stack = &*STACK.init(Stack::new( | ||
| 92 | device, | 94 | device, |
| 93 | config, | 95 | config, |
| 94 | make_static!(StackResources::<2>::new()), | 96 | RESOURCES.init(StackResources::<2>::new()), |
| 95 | seed | 97 | seed, |
| 96 | )); | 98 | )); |
| 97 | 99 | ||
| 98 | // Launch network task | 100 | // Launch network task |
diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index 93c54e943..1e8cabab4 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::{info, unwrap}; | 4 | use defmt::{info, unwrap}; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| @@ -31,7 +30,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { | |||
| 31 | 30 | ||
| 32 | info!("Reading..."); | 31 | info!("Reading..."); |
| 33 | let mut buf = [0u8; 32]; | 32 | let mut buf = [0u8; 32]; |
| 34 | unwrap!(f.read(offset, &mut buf)); | 33 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 35 | info!("Read: {=[u8]:x}", buf); | 34 | info!("Read: {=[u8]:x}", buf); |
| 36 | 35 | ||
| 37 | info!("Erasing..."); | 36 | info!("Erasing..."); |
| @@ -39,7 +38,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { | |||
| 39 | 38 | ||
| 40 | info!("Reading..."); | 39 | info!("Reading..."); |
| 41 | let mut buf = [0u8; 32]; | 40 | let mut buf = [0u8; 32]; |
| 42 | unwrap!(f.read(offset, &mut buf)); | 41 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 43 | info!("Read after erase: {=[u8]:x}", buf); | 42 | info!("Read after erase: {=[u8]:x}", buf); |
| 44 | 43 | ||
| 45 | info!("Writing..."); | 44 | info!("Writing..."); |
| @@ -53,7 +52,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { | |||
| 53 | 52 | ||
| 54 | info!("Reading..."); | 53 | info!("Reading..."); |
| 55 | let mut buf = [0u8; 32]; | 54 | let mut buf = [0u8; 32]; |
| 56 | unwrap!(f.read(offset, &mut buf)); | 55 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 57 | info!("Read: {=[u8]:x}", buf); | 56 | info!("Read: {=[u8]:x}", buf); |
| 58 | assert_eq!( | 57 | assert_eq!( |
| 59 | &buf[..], | 58 | &buf[..], |
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index f0a65a725..493a536f3 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::{info, unwrap}; | 4 | use defmt::{info, unwrap}; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| @@ -48,7 +47,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | |||
| 48 | 47 | ||
| 49 | info!("Reading..."); | 48 | info!("Reading..."); |
| 50 | let mut buf = [0u8; 32]; | 49 | let mut buf = [0u8; 32]; |
| 51 | unwrap!(f.read(offset, &mut buf)); | 50 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 52 | info!("Read: {=[u8]:x}", buf); | 51 | info!("Read: {=[u8]:x}", buf); |
| 53 | 52 | ||
| 54 | info!("Erasing..."); | 53 | info!("Erasing..."); |
| @@ -56,7 +55,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | |||
| 56 | 55 | ||
| 57 | info!("Reading..."); | 56 | info!("Reading..."); |
| 58 | let mut buf = [0u8; 32]; | 57 | let mut buf = [0u8; 32]; |
| 59 | unwrap!(f.read(offset, &mut buf)); | 58 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 60 | info!("Read after erase: {=[u8]:x}", buf); | 59 | info!("Read after erase: {=[u8]:x}", buf); |
| 61 | 60 | ||
| 62 | info!("Writing..."); | 61 | info!("Writing..."); |
| @@ -73,7 +72,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | |||
| 73 | 72 | ||
| 74 | info!("Reading..."); | 73 | info!("Reading..."); |
| 75 | let mut buf = [0u8; 32]; | 74 | let mut buf = [0u8; 32]; |
| 76 | unwrap!(f.read(offset, &mut buf)); | 75 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 77 | info!("Read: {=[u8]:x}", buf); | 76 | info!("Read: {=[u8]:x}", buf); |
| 78 | assert_eq!( | 77 | assert_eq!( |
| 79 | &buf[..], | 78 | &buf[..], |
diff --git a/examples/stm32f4/src/bin/hello.rs b/examples/stm32f4/src/bin/hello.rs index a2a287110..3c295612c 100644 --- a/examples/stm32f4/src/bin/hello.rs +++ b/examples/stm32f4/src/bin/hello.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::info; | 4 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs index 4f4adde28..4b5da774d 100644 --- a/examples/stm32f4/src/bin/i2c.rs +++ b/examples/stm32f4/src/bin/i2c.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs index 9f59e4d41..90d11d4b4 100644 --- a/examples/stm32f4/src/bin/i2c_async.rs +++ b/examples/stm32f4/src/bin/i2c_async.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | // Example originally designed for stm32f411ceu6 reading an A1454 hall effect sensor on I2C1 | 4 | // Example originally designed for stm32f411ceu6 reading an A1454 hall effect sensor on I2C1 |
| 6 | // DMA peripherals changed to compile for stm32f429zi, for the CI. | 5 | // DMA peripherals changed to compile for stm32f429zi, for the CI. |
diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs index 6d23c0ed8..30cfbdf57 100644 --- a/examples/stm32f4/src/bin/i2c_comparison.rs +++ b/examples/stm32f4/src/bin/i2c_comparison.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | // Example originally designed for stm32f411ceu6 with three A1454 hall effect sensors, connected to I2C1, 2 and 3 | 4 | // Example originally designed for stm32f411ceu6 with three A1454 hall effect sensors, connected to I2C1, 2 and 3 |
| 6 | // on the pins referenced in the peripheral definitions. | 5 | // on the pins referenced in the peripheral definitions. |
diff --git a/examples/stm32f4/src/bin/i2s_dma.rs b/examples/stm32f4/src/bin/i2s_dma.rs index e8d7b5f77..97a04b2aa 100644 --- a/examples/stm32f4/src/bin/i2s_dma.rs +++ b/examples/stm32f4/src/bin/i2s_dma.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use core::fmt::Write; | 4 | use core::fmt::Write; |
| 6 | 5 | ||
diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs index 3315e7652..eb7bb6261 100644 --- a/examples/stm32f4/src/bin/mco.rs +++ b/examples/stm32f4/src/bin/mco.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 74f3bb1c5..328447210 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs | |||
| @@ -55,7 +55,6 @@ | |||
| 55 | 55 | ||
| 56 | #![no_std] | 56 | #![no_std] |
| 57 | #![no_main] | 57 | #![no_main] |
| 58 | #![feature(type_alias_impl_trait)] | ||
| 59 | 58 | ||
| 60 | use cortex_m_rt::entry; | 59 | use cortex_m_rt::entry; |
| 61 | use defmt::*; | 60 | use defmt::*; |
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs index 8e41d0e78..8844a9f0e 100644 --- a/examples/stm32f4/src/bin/pwm.rs +++ b/examples/stm32f4/src/bin/pwm.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs index d925f26d9..161f43c48 100644 --- a/examples/stm32f4/src/bin/pwm_complementary.rs +++ b/examples/stm32f4/src/bin/pwm_complementary.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index 44b4303c0..abab07b6b 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use chrono::{NaiveDate, NaiveDateTime}; | 4 | use chrono::{NaiveDate, NaiveDateTime}; |
| 6 | use defmt::*; | 5 | use defmt::*; |
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs index 91747b2d5..66e4e527c 100644 --- a/examples/stm32f4/src/bin/sdmmc.rs +++ b/examples/stm32f4/src/bin/sdmmc.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs index 0919e9874..dc9141c62 100644 --- a/examples/stm32f4/src/bin/spi.rs +++ b/examples/stm32f4/src/bin/spi.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 6 | use defmt::*; | 5 | use defmt::*; |
diff --git a/examples/stm32f4/src/bin/spi_dma.rs b/examples/stm32f4/src/bin/spi_dma.rs index f291f7dba..7249c831a 100644 --- a/examples/stm32f4/src/bin/spi_dma.rs +++ b/examples/stm32f4/src/bin/spi_dma.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use core::fmt::Write; | 4 | use core::fmt::Write; |
| 6 | use core::str::from_utf8; | 5 | use core::str::from_utf8; |
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs index 45e94715f..40d9d70f1 100644 --- a/examples/stm32f4/src/bin/usart.rs +++ b/examples/stm32f4/src/bin/usart.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 6 | use defmt::*; | 5 | use defmt::*; |
diff --git a/examples/stm32f4/src/bin/usart_buffered.rs b/examples/stm32f4/src/bin/usart_buffered.rs index 71abc2893..c99807f11 100644 --- a/examples/stm32f4/src/bin/usart_buffered.rs +++ b/examples/stm32f4/src/bin/usart_buffered.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs index dca25a78c..dd6de599c 100644 --- a/examples/stm32f4/src/bin/usart_dma.rs +++ b/examples/stm32f4/src/bin/usart_dma.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use core::fmt::Write; | 4 | use core::fmt::Write; |
| 6 | 5 | ||
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index 6bf5b1cba..a196259a8 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| @@ -14,7 +13,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState | |||
| 14 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; | 13 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; |
| 15 | use embassy_usb::{Builder, UsbDevice}; | 14 | use embassy_usb::{Builder, UsbDevice}; |
| 16 | use embedded_io_async::Write; | 15 | use embedded_io_async::Write; |
| 17 | use static_cell::make_static; | 16 | use static_cell::StaticCell; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 19 | 18 | ||
| 20 | type UsbDriver = Driver<'static, embassy_stm32::peripherals::USB_OTG_FS>; | 19 | type UsbDriver = Driver<'static, embassy_stm32::peripherals::USB_OTG_FS>; |
| @@ -68,7 +67,8 @@ async fn main(spawner: Spawner) { | |||
| 68 | let p = embassy_stm32::init(config); | 67 | let p = embassy_stm32::init(config); |
| 69 | 68 | ||
| 70 | // Create the driver, from the HAL. | 69 | // Create the driver, from the HAL. |
| 71 | let ep_out_buffer = &mut make_static!([0; 256])[..]; | 70 | static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new(); |
| 71 | let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..]; | ||
| 72 | let mut config = embassy_stm32::usb_otg::Config::default(); | 72 | let mut config = embassy_stm32::usb_otg::Config::default(); |
| 73 | config.vbus_detection = true; | 73 | config.vbus_detection = true; |
| 74 | let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config); | 74 | let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config); |
| @@ -88,14 +88,18 @@ async fn main(spawner: Spawner) { | |||
| 88 | config.device_protocol = 0x01; | 88 | config.device_protocol = 0x01; |
| 89 | 89 | ||
| 90 | // Create embassy-usb DeviceBuilder using the driver and config. | 90 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 91 | static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new(); | ||
| 92 | static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); | ||
| 93 | static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); | ||
| 94 | static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); | ||
| 91 | let mut builder = Builder::new( | 95 | let mut builder = Builder::new( |
| 92 | driver, | 96 | driver, |
| 93 | config, | 97 | config, |
| 94 | &mut make_static!([0; 256])[..], | 98 | &mut DEVICE_DESC.init([0; 256])[..], |
| 95 | &mut make_static!([0; 256])[..], | 99 | &mut CONFIG_DESC.init([0; 256])[..], |
| 96 | &mut make_static!([0; 256])[..], | 100 | &mut BOS_DESC.init([0; 256])[..], |
| 97 | &mut [], // no msos descriptors | 101 | &mut [], // no msos descriptors |
| 98 | &mut make_static!([0; 128])[..], | 102 | &mut CONTROL_BUF.init([0; 128])[..], |
| 99 | ); | 103 | ); |
| 100 | 104 | ||
| 101 | // Our MAC addr. | 105 | // Our MAC addr. |
| @@ -104,14 +108,16 @@ async fn main(spawner: Spawner) { | |||
| 104 | let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; | 108 | let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; |
| 105 | 109 | ||
| 106 | // Create classes on the builder. | 110 | // Create classes on the builder. |
| 107 | let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); | 111 | static STATE: StaticCell<State> = StaticCell::new(); |
| 112 | let class = CdcNcmClass::new(&mut builder, STATE.init(State::new()), host_mac_addr, 64); | ||
| 108 | 113 | ||
| 109 | // Build the builder. | 114 | // Build the builder. |
| 110 | let usb = builder.build(); | 115 | let usb = builder.build(); |
| 111 | 116 | ||
| 112 | unwrap!(spawner.spawn(usb_task(usb))); | 117 | unwrap!(spawner.spawn(usb_task(usb))); |
| 113 | 118 | ||
| 114 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(make_static!(NetState::new()), our_mac_addr); | 119 | static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); |
| 120 | let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); | ||
| 115 | unwrap!(spawner.spawn(usb_ncm_task(runner))); | 121 | unwrap!(spawner.spawn(usb_ncm_task(runner))); |
| 116 | 122 | ||
| 117 | let config = embassy_net::Config::dhcpv4(Default::default()); | 123 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| @@ -128,11 +134,13 @@ async fn main(spawner: Spawner) { | |||
| 128 | let seed = u64::from_le_bytes(seed); | 134 | let seed = u64::from_le_bytes(seed); |
| 129 | 135 | ||
| 130 | // Init network stack | 136 | // Init network stack |
| 131 | let stack = &*make_static!(Stack::new( | 137 | static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new(); |
| 138 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | ||
| 139 | let stack = &*STACK.init(Stack::new( | ||
| 132 | device, | 140 | device, |
| 133 | config, | 141 | config, |
| 134 | make_static!(StackResources::<2>::new()), | 142 | RESOURCES.init(StackResources::<2>::new()), |
| 135 | seed | 143 | seed, |
| 136 | )); | 144 | )); |
| 137 | 145 | ||
| 138 | unwrap!(spawner.spawn(net_task(stack))); | 146 | unwrap!(spawner.spawn(net_task(stack))); |
diff --git a/examples/stm32f4/src/bin/usb_raw.rs b/examples/stm32f4/src/bin/usb_raw.rs index 719b22bb9..afff55187 100644 --- a/examples/stm32f4/src/bin/usb_raw.rs +++ b/examples/stm32f4/src/bin/usb_raw.rs | |||
| @@ -48,7 +48,6 @@ | |||
| 48 | 48 | ||
| 49 | #![no_std] | 49 | #![no_std] |
| 50 | #![no_main] | 50 | #![no_main] |
| 51 | #![feature(type_alias_impl_trait)] | ||
| 52 | 51 | ||
| 53 | use defmt::*; | 52 | use defmt::*; |
| 54 | use embassy_executor::Spawner; | 53 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs index e2ccc9142..58d994a61 100644 --- a/examples/stm32f4/src/bin/usb_serial.rs +++ b/examples/stm32f4/src/bin/usb_serial.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::{panic, *}; | 4 | use defmt::{panic, *}; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs index 0443b61c5..ea27ebce0 100644 --- a/examples/stm32f4/src/bin/wdt.rs +++ b/examples/stm32f4/src/bin/wdt.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | 3 | ||
| 5 | use defmt::*; | 4 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
diff --git a/examples/stm32f4/src/bin/ws2812_pwm_dma.rs b/examples/stm32f4/src/bin/ws2812_pwm_dma.rs new file mode 100644 index 000000000..4458b643f --- /dev/null +++ b/examples/stm32f4/src/bin/ws2812_pwm_dma.rs | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | // Configure TIM3 in PWM mode, and start DMA Transfer(s) to send color data into ws2812. | ||
| 2 | // We assume the DIN pin of ws2812 connect to GPIO PB4, and ws2812 is properly powered. | ||
| 3 | // | ||
| 4 | // The idea is that the data rate of ws2812 is 800 kHz, and it use different duty ratio to represent bit 0 and bit 1. | ||
| 5 | // Thus we can set TIM overflow at 800 kHz, and let TIM Update Event trigger a DMA transfer, then let DMA change CCR value, | ||
| 6 | // such that pwm duty ratio meet the bit representation of ws2812. | ||
| 7 | // | ||
| 8 | // You may want to modify TIM CCR with Cortex core directly, | ||
| 9 | // but according to my test, Cortex core will need to run far more than 100 MHz to catch up with TIM. | ||
| 10 | // Thus we need to use a DMA. | ||
| 11 | // | ||
| 12 | // This demo is a combination of HAL, PAC, and manually invoke `dma::Transfer`. | ||
| 13 | // If you need a simpler way to control ws2812, you may want to take a look at `ws2812_spi.rs` file, which make use of SPI. | ||
| 14 | // | ||
| 15 | // Warning: | ||
| 16 | // DO NOT stare at ws2812 directy (especially after each MCU Reset), its (max) brightness could easily make your eyes feel burn. | ||
| 17 | |||
| 18 | #![no_std] | ||
| 19 | #![no_main] | ||
| 20 | |||
| 21 | use embassy_executor::Spawner; | ||
| 22 | use embassy_stm32::gpio::OutputType; | ||
| 23 | use embassy_stm32::pac; | ||
| 24 | use embassy_stm32::time::khz; | ||
| 25 | use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; | ||
| 26 | use embassy_stm32::timer::{Channel, CountingMode}; | ||
| 27 | use embassy_time::{Duration, Ticker, Timer}; | ||
| 28 | use {defmt_rtt as _, panic_probe as _}; | ||
| 29 | |||
| 30 | #[embassy_executor::main] | ||
| 31 | async fn main(_spawner: Spawner) { | ||
| 32 | let mut device_config = embassy_stm32::Config::default(); | ||
| 33 | |||
| 34 | // set SYSCLK/HCLK/PCLK2 to 20 MHz, thus each tick is 0.05 us, | ||
| 35 | // and ws2812 timings are integer multiples of 0.05 us | ||
| 36 | { | ||
| 37 | use embassy_stm32::rcc::*; | ||
| 38 | use embassy_stm32::time::*; | ||
| 39 | device_config.enable_debug_during_sleep = true; | ||
| 40 | device_config.rcc.hse = Some(Hse { | ||
| 41 | freq: mhz(12), | ||
| 42 | mode: HseMode::Oscillator, | ||
| 43 | }); | ||
| 44 | device_config.rcc.pll_src = PllSource::HSE; | ||
| 45 | device_config.rcc.pll = Some(Pll { | ||
| 46 | prediv: PllPreDiv::DIV6, | ||
| 47 | mul: PllMul::MUL80, | ||
| 48 | divp: Some(PllPDiv::DIV8), | ||
| 49 | divq: None, | ||
| 50 | divr: None, | ||
| 51 | }); | ||
| 52 | device_config.rcc.sys = Sysclk::PLL1_P; | ||
| 53 | } | ||
| 54 | |||
| 55 | let mut dp = embassy_stm32::init(device_config); | ||
| 56 | |||
| 57 | let mut ws2812_pwm = SimplePwm::new( | ||
| 58 | dp.TIM3, | ||
| 59 | Some(PwmPin::new_ch1(dp.PB4, OutputType::PushPull)), | ||
| 60 | None, | ||
| 61 | None, | ||
| 62 | None, | ||
| 63 | khz(800), // data rate of ws2812 | ||
| 64 | CountingMode::EdgeAlignedUp, | ||
| 65 | ); | ||
| 66 | |||
| 67 | // construct ws2812 non-return-to-zero (NRZ) code bit by bit | ||
| 68 | // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low | ||
| 69 | |||
| 70 | let max_duty = ws2812_pwm.get_max_duty(); | ||
| 71 | let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing | ||
| 72 | let n1 = 2 * n0; // ws2812 Bit 1 high level timing | ||
| 73 | |||
| 74 | let turn_off = [ | ||
| 75 | n0, n0, n0, n0, n0, n0, n0, n0, // Green | ||
| 76 | n0, n0, n0, n0, n0, n0, n0, n0, // Red | ||
| 77 | n0, n0, n0, n0, n0, n0, n0, n0, // Blue | ||
| 78 | 0, // keep PWM output low after a transfer | ||
| 79 | ]; | ||
| 80 | |||
| 81 | let dim_white = [ | ||
| 82 | n0, n0, n0, n0, n0, n0, n1, n0, // Green | ||
| 83 | n0, n0, n0, n0, n0, n0, n1, n0, // Red | ||
| 84 | n0, n0, n0, n0, n0, n0, n1, n0, // Blue | ||
| 85 | 0, // keep PWM output low after a transfer | ||
| 86 | ]; | ||
| 87 | |||
| 88 | let color_list = &[&turn_off, &dim_white]; | ||
| 89 | |||
| 90 | let pwm_channel = Channel::Ch1; | ||
| 91 | |||
| 92 | // PAC level hacking, enable output compare preload | ||
| 93 | // keep output waveform integrity | ||
| 94 | pac::TIM3 | ||
| 95 | .ccmr_output(pwm_channel.index()) | ||
| 96 | .modify(|v| v.set_ocpe(0, true)); | ||
| 97 | |||
| 98 | // make sure PWM output keep low on first start | ||
| 99 | ws2812_pwm.set_duty(pwm_channel, 0); | ||
| 100 | |||
| 101 | { | ||
| 102 | use embassy_stm32::dma::{Burst, FifoThreshold, Transfer, TransferOptions}; | ||
| 103 | |||
| 104 | // configure FIFO and MBURST of DMA, to minimize DMA occupation on AHB/APB | ||
| 105 | let mut dma_transfer_option = TransferOptions::default(); | ||
| 106 | dma_transfer_option.fifo_threshold = Some(FifoThreshold::Full); | ||
| 107 | dma_transfer_option.mburst = Burst::Incr8; | ||
| 108 | |||
| 109 | // flip color at 2 Hz | ||
| 110 | let mut ticker = Ticker::every(Duration::from_millis(500)); | ||
| 111 | |||
| 112 | loop { | ||
| 113 | for &color in color_list { | ||
| 114 | // start PWM output | ||
| 115 | ws2812_pwm.enable(pwm_channel); | ||
| 116 | |||
| 117 | // PAC level hacking, enable timer-update-event trigger DMA | ||
| 118 | pac::TIM3.dier().modify(|v| v.set_ude(true)); | ||
| 119 | |||
| 120 | unsafe { | ||
| 121 | Transfer::new_write( | ||
| 122 | // with &mut, we can easily reuse same DMA channel multiple times | ||
| 123 | &mut dp.DMA1_CH2, | ||
| 124 | 5, | ||
| 125 | color, | ||
| 126 | pac::TIM3.ccr(pwm_channel.index()).as_ptr() as *mut _, | ||
| 127 | dma_transfer_option, | ||
| 128 | ) | ||
| 129 | .await; | ||
| 130 | |||
| 131 | // Turn off timer-update-event trigger DMA as soon as possible. | ||
| 132 | // Then clean the FIFO Error Flag if set. | ||
| 133 | pac::TIM3.dier().modify(|v| v.set_ude(false)); | ||
| 134 | if pac::DMA1.isr(0).read().feif(2) { | ||
| 135 | pac::DMA1.ifcr(0).write(|v| v.set_feif(2, true)); | ||
| 136 | } | ||
| 137 | |||
| 138 | // ws2812 need at least 50 us low level input to confirm the input data and change it's state | ||
| 139 | Timer::after_micros(50).await; | ||
| 140 | } | ||
| 141 | |||
| 142 | // stop PWM output for saving some energy | ||
| 143 | ws2812_pwm.disable(pwm_channel); | ||
| 144 | |||
| 145 | // wait until ticker tick | ||
| 146 | ticker.next().await; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
| 150 | } | ||
diff --git a/examples/stm32f4/src/bin/ws2812_spi.rs b/examples/stm32f4/src/bin/ws2812_spi.rs new file mode 100644 index 000000000..a280a3b77 --- /dev/null +++ b/examples/stm32f4/src/bin/ws2812_spi.rs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | // Mimic PWM with SPI, to control ws2812 | ||
| 2 | // We assume the DIN pin of ws2812 connect to GPIO PB5, and ws2812 is properly powered. | ||
| 3 | // | ||
| 4 | // The idea is that the data rate of ws2812 is 800 kHz, and it use different duty ratio to represent bit 0 and bit 1. | ||
| 5 | // Thus we can adjust SPI to send each *round* of data at 800 kHz, and in each *round*, we can adjust each *bit* to mimic 2 different PWM waveform. | ||
| 6 | // such that the output waveform meet the bit representation of ws2812. | ||
| 7 | // | ||
| 8 | // If you want to save SPI for other purpose, you may want to take a look at `ws2812_pwm_dma.rs` file, which make use of TIM and DMA. | ||
| 9 | // | ||
| 10 | // Warning: | ||
| 11 | // DO NOT stare at ws2812 directy (especially after each MCU Reset), its (max) brightness could easily make your eyes feel burn. | ||
| 12 | |||
| 13 | #![no_std] | ||
| 14 | #![no_main] | ||
| 15 | |||
| 16 | use embassy_stm32::time::khz; | ||
| 17 | use embassy_stm32::{dma, spi}; | ||
| 18 | use embassy_time::{Duration, Ticker, Timer}; | ||
| 19 | use {defmt_rtt as _, panic_probe as _}; | ||
| 20 | |||
| 21 | // we use 16 bit data frame format of SPI, to let timing as accurate as possible. | ||
| 22 | // thanks to loose tolerance of ws2812 timing, you can also use 8 bit data frame format, thus you will need to adjust the bit representation. | ||
| 23 | const N0: u16 = 0b1111100000000000u16; // ws2812 Bit 0 high level timing | ||
| 24 | const N1: u16 = 0b1111111111000000u16; // ws2812 Bit 1 high level timing | ||
| 25 | |||
| 26 | // ws2812 only need 24 bits for each LED, | ||
| 27 | // but we add one bit more to keep SPI output low at the end | ||
| 28 | |||
| 29 | static TURN_OFF: [u16; 25] = [ | ||
| 30 | N0, N0, N0, N0, N0, N0, N0, N0, // Green | ||
| 31 | N0, N0, N0, N0, N0, N0, N0, N0, // Red | ||
| 32 | N0, N0, N0, N0, N0, N0, N0, N0, // Blue | ||
| 33 | 0, // keep SPI output low after last bit | ||
| 34 | ]; | ||
| 35 | |||
| 36 | static DIM_WHITE: [u16; 25] = [ | ||
| 37 | N0, N0, N0, N0, N0, N0, N1, N0, // Green | ||
| 38 | N0, N0, N0, N0, N0, N0, N1, N0, // Red | ||
| 39 | N0, N0, N0, N0, N0, N0, N1, N0, // Blue | ||
| 40 | 0, // keep SPI output low after last bit | ||
| 41 | ]; | ||
| 42 | |||
| 43 | static COLOR_LIST: &[&[u16]] = &[&TURN_OFF, &DIM_WHITE]; | ||
| 44 | |||
| 45 | #[embassy_executor::main] | ||
| 46 | async fn main(_spawner: embassy_executor::Spawner) { | ||
| 47 | let mut device_config = embassy_stm32::Config::default(); | ||
| 48 | |||
| 49 | // Since we use 16 bit SPI, and we need each round 800 kHz, | ||
| 50 | // thus SPI output speed should be 800 kHz * 16 = 12.8 MHz, and APB clock should be 2 * 12.8 MHz = 25.6 MHz. | ||
| 51 | // | ||
| 52 | // As for my setup, with 12 MHz HSE, I got 25.5 MHz SYSCLK, which is slightly slower, but it's ok for ws2812. | ||
| 53 | { | ||
| 54 | use embassy_stm32::rcc::{Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllSource, Sysclk}; | ||
| 55 | use embassy_stm32::time::mhz; | ||
| 56 | device_config.enable_debug_during_sleep = true; | ||
| 57 | device_config.rcc.hse = Some(Hse { | ||
| 58 | freq: mhz(12), | ||
| 59 | mode: HseMode::Oscillator, | ||
| 60 | }); | ||
| 61 | device_config.rcc.pll_src = PllSource::HSE; | ||
| 62 | device_config.rcc.pll = Some(Pll { | ||
| 63 | prediv: PllPreDiv::DIV6, | ||
| 64 | mul: PllMul::MUL102, | ||
| 65 | divp: Some(PllPDiv::DIV8), | ||
| 66 | divq: None, | ||
| 67 | divr: None, | ||
| 68 | }); | ||
| 69 | device_config.rcc.sys = Sysclk::PLL1_P; | ||
| 70 | } | ||
| 71 | |||
| 72 | let dp = embassy_stm32::init(device_config); | ||
| 73 | |||
| 74 | // Set SPI output speed. | ||
| 75 | // It's ok to blindly set frequency to 12800 kHz, the hal crate will take care of the SPI CR1 BR field. | ||
| 76 | // And in my case, the real bit rate will be 25.5 MHz / 2 = 12_750 kHz | ||
| 77 | let mut spi_config = spi::Config::default(); | ||
| 78 | spi_config.frequency = khz(12_800); | ||
| 79 | |||
| 80 | // Since we only output waveform, then the Rx and Sck and RxDma it is not considered | ||
| 81 | let mut ws2812_spi = spi::Spi::new_txonly_nosck(dp.SPI1, dp.PB5, dp.DMA2_CH3, dma::NoDma, spi_config); | ||
| 82 | |||
| 83 | // flip color at 2 Hz | ||
| 84 | let mut ticker = Ticker::every(Duration::from_millis(500)); | ||
| 85 | |||
| 86 | loop { | ||
| 87 | for &color in COLOR_LIST { | ||
| 88 | ws2812_spi.write(color).await.unwrap(); | ||
| 89 | // ws2812 need at least 50 us low level input to confirm the input data and change it's state | ||
| 90 | Timer::after_micros(50).await; | ||
| 91 | // wait until ticker tick | ||
| 92 | ticker.next().await; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
