diff options
| author | Gustav Toft <[email protected]> | 2024-04-10 13:26:59 +0200 |
|---|---|---|
| committer | Gustav Toft <[email protected]> | 2024-04-10 13:26:59 +0200 |
| commit | 4ffe35c840f1a35e3bbc0cdb29203cbaac5abd08 (patch) | |
| tree | 052084b9cbc9452f5964ab08e71f0468b4eea8b6 /examples | |
| parent | 11bf2ca987f5830fe8637029adbc208b1ff7349d (diff) | |
| parent | c575c7dc6cab49a99f36eedbdd41e97868e1102b (diff) | |
Merge branch 'main' of https://github.com/embassy-rs/embassy
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/src/bin/pio_stepper.rs | 2 | ||||
| -rw-r--r-- | examples/rp/src/bin/pwm_input.rs | 3 | ||||
| -rw-r--r-- | examples/stm32f0/src/bin/multiprio.rs | 5 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/multiprio.rs | 5 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/multiprio.rs | 5 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/usb_hid_keyboard.rs | 1 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/cordic.rs | 78 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/multiprio.rs | 5 |
8 files changed, 102 insertions, 2 deletions
diff --git a/examples/rp/src/bin/pio_stepper.rs b/examples/rp/src/bin/pio_stepper.rs index ab9ecf623..4952f4fbd 100644 --- a/examples/rp/src/bin/pio_stepper.rs +++ b/examples/rp/src/bin/pio_stepper.rs | |||
| @@ -69,7 +69,7 @@ impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> { | |||
| 69 | let clock_divider: FixedU32<U8> = (125_000_000 / (freq * 136)).to_fixed(); | 69 | let clock_divider: FixedU32<U8> = (125_000_000 / (freq * 136)).to_fixed(); |
| 70 | assert!(clock_divider <= 65536, "clkdiv must be <= 65536"); | 70 | assert!(clock_divider <= 65536, "clkdiv must be <= 65536"); |
| 71 | assert!(clock_divider >= 1, "clkdiv must be >= 1"); | 71 | assert!(clock_divider >= 1, "clkdiv must be >= 1"); |
| 72 | T::PIO.sm(SM).clkdiv().write(|w| w.0 = clock_divider.to_bits() << 8); | 72 | self.sm.set_clock_divider(clock_divider); |
| 73 | self.sm.clkdiv_restart(); | 73 | self.sm.clkdiv_restart(); |
| 74 | } | 74 | } |
| 75 | 75 | ||
diff --git a/examples/rp/src/bin/pwm_input.rs b/examples/rp/src/bin/pwm_input.rs index 0652dc42b..bf454a936 100644 --- a/examples/rp/src/bin/pwm_input.rs +++ b/examples/rp/src/bin/pwm_input.rs | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::gpio::Pull; | ||
| 8 | use embassy_rp::pwm::{Config, InputMode, Pwm}; | 9 | use embassy_rp::pwm::{Config, InputMode, Pwm}; |
| 9 | use embassy_time::{Duration, Ticker}; | 10 | use embassy_time::{Duration, Ticker}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -14,7 +15,7 @@ async fn main(_spawner: Spawner) { | |||
| 14 | let p = embassy_rp::init(Default::default()); | 15 | let p = embassy_rp::init(Default::default()); |
| 15 | 16 | ||
| 16 | let cfg: Config = Default::default(); | 17 | let cfg: Config = Default::default(); |
| 17 | let pwm = Pwm::new_input(p.PWM_SLICE2, p.PIN_5, InputMode::RisingEdge, cfg); | 18 | let pwm = Pwm::new_input(p.PWM_SLICE2, p.PIN_5, Pull::None, InputMode::RisingEdge, cfg); |
| 18 | 19 | ||
| 19 | let mut ticker = Ticker::every(Duration::from_secs(1)); | 20 | let mut ticker = Ticker::every(Duration::from_secs(1)); |
| 20 | loop { | 21 | loop { |
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index e49951726..1c3f3991a 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs | |||
| @@ -126,6 +126,11 @@ fn main() -> ! { | |||
| 126 | // Initialize and create handle for devicer peripherals | 126 | // Initialize and create handle for devicer peripherals |
| 127 | let _p = embassy_stm32::init(Default::default()); | 127 | let _p = embassy_stm32::init(Default::default()); |
| 128 | 128 | ||
| 129 | // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as | ||
| 130 | // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. | ||
| 131 | // In this case we’re using UART1 and UART2, but there’s nothing special about them. Any otherwise unused interrupt | ||
| 132 | // vector would work exactly the same. | ||
| 133 | |||
| 129 | // High-priority executor: USART1, priority level 6 | 134 | // High-priority executor: USART1, priority level 6 |
| 130 | interrupt::USART1.set_priority(Priority::P6); | 135 | interrupt::USART1.set_priority(Priority::P6); |
| 131 | let spawner = EXECUTOR_HIGH.start(interrupt::USART1); | 136 | let spawner = EXECUTOR_HIGH.start(interrupt::USART1); |
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index 328447210..87830b416 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs | |||
| @@ -127,6 +127,11 @@ fn main() -> ! { | |||
| 127 | 127 | ||
| 128 | let _p = embassy_stm32::init(Default::default()); | 128 | let _p = embassy_stm32::init(Default::default()); |
| 129 | 129 | ||
| 130 | // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as | ||
| 131 | // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. | ||
| 132 | // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt | ||
| 133 | // vector would work exactly the same. | ||
| 134 | |||
| 130 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 131 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 132 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 328447210..87830b416 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs | |||
| @@ -127,6 +127,11 @@ fn main() -> ! { | |||
| 127 | 127 | ||
| 128 | let _p = embassy_stm32::init(Default::default()); | 128 | let _p = embassy_stm32::init(Default::default()); |
| 129 | 129 | ||
| 130 | // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as | ||
| 131 | // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. | ||
| 132 | // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt | ||
| 133 | // vector would work exactly the same. | ||
| 134 | |||
| 130 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 131 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 132 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs index a799b4e72..d6e0be5ea 100644 --- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs +++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs | |||
| @@ -49,6 +49,7 @@ async fn main(_spawner: Spawner) { | |||
| 49 | // Create the driver, from the HAL. | 49 | // Create the driver, from the HAL. |
| 50 | let mut ep_out_buffer = [0u8; 256]; | 50 | let mut ep_out_buffer = [0u8; 256]; |
| 51 | let mut config = embassy_stm32::usb::Config::default(); | 51 | let mut config = embassy_stm32::usb::Config::default(); |
| 52 | // If the board you’re using doesn’t have the VBUS pin wired up correctly for detecting the USB bus voltage (e.g. on the f4 blackpill board), set this to false | ||
| 52 | config.vbus_detection = true; | 53 | config.vbus_detection = true; |
| 53 | let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); | 54 | let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); |
| 54 | 55 | ||
diff --git a/examples/stm32h5/src/bin/cordic.rs b/examples/stm32h5/src/bin/cordic.rs new file mode 100644 index 000000000..73e873574 --- /dev/null +++ b/examples/stm32h5/src/bin/cordic.rs | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::cordic::{self, utils}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let mut dp = embassy_stm32::init(Default::default()); | ||
| 12 | |||
| 13 | let mut cordic = cordic::Cordic::new( | ||
| 14 | &mut dp.CORDIC, | ||
| 15 | unwrap!(cordic::Config::new( | ||
| 16 | cordic::Function::Sin, | ||
| 17 | Default::default(), | ||
| 18 | Default::default(), | ||
| 19 | )), | ||
| 20 | ); | ||
| 21 | |||
| 22 | // for output buf, the length is not that strict, larger than minimal required is ok. | ||
| 23 | let mut output_f64 = [0f64; 19]; | ||
| 24 | let mut output_u32 = [0u32; 21]; | ||
| 25 | |||
| 26 | // tips: | ||
| 27 | // CORDIC peripheral has some strict on input value, you can also use ".check_argX_fXX()" methods | ||
| 28 | // to make sure your input values are compatible with current CORDIC setup. | ||
| 29 | let arg1 = [-1.0, -0.5, 0.0, 0.5, 1.0]; // for trigonometric function, the ARG1 value [-pi, pi] should be map to [-1, 1] | ||
| 30 | let arg2 = [0.5]; // and for Sin function, ARG2 should be in [0, 1] | ||
| 31 | |||
| 32 | let mut input_buf = [0u32; 9]; | ||
| 33 | |||
| 34 | // convert input from floating point to fixed point | ||
| 35 | input_buf[0] = unwrap!(utils::f64_to_q1_31(arg1[0])); | ||
| 36 | input_buf[1] = unwrap!(utils::f64_to_q1_31(arg2[0])); | ||
| 37 | |||
| 38 | // If input length is small, blocking mode can be used to minimize overhead. | ||
| 39 | let cnt0 = unwrap!(cordic.blocking_calc_32bit( | ||
| 40 | &input_buf[..2], // input length is strict, since driver use its length to detect calculation count | ||
| 41 | &mut output_u32, | ||
| 42 | false, | ||
| 43 | false | ||
| 44 | )); | ||
| 45 | |||
| 46 | // convert result from fixed point into floating point | ||
| 47 | for (&u32_val, f64_val) in output_u32[..cnt0].iter().zip(output_f64.iter_mut()) { | ||
| 48 | *f64_val = utils::q1_31_to_f64(u32_val); | ||
| 49 | } | ||
| 50 | |||
| 51 | // convert input from floating point to fixed point | ||
| 52 | // | ||
| 53 | // first value from arg1 is used, so truncate to arg1[1..] | ||
| 54 | for (&f64_val, u32_val) in arg1[1..].iter().zip(input_buf.iter_mut()) { | ||
| 55 | *u32_val = unwrap!(utils::f64_to_q1_31(f64_val)); | ||
| 56 | } | ||
| 57 | |||
| 58 | // If calculation is a little longer, async mode can make use of DMA, and let core do some other stuff. | ||
| 59 | let cnt1 = unwrap!( | ||
| 60 | cordic | ||
| 61 | .async_calc_32bit( | ||
| 62 | &mut dp.GPDMA1_CH0, | ||
| 63 | &mut dp.GPDMA1_CH1, | ||
| 64 | &input_buf[..arg1.len() - 1], // limit input buf to its actual length | ||
| 65 | &mut output_u32, | ||
| 66 | true, | ||
| 67 | false | ||
| 68 | ) | ||
| 69 | .await | ||
| 70 | ); | ||
| 71 | |||
| 72 | // convert result from fixed point into floating point | ||
| 73 | for (&u32_val, f64_val) in output_u32[..cnt1].iter().zip(output_f64[cnt0..cnt0 + cnt1].iter_mut()) { | ||
| 74 | *f64_val = utils::q1_31_to_f64(u32_val); | ||
| 75 | } | ||
| 76 | |||
| 77 | println!("result: {}", output_f64[..cnt0 + cnt1]); | ||
| 78 | } | ||
diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index 73f8dd092..fcbb6c653 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs | |||
| @@ -127,6 +127,11 @@ fn main() -> ! { | |||
| 127 | 127 | ||
| 128 | let _p = embassy_stm32::init(Default::default()); | 128 | let _p = embassy_stm32::init(Default::default()); |
| 129 | 129 | ||
| 130 | // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as | ||
| 131 | // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. | ||
| 132 | // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt | ||
| 133 | // vector would work exactly the same. | ||
| 134 | |||
| 130 | // High-priority executor: UART4, priority level 6 | 135 | // High-priority executor: UART4, priority level 6 |
| 131 | interrupt::UART4.set_priority(Priority::P6); | 136 | interrupt::UART4.set_priority(Priority::P6); |
| 132 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); | 137 | let spawner = EXECUTOR_HIGH.start(interrupt::UART4); |
