From 70b3c4374d57ab638e0cb76013b725e1ea229546 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Sat, 3 Feb 2024 09:44:00 +1000 Subject: Port FDCAN HAL to use PAC directly instead of fdcan crate. - Provide separate FDCAN capable and Classic CAN API's - Don't use fdcan crate dep anymore - Provide embedded-can traits. --- examples/stm32g4/Cargo.toml | 1 + examples/stm32g4/src/bin/can.rs | 96 +++++++++++++++++++++++++++++++++++------ examples/stm32h5/src/bin/can.rs | 89 ++++++++++++++++++++++++-------------- examples/stm32h7/src/bin/can.rs | 89 ++++++++++++++++++++++++-------------- 4 files changed, 195 insertions(+), 80 deletions(-) (limited to 'examples') diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 895ad3e7c..fdb325f06 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -20,6 +20,7 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" +embedded-can = { version = "0.4" } panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.8", default-features = false } diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 727921fba..5ff4f0ef0 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs @@ -20,32 +20,100 @@ async fn main(_spawner: Spawner) { let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + can.set_extended_filter( + can::fd::filter::ExtendedFilterSlot::_0, + can::fd::filter::ExtendedFilter::accept_all_into_fifo1(), + ); + // 250k bps can.set_bitrate(250_000); + // 1M bps + can.set_fd_data_bitrate(1_000_000, false); + info!("Configured"); - //let mut can = can.into_external_loopback_mode(); - let mut can = can.into_normal_mode(); + //let mut can = can.into_normal_mode(); + let mut can = can.into_internal_loopback_mode(); let mut i = 0; + let mut last_read_ts = embassy_time::Instant::now(); + 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(); + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); info!("Writing frame"); + _ = can.write(&frame).await; match can.read().await { - Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {} {:02x} --- {}ms", + rx_frame.header().len(), + rx_frame.data()[0..rx_frame.header().len() as usize], + delta, + ) + } + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + if i > 2 { + break; + } + } + + // Use the FD API's even if we don't get FD packets. + loop { + let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); + info!("Writing frame using FD API"); + + _ = can.write_fd(&frame).await; + + match can.read_fd().await { + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {} {:02x} --- using FD API {}ms", + rx_frame.header().len(), + rx_frame.data()[0..rx_frame.header().len() as usize], + delta, + ) + } + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + if i > 4 { + break; + } + } + + let (mut tx, mut rx) = can.split(); + // With split + loop { + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); + info!("Writing frame"); + _ = tx.write(&frame).await; + + match rx.read().await { + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {} {:02x} --- {}ms", + rx_frame.header().len(), + rx_frame.data()[0..rx_frame.header().len() as usize], + delta, + ) + } Err(_err) => error!("Error in frame"), } diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs index 2906d1576..4b29a0d21 100644 --- a/examples/stm32h5/src/bin/can.rs +++ b/examples/stm32h5/src/bin/can.rs @@ -16,54 +16,77 @@ bind_interrupts!(struct Irqs { #[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.hse = Some(rcc::Hse { + freq: embassy_stm32::time::Hertz(25_000_000), + mode: rcc::HseMode::Oscillator, }); - config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q; + config.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; let peripherals = embassy_stm32::init(config); + //let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); 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(), - }), - ); + // 250k bps + can.set_bitrate(250_000); - info!("Configured"); + //let mut can = can.into_internal_loopback_mode(); + let mut can = can.into_normal_mode(); - let mut can = can.into_external_loopback_mode(); - //let mut can = can.into_normal_mode(); + info!("CAN Configured"); let mut i = 0; + let mut last_read_ts = embassy_time::Instant::now(); + 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(); + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); info!("Writing frame"); _ = can.write(&frame).await; match can.read().await { - Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {:x} {:x} {:x} {:x} --- NEW {}", + rx_frame.data()[0], + rx_frame.data()[1], + rx_frame.data()[2], + rx_frame.data()[3], + delta, + ) + } + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + if i > 3 { + break; + } + } + + let (mut tx, mut rx) = can.split(); + // With split + loop { + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); + info!("Writing frame"); + _ = tx.write(&frame).await; + + match rx.read().await { + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {:x} {:x} {:x} {:x} --- NEW {}", + rx_frame.data()[0], + rx_frame.data()[1], + rx_frame.data()[2], + rx_frame.data()[3], + delta, + ) + } Err(_err) => error!("Error in frame"), } diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs index 2906d1576..4b29a0d21 100644 --- a/examples/stm32h7/src/bin/can.rs +++ b/examples/stm32h7/src/bin/can.rs @@ -16,54 +16,77 @@ bind_interrupts!(struct Irqs { #[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.hse = Some(rcc::Hse { + freq: embassy_stm32::time::Hertz(25_000_000), + mode: rcc::HseMode::Oscillator, }); - config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q; + config.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; let peripherals = embassy_stm32::init(config); + //let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); 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(), - }), - ); + // 250k bps + can.set_bitrate(250_000); - info!("Configured"); + //let mut can = can.into_internal_loopback_mode(); + let mut can = can.into_normal_mode(); - let mut can = can.into_external_loopback_mode(); - //let mut can = can.into_normal_mode(); + info!("CAN Configured"); let mut i = 0; + let mut last_read_ts = embassy_time::Instant::now(); + 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(); + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); info!("Writing frame"); _ = can.write(&frame).await; match can.read().await { - Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]), + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {:x} {:x} {:x} {:x} --- NEW {}", + rx_frame.data()[0], + rx_frame.data()[1], + rx_frame.data()[2], + rx_frame.data()[3], + delta, + ) + } + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + if i > 3 { + break; + } + } + + let (mut tx, mut rx) = can.split(); + // With split + loop { + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); + info!("Writing frame"); + _ = tx.write(&frame).await; + + match rx.read().await { + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {:x} {:x} {:x} {:x} --- NEW {}", + rx_frame.data()[0], + rx_frame.data()[1], + rx_frame.data()[2], + rx_frame.data()[3], + delta, + ) + } Err(_err) => error!("Error in frame"), } -- cgit From 5ad291b708528b5772d6ebcc9309fbd3f8a002c8 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Sat, 17 Feb 2024 18:12:47 +1000 Subject: Add a buffered mode. --- examples/stm32g4/src/bin/can.rs | 97 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 7 deletions(-) (limited to 'examples') diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 5ff4f0ef0..043ca7144 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs @@ -5,6 +5,7 @@ use embassy_executor::Spawner; use embassy_stm32::peripherals::*; use embassy_stm32::{bind_interrupts, can, Config}; use embassy_time::Timer; +use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -28,13 +29,17 @@ async fn main(_spawner: Spawner) { // 250k bps can.set_bitrate(250_000); + let use_fd = false; + // 1M bps - can.set_fd_data_bitrate(1_000_000, false); + if use_fd { + can.set_fd_data_bitrate(1_000_000, false); + } info!("Configured"); - //let mut can = can.into_normal_mode(); - let mut can = can.into_internal_loopback_mode(); + let mut can = can.into_normal_mode(); + //let mut can = can.into_internal_loopback_mode(); let mut i = 0; let mut last_read_ts = embassy_time::Instant::now(); @@ -68,11 +73,17 @@ async fn main(_spawner: Spawner) { } // Use the FD API's even if we don't get FD packets. - loop { - let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); - info!("Writing frame using FD API"); - _ = can.write_fd(&frame).await; + loop { + if use_fd { + let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); + info!("Writing frame using FD API"); + _ = can.write_fd(&frame).await; + } else { + let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 8]).unwrap(); + info!("Writing frame using FD API"); + _ = can.write_fd(&frame).await; + } match can.read_fd().await { Ok((rx_frame, ts)) => { @@ -96,6 +107,7 @@ async fn main(_spawner: Spawner) { } } + i = 0; let (mut tx, mut rx) = can.split(); // With split loop { @@ -120,5 +132,76 @@ async fn main(_spawner: Spawner) { Timer::after_millis(250).await; i += 1; + + if i > 2 { + break; + } + } + + let can = can::Fdcan::join(tx, rx); + + info!("\n\n\nBuffered\n"); + if use_fd { + static TX_BUF: StaticCell> = StaticCell::new(); + static RX_BUF: StaticCell> = StaticCell::new(); + let mut can = can.buffered_fd( + TX_BUF.init(can::TxFdBuf::<8>::new()), + RX_BUF.init(can::RxFdBuf::<10>::new()), + ); + loop { + let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); + info!("Writing frame"); + + _ = can.write(frame).await; + + match can.read().await { + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {} {:02x} --- {}ms", + rx_frame.header().len(), + rx_frame.data()[0..rx_frame.header().len() as usize], + delta, + ) + } + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + } + } else { + static TX_BUF: StaticCell> = StaticCell::new(); + static RX_BUF: StaticCell> = StaticCell::new(); + let mut can = can.buffered( + TX_BUF.init(can::TxBuf::<8>::new()), + RX_BUF.init(can::RxBuf::<10>::new()), + ); + loop { + let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); + info!("Writing frame"); + + _ = can.write(frame).await; + + match can.read().await { + Ok((rx_frame, ts)) => { + let delta = (ts - last_read_ts).as_millis(); + last_read_ts = ts; + info!( + "Rx: {} {:02x} --- {}ms", + rx_frame.header().len(), + rx_frame.data()[0..rx_frame.header().len() as usize], + delta, + ) + } + Err(_err) => error!("Error in frame"), + } + + Timer::after_millis(250).await; + + i += 1; + } } } -- cgit From eafa90cd0707298f354d5d1e496f8364117bd781 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Sun, 18 Feb 2024 13:09:37 +1000 Subject: Remove the OperatingMode typestates Instead have two explcit types(without the mode generic arg)types: - One for config - One for all operating modes --- examples/stm32g4/src/bin/can.rs | 9 +++++---- examples/stm32h5/src/bin/can.rs | 3 +-- examples/stm32h7/src/bin/can.rs | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'examples') diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 043ca7144..affa97039 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs @@ -19,7 +19,7 @@ async fn main(_spawner: Spawner) { let peripherals = embassy_stm32::init(config); - let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); can.set_extended_filter( can::fd::filter::ExtendedFilterSlot::_0, @@ -38,8 +38,10 @@ async fn main(_spawner: Spawner) { info!("Configured"); - let mut can = can.into_normal_mode(); - //let mut can = can.into_internal_loopback_mode(); + let mut can = can.start(match use_fd { + true => can::FdcanOperatingMode::InternalLoopbackMode, + false => can::FdcanOperatingMode::NormalOperationMode, + }); let mut i = 0; let mut last_read_ts = embassy_time::Instant::now(); @@ -106,7 +108,6 @@ async fn main(_spawner: Spawner) { break; } } - i = 0; let (mut tx, mut rx) = can.split(); // With split diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs index 4b29a0d21..e5ccfe4f7 100644 --- a/examples/stm32h5/src/bin/can.rs +++ b/examples/stm32h5/src/bin/can.rs @@ -24,8 +24,7 @@ async fn main(_spawner: Spawner) { let peripherals = embassy_stm32::init(config); - //let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); - let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); // 250k bps can.set_bitrate(250_000); diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs index 4b29a0d21..e5ccfe4f7 100644 --- a/examples/stm32h7/src/bin/can.rs +++ b/examples/stm32h7/src/bin/can.rs @@ -24,8 +24,7 @@ async fn main(_spawner: Spawner) { let peripherals = embassy_stm32::init(config); - //let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); - let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); + let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); // 250k bps can.set_bitrate(250_000); -- cgit From 3f93105e9fe7c5cbdada46a4367b01448fd61c62 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Mon, 19 Feb 2024 08:33:19 +1000 Subject: Add dep for static_cell to example. --- examples/stm32g4/Cargo.toml | 1 + 1 file changed, 1 insertion(+) (limited to 'examples') diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index fdb325f06..74ccfa3b0 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -24,6 +24,7 @@ embedded-can = { version = "0.4" } panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.8", default-features = false } +static_cell = "2.0.0" [profile.release] debug = 2 -- cgit