Skip to content

Commit 781532c

Browse files
committed
Started bxCAN impl
1 parent 1adf2c9 commit 781532c

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-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

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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+
Floating, Input,
33+
gpioa::{PA11, PA12},
34+
gpiob::{PB8, PB9},
35+
gpiod::{PD0, PD1},
36+
AF9,
37+
};
38+
use crate::pac::CAN1;
39+
40+
// All STM32L4 models with CAN support these pins
41+
pins! {
42+
CAN1 => (PA12<AF9>, PA11<AF9>),
43+
CAN1 => (PD1<AF9>, PD0<AF9>),
44+
CAN1 => (PB9<AF9>, PB8<AF9>),
45+
}
46+
}
47+
48+
#[cfg(feature = "stm32l4x1")]
49+
mod pb13_pb12_af10 {
50+
use crate::gpio::{
51+
Floating, Input,
52+
gpiob::{PB12, PB13},
53+
AF10,
54+
};
55+
use crate::pac::CAN1;
56+
pins! { CAN1 => (PB13<AF10>, PB12<AF10>), }
57+
}
58+
59+
/// Enable/disable peripheral
60+
pub trait Enable: sealed::Sealed {
61+
/// Enables this peripheral by setting the associated enable bit in an RCC enable register
62+
fn enable();
63+
}
64+
65+
impl crate::can::sealed::Sealed for crate::pac::CAN1 {}
66+
67+
impl crate::can::Enable for crate::pac::CAN1 {
68+
#[inline(always)]
69+
fn enable() {
70+
unsafe {
71+
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
72+
let rcc = &(*crate::pac::RCC::ptr());
73+
// Enable peripheral clock
74+
rcc.apb1enr1.modify(|_, w| w.can1en().set_bit());
75+
rcc.apb1rstr1.modify(|_, w| w.can1rst().set_bit());
76+
rcc.apb1rstr1.modify(|_, w| w.can1rst().clear_bit());
77+
};
78+
}
79+
}
80+
81+
/// Interface to the CAN peripheral.
82+
pub struct Can<Instance> {
83+
_peripheral: Instance,
84+
}
85+
86+
impl<Instance> Can<Instance>
87+
where
88+
Instance: Enable,
89+
{
90+
/// Creates a CAN interface.
91+
pub fn new<P>(can: Instance, _pins: P) -> Can<Instance>
92+
where
93+
P: Pins<Instance = Instance>,
94+
{
95+
Instance::enable();
96+
Can { _peripheral: can }
97+
}
98+
99+
pub fn new_unchecked(can: Instance) -> Can<Instance> {
100+
Instance::enable();
101+
Can { _peripheral: can }
102+
}
103+
}
104+
105+
unsafe impl bxcan::Instance for Can<CAN1> {
106+
const REGISTERS: *mut bxcan::RegisterBlock = CAN1::ptr() as *mut _;
107+
}
108+
109+
unsafe impl bxcan::FilterOwner for Can<CAN1> {
110+
const NUM_FILTER_BANKS: u8 = 14;
111+
}
112+
113+
unsafe impl bxcan::MasterInstance for Can<CAN1> {}

src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ pub mod traits;
6868
feature = "stm32l4x6"
6969
))]
7070
pub mod adc;
71+
#[cfg(any(
72+
feature = "stm32l4x1",
73+
feature = "stm32l4x5",
74+
))]
75+
pub mod can;
7176
#[cfg(any(
7277
feature = "stm32l4x1",
7378
feature = "stm32l4x2",

0 commit comments

Comments
 (0)