Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BSP Support for FlexCAN(1/2) #162

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,23 @@ version = "0.5"
features = ["imxrt1062"]

[dependencies.imxrt-hal]
version = "0.5.3"
#git = "https://github.com/dstric-aqueduct/imxrt-hal"
#branch = "dev/can"
path = "../imxrt-hal"
features = ["imxrt1060"]

#[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.imxrt-rt]
version = "0.1.4"
optional = true
Expand Down Expand Up @@ -99,6 +113,7 @@ rtic = { version = "2", features = ["thumbv7-backend"] }
rtic-monotonics = { version = "1", default-features = false, features = ["cortex-m-systick"] }
usb-device = "0.2"
usbd-serial = "0.1"
heapless = "0.8"

[[example]]
name = "blocking_gpt"
Expand All @@ -120,6 +135,14 @@ required-features = ["rt"]
name = "blocking_uart"
required-features = ["rt"]

[[example]]
name = "can"
required-features = ["rt"]

[[example]]
name = "rtic_can_log"
required-features = ["rt"]

[[example]]
name = "rtic_configure_pin"
required-features = ["rt"]
Expand Down
136 changes: 136 additions & 0 deletions examples/rtic_can_log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//! Demonstrates how to use a FlexCAN peripheral..
//!
//! This example requires:
//!
//! - The `rt` 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 _;

// Type aliases for the Queue we want to use.
// type Ty = u8;
// const CAP: usize = 256;
// type Queue = heapless::spsc::Queue<Ty, { CAP }>;
// type Consumer = heapless::spsc::Consumer<'static, Ty, { CAP }>;

#[rtic::app(device = teensy4_bsp, peripherals = true, dispatchers = [KPP])]
mod app {
use bsp::board;
use teensy4_bsp as bsp;

use imxrt_log as logging;

use rtic_monotonics::systick::*;

#[local]
struct Local {
/// For driving the logging endpoint.
poller: logging::Poller,
/// For periodically signaling activity.
led: board::Led,
}

#[shared]
struct Shared {
// CAN interface on the board
can: board::Flexcan1,
}

#[init]
fn init(cx: init::Context) -> (Shared, Local) {
let board::Resources {
usb,
pins,
flexcan1,
mut gpio2,
..
} = board::t41(cx.device);
let led = board::led(&mut gpio2, pins.p13);

// Set up the logging system.
//
// There's various ways to control log levels at build- and run-time.
// See the imxrt-log documentation for more information. This example
// doesn't demonstrate any of that.
let poller = logging::log::usbd(usb, logging::Interrupts::Enabled).unwrap();

let mut can = board::flexcan(flexcan1, pins.p22, pins.p23);
can.set_baud_rate(125_000);
can.set_max_mailbox(16);
can.disable_fifo();
// Set up a system timer for our software task.
{
Systick::start(
cx.core.SYST,
board::ARM_FREQUENCY,
rtic_monotonics::create_systick_token!(),
);
}

blink::spawn().unwrap();

run_can_rx::spawn().unwrap();
run_can_tx::spawn().unwrap();
// If the LED turns on, we've made it past init.
led.set();

(Shared { can }, Local { poller, led })
}

#[task(shared = [can])]
async fn run_can_rx(cx: run_can_rx::Context) {
let run_can_rx::SharedResources { mut can, .. } = cx.shared;
loop {
// read all available mailboxes for any available frames
if let Some(data) = can.lock(|can| can.read_mailboxes()) {
log::info!("RX: MB{} - {:?}", data.mailbox_number, data.frame);
}

Systick::delay(1.millis()).await;
}
}

#[task(shared = [can])]
async fn run_can_tx(cx: run_can_tx::Context) {
let run_can_tx::SharedResources { mut can, .. } = cx.shared;
// create a `Frame` with `StandardID` 0x00
// and `Data` [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
let id = imxrt_hal::can::Id::from(imxrt_hal::can::StandardId::new(0x03).unwrap());
let data: [u8; 1] = [0x03];
let frame = imxrt_hal::can::Frame::new_data(id, data);

loop {
// Transmit CAN frame
if let Err(e) = can.lock(|can| can.transmit(&frame)) {
log::error!("{e:?}");
}
Systick::delay(1000.millis()).await;
}
}

/// This task runs when the USB1 interrupt activates.
/// Simply poll the logger to control the logging process.
#[task(binds = USB_OTG1, local = [poller])]
fn usb_interrupt(cx: usb_interrupt::Context) {
cx.local.poller.poll();
}

#[task(local = [led])]
async fn blink(cx: blink::Context) {
loop {
// Toggle the LED.
cx.local.led.toggle();
Systick::delay(1000.millis()).await;
}
}
}
42 changes: 42 additions & 0 deletions src/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@

use crate::{hal, pins, ral};
use core::sync::atomic::{AtomicBool, Ordering};
pub use hal::can::Pins as CanPins;
pub use hal::lpspi::Pins as LpspiPins;

/// Use [`instances()`] to safely acquire.
Expand Down Expand Up @@ -267,6 +268,10 @@ pub struct Resources<Pins> {
pub flexio2: ral::flexio::FLEXIO2,
/// The FlexIO3 register block.
pub flexio3: ral::flexio::FLEXIO3,
/// The FlexCAN1 register block.
pub flexcan1: ral::can::CAN1,
/// The FlexCAN1 register block.
pub flexcan2: ral::can::CAN2,
/// The register block for ADC1.
///
/// ADC drivers constructed by `board` use a pre-configured clock and divisor. To change
Expand Down Expand Up @@ -359,6 +364,41 @@ pub type Lpi2c1 = hal::lpi2c::Lpi2c<hal::lpi2c::Pins<pins::common::P19, pins::co
/// Use [`lpi2c`] to create this driver.
pub type Lpi2c3 = hal::lpi2c::Lpi2c<hal::lpi2c::Pins<pins::common::P16, pins::common::P17>, 3>;

/// FlexCAN peripheral
pub fn flexcan<Tx, Rx, const N: u8>(
instance: ral::can::Instance<N>,
tx: Tx,
rx: Rx,
) -> hal::can::CAN<CanPins<Tx, Rx>, N>
where
Tx: hal::iomuxc::flexcan::Pin<
Signal = hal::iomuxc::flexcan::Tx,
Module = hal::iomuxc::consts::Const<N>,
>,
Rx: hal::iomuxc::flexcan::Pin<
Signal = hal::iomuxc::flexcan::Rx,
Module = hal::iomuxc::consts::Const<N>,
>,
{
hal::can::CAN::new(instance, tx, rx, CAN_FREQUENCY)
}

/// FlexCAN1 peripheral
///
/// - Pin 22 is TX
/// - Pin 23 is RX
///
/// use [`flexcan`] to create this driver.
pub type Flexcan1 = hal::can::CAN<CanPins<pins::common::P22, pins::common::P23>, 1>;

/// FlexCAN2 peripheral
///
/// - Pin 1 is TX
/// - Pin 0 is RX
///
/// use [`flexcan`] to create this driver.
pub type Flexcan2 = hal::can::CAN<CanPins<pins::common::P1, pins::common::P0>, 2>;

/// LPSPI4 peripheral.
///
/// - Pin 10 is chip select (CS).
Expand Down Expand Up @@ -607,6 +647,8 @@ fn prepare_resources<Pins>(
flexpwm2: hal::flexpwm::new(instances.PWM2),
flexpwm3: hal::flexpwm::new(instances.PWM3),
flexpwm4: hal::flexpwm::new(instances.PWM4),
flexcan1: instances.CAN1,
flexcan2: instances.CAN2,
adc1,
adc2,
trng,
Expand Down
16 changes: 16 additions & 0 deletions src/clock_power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ fn setup_lpspi_clk(ccm: &mut ral::ccm::CCM) {
ccm::lpspi_clk::set_divider(ccm, LPSPI_DIVIDER);
}

// Set up CAN clock root
const CAN_DIVIDER: u32 = 1;
pub const CAN_FREQUENCY: u32 = ccm::XTAL_OSCILLATOR_HZ / CAN_DIVIDER;
fn setup_can_clk(ccm: &mut ral::ccm::CCM) {
clock_gate::FLEXCAN_CLOCK_GATES
.iter()
.for_each(|locator| locator.set(ccm, clock_gate::OFF));
ccm::can_clk::set_selection(ccm, ccm::can_clk::Selection::Oscillator);
ccm::can_clk::set_divider(ccm, CAN_DIVIDER);
}

const CLOCK_GATES: &[clock_gate::Locator] = &[
clock_gate::pit(),
clock_gate::gpt_bus::<1>(),
Expand Down Expand Up @@ -201,6 +212,10 @@ const CLOCK_GATES: &[clock_gate::Locator] = &[
clock_gate::flexpwm::<2>(),
clock_gate::flexpwm::<3>(),
clock_gate::flexpwm::<4>(),
clock_gate::can::<1>(),
clock_gate::can::<2>(),
clock_gate::can_pe::<1>(),
clock_gate::can_pe::<2>(),
clock_gate::flexio::<1>(),
clock_gate::flexio::<2>(),
clock_gate::flexio::<3>(),
Expand All @@ -227,6 +242,7 @@ pub fn prepare_clocks_and_power(
setup_lpspi_clk(ccm);
setup_perclk_clk(ccm);
setup_uart_clk(ccm);
setup_can_clk(ccm);

CLOCK_GATES
.iter()
Expand Down