From 1698f4dbc3b5f4e561c3edd20246af63c22da507 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Thu, 25 Jan 2024 17:10:25 +1000 Subject: [PATCH] Add FDCAN examples for STM32G4, STM32H5 and STM32H7 Fix examples Fix examples Fix examples. --- examples/stm32g4/Cargo.toml | 2 +- examples/stm32g4/src/bin/can.rs | 56 +++++++++++++++++++++++++ examples/stm32h5/src/bin/can.rs | 74 +++++++++++++++++++++++++++++++++ examples/stm32h7/src/bin/can.rs | 74 +++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 examples/stm32g4/src/bin/can.rs create mode 100644 examples/stm32h5/src/bin/can.rs create mode 100644 examples/stm32h7/src/bin/can.rs diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index b87f461b4..895ad3e7c 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g491re to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g473re", "memory-x", "unstable-pac", "exti", "fdcan"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs new file mode 100644 index 000000000..727921fba --- /dev/null +++ b/examples/stm32g4/src/bin/can.rs @@ -0,0 +1,56 @@ +#![no_std] +#![no_main] +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::peripherals::*; +use embassy_stm32::{bind_interrupts, can, Config}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + FDCAN1_IT0 => can::IT0InterruptHandler; + FDCAN1_IT1 => can::IT1InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let config = Config::default(); + + let peripherals = embassy_stm32::init(config); + + let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + + // 250k bps + can.set_bitrate(250_000); + + info!("Configured"); + + //let mut can = can.into_external_loopback_mode(); + let mut can = can.into_normal_mode(); + + let mut i = 0; + loop { + let frame = can::TxFrame::new( + can::TxFrameHeader { + len: 1, + frame_format: can::FrameFormat::Standard, + id: can::StandardId::new(0x123).unwrap().into(), + bit_rate_switching: false, + marker: None, + }, + &[i], + ) + .unwrap(); + info!("Writing frame"); + _ = can.write(&frame).await; + + match can.read().await { + Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + } +} diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs new file mode 100644 index 000000000..2906d1576 --- /dev/null +++ b/examples/stm32h5/src/bin/can.rs @@ -0,0 +1,74 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::peripherals::*; +use embassy_stm32::{bind_interrupts, can, rcc, Config}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + FDCAN1_IT0 => can::IT0InterruptHandler; + FDCAN1_IT1 => can::IT1InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + + // configure FDCAN to use PLL1_Q at 64 MHz + config.rcc.pll1 = Some(rcc::Pll { + source: rcc::PllSource::HSI, + prediv: rcc::PllPreDiv::DIV4, + mul: rcc::PllMul::MUL8, + divp: None, + divq: Some(rcc::PllDiv::DIV2), + divr: None, + }); + config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q; + + let peripherals = embassy_stm32::init(config); + + let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + + can.can.apply_config( + can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming { + sync_jump_width: 1.try_into().unwrap(), + prescaler: 8.try_into().unwrap(), + seg1: 13.try_into().unwrap(), + seg2: 2.try_into().unwrap(), + }), + ); + + info!("Configured"); + + let mut can = can.into_external_loopback_mode(); + //let mut can = can.into_normal_mode(); + + let mut i = 0; + loop { + let frame = can::TxFrame::new( + can::TxFrameHeader { + len: 1, + frame_format: can::FrameFormat::Standard, + id: can::StandardId::new(0x123).unwrap().into(), + bit_rate_switching: false, + marker: None, + }, + &[i], + ) + .unwrap(); + info!("Writing frame"); + _ = can.write(&frame).await; + + match can.read().await { + Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + } +} diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs new file mode 100644 index 000000000..2906d1576 --- /dev/null +++ b/examples/stm32h7/src/bin/can.rs @@ -0,0 +1,74 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::peripherals::*; +use embassy_stm32::{bind_interrupts, can, rcc, Config}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + FDCAN1_IT0 => can::IT0InterruptHandler; + FDCAN1_IT1 => can::IT1InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + + // configure FDCAN to use PLL1_Q at 64 MHz + config.rcc.pll1 = Some(rcc::Pll { + source: rcc::PllSource::HSI, + prediv: rcc::PllPreDiv::DIV4, + mul: rcc::PllMul::MUL8, + divp: None, + divq: Some(rcc::PllDiv::DIV2), + divr: None, + }); + config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q; + + let peripherals = embassy_stm32::init(config); + + let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + + can.can.apply_config( + can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming { + sync_jump_width: 1.try_into().unwrap(), + prescaler: 8.try_into().unwrap(), + seg1: 13.try_into().unwrap(), + seg2: 2.try_into().unwrap(), + }), + ); + + info!("Configured"); + + let mut can = can.into_external_loopback_mode(); + //let mut can = can.into_normal_mode(); + + let mut i = 0; + loop { + let frame = can::TxFrame::new( + can::TxFrameHeader { + len: 1, + frame_format: can::FrameFormat::Standard, + id: can::StandardId::new(0x123).unwrap().into(), + bit_rate_switching: false, + marker: None, + }, + &[i], + ) + .unwrap(); + info!("Writing frame"); + _ = can.write(&frame).await; + + match can.read().await { + Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + } +}