From 83069e7b49bd181236e6a68005ad6119d39b39c3 Mon Sep 17 00:00:00 2001 From: eZio Pan Date: Fri, 22 Mar 2024 00:58:03 +0800 Subject: stm32 CORDIC: add example --- examples/stm32h5/src/bin/cordic.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 examples/stm32h5/src/bin/cordic.rs (limited to 'examples') diff --git a/examples/stm32h5/src/bin/cordic.rs b/examples/stm32h5/src/bin/cordic.rs new file mode 100644 index 000000000..d49f75b8f --- /dev/null +++ b/examples/stm32h5/src/bin/cordic.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::cordic; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut dp = embassy_stm32::init(Default::default()); + + let mut cordic = cordic::Cordic::new( + &mut dp.CORDIC, + unwrap!(cordic::Config::new( + cordic::Function::Sin, + Default::default(), + Default::default(), + false, + )), + ); + + let mut output = [0f64; 16]; + + let arg1 = [1.0, 0.0, -1.0]; // for trigonometric function, the ARG1 value [-pi, pi] should be map to [-1, 1] + let arg2 = [0.5, 1.0]; + + let cnt = unwrap!( + cordic + .async_calc_32bit(&mut dp.GPDMA1_CH0, &mut dp.GPDMA1_CH1, &arg1, Some(&arg2), &mut output,) + .await + ); + + println!("async calc 32bit: {}", output[..cnt]); +} -- cgit From 0abcccee966af0b12e62fc7fae8499fa03194823 Mon Sep 17 00:00:00 2001 From: eZio Pan Date: Fri, 22 Mar 2024 17:29:10 +0800 Subject: stm32 CORDIC: re-design API --- examples/stm32h5/src/bin/cordic.rs | 59 ++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 8 deletions(-) (limited to 'examples') diff --git a/examples/stm32h5/src/bin/cordic.rs b/examples/stm32h5/src/bin/cordic.rs index d49f75b8f..73e873574 100644 --- a/examples/stm32h5/src/bin/cordic.rs +++ b/examples/stm32h5/src/bin/cordic.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::cordic; +use embassy_stm32::cordic::{self, utils}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -16,20 +16,63 @@ async fn main(_spawner: Spawner) { cordic::Function::Sin, Default::default(), Default::default(), - false, )), ); - let mut output = [0f64; 16]; + // for output buf, the length is not that strict, larger than minimal required is ok. + let mut output_f64 = [0f64; 19]; + let mut output_u32 = [0u32; 21]; - let arg1 = [1.0, 0.0, -1.0]; // for trigonometric function, the ARG1 value [-pi, pi] should be map to [-1, 1] - let arg2 = [0.5, 1.0]; + // tips: + // CORDIC peripheral has some strict on input value, you can also use ".check_argX_fXX()" methods + // to make sure your input values are compatible with current CORDIC setup. + 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] + let arg2 = [0.5]; // and for Sin function, ARG2 should be in [0, 1] - let cnt = unwrap!( + let mut input_buf = [0u32; 9]; + + // convert input from floating point to fixed point + input_buf[0] = unwrap!(utils::f64_to_q1_31(arg1[0])); + input_buf[1] = unwrap!(utils::f64_to_q1_31(arg2[0])); + + // If input length is small, blocking mode can be used to minimize overhead. + let cnt0 = unwrap!(cordic.blocking_calc_32bit( + &input_buf[..2], // input length is strict, since driver use its length to detect calculation count + &mut output_u32, + false, + false + )); + + // convert result from fixed point into floating point + for (&u32_val, f64_val) in output_u32[..cnt0].iter().zip(output_f64.iter_mut()) { + *f64_val = utils::q1_31_to_f64(u32_val); + } + + // convert input from floating point to fixed point + // + // first value from arg1 is used, so truncate to arg1[1..] + for (&f64_val, u32_val) in arg1[1..].iter().zip(input_buf.iter_mut()) { + *u32_val = unwrap!(utils::f64_to_q1_31(f64_val)); + } + + // If calculation is a little longer, async mode can make use of DMA, and let core do some other stuff. + let cnt1 = unwrap!( cordic - .async_calc_32bit(&mut dp.GPDMA1_CH0, &mut dp.GPDMA1_CH1, &arg1, Some(&arg2), &mut output,) + .async_calc_32bit( + &mut dp.GPDMA1_CH0, + &mut dp.GPDMA1_CH1, + &input_buf[..arg1.len() - 1], // limit input buf to its actual length + &mut output_u32, + true, + false + ) .await ); - println!("async calc 32bit: {}", output[..cnt]); + // convert result from fixed point into floating point + for (&u32_val, f64_val) in output_u32[..cnt1].iter().zip(output_f64[cnt0..cnt0 + cnt1].iter_mut()) { + *f64_val = utils::q1_31_to_f64(u32_val); + } + + println!("result: {}", output_f64[..cnt0 + cnt1]); } -- cgit From a84b33995eacc32e0e13d70293fa9bd7b2bd75f8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 5 Apr 2024 00:35:25 +0200 Subject: rp: remove mod sealed. --- examples/rp/src/bin/pio_stepper.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') 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> { let clock_divider: FixedU32 = (125_000_000 / (freq * 136)).to_fixed(); assert!(clock_divider <= 65536, "clkdiv must be <= 65536"); assert!(clock_divider >= 1, "clkdiv must be >= 1"); - T::PIO.sm(SM).clkdiv().write(|w| w.0 = clock_divider.to_bits() << 8); + self.sm.set_clock_divider(clock_divider); self.sm.clkdiv_restart(); } -- cgit From 143b288333a96c3caf6a0f372edca13ebea10af1 Mon Sep 17 00:00:00 2001 From: pawel00100 Date: Wed, 24 Jan 2024 23:24:26 +0100 Subject: Add parameter for enabling pull-up and pull-down in RP PWM input mode --- examples/rp/src/bin/pwm_input.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'examples') 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 @@ use defmt::*; use embassy_executor::Spawner; +use embassy_rp::gpio::Pull; use embassy_rp::pwm::{Config, InputMode, Pwm}; use embassy_time::{Duration, Ticker}; use {defmt_rtt as _, panic_probe as _}; @@ -14,7 +15,7 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let cfg: Config = Default::default(); - let pwm = Pwm::new_input(p.PWM_SLICE2, p.PIN_5, InputMode::RisingEdge, cfg); + let pwm = Pwm::new_input(p.PWM_SLICE2, p.PIN_5, Pull::None, InputMode::RisingEdge, cfg); let mut ticker = Ticker::every(Duration::from_secs(1)); loop { -- cgit From 99ea564f1c5cc3dcce908cb853f528a52cca8ae8 Mon Sep 17 00:00:00 2001 From: Barnaby Walters Date: Fri, 5 Apr 2024 22:11:01 +0200 Subject: Add VBUS detection blackpill comment --- examples/stm32f4/src/bin/usb_hid_keyboard.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'examples') 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) { // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; let mut config = embassy_stm32::usb::Config::default(); + // 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 config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); -- cgit From cf0097162cb33d77d90ce5cb50f8fb5c24972748 Mon Sep 17 00:00:00 2001 From: Barnaby Walters Date: Sun, 7 Apr 2024 15:19:56 +0200 Subject: [embassy-stm32] added comments explaining multiprio interrupts --- examples/stm32f0/src/bin/multiprio.rs | 4 ++++ examples/stm32f3/src/bin/multiprio.rs | 4 ++++ examples/stm32f4/src/bin/multiprio.rs | 4 ++++ examples/stm32h7/src/bin/multiprio.rs | 4 ++++ 4 files changed, 16 insertions(+) (limited to 'examples') diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index e49951726..e36c0d6c2 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs @@ -126,6 +126,10 @@ fn main() -> ! { // Initialize and create handle for devicer peripherals let _p = embassy_stm32::init(Default::default()); + // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used + // by the rest of your application. In this case we’re using UART1 and UART2, but there’s nothing special + // about them. Any otherwise unused interrupt vector would work exactly the same. + // High-priority executor: USART1, priority level 6 interrupt::USART1.set_priority(Priority::P6); 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..3a3059db1 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs @@ -127,6 +127,10 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); + // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used + // by the rest of your application. In this case we’re using UART4 and UART5, but there’s nothing special + // about them. Any otherwise unused interrupt vector would work exactly the same. + // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); 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..5a55cd291 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs @@ -127,6 +127,10 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); + // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used + // by the rest of your application. In this case we’re using UART6 and UART7, but there’s nothing special + // about them. Any otherwise unused interrupt vector would work exactly the same. + // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::UART4); diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index 73f8dd092..f9a00f806 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs @@ -127,6 +127,10 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); + // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used + // by the rest of your application. In this case we’re using UART6 and UART7, but there’s nothing special + // about them. Any otherwise unused interrupt vector would work exactly the same. + // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::UART4); -- cgit From 56d34eefaa2862ebaf883e5388f909f7989aba1f Mon Sep 17 00:00:00 2001 From: Barnaby Walters Date: Sun, 7 Apr 2024 15:33:51 +0200 Subject: Apply suggestions from code review Co-authored-by: becothas <41289937+becothas@users.noreply.github.com> --- examples/stm32f4/src/bin/multiprio.rs | 2 +- examples/stm32h7/src/bin/multiprio.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 5a55cd291..3a3059db1 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs @@ -128,7 +128,7 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used - // by the rest of your application. In this case we’re using UART6 and UART7, but there’s nothing special + // by the rest of your application. In this case we’re using UART4 and UART5, but there’s nothing special // about them. Any otherwise unused interrupt vector would work exactly the same. // High-priority executor: UART4, priority level 6 diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index f9a00f806..ded9d390e 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs @@ -128,7 +128,7 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used - // by the rest of your application. In this case we’re using UART6 and UART7, but there’s nothing special + // by the rest of your application. In this case we’re using UART4 and UART5, but there’s nothing special // about them. Any otherwise unused interrupt vector would work exactly the same. // High-priority executor: UART4, priority level 6 -- cgit From effc08dde34c39da3f6bb4363d517de4f5c1ddd4 Mon Sep 17 00:00:00 2001 From: Barnaby Walters Date: Sun, 7 Apr 2024 16:22:42 +0200 Subject: Incorporated adam’s suggestion into all multiprio comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/stm32f0/src/bin/multiprio.rs | 7 ++++--- examples/stm32f3/src/bin/multiprio.rs | 7 ++++--- examples/stm32f4/src/bin/multiprio.rs | 7 ++++--- examples/stm32h7/src/bin/multiprio.rs | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) (limited to 'examples') diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index e36c0d6c2..1c3f3991a 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs @@ -126,9 +126,10 @@ fn main() -> ! { // Initialize and create handle for devicer peripherals let _p = embassy_stm32::init(Default::default()); - // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used - // by the rest of your application. In this case we’re using UART1 and UART2, but there’s nothing special - // about them. Any otherwise unused interrupt vector would work exactly the same. + // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as + // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. + // In this case we’re using UART1 and UART2, but there’s nothing special about them. Any otherwise unused interrupt + // vector would work exactly the same. // High-priority executor: USART1, priority level 6 interrupt::USART1.set_priority(Priority::P6); diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index 3a3059db1..87830b416 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs @@ -127,9 +127,10 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); - // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used - // by the rest of your application. In this case we’re using UART4 and UART5, but there’s nothing special - // about them. Any otherwise unused interrupt vector would work exactly the same. + // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as + // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. + // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt + // vector would work exactly the same. // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 3a3059db1..87830b416 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs @@ -127,9 +127,10 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); - // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used - // by the rest of your application. In this case we’re using UART4 and UART5, but there’s nothing special - // about them. Any otherwise unused interrupt vector would work exactly the same. + // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as + // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. + // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt + // vector would work exactly the same. // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index ded9d390e..fcbb6c653 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs @@ -127,9 +127,10 @@ fn main() -> ! { let _p = embassy_stm32::init(Default::default()); - // STM32s don’t have software-defined interrupts, so just use any free interrupt vectors which aren’t used - // by the rest of your application. In this case we’re using UART4 and UART5, but there’s nothing special - // about them. Any otherwise unused interrupt vector would work exactly the same. + // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as + // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application. + // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt + // vector would work exactly the same. // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); -- cgit