From 501372519094e3e15553ce46d184a7ee1806d967 Mon Sep 17 00:00:00 2001 From: djstrickland <96876452+dstric-aqueduct@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:26:42 -0500 Subject: [PATCH 1/3] init flexcan --- Cargo.toml | 12 ++- examples/can.rs | 67 +++++++++++++++++ examples/rtic_can_log.rs | 156 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 examples/can.rs create mode 100644 examples/rtic_can_log.rs diff --git a/Cargo.toml b/Cargo.toml index 5d201901..ceaa9d52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,8 +53,8 @@ path = "teensy4-fcb" version = "0.4" [dependencies.imxrt-hal] -version = "0.4.2" -features = ["imxrt1062"] +git = "https://github.com/dstric-aqueduct/imxrt-hal" +branch = "dev/can" [dependencies.teensy4-pins] version = "0.2" @@ -132,6 +132,10 @@ required-features = ["rt"] # Examples that require USB logging. +[[example]] +name = "can" +required-features = ["rt", "usb-logging"] + [[example]] name = "dma_memcpy" required-features = ["rt", "usb-logging"] @@ -196,6 +200,10 @@ required-features = ["rt", "rtic"] name = "rtic_pit" required-features = ["rt", "rtic"] +[[example]] +name = "rtic_can_log" +required-features = ["rt", "rtic", "usb-logging"] + [[example]] name = "rtic_uart_log" required-features = ["rt", "rtic"] diff --git a/examples/can.rs b/examples/can.rs new file mode 100644 index 00000000..fec571fc --- /dev/null +++ b/examples/can.rs @@ -0,0 +1,67 @@ +//! Demonstrates how to use a FlexCAN peripheral. +//! +//! Pinout: +//! +//! - Teensy 4 Pin 22 (CAN1 TX) to TX pin of CAN Transceiver +//! - Teensy 4 Pin 23 (CAN2 RX) to RX pin of CAN Transceiver +//! +//! A Can transceiver (such as the Texas Instruments SN65HVD230) is required for this demo. +//! + +#![no_std] +#![no_main] + +mod systick; +mod usb_io; + +use teensy4_panic as _; + +use cortex_m_rt::entry; +use teensy4_bsp as bsp; + +#[entry] +fn main() -> ! { + let mut peripherals = bsp::Peripherals::take().unwrap(); + let mut systick = systick::new(cortex_m::Peripherals::take().unwrap().SYST); + + usb_io::init().unwrap(); + let pins = bsp::pins::t40::from_pads(peripherals.iomuxc); + + let mut led = bsp::configure_led(pins.p13); + led.set(); + + peripherals.ccm.pll1.set_arm_clock( + bsp::hal::ccm::PLL1::ARM_HZ, + &mut peripherals.ccm.handle, + &mut peripherals.dcdc, + ); + + systick.delay_ms(1000); + log::info!("Initializing CAN clocks..."); + + let (can1_builder, _) = peripherals.can.clock( + &mut peripherals.ccm.handle, + bsp::hal::ccm::can::ClockSelect::Pll2, + bsp::hal::ccm::can::PrescalarSelect::DIVIDE_1, + ); + + let mut can1 = can1_builder.build(); + + can1.set_baud_rate(1_000_000); + can1.set_max_mailbox(16); + can1.enable_fifo(); + can1.set_fifo_interrupt(true); + can1.set_fifo_accept_all(); + can1.print_registers(); + + let id = bsp::hal::can::Id::from(bsp::hal::can::StandardId::new(0x00).unwrap()); + let data: [u8; 8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; + let frame = bsp::hal::can::Frame::new_data(id, data); + + loop { + systick.delay_ms(1000); + led.toggle(); + can1.read_mailboxes(); + can1.transmit(&frame).ok(); + } +} diff --git a/examples/rtic_can_log.rs b/examples/rtic_can_log.rs new file mode 100644 index 00000000..ff12c92e --- /dev/null +++ b/examples/rtic_can_log.rs @@ -0,0 +1,156 @@ +//! Demonstrates how to use a FlexCAN peripheral.. +//! +//! This example requires: +//! +//! - The `rtic` feature to be enabled. +//! - a Can transceiver (such as the Texas Instruments SN65HVD230). +//! +//! Pinout: +//! +//! - Teensy 4 Pin 22 (CAN1 TX) to TX pin of CAN Transceiver +//! - Teensy 4 Pin 23 (CAN2 RX) to RX pin of CAN Transceiver +//! +//! + +#![no_std] +#![no_main] + +use teensy4_panic as _; +mod usb_io; + +// Type aliases for the Queue we want to use. +type Ty = u8; +const CAP: usize = 256; +type Queue = heapless::spsc::Queue; +type Consumer = heapless::spsc::Consumer<'static, Ty, { CAP }>; + +#[rtic::app(device = teensy4_bsp, peripherals = true, dispatchers = [LPUART8])] +mod app { + use crate::{usb_io, Consumer, Queue}; + use embedded_hal::digital::v2::OutputPin; + use teensy4_bsp as bsp; + use bsp::hal::iomuxc::consts::U1; + + use dwt_systick_monotonic::{fugit::ExtU32, DwtSystick}; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = DwtSystick<{ bsp::hal::ccm::PLL1::ARM_HZ }>; + + #[local] + struct Local { + led: bsp::Led, + q_rx: Consumer, + blink_count: u32, + } + + #[shared] + struct Shared { + can1: bsp::hal::can::CAN, + } + + #[init(local = [ + queue: Queue = heapless::spsc::Queue::new(), + ])] + fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) { + let mut dcb = cx.core.DCB; + let dwt = cx.core.DWT; + let systick = cx.core.SYST; + + usb_io::init().unwrap(); + + let mono = DwtSystick::new(&mut dcb, dwt, systick, bsp::hal::ccm::PLL1::ARM_HZ); + + cx.device.ccm.pll1.set_arm_clock( + bsp::hal::ccm::PLL1::ARM_HZ, + &mut cx.device.ccm.handle, + &mut cx.device.dcdc, + ); + + let pins = bsp::pins::t40::from_pads(cx.device.iomuxc); + + let (can1_builder, _) = cx.device.can.clock( + &mut cx.device.ccm.handle, + bsp::hal::ccm::can::ClockSelect::Pll2, + bsp::hal::ccm::can::PrescalarSelect::DIVIDE_1, + ); + + let can1: bsp::hal::can::CAN = can1_builder.build(); + + // The queue used for buffering bytes. + let (_q_tx, q_rx) = cx.local.queue.split(); + + // LED setup. + let mut led = bsp::configure_led(pins.p13); + led.set_high().unwrap(); + + // Schedule the first blink. + blink::spawn_after(1_u32.secs()).unwrap(); + + can1_init::spawn_after(1_u32.secs()).unwrap(); + + ( + Shared { can1 }, + Local { + led, + q_rx, + blink_count: 0, + }, + init::Monotonics(mono), + ) + } + + #[task(local = [led, q_rx, blink_count])] + fn blink(cx: blink::Context) { + if cx.local.q_rx.ready() { + let mut buffer = [0u8; 256]; + for elem in buffer.iter_mut() { + *elem = match cx.local.q_rx.dequeue() { + None => break, + Some(b) => b, + }; + } + let s = core::str::from_utf8(&buffer).unwrap(); + log::info!("read: {}", s); + } + + // Toggle the LED. + cx.local.led.toggle(); + + // Schedule the following blink. + blink::spawn_after(100_u32.millis()).unwrap(); + } + + #[task(shared = [can1])] + fn can1_init(mut cx: can1_init::Context) { + cx.shared.can1.lock(|can1| { + can1.set_baud_rate(1_000_000); + can1.set_max_mailbox(16); + can1.enable_fifo(); + can1.set_fifo_interrupt(true); + can1.set_fifo_accept_all(); + can1.print_registers(); + }); + can1::spawn_after(100_u32.millis()).unwrap(); + } + + #[task(shared = [can1])] + fn can1(mut cx: can1::Context) { + let data: [u8; 8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; + let id = bsp::hal::can::Id::from(bsp::hal::can::StandardId::new(0x00).unwrap()); + let frame = bsp::hal::can::Frame::new_data(id, data); + cx.shared.can1.lock(|can1| { + can1.transmit(&frame).ok(); + }); + can1::spawn_after(100_u32.millis()).unwrap(); + } + + #[task(binds = CAN1, shared = [can1],)] + fn can1_int(mut cx: can1_int::Context) { + cx.shared.can1.lock(|can1| { + match can1.handle_interrupt() { + Some(f) => log::info!("Rx: {:?}", &f), + None => { }, + }; + }); + } +} From d176a6d17ea2c7e022aad9d21461168d3cc59473 Mon Sep 17 00:00:00 2001 From: djstrickland <96876452+dstric-aqueduct@users.noreply.github.com> Date: Wed, 14 Dec 2022 16:43:03 -0500 Subject: [PATCH 2/3] align Can builder with Pin trait convention --- examples/can.rs | 4 ++-- examples/rtic_can_log.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/can.rs b/examples/can.rs index fec571fc..0067e683 100644 --- a/examples/can.rs +++ b/examples/can.rs @@ -41,11 +41,11 @@ fn main() -> ! { let (can1_builder, _) = peripherals.can.clock( &mut peripherals.ccm.handle, - bsp::hal::ccm::can::ClockSelect::Pll2, + bsp::hal::ccm::can::ClockSelect::OSC, bsp::hal::ccm::can::PrescalarSelect::DIVIDE_1, ); - let mut can1 = can1_builder.build(); + let mut can1 = can1_builder.build(pins.p22, pins.p23); can1.set_baud_rate(1_000_000); can1.set_max_mailbox(16); diff --git a/examples/rtic_can_log.rs b/examples/rtic_can_log.rs index ff12c92e..7b573dc2 100644 --- a/examples/rtic_can_log.rs +++ b/examples/rtic_can_log.rs @@ -68,13 +68,13 @@ mod app { let pins = bsp::pins::t40::from_pads(cx.device.iomuxc); - let (can1_builder, _) = cx.device.can.clock( - &mut cx.device.ccm.handle, - bsp::hal::ccm::can::ClockSelect::Pll2, + let (can1_builder, _) = peripherals.can.clock( + &mut peripherals.ccm.handle, + bsp::hal::ccm::can::ClockSelect::OSC, bsp::hal::ccm::can::PrescalarSelect::DIVIDE_1, ); - - let can1: bsp::hal::can::CAN = can1_builder.build(); + + let mut can1 = can1_builder.build(pins.p22, pins.p23); // The queue used for buffering bytes. let (_q_tx, q_rx) = cx.local.queue.split(); From 480dde4ee4f0b837ceed1c5d4a2da5e45f2a4547 Mon Sep 17 00:00:00 2001 From: Ian McIntyre Date: Mon, 2 Jan 2023 11:03:59 -0500 Subject: [PATCH 3/3] Test CAN1 set_fifo_interrupt(false) behaviors This commit corresponds to a FlexCAN PR review question in imxrt-hal. I'm sharing it to make reproduction easier. https://github.com/imxrt-rs/imxrt-hal/pull/122#discussion_r1060106501 --- Cargo.toml | 8 ++++++++ examples/can.rs | 15 +++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ceaa9d52..b73592c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,9 +53,17 @@ path = "teensy4-fcb" version = "0.4" [dependencies.imxrt-hal] +version = "0.4.2" +features = ["imxrt1062"] + +[patch.crates-io.imxrt-hal] git = "https://github.com/dstric-aqueduct/imxrt-hal" branch = "dev/can" +[patch.crates-io.imxrt-iomuxc] +git = "https://github.com/dstric-aqueduct/imxrt-iomuxc.git" +tag = "v0.1.5-can" + [dependencies.teensy4-pins] version = "0.2" path = "teensy4-pins" diff --git a/examples/can.rs b/examples/can.rs index 0067e683..ca842ce2 100644 --- a/examples/can.rs +++ b/examples/can.rs @@ -2,8 +2,8 @@ //! //! Pinout: //! -//! - Teensy 4 Pin 22 (CAN1 TX) to TX pin of CAN Transceiver -//! - Teensy 4 Pin 23 (CAN2 RX) to RX pin of CAN Transceiver +//! - Teensy 4 Pin 22 (CAN1 TX) to TX pin of CAN Transceiver +//! - Teensy 4 Pin 23 (CAN2 RX) to RX pin of CAN Transceiver //! //! A Can transceiver (such as the Texas Instruments SN65HVD230) is required for this demo. //! @@ -46,11 +46,11 @@ fn main() -> ! { ); let mut can1 = can1_builder.build(pins.p22, pins.p23); - + can1.set_baud_rate(1_000_000); can1.set_max_mailbox(16); can1.enable_fifo(); - can1.set_fifo_interrupt(true); + can1.set_fifo_interrupt(false); can1.set_fifo_accept_all(); can1.print_registers(); @@ -58,6 +58,7 @@ fn main() -> ! { let data: [u8; 8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; let frame = bsp::hal::can::Frame::new_data(id, data); + unsafe { cortex_m::peripheral::NVIC::unmask(bsp::interrupt::CAN1) }; loop { systick.delay_ms(1000); led.toggle(); @@ -65,3 +66,9 @@ fn main() -> ! { can1.transmit(&frame).ok(); } } + +use bsp::interrupt; +#[cortex_m_rt::interrupt] +fn CAN1() { + log::warn!("CAN1 interrupt fired"); +}