Skip to content

Commit 8702fa7

Browse files
committed
Started bxCAN impl
1 parent 1adf2c9 commit 8702fa7

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ edition = "2018"
2424
cortex-m = "0.6.3"
2525
nb = "0.1.1"
2626
stm32l4 = "0.13.0"
27+
bxcan = "0.5"
2728

2829
[dependencies.rand_core]
2930
version = "0.6.2"

src/can.rs

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//! # Controller Area Network (CAN) Interface
2+
//!
3+
//! Based on STM32F4xx HAL.
4+
5+
use crate::pac::CAN1;
6+
7+
mod sealed {
8+
pub trait Sealed {}
9+
}
10+
11+
/// A pair of (TX, RX) pins configured for CAN communication
12+
pub trait Pins: sealed::Sealed {
13+
/// The CAN peripheral that uses these pins
14+
type Instance;
15+
}
16+
17+
/// Implements sealed::Sealed and Pins for a (TX, RX) pair of pins associated with a CAN peripheral
18+
/// The alternate function number can be specified after each pin name.
19+
macro_rules! pins {
20+
($($PER:ident => ($tx:ident<$txaf:ident>, $rx:ident<$rxaf:ident>),)+) => {
21+
$(
22+
impl crate::can::sealed::Sealed for ($tx<crate::gpio::Alternate<$txaf, Input<Floating>>>, $rx<crate::gpio::Alternate<$rxaf, Input<Floating>>>) {}
23+
impl crate::can::Pins for ($tx<crate::gpio::Alternate<$txaf, Input<Floating>>>, $rx<crate::gpio::Alternate<$rxaf, Input<Floating>>>) {
24+
type Instance = $PER;
25+
}
26+
)+
27+
}
28+
}
29+
30+
mod common_pins {
31+
use crate::gpio::{
32+
gpioa::{PA11, PA12},
33+
gpiob::{PB8, PB9},
34+
gpiod::{PD0, PD1},
35+
Floating, Input, AF9,
36+
};
37+
use crate::pac::CAN1;
38+
39+
// All STM32L4 models with CAN support these pins
40+
pins! {
41+
CAN1 => (PA12<AF9>, PA11<AF9>),
42+
CAN1 => (PD1<AF9>, PD0<AF9>),
43+
CAN1 => (PB9<AF9>, PB8<AF9>),
44+
}
45+
}
46+
47+
#[cfg(feature = "stm32l4x1")]
48+
mod pb13_pb12_af10 {
49+
use crate::gpio::{
50+
gpiob::{PB12, PB13},
51+
Floating, Input, AF10,
52+
};
53+
use crate::pac::CAN1;
54+
pins! { CAN1 => (PB13<AF10>, PB12<AF10>), }
55+
}
56+
57+
/// Enable/disable peripheral
58+
pub trait Enable: sealed::Sealed {
59+
/// Enables this peripheral by setting the associated enable bit in an RCC enable register
60+
fn enable();
61+
}
62+
63+
impl crate::can::sealed::Sealed for crate::pac::CAN1 {}
64+
65+
impl crate::can::Enable for crate::pac::CAN1 {
66+
#[inline(always)]
67+
fn enable() {
68+
unsafe {
69+
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
70+
let rcc = &(*crate::pac::RCC::ptr());
71+
// Enable peripheral clock
72+
rcc.apb1enr1.modify(|_, w| w.can1en().set_bit());
73+
rcc.apb1rstr1.modify(|_, w| w.can1rst().set_bit());
74+
rcc.apb1rstr1.modify(|_, w| w.can1rst().clear_bit());
75+
};
76+
}
77+
}
78+
79+
/// Interface to the CAN peripheral.
80+
pub struct Can<Instance> {
81+
_peripheral: Instance,
82+
}
83+
84+
impl<Instance> Can<Instance>
85+
where
86+
Instance: Enable,
87+
{
88+
/// Creates a CAN interface.
89+
pub fn new<P>(can: Instance, _pins: P) -> Can<Instance>
90+
where
91+
P: Pins<Instance = Instance>,
92+
{
93+
Instance::enable();
94+
Can { _peripheral: can }
95+
}
96+
97+
pub fn new_unchecked(can: Instance) -> Can<Instance> {
98+
Instance::enable();
99+
Can { _peripheral: can }
100+
}
101+
}
102+
103+
unsafe impl bxcan::Instance for Can<CAN1> {
104+
const REGISTERS: *mut bxcan::RegisterBlock = CAN1::ptr() as *mut _;
105+
}
106+
107+
unsafe impl bxcan::FilterOwner for Can<CAN1> {
108+
const NUM_FILTER_BANKS: u8 = 14;
109+
}
110+
111+
unsafe impl bxcan::MasterInstance for Can<CAN1> {}

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ pub mod traits;
6868
feature = "stm32l4x6"
6969
))]
7070
pub mod adc;
71+
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x5",))]
72+
pub mod can;
7173
#[cfg(any(
7274
feature = "stm32l4x1",
7375
feature = "stm32l4x2",

0 commit comments

Comments
 (0)