Skip to content

Commit

Permalink
Prototype a FlexCAN peripheral
Browse files Browse the repository at this point in the history
Implementation of the FlexCAN1 and FlexCAN2 peripherals for the  NXP i.MX RT 1060 processor.

Includes APIs for initializing the peripherals, setting the clock source, setting mailbox receive filters, setting mailbox FIFO functionality, and receiving and transmitting frames.

The FlexCAN3 peripheral is not implemented.
  • Loading branch information
dstric-aqueduct committed Dec 18, 2022
2 parents 68677eb + c09452b commit 3836c28
Show file tree
Hide file tree
Showing 19 changed files with 977 additions and 469 deletions.
41 changes: 32 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Thanks for helping us build embedded Rust support for NXP's i.MX RT processors! Please open an issue if

- you find a bug in any chip HAL
- you find a bug in the HAL, RAL, or IOMUXC crates
- you have an idea for a feature
- something isn't clear in our documentation

Expand All @@ -20,22 +20,45 @@ You'll need
```bash
rustup target add thumbv7em-none-eabihf
```
### Chip-specific HAL(s)

We support one HAL crate per i.MX RT processor family. A "processor family" is described by an NXP datasheet and reference manual. For example, the `imxrt1060-hal` supports the [i.MX RT1060 Crossover Processors](https://www.nxp.com/docs/en/nxp/data-sheets/IMXRT1060CEC.pdf), which includes the following processors:
### RAL

- i.MX RT 1061
- i.MX RT 1062
The `imxrt-ral` crate is auto-generated from the checked-in SVD files, available in `imxrt-ral/svd`. It's checked into git, and you should always have whatever represents the latest auto-generated RAL. Generally, you should **not** manually change RAL source files; rather, you should describe changes in `imxrtral.py`, the Python script that auto-generates the RAL.

When developing the HAL(s) a quick way to check everything compiles, in the project root
To generate the RAL,

- Install Python 3. You'll need at least Python 3.6.
- Install the Python dependencies needed to generate the RAL: `pip3 install --user svdtools`. Alternatively, use the rules in the RAL's `Makefile` to create a virtual environment with the necessary dependencies: `make venv update-venv && source venv/bin/activate`.
- Run `make` in the `imxrt-ral` directory: `make -C imxrt-ral`. The auto-generation script might generate warnings; that's OK.

If everything went well, you should find that the `imxrt-ral/src` directory is populated with Rust files. If you made changes in `imxrtral.py`, you should see those changes reflected in the Rust files. The RAL can build by itself: `cd imxrt-ral && cargo check --features imxrt1062 --target thumbv7em-none-eabihf`.

If you add a SVD patch, or if you change something in `imxrtral.py`, you'll need to re-generate the RAL to realize the change.

### HAL

Make sure you've generated the RAL (see above). When developing the HAL, specify a feature flag from the command line. To check the HAL for `imxrt1062` processors, `cd imxrt-hal`, then

```
cargo check --features imxrt1062 --target thumbv7em-none-eabihf
```
cargo check --target thumbv7em-none-eabihf

### IOMUXC

The `imxrt-iomuxc` crate family does not require any feature flags, and it will build for your host. Consider using `--package` flags to build and test the crate family in one command:

```
cargo build --package=imxrt-iomuxc --package=imxrt-iomuxc-build
cargo test -p imxrt-iomuxc -p imxrt-iomuxc-build
```

### SVD Patches

To modify the RAL, you'll need to describe your change as an SVD patch. If you'd like to add patches to the i.MX RT SVD files, learn about [svdtools](https://github.com/stm32-rs/svdtools). Use some of the existing SVD patches as a guide.

### Testing

Our CI system ensures that the RAL and HAL(s) build for all processor variants. But, we can't automatically test against hardware! To test your changes on hardware, you'll need to test the RAL and the HAL(s) using another project, like a Rust BSP crate. Some BSP crates that use the `imxrt1060-hal` include
Our CI system ensures that the RAL and HAL builds for all processor variants. But, we can't automatically test against hardware! To test your changes on hardware, you'll need to test the RAL and the HAL using another project, like a Rust BSP crate. Some BSP crates that use the `imxrt-hal` include

- [the `imxrt1060evk-bsp` crate](https://github.com/imxrt-rs/imxrt1060evk-bsp)
- [the `teensy4-bsp` crate](https://github.com/mciantyre/teensy4-rs)
Expand All @@ -53,4 +76,4 @@ Follow the instructions in those projects to prepare an environment for testing

## Release Steps

To create a release of the RAL and HAL crates, see [RELEASE.md](docs/RELEASE.md).
To create a release of the RAL and HAL crates, see [RELEASE.md](docs/RELEASE.md).
8 changes: 4 additions & 4 deletions imxrt-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ log = "0.4.8"
rand_core = { version = "0.5", default-features = false, optional = true }

[dependencies.imxrt-iomuxc]
version = "0.1.2"
git = "https://github.com/imxrt-rs/imxrt-iomuxc.git"
branch = "v0.1"
features = ["imxrt106x"]
git = "https://github.com/dstric-aqueduct/imxrt-iomuxc.git"
tag = "v0.1.5-can"

[dev-dependencies.cortex-m-rt]
version = "0.6"
Expand All @@ -34,7 +34,7 @@ features = ["device"]
bench = false

[features]
default = ["embedded-hal/unproven"] # Allows us to access the new digital pin traits
default = ["embedded-hal/unproven", "imxrt1062"] # Allows us to access the new digital pin traits

# Device specific feature flags
# these need fixes and conditional sections in CCM
Expand Down
28 changes: 16 additions & 12 deletions imxrt-hal/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
# imxrt1060-hal
# imxrt-hal

`imxrt1060-hal` is a Rust hardware abstraction layer that's specific to i.MX
RT 1060 processors. This includes some of the following processor parts:
This project provides a Rust HAL (hardware abstraction layer) for all NXP i.MX RT
microcontrollers based on the imxrt-ral crate.

- i.MX RT 1061
- i.MX RT 1062
A feature flag needs to be set for any of the supported i.MX RT SoC.

It is the successor to `imxrt-hal`, version 0.4, with `feature = "imxrt1062"`.
## What is it?

## Features
imxrt-hal is an experiment into a lightweight hardware abstraction layer. It
provides access to some of the peripherals of the i.MX RT series processors
from NXP using embedded-hal and other community driven hardware APIs.

The table below describes the optional features supported by `imxrt1060-hal`.
The main aims are fast compilation, compactness, and simplicity.

| Feature | Description |
| -------- | ---------------------------------- |
| `"rt"` | Runtime support with `cortex-m-rt` |
| `"rtic"` | Support for RTIC |
Please consider trying it out and contributing or leaving feedback!

## Goals

* Simple to use and hard to use incorrectly
* All peripherals and busses supported
* Support the entire i.MX RT Series with a single crate to maximize code reuse
17 changes: 9 additions & 8 deletions imxrt-hal/src/can/embedded_hal.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! `embedded_hal` trait impls.

use super::{Data, ExtendedId, Frame, Id, OverrunError, StandardId, CAN};

use super::{Data, Frame, NoDataError, CAN};
use crate::iomuxc::consts::Unsigned;

use embedded_hal::can;
pub use embedded_hal::can::{ExtendedId, Id, StandardId};

impl<M> can::Can for CAN<M>
where
M: Unsigned,
{
type Frame = Frame;

type Error = OverrunError;
type Error = NoDataError;

fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
match self.transmit(frame) {
Expand All @@ -22,14 +23,14 @@ where
}

fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
let data: [u8; 8] = [255, 255, 255, 255, 255, 255, 255, 255];
let id = StandardId::new(0).unwrap();

Ok(Frame::new_data(id, Data::new(&data).unwrap()))
match self.read_mailboxes() {
Some(d) => Ok(d.frame),
None => Err(nb::Error::Other(NoDataError { _priv: () })),
}
}
}

impl can::Error for OverrunError {
impl can::Error for NoDataError {
fn kind(&self) -> can::ErrorKind {
can::ErrorKind::Overrun
}
Expand Down
38 changes: 16 additions & 22 deletions imxrt-hal/src/can/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod tests;
use core::convert::TryFrom;
use core::ops::{Deref, DerefMut};

use super::id::{ExtendedId, Id, StandardId};
use super::{ExtendedId, Id, StandardId};

/// A CAN data or remote frame.
#[derive(Clone, Debug, Eq)]
Expand Down Expand Up @@ -143,27 +143,21 @@ pub enum FlexCanMailboxCSCode {
Unknown,
}

impl ::core::convert::TryFrom<u8> for FlexCanMailboxCSCode {
type Error = ();

impl ::core::convert::From<u8> for FlexCanMailboxCSCode {
#[inline(always)]
fn try_from(value: u8) -> Result<Self, Self::Error> {
fn from(value: u8) -> Self {
match value {
v if v == FlexCanMailboxCSCode::RxInactive as u8 => {
Ok(FlexCanMailboxCSCode::RxInactive)
}
v if v == FlexCanMailboxCSCode::RxEmpty as u8 => Ok(FlexCanMailboxCSCode::RxEmpty),
v if v == FlexCanMailboxCSCode::RxFull as u8 => Ok(FlexCanMailboxCSCode::RxFull),
v if v == FlexCanMailboxCSCode::RxOverrun as u8 => Ok(FlexCanMailboxCSCode::RxOverrun),
v if v == FlexCanMailboxCSCode::RxAnswer as u8 => Ok(FlexCanMailboxCSCode::RxAnswer),
v if v == FlexCanMailboxCSCode::RxBusy as u8 => Ok(FlexCanMailboxCSCode::RxBusy),
v if v == FlexCanMailboxCSCode::TxInactive as u8 => {
Ok(FlexCanMailboxCSCode::TxInactive)
}
v if v == FlexCanMailboxCSCode::TxAbort as u8 => Ok(FlexCanMailboxCSCode::TxAbort),
v if v == FlexCanMailboxCSCode::TxOnce as u8 => Ok(FlexCanMailboxCSCode::TxOnce),
v if v == FlexCanMailboxCSCode::TxAnswer as u8 => Ok(FlexCanMailboxCSCode::TxAnswer),
_ => Ok(FlexCanMailboxCSCode::Unknown),
v if v == FlexCanMailboxCSCode::RxInactive as u8 => FlexCanMailboxCSCode::RxInactive,
v if v == FlexCanMailboxCSCode::RxEmpty as u8 => FlexCanMailboxCSCode::RxEmpty,
v if v == FlexCanMailboxCSCode::RxFull as u8 => FlexCanMailboxCSCode::RxFull,
v if v == FlexCanMailboxCSCode::RxOverrun as u8 => FlexCanMailboxCSCode::RxOverrun,
v if v == FlexCanMailboxCSCode::RxAnswer as u8 => FlexCanMailboxCSCode::RxAnswer,
v if v == FlexCanMailboxCSCode::RxBusy as u8 => FlexCanMailboxCSCode::RxBusy,
v if v == FlexCanMailboxCSCode::TxInactive as u8 => FlexCanMailboxCSCode::TxInactive,
v if v == FlexCanMailboxCSCode::TxAbort as u8 => FlexCanMailboxCSCode::TxAbort,
v if v == FlexCanMailboxCSCode::TxOnce as u8 => FlexCanMailboxCSCode::TxOnce,
v if v == FlexCanMailboxCSCode::TxAnswer as u8 => FlexCanMailboxCSCode::TxAnswer,
_ => FlexCanMailboxCSCode::Unknown,
}
}
}
Expand All @@ -175,8 +169,8 @@ impl FlexCanMailboxCSCode {
}

#[inline(always)]
pub fn from_code_reg(reg: u32) -> Result<Self, ()> {
Self::try_from(((reg & CodeReg::CODE_MASK) >> CodeReg::CODE_SHIFT) as u8)
pub fn from_code_reg(reg: u32) -> Self {
Self::from(((reg & CodeReg::CODE_MASK) >> CodeReg::CODE_SHIFT) as u8)
}

#[inline(always)]
Expand Down
5 changes: 1 addition & 4 deletions imxrt-hal/src/can/frame/tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::can::{
frame::Frame,
id::{ExtendedId, StandardId},
};
use crate::can::{frame::Frame, ExtendedId, StandardId};

#[test]
fn data_greater_remote() {
Expand Down

0 comments on commit 3836c28

Please sign in to comment.