Skip to content

Commit fbe30bb

Browse files
committed
i2c + spi + serial + can
1 parent 30a974d commit fbe30bb

19 files changed

+566
-551
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
- Use `enum`s for alternate peripheral pins
1011
- Added missing U(S)ART DMA traits for HAL serial types [#593]
1112
- Improve SPI::new* docs [#587]
1213
- Add advanced timer dead time insertion example [#585]

examples/rtic-usart-shell-ssd1306.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ mod usart_shell {
2121
use ssd1306::{mode::BufferedGraphicsMode, prelude::*, I2CDisplayInterface, Ssd1306};
2222

2323
use stm32f4xx_hal::{
24-
gpio::{
25-
gpioa::PA0, gpioa::PA10, gpioa::PA9, gpiob::PB8, gpiob::PB9, gpioc::PC13, Alternate,
26-
Edge, Input, OpenDrain, Output, PushPull,
27-
},
24+
gpio::{gpioa::PA0, gpioc::PC13, Edge, Input, Output, PushPull},
2825
i2c::I2c,
2926
pac::I2C1,
3027
pac::USART1,
@@ -40,14 +37,9 @@ mod usart_shell {
4037

4138
type LedType = PC13<Output<PushPull>>;
4239
type ButtonType = PA0<Input>;
43-
type ShellType = UShell<
44-
Serial<USART1, (PA9<Alternate<7>>, PA10<Alternate<7>>)>,
45-
StaticAutocomplete<5>,
46-
LRUHistory<32, 4>,
47-
32,
48-
>;
40+
type ShellType = UShell<Serial<USART1>, StaticAutocomplete<5>, LRUHistory<32, 4>, 32>;
4941
type DisplayType = Ssd1306<
50-
I2CInterface<I2c<I2C1, (PB8<Alternate<4, OpenDrain>>, PB9<Alternate<4, OpenDrain>>)>>,
42+
I2CInterface<I2c<I2C1>>,
5143
DisplaySize128x64,
5244
BufferedGraphicsMode<DisplaySize128x64>,
5345
>;

examples/rtic-usart-shell.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ mod usart_shell {
1010
use core::fmt::Write;
1111
use dwt_systick_monotonic::DwtSystick;
1212
use stm32f4xx_hal::{
13-
gpio::{
14-
gpioa::PA0, gpioa::PA10, gpioa::PA9, gpioc::PC13, Alternate, Edge, Input, Output,
15-
PushPull,
16-
},
13+
gpio::{gpioa::PA0, gpioc::PC13, Edge, Input, Output, PushPull},
1714
pac::USART1,
1815
prelude::*,
1916
serial::{config::Config, Event::Rxne, Serial},
@@ -26,12 +23,7 @@ mod usart_shell {
2623

2724
type LedType = PC13<Output<PushPull>>;
2825
type ButtonType = PA0<Input>;
29-
type ShellType = UShell<
30-
Serial<USART1, (PA9<Alternate<7>>, PA10<Alternate<7>>)>,
31-
StaticAutocomplete<5>,
32-
LRUHistory<32, 4>,
33-
32,
34-
>;
26+
type ShellType = UShell<Serial<USART1>, StaticAutocomplete<5>, LRUHistory<32, 4>, 32>;
3527

3628
const SHELL_PROMPT: &str = "#> ";
3729
const CR: &str = "\r\n";

examples/stopwatch-with-ssd1306-and-interrupts-and-dma-i2c.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,11 @@ use heapless::String;
5252
use ssd1306::{prelude::*, Ssd1306};
5353

5454
pub type I2c1Handle = I2CMasterDma<
55-
I2C1, // Instance of I2C
56-
(PB8<AF4<OpenDrain>>, PB9<AF4<OpenDrain>>), // Pins
57-
Stream1<DMA1>, // Stream used for Tx
58-
0, // Channel for Tx
59-
Stream0<DMA1>, // Stream used for Rx (Not used in example)
60-
1, // Channel for Rx (Not used in example)
55+
I2C1, // Instance of I2C
56+
Stream1<DMA1>, // Stream used for Tx
57+
0, // Channel for Tx
58+
Stream0<DMA1>, // Stream used for Rx (Not used in example)
59+
1, // Channel for Rx (Not used in example)
6160
>;
6261

6362
// Set up global state. It's all mutexed up for concurrency safety.

src/can.rs

Lines changed: 60 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,142 @@
11
//! # Controller Area Network (CAN) Interface
22
//!
33
4-
use crate::gpio::{Const, NoPin, PinA, PushPull, SetAlternate};
4+
use crate::gpio::{self, NoPin};
55
use crate::pac::{CAN1, CAN2};
66
use crate::rcc;
77

8-
pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset {}
8+
pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset {
9+
type Tx;
10+
type Rx;
11+
}
12+
13+
macro_rules! can {
14+
($CAN:ty: $Can:ident, $can:ident) => {
15+
pub type $Can = Can<$CAN>;
16+
17+
impl Instance for $CAN {
18+
type Tx = gpio::alt::$can::Tx;
19+
type Rx = gpio::alt::$can::Rx;
20+
}
21+
};
22+
}
923

1024
// Implemented by all SPI instances
11-
impl Instance for CAN1 {}
12-
pub type Can1<PINS> = Can<CAN1, PINS>;
13-
impl Instance for CAN2 {}
14-
pub type Can2<PINS> = Can<CAN2, PINS>;
25+
can! { CAN1: Can1, can1 }
26+
can! { CAN2: Can2, can2 }
1527
#[cfg(feature = "can3")]
16-
pub type Can3<PINS> = Can<crate::pac::CAN3, PINS>;
28+
can! { crate::pac::CAN3: Can3, can3 }
1729

1830
pub struct Tx;
1931
impl crate::Sealed for Tx {}
2032
pub struct Rx;
2133
impl crate::Sealed for Rx {}
2234

23-
pub trait Pins<CAN> {
24-
fn set_alt_mode(&mut self);
25-
fn restore_mode(&mut self);
26-
}
27-
28-
impl<CAN, TX, RX, const TXA: u8, const RXA: u8> Pins<CAN> for (TX, RX)
29-
where
30-
TX: PinA<Tx, CAN, A = Const<TXA>> + SetAlternate<TXA, PushPull>,
31-
RX: PinA<Rx, CAN, A = Const<RXA>> + SetAlternate<RXA, PushPull>,
32-
{
33-
fn set_alt_mode(&mut self) {
34-
self.0.set_alt_mode();
35-
self.1.set_alt_mode();
36-
}
37-
fn restore_mode(&mut self) {
38-
self.0.restore_mode();
39-
self.1.restore_mode();
40-
}
41-
}
42-
4335
/// Pins and definitions for models with a third CAN peripheral
4436
#[cfg(feature = "can3")]
4537
mod can3 {
4638
use super::*;
4739
use crate::pac::CAN3;
4840

49-
impl Instance for CAN3 {}
50-
51-
unsafe impl<PINS> bxcan::Instance for Can<CAN3, PINS> {
41+
unsafe impl bxcan::Instance for Can<CAN3> {
5242
const REGISTERS: *mut bxcan::RegisterBlock = CAN3::ptr() as *mut _;
5343
}
5444

55-
unsafe impl<PINS> bxcan::FilterOwner for Can<CAN3, PINS> {
45+
unsafe impl bxcan::FilterOwner for Can<CAN3> {
5646
const NUM_FILTER_BANKS: u8 = 14;
5747
}
5848
}
5949

6050
pub trait CanExt: Sized + Instance {
61-
fn can<TX, RX>(self, pins: (TX, RX)) -> Can<Self, (TX, RX)>
62-
where
63-
(TX, RX): Pins<Self>;
64-
fn tx<TX>(self, tx_pin: TX) -> Can<Self, (TX, NoPin)>
51+
fn can(self, pins: (impl Into<Self::Tx>, impl Into<Self::Rx>)) -> Can<Self>;
52+
53+
fn tx(self, tx_pin: impl Into<Self::Tx>) -> Can<Self>
6554
where
66-
(TX, NoPin): Pins<Self>;
67-
fn rx<RX>(self, rx_pin: RX) -> Can<Self, (NoPin, RX)>
55+
NoPin: Into<Self::Rx>;
56+
57+
fn rx(self, rx_pin: impl Into<Self::Rx>) -> Can<Self>
6858
where
69-
(NoPin, RX): Pins<Self>;
59+
NoPin: Into<Self::Tx>;
7060
}
7161

7262
impl<CAN: Instance> CanExt for CAN {
73-
fn can<TX, RX>(self, pins: (TX, RX)) -> Can<Self, (TX, RX)>
74-
where
75-
(TX, RX): Pins<Self>,
76-
{
63+
fn can(self, pins: (impl Into<Self::Tx>, impl Into<Self::Rx>)) -> Can<Self> {
7764
Can::new(self, pins)
7865
}
79-
fn tx<TX>(self, tx_pin: TX) -> Can<Self, (TX, NoPin)>
66+
67+
fn tx(self, tx_pin: impl Into<Self::Tx>) -> Can<Self>
8068
where
81-
(TX, NoPin): Pins<Self>,
69+
NoPin: Into<Self::Rx>,
8270
{
8371
Can::tx(self, tx_pin)
8472
}
85-
fn rx<RX>(self, rx_pin: RX) -> Can<Self, (NoPin, RX)>
73+
74+
fn rx(self, rx_pin: impl Into<Self::Rx>) -> Can<Self>
8675
where
87-
(NoPin, RX): Pins<Self>,
76+
NoPin: Into<Self::Tx>,
8877
{
8978
Can::rx(self, rx_pin)
9079
}
9180
}
9281

9382
/// Interface to the CAN peripheral.
94-
pub struct Can<CAN, PINS> {
83+
pub struct Can<CAN: Instance> {
9584
can: CAN,
96-
pins: PINS,
85+
pins: (CAN::Tx, CAN::Rx),
9786
}
9887

99-
impl<CAN, TX, RX> Can<CAN, (TX, RX)>
100-
where
101-
CAN: Instance,
102-
(TX, RX): Pins<CAN>,
103-
{
88+
impl<CAN: Instance> Can<CAN> {
10489
/// Creates a CAN interface.
105-
pub fn new(can: CAN, mut pins: (TX, RX)) -> Self {
90+
pub fn new(can: CAN, pins: (impl Into<CAN::Tx>, impl Into<CAN::Rx>)) -> Self {
10691
unsafe {
10792
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
10893
let rcc = &(*crate::pac::RCC::ptr());
10994
CAN::enable(rcc);
11095
CAN::reset(rcc);
11196
}
11297

113-
pins.set_alt_mode();
98+
let pins = (pins.0.into(), pins.1.into());
11499

115100
Can { can, pins }
116101
}
117102

118-
pub fn release(mut self) -> (CAN, (TX, RX)) {
119-
self.pins.restore_mode();
120-
121-
(self.can, (self.pins.0, self.pins.1))
103+
pub fn release<TX, RX, E>(self) -> Result<(CAN, (TX, RX)), E>
104+
where
105+
TX: TryFrom<CAN::Tx, Error = E>,
106+
RX: TryFrom<CAN::Rx, Error = E>,
107+
{
108+
Ok((self.can, (self.pins.0.try_into()?, self.pins.1.try_into()?)))
122109
}
123110
}
124111

125-
impl<CAN, TX> Can<CAN, (TX, NoPin)>
126-
where
127-
CAN: Instance,
128-
(TX, NoPin): Pins<CAN>,
129-
{
130-
pub fn tx(usart: CAN, tx_pin: TX) -> Self {
112+
impl<CAN: Instance> Can<CAN> {
113+
pub fn tx(usart: CAN, tx_pin: impl Into<CAN::Tx>) -> Self
114+
where
115+
NoPin: Into<CAN::Rx>,
116+
{
131117
Self::new(usart, (tx_pin, NoPin))
132118
}
133119
}
134120

135-
impl<CAN, RX> Can<CAN, (NoPin, RX)>
136-
where
137-
CAN: Instance,
138-
(NoPin, RX): Pins<CAN>,
139-
{
140-
pub fn rx(usart: CAN, rx_pin: RX) -> Self {
121+
impl<CAN: Instance> Can<CAN> {
122+
pub fn rx(usart: CAN, rx_pin: impl Into<CAN::Rx>) -> Self
123+
where
124+
NoPin: Into<CAN::Tx>,
125+
{
141126
Self::new(usart, (NoPin, rx_pin))
142127
}
143128
}
144129

145-
unsafe impl<PINS> bxcan::Instance for Can<CAN1, PINS> {
130+
unsafe impl bxcan::Instance for Can<CAN1> {
146131
const REGISTERS: *mut bxcan::RegisterBlock = CAN1::ptr() as *mut _;
147132
}
148133

149-
unsafe impl<PINS> bxcan::Instance for Can<CAN2, PINS> {
134+
unsafe impl bxcan::Instance for Can<CAN2> {
150135
const REGISTERS: *mut bxcan::RegisterBlock = CAN2::ptr() as *mut _;
151136
}
152137

153-
unsafe impl<PINS> bxcan::FilterOwner for Can<CAN1, PINS> {
138+
unsafe impl bxcan::FilterOwner for Can<CAN1> {
154139
const NUM_FILTER_BANKS: u8 = 28;
155140
}
156141

157-
unsafe impl<PINS> bxcan::MasterInstance for Can<CAN1, PINS> {}
142+
unsafe impl bxcan::MasterInstance for Can<CAN1> {}

0 commit comments

Comments
 (0)