Skip to content

Commit

Permalink
ext traits
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Apr 12, 2023
1 parent b69050b commit 27d0358
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 58 deletions.
15 changes: 9 additions & 6 deletions examples/can-echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use panic_halt as _;
use bxcan::filter::Mask32;
use cortex_m_rt::entry;
use nb::block;
use stm32f1xx_hal::{can::Can, gpio::Floating, pac, prelude::*};
use stm32f1xx_hal::{gpio::Floating, pac, prelude::*};

#[entry]
fn main() -> ! {
Expand All @@ -31,10 +31,11 @@ fn main() -> ! {
let rx = gpioa.pa11;
let tx = gpioa.pa12;

#[cfg(not(feature = "connectivity"))]
let can = Can::<_, Floating>::new(dp.CAN1, dp.USB, (tx, rx, &mut afio.mapr));
#[cfg(feature = "connectivity")]
let can = Can::<_, Floating>::new(dp.CAN1, (tx, rx, &mut afio.mapr));
let can = dp.CAN1.can::<Floating>(
#[cfg(not(feature = "connectivity"))]
dp.USB,
(tx, rx, &mut afio.mapr),
);

// APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
Expand All @@ -50,7 +51,9 @@ fn main() -> ! {
#[cfg(feature = "connectivity")]
let _can2 = {
let gpiob = dp.GPIOB.split();
let can = Can::<_, Floating>::new(dp.CAN2, (gpiob.pb6, gpiob.pb5, &mut afio.mapr));
let can = dp
.CAN2
.can::<Floating>((gpiob.pb6, gpiob.pb5, &mut afio.mapr));

// APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
Expand Down
10 changes: 5 additions & 5 deletions examples/can-loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ fn main() -> ! {
// resonator must be used.
rcc.cfgr.use_hse(8.MHz()).freeze(&mut flash.acr);

#[cfg(not(feature = "connectivity"))]
let can = Can::<_, Floating>::new_loopback(dp.CAN1, dp.USB);

#[cfg(feature = "connectivity")]
let can = Can::<_, Floating>::new_loopback(dp.CAN1);
let can = Can::<_, Floating>::new_loopback(
dp.CAN1,
#[cfg(not(feature = "connectivity"))]
dp.USB,
);

// Use loopback mode: No pins need to be assigned to peripheral.
// APB1 (PCLK1): 8MHz, Bit rate: 500Bit/s, Sample Point 87.5%
Expand Down
9 changes: 2 additions & 7 deletions examples/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ use cortex_m::asm;
use nb::block;

use cortex_m_rt::entry;
use stm32f1xx_hal::{
pac,
prelude::*,
serial::{Config, Serial},
};
use stm32f1xx_hal::{pac, prelude::*, serial::Config};
use unwrap_infallible::UnwrapInfallible;

#[entry]
Expand Down Expand Up @@ -61,8 +57,7 @@ fn main() -> ! {

// Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of
// the registers are used to enable and configure the device.
let mut serial = Serial::new(
p.USART3,
let mut serial = p.USART3.serial(
(tx, rx, &mut afio.mapr),
Config::default().baudrate(9600.bps()),
&clocks,
Expand Down
14 changes: 5 additions & 9 deletions examples/spi-slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use stm32f1xx_hal::{
gpio::Floating,
pac::{self, interrupt, Peripherals, SPI2},
prelude::*,
spi::{Event, Spi, SpiSlave},
spi::{Event, SpiSlave},
};

static mut SPI2SLAVE: Option<SpiSlave<SPI2, u8>> = None;
Expand All @@ -47,21 +47,17 @@ fn main() -> ! {
let miso = gpioa.pa6;
let mosi = gpioa.pa7;

let spi1 = Spi::<_, _, Floating>::new(
dp.SPI1,
(sck, miso, mosi, &mut afio.mapr),
MODE,
10.kHz(),
&clocks,
);
let spi1 = dp
.SPI1
.spi::<Floating>((sck, miso, mosi, &mut afio.mapr), MODE, 10.kHz(), &clocks);

// SPI2
// Convert pins before SPI initialization
let sck = gpiob.pb13;
let miso = gpiob.pb14.into_alternate_push_pull(&mut gpiob.crh);
let mosi = gpiob.pb15;

let spi2 = SpiSlave::new(dp.SPI2, (sck, miso, mosi), MODE);
let spi2 = dp.SPI2.spi_slave((sck, miso, mosi), MODE);

// Set up the DMA device
let dma = dp.DMA1.split();
Expand Down
69 changes: 46 additions & 23 deletions src/can.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,43 @@ macro_rules! remap {
}
use remap;

pub trait CanExt: Sized + Instance {
fn can<INMODE>(
self,
#[cfg(not(feature = "connectivity"))] usb: pac::USB,
pins: impl Into<Self::Pins<INMODE>>,
) -> Can<Self, INMODE>;
fn can_loopback<INMODE>(
self,
#[cfg(not(feature = "connectivity"))] usb: pac::USB,
) -> Can<Self, INMODE>;
}

impl<CAN: Instance> CanExt for CAN {
fn can<INMODE>(
self,
#[cfg(not(feature = "connectivity"))] usb: pac::USB,
pins: impl Into<Self::Pins<INMODE>>,
) -> Can<Self, INMODE> {
Can::new(
self,
#[cfg(not(feature = "connectivity"))]
usb,
pins,
)
}
fn can_loopback<INMODE>(
self,
#[cfg(not(feature = "connectivity"))] usb: pac::USB,
) -> Can<Self, INMODE> {
Can::new_loopback(
self,
#[cfg(not(feature = "connectivity"))]
usb,
)
}
}

pub trait Instance: crate::rcc::Enable {
type Pins<INMODE>;
}
Expand All @@ -144,18 +181,11 @@ impl<CAN: Instance, INMODE> Can<CAN, INMODE> {
///
/// CAN shares SRAM with the USB peripheral. Take ownership of USB to
/// prevent accidental shared usage.
#[cfg(not(feature = "connectivity"))]
pub fn new(can: CAN, _usb: pac::USB, pins: impl Into<CAN::Pins<INMODE>>) -> Can<CAN, INMODE> {
let rcc = unsafe { &(*RCC::ptr()) };
CAN::enable(rcc);

let pins = Some(pins.into());
Can { can, pins }
}

/// Creates a CAN interaface.
#[cfg(feature = "connectivity")]
pub fn new(can: CAN, pins: impl Into<CAN::Pins<INMODE>>) -> Can<CAN, INMODE> {
pub fn new(
can: CAN,
#[cfg(not(feature = "connectivity"))] _usb: pac::USB,
pins: impl Into<CAN::Pins<INMODE>>,
) -> Can<CAN, INMODE> {
let rcc = unsafe { &(*RCC::ptr()) };
CAN::enable(rcc);

Expand All @@ -164,17 +194,10 @@ impl<CAN: Instance, INMODE> Can<CAN, INMODE> {
}

/// Creates a CAN interface in loopback mode
#[cfg(not(feature = "connectivity"))]
pub fn new_loopback(can: CAN, _usb: pac::USB) -> Can<CAN, INMODE> {
let rcc = unsafe { &(*RCC::ptr()) };
CAN::enable(rcc);

Can { can, pins: None }
}

/// Creates a CAN interface in loopback mode
#[cfg(feature = "connectivity")]
pub fn new_loopback(can: CAN) -> Can<CAN, INMODE> {
pub fn new_loopback(
can: CAN,
#[cfg(not(feature = "connectivity"))] _usb: pac::USB,
) -> Can<CAN, INMODE> {
let rcc = unsafe { &(*RCC::ptr()) };
CAN::enable(rcc);

Expand Down
37 changes: 33 additions & 4 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,35 @@ macro_rules! remap {
}
use remap;

pub trait I2cExt: Sized + Instance {
fn i2c(self, pins: impl Into<Self::Pins>, mode: impl Into<Mode>, clocks: &Clocks) -> I2c<Self>;

fn blocking_i2c(
self,
pins: impl Into<Self::Pins>,
mode: impl Into<Mode>,
clocks: &Clocks,
start_timeout_us: u32,
start_retries: u8,
addr_timeout_us: u32,
data_timeout_us: u32,
) -> BlockingI2c<Self> {
Self::i2c(self, pins, mode, clocks).blocking(
start_timeout_us,
start_retries,
addr_timeout_us,
data_timeout_us,
clocks,
)
}
}

impl<I2C: Instance> I2cExt for I2C {
fn i2c(self, pins: impl Into<Self::Pins>, mode: impl Into<Mode>, clocks: &Clocks) -> I2c<Self> {
I2c::new(self, pins, mode, clocks)
}
}

/// I2C peripheral operating in master mode
pub struct I2c<I2C: Instance> {
i2c: I2C,
Expand All @@ -158,18 +187,18 @@ impl Instance for I2C2 {

impl<I2C: Instance> I2c<I2C> {
/// Creates a generic I2C object
pub fn new<M: Into<Mode>>(
pub fn new(
i2c: I2C,
pins: impl Into<I2C::Pins>,
mode: M,
clocks: Clocks,
mode: impl Into<Mode>,
clocks: &Clocks,
) -> Self {
let mode = mode.into();
let rcc = unsafe { &(*RCC::ptr()) };
I2C::enable(rcc);
I2C::reset(rcc);

let pclk1 = I2C::clock(&clocks);
let pclk1 = I2C::clock(clocks);

assert!(mode.get_frequency() <= kHz(400));

Expand Down
8 changes: 4 additions & 4 deletions src/i2c/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ pub struct DwtTimeouts {
impl<I2C: Instance> BlockingI2c<I2C> {
/// Creates a blocking I2C1 object on pins PB6 and PB7 or PB8 and PB9 using the embedded-hal `BlockingI2c` trait.
#[allow(clippy::too_many_arguments)]
pub fn i2c1<M: Into<Mode>>(
pub fn new(
i2c: I2C,
pins: impl Into<I2C::Pins>,
mode: M,
clocks: Clocks,
mode: impl Into<Mode>,
clocks: &Clocks,
start_timeout_us: u32,
start_retries: u8,
addr_timeout_us: u32,
Expand All @@ -48,7 +48,7 @@ impl<I2C: Instance> I2c<I2C> {
start_retries: u8,
addr_timeout_us: u32,
data_timeout_us: u32,
clocks: Clocks,
clocks: &Clocks,
) -> BlockingI2c<I2C> {
let sysclk_mhz = clocks.sysclk().to_MHz();
BlockingI2c {
Expand Down
5 changes: 5 additions & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub use crate::adc::ChannelTimeSequence as _stm32_hal_adc_ChannelTimeSequence;
pub use crate::afio::AfioExt as _stm32_hal_afio_AfioExt;
#[cfg(feature = "has-can")]
pub use crate::can::CanExt as _;
pub use crate::crc::CrcExt as _stm32_hal_crc_CrcExt;
pub use crate::dma::CircReadDma as _stm32_hal_dma_CircReadDma;
pub use crate::dma::DmaExt as _stm32_hal_dma_DmaExt;
Expand All @@ -12,7 +14,10 @@ pub use crate::hal::adc::OneShot as _embedded_hal_adc_OneShot;
pub use crate::hal::digital::v2::StatefulOutputPin as _embedded_hal_digital_StatefulOutputPin;
pub use crate::hal::digital::v2::ToggleableOutputPin as _embedded_hal_digital_ToggleableOutputPin;
pub use crate::hal::prelude::*;
pub use crate::i2c::I2cExt as _;
pub use crate::rcc::RccExt as _stm32_hal_rcc_RccExt;
pub use crate::serial::SerialExt as _;
pub use crate::spi::SpiExt as _;
pub use crate::time::U32Ext as _stm32_hal_time_U32Ext;
#[cfg(feature = "rtic")]
pub use crate::timer::MonoTimerExt as _stm32f4xx_hal_timer_MonoTimerExt;
Expand Down
20 changes: 20 additions & 0 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,26 @@ macro_rules! remap {
}
use remap;

pub trait SerialExt: Sized + Instance {
fn serial<OUTMODE, INMODE>(
self,
pins: impl Into<Self::Pins<OUTMODE, INMODE>>,
config: impl Into<Config>,
clocks: &Clocks,
) -> Serial<Self, OUTMODE, INMODE>;
}

impl<USART: Instance> SerialExt for USART {
fn serial<OUTMODE, INMODE>(
self,
pins: impl Into<Self::Pins<OUTMODE, INMODE>>,
config: impl Into<Config>,
clocks: &Clocks,
) -> Serial<Self, OUTMODE, INMODE> {
Serial::new(self, pins, config, clocks)
}
}

use crate::pac::usart1 as uart_base;

pub trait Instance:
Expand Down
50 changes: 50 additions & 0 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,56 @@ macro_rules! remap {
}
use remap;

pub trait SpiExt: Sized + Instance {
fn spi<INMODE>(
self,
pins: impl Into<Self::MasterPins<INMODE>>,
mode: Mode,
freq: Hertz,
clocks: &Clocks,
) -> Spi<Self, u8, INMODE>;
fn spi_u16<INMODE>(
self,
pins: impl Into<Self::MasterPins<INMODE>>,
mode: Mode,
freq: Hertz,
clocks: &Clocks,
) -> Spi<Self, u16, INMODE> {
Self::spi(self, pins, mode, freq, clocks).frame_size_16bit()
}
fn spi_slave<OUTMODE, INMODE>(
self,
pins: impl Into<Self::SlavePins<OUTMODE, INMODE>>,
mode: Mode,
) -> SpiSlave<Self, u8, OUTMODE, INMODE>;
fn spi_slave_u16<OUTMODE, INMODE>(
self,
pins: impl Into<Self::SlavePins<OUTMODE, INMODE>>,
mode: Mode,
) -> SpiSlave<Self, u16, OUTMODE, INMODE> {
Self::spi_slave(self, pins, mode).frame_size_16bit()
}
}

impl<SPI: Instance> SpiExt for SPI {
fn spi<INMODE>(
self,
pins: impl Into<Self::MasterPins<INMODE>>,
mode: Mode,
freq: Hertz,
clocks: &Clocks,
) -> Spi<Self, u8, INMODE> {
Spi::new(self, pins, mode, freq, clocks)
}
fn spi_slave<OUTMODE, INMODE>(
self,
pins: impl Into<Self::SlavePins<OUTMODE, INMODE>>,
mode: Mode,
) -> SpiSlave<Self, u8, OUTMODE, INMODE> {
SpiSlave::new(self, pins, mode)
}
}

pub struct SpiInner<SPI, FRAMESIZE> {
spi: SPI,
_framesize: PhantomData<FRAMESIZE>,
Expand Down

0 comments on commit 27d0358

Please sign in to comment.