continue CAN support
This commit is contained in:
parent
e8e7ea9b1c
commit
a6c9a6fcdc
@ -25,6 +25,7 @@ typenum = "1"
|
|||||||
bitflags = "2"
|
bitflags = "2"
|
||||||
bitbybit = "1.3"
|
bitbybit = "1.3"
|
||||||
arbitrary-int = "1.3"
|
arbitrary-int = "1.3"
|
||||||
|
derive-mmio = "0.4"
|
||||||
fugit = "0.3"
|
fugit = "0.3"
|
||||||
delegate = ">=0.12, <=0.13"
|
delegate = ">=0.12, <=0.13"
|
||||||
heapless = "0.8"
|
heapless = "0.8"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
|
|
67
va416xx-hal/src/can/mod.rs
Normal file
67
va416xx-hal/src/can/mod.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use arbitrary_int::{u2, u3, u4, u7};
|
||||||
|
|
||||||
|
use crate::{clock::Clocks, enable_peripheral_clock, PeripheralSelect};
|
||||||
|
|
||||||
|
pub mod regs;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum CanId {
|
||||||
|
Can0 = 0,
|
||||||
|
Can1 = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanId {}
|
||||||
|
|
||||||
|
pub struct Can {
|
||||||
|
id: CanId,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Instance {
|
||||||
|
const ID: CanId;
|
||||||
|
const PERIPH_SEL: PeripheralSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for va416xx::Can0 {
|
||||||
|
const ID: CanId = CanId::Can0;
|
||||||
|
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Can0;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for va416xx::Can1 {
|
||||||
|
const ID: CanId = CanId::Can1;
|
||||||
|
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Can1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ClockConfig {
|
||||||
|
prescaler: u7,
|
||||||
|
tseg1: u4,
|
||||||
|
tseg2: u3,
|
||||||
|
sjw: u2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClockConfig {
|
||||||
|
/// New clock configuration from the raw configuration values.
|
||||||
|
pub fn new(prescaler: u7, tseg1: u4, tseg2: u3, sjw: u2) -> Self {
|
||||||
|
Self {
|
||||||
|
prescaler,
|
||||||
|
tseg1,
|
||||||
|
tseg2,
|
||||||
|
sjw,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Can {
|
||||||
|
pub fn new<CanI: Instance>(_can: CanI, clk_config: ClockConfig) -> Self {
|
||||||
|
enable_peripheral_clock(CanI::PERIPH_SEL);
|
||||||
|
let id = CanI::ID;
|
||||||
|
let mut regs = if id == CanId::Can0 {
|
||||||
|
unsafe { regs::Can::new_mmio_fixed_0() }
|
||||||
|
} else {
|
||||||
|
unsafe { regs::Can::new_mmio_fixed_1() }
|
||||||
|
};
|
||||||
|
for i in 0..15 {
|
||||||
|
regs.msg_buf_block_mut(i).reset();
|
||||||
|
}
|
||||||
|
Self { id }
|
||||||
|
}
|
||||||
|
}
|
298
va416xx-hal/src/can/regs.rs
Normal file
298
va416xx-hal/src/can/regs.rs
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
//! Custom register definitions for the CAN register block to circumvent PAC API / SVD
|
||||||
|
//! shortcomings.
|
||||||
|
|
||||||
|
use arbitrary_int::{u2, u3, u4, u7};
|
||||||
|
|
||||||
|
pub const CAN_0_BASE: usize = 0x4001_4000;
|
||||||
|
pub const CAN_1_BASE: usize = 0x4001_4400;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[bitbybit::bitenum(u4)]
|
||||||
|
pub enum BufferStatus {
|
||||||
|
RxNotActive = 0b0000,
|
||||||
|
RxReady = 0b0001,
|
||||||
|
RxBusy0 = 0b0010,
|
||||||
|
RxFull = 0b0100,
|
||||||
|
RxBusy1 = 0b0101,
|
||||||
|
RxOverrun = 0b0110,
|
||||||
|
RxBusy2 = 0b0111,
|
||||||
|
TxNotActive = 0b1000,
|
||||||
|
TxRtr = 0b1010,
|
||||||
|
TxOnce = 0b1100,
|
||||||
|
TxBusy0 = 0b1101,
|
||||||
|
TxOnceRtr = 0b1110,
|
||||||
|
TxBusy2 = 0b1111,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Status control register for individual message buffers.
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct BufStatusAndControl {
|
||||||
|
/// Data length code.
|
||||||
|
#[bits(12..=15, rw)]
|
||||||
|
dlc: u4,
|
||||||
|
#[bits(4..=7, rw)]
|
||||||
|
priority: u4,
|
||||||
|
#[bits(0..=3, rw)]
|
||||||
|
status: Option<BufferStatus>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Data16Bit(arbitrary_int::UInt<u32, 16>);
|
||||||
|
|
||||||
|
impl Data16Bit {
|
||||||
|
pub fn new(value: u16) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
pub fn value(&self) -> u16 {
|
||||||
|
self.0.value() as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&mut self, value: u16) {
|
||||||
|
self.0 = value.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CanMsgBuf {
|
||||||
|
stat_ctrl: BufStatusAndControl,
|
||||||
|
timestamp: Data16Bit,
|
||||||
|
data3: Data16Bit,
|
||||||
|
data2: Data16Bit,
|
||||||
|
data1: Data16Bit,
|
||||||
|
data0: Data16Bit,
|
||||||
|
id0: Data16Bit,
|
||||||
|
id1: Data16Bit,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MmioCanMsgBuf<'_> {
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.write_stat_ctrl(BufStatusAndControl::new_with_raw_value(0));
|
||||||
|
self.write_timestamp(Data16Bit::new(0));
|
||||||
|
self.write_data3(Data16Bit::new(0));
|
||||||
|
self.write_data2(Data16Bit::new(0));
|
||||||
|
self.write_data1(Data16Bit::new(0));
|
||||||
|
self.write_data0(Data16Bit::new(0));
|
||||||
|
self.write_id1(Data16Bit::new(0));
|
||||||
|
self.write_id0(Data16Bit::new(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PinLogicLevel {
|
||||||
|
DominantIsZero = 0b0,
|
||||||
|
DominantIsOne = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ErrorInterruptType {
|
||||||
|
/// EIPND bit is set on every error.
|
||||||
|
EveryError = 0b0,
|
||||||
|
/// EIPND bit is only set if error state changes as a result of a receive or transmit
|
||||||
|
/// error counter increment.
|
||||||
|
ErrorOnRxTxCounterChange = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DataDirection {
|
||||||
|
FirstByteAtHighestAddr = 0b0,
|
||||||
|
LastByteAtHighestAddr = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
pub struct Control {
|
||||||
|
#[bit(11, rw)]
|
||||||
|
error_interrupt_type: ErrorInterruptType,
|
||||||
|
/// Enables special diagnostics features of the CAN like LO, IGNACK, LOOPBACK, INTERNAL.
|
||||||
|
#[bit(10, rw)]
|
||||||
|
diag_enable: bool,
|
||||||
|
/// CANTX and CANRX pins are internally connected to each other.
|
||||||
|
#[bit(9, rw)]
|
||||||
|
internal: bool,
|
||||||
|
/// All messages sent by the CAN controller can also be received by a CAN buffer with a
|
||||||
|
/// matching buffer ID.
|
||||||
|
#[bit(8, rw)]
|
||||||
|
loopback: bool,
|
||||||
|
/// IGNACK feature. The CAN does not expect to receive an ACK bit.
|
||||||
|
#[bit(7, rw)]
|
||||||
|
ignore_ack: bool,
|
||||||
|
/// LO feature. The CAN is only configured as a receiver.
|
||||||
|
#[bit(6, rw)]
|
||||||
|
listen_only: bool,
|
||||||
|
#[bit(5, rw)]
|
||||||
|
data_dir: DataDirection,
|
||||||
|
#[bit(4, rw)]
|
||||||
|
timestamp_enable: bool,
|
||||||
|
#[bit(3, rw)]
|
||||||
|
bufflock: bool,
|
||||||
|
#[bit(2, rw)]
|
||||||
|
tx_logic_level: PinLogicLevel,
|
||||||
|
#[bit(1, rw)]
|
||||||
|
rx_logic_level: PinLogicLevel,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
enable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TimingConfig {
|
||||||
|
#[bits(0..=2, rw)]
|
||||||
|
tseg2: u3,
|
||||||
|
#[bits(3..=6, rw)]
|
||||||
|
tseg1: u4,
|
||||||
|
#[bits(7..=8, rw)]
|
||||||
|
sync_jump_width: u2,
|
||||||
|
#[bits(9..=15, rw)]
|
||||||
|
prescaler: u7,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InterruptEnable {
|
||||||
|
#[bit(15, rw)]
|
||||||
|
error: bool,
|
||||||
|
#[bit(0, rw)]
|
||||||
|
buffer: [bool; 15],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InterruptClear {
|
||||||
|
#[bit(15, w)]
|
||||||
|
error: bool,
|
||||||
|
#[bit(0, w)]
|
||||||
|
buffer: [bool; 15],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InterruptPending {
|
||||||
|
#[bit(15, r)]
|
||||||
|
error: bool,
|
||||||
|
#[bit(0, r)]
|
||||||
|
buffer: [bool; 15],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ErrorCounter {
|
||||||
|
#[bits(0..=7, r)]
|
||||||
|
transmit: u8,
|
||||||
|
#[bits(8..=15, r)]
|
||||||
|
receive: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(derive_mmio::Mmio)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Can {
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb0: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb1: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb2: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb3: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb4: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb5: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb6: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb7: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb8: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb9: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb10: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb11: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb12: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb13: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
cmb14: CanMsgBuf,
|
||||||
|
#[mmio(inner)]
|
||||||
|
hcmb: CanMsgBuf,
|
||||||
|
control: Control,
|
||||||
|
timing: TimingConfig,
|
||||||
|
/// Global mask extension.
|
||||||
|
gmskx: u32,
|
||||||
|
/// Global mask base.
|
||||||
|
gmskb: u32,
|
||||||
|
/// Basic mask extension.
|
||||||
|
bmskx: u32,
|
||||||
|
/// Basic mask base.
|
||||||
|
bmskb: u32,
|
||||||
|
ien: InterruptEnable,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
ipnd: InterruptPending,
|
||||||
|
#[mmio(Write)]
|
||||||
|
iclr: InterruptClear,
|
||||||
|
/// Interrupt Code Enable Register.
|
||||||
|
icen: InterruptEnable,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
status_pending: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
error_counter: ErrorCounter,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
diag: u32,
|
||||||
|
#[mmio(PureRead)]
|
||||||
|
timer: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Can {
|
||||||
|
/// Create a new CAN MMIO instance for peripheral 0.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
pub const unsafe fn new_mmio_fixed_0() -> MmioCan<'static> {
|
||||||
|
Self::new_mmio_at(CAN_0_BASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new CAN MMIO instance for peripheral 1.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||||
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
|
/// interfere with each other.
|
||||||
|
pub const unsafe fn new_mmio_fixed_1() -> MmioCan<'static> {
|
||||||
|
Self::new_mmio_at(CAN_1_BASE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MmioCan<'_> {
|
||||||
|
// TODO: It would be nice if derive-mmio could generate this for us..
|
||||||
|
pub fn msg_buf_block_mut(&mut self, idx: usize) -> MmioCanMsgBuf<'static> {
|
||||||
|
assert!(idx < 16, "invalid index for CAN message buffer");
|
||||||
|
match idx {
|
||||||
|
0 => unsafe { self.steal_cmb0() },
|
||||||
|
1 => unsafe { self.steal_cmb1() },
|
||||||
|
2 => unsafe { self.steal_cmb2() },
|
||||||
|
3 => unsafe { self.steal_cmb3() },
|
||||||
|
4 => unsafe { self.steal_cmb4() },
|
||||||
|
5 => unsafe { self.steal_cmb5() },
|
||||||
|
6 => unsafe { self.steal_cmb6() },
|
||||||
|
7 => unsafe { self.steal_cmb7() },
|
||||||
|
8 => unsafe { self.steal_cmb8() },
|
||||||
|
9 => unsafe { self.steal_cmb9() },
|
||||||
|
10 => unsafe { self.steal_cmb10() },
|
||||||
|
11 => unsafe { self.steal_cmb11() },
|
||||||
|
12 => unsafe { self.steal_cmb12() },
|
||||||
|
13 => unsafe { self.steal_cmb13() },
|
||||||
|
14 => unsafe { self.steal_cmb14() },
|
||||||
|
15 => unsafe { self.steal_hcmb() },
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -396,16 +396,45 @@ impl Clocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the frequency of the APB0 which is equal to the system clock.
|
/// Returns the frequency of the APB0 which is equal to the system clock.
|
||||||
|
///
|
||||||
|
/// This clock is the reference clock for the following peripherals:
|
||||||
|
///
|
||||||
|
/// - Ethernet
|
||||||
|
/// - SpaceWire
|
||||||
|
/// - IRQ Router
|
||||||
|
/// - DMA
|
||||||
|
/// - Clock Generator
|
||||||
pub const fn apb0(&self) -> Hertz {
|
pub const fn apb0(&self) -> Hertz {
|
||||||
self.sysclk()
|
self.sysclk()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns system clock divied by 2.
|
/// Returns system clock divied by 2.
|
||||||
|
///
|
||||||
|
/// This clock is the reference clock for the following peripherals:
|
||||||
|
///
|
||||||
|
/// - Timer[15:0]
|
||||||
|
/// - UART2
|
||||||
|
/// - SPI
|
||||||
|
/// - I2C
|
||||||
|
/// - CAN
|
||||||
|
/// - GPIO
|
||||||
|
/// - IOCONFIG
|
||||||
|
/// - System Config
|
||||||
pub const fn apb1(&self) -> Hertz {
|
pub const fn apb1(&self) -> Hertz {
|
||||||
self.apb1
|
self.apb1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns system clock divied by 4.
|
/// Returns system clock divied by 4.
|
||||||
|
///
|
||||||
|
/// This clock is the reference clock for the following peripherals:
|
||||||
|
///
|
||||||
|
/// - Timer[23:16]
|
||||||
|
/// - TRNG
|
||||||
|
/// - UART[1:0]
|
||||||
|
/// - DAC
|
||||||
|
/// - ADC
|
||||||
|
/// - Watchdog
|
||||||
|
/// - Utility
|
||||||
pub const fn apb2(&self) -> Hertz {
|
pub const fn apb2(&self) -> Hertz {
|
||||||
self.apb2
|
self.apb2
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [PEB1 accelerometer example](https://egit.irs.uni-stuttgart.de/rust/va416xx-rs/src/branch/main/examples/simple/examples/peb1-accelerometer.rs)
|
//! - [PEB1 accelerometer example](https://egit.irs.uni-stuttgart.de/rust/va416xx-rs/src/branch/main/examples/simple/examples/peb1-accelerometer.rs)
|
||||||
use crate::{clock::Clocks, pac, time::Hertz, typelevel::Sealed, PeripheralSelect, SyscfgExt as _};
|
use crate::{
|
||||||
|
clock::Clocks, enable_peripheral_clock, pac, time::Hertz, typelevel::Sealed, PeripheralSelect,
|
||||||
|
};
|
||||||
use core::{marker::PhantomData, ops::Deref};
|
use core::{marker::PhantomData, ops::Deref};
|
||||||
use embedded_hal::i2c::{self, Operation, SevenBitAddress, TenBitAddress};
|
use embedded_hal::i2c::{self, Operation, SevenBitAddress, TenBitAddress};
|
||||||
|
|
||||||
@ -318,13 +320,12 @@ impl<I2C> I2cBase<I2C> {
|
|||||||
impl<I2c: Instance> I2cBase<I2c> {
|
impl<I2c: Instance> I2cBase<I2c> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
i2c: I2c,
|
i2c: I2c,
|
||||||
syscfg: &mut pac::Sysconfig,
|
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
ms_cfg: Option<&MasterConfig>,
|
ms_cfg: Option<&MasterConfig>,
|
||||||
sl_cfg: Option<&SlaveConfig>,
|
sl_cfg: Option<&SlaveConfig>,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
syscfg.enable_peripheral_clock(I2c::PERIPH_SEL);
|
enable_peripheral_clock(I2c::PERIPH_SEL);
|
||||||
|
|
||||||
let mut i2c_base = I2cBase {
|
let mut i2c_base = I2cBase {
|
||||||
i2c,
|
i2c,
|
||||||
@ -476,13 +477,12 @@ pub struct I2cMaster<I2c, Addr = SevenBitAddress> {
|
|||||||
impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
|
impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
i2c: I2c,
|
i2c: I2c,
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
|
||||||
cfg: MasterConfig,
|
cfg: MasterConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
Ok(I2cMaster {
|
Ok(I2cMaster {
|
||||||
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, Some(&cfg), None)?,
|
i2c_base: I2cBase::new(i2c, clocks, speed_mode, Some(&cfg), None)?,
|
||||||
addr: PhantomData,
|
addr: PhantomData,
|
||||||
}
|
}
|
||||||
.enable_master())
|
.enable_master())
|
||||||
@ -737,13 +737,12 @@ pub struct I2cSlave<I2c, Addr = SevenBitAddress> {
|
|||||||
impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
|
impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
|
||||||
fn new_generic(
|
fn new_generic(
|
||||||
i2c: I2c,
|
i2c: I2c,
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
|
||||||
cfg: SlaveConfig,
|
cfg: SlaveConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
Ok(I2cSlave {
|
Ok(I2cSlave {
|
||||||
i2c_base: I2cBase::new(i2c, sys_cfg, clocks, speed_mode, None, Some(&cfg))?,
|
i2c_base: I2cBase::new(i2c, clocks, speed_mode, None, Some(&cfg))?,
|
||||||
addr: PhantomData,
|
addr: PhantomData,
|
||||||
}
|
}
|
||||||
.enable_slave())
|
.enable_slave())
|
||||||
@ -884,7 +883,6 @@ impl<I2c: Instance> I2cSlave<I2c, SevenBitAddress> {
|
|||||||
/// Create a new I2C slave for seven bit addresses
|
/// Create a new I2C slave for seven bit addresses
|
||||||
pub fn new(
|
pub fn new(
|
||||||
i2c: I2c,
|
i2c: I2c,
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
|
||||||
cfg: SlaveConfig,
|
cfg: SlaveConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
@ -892,18 +890,17 @@ impl<I2c: Instance> I2cSlave<I2c, SevenBitAddress> {
|
|||||||
if let I2cAddress::TenBit(_) = cfg.addr {
|
if let I2cAddress::TenBit(_) = cfg.addr {
|
||||||
return Err(InitError::WrongAddrMode);
|
return Err(InitError::WrongAddrMode);
|
||||||
}
|
}
|
||||||
Ok(Self::new_generic(i2c, sys_cfg, cfg, clocks, speed_mode)?)
|
Ok(Self::new_generic(i2c, cfg, clocks, speed_mode)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I2c: Instance> I2cSlave<I2c, TenBitAddress> {
|
impl<I2c: Instance> I2cSlave<I2c, TenBitAddress> {
|
||||||
pub fn new_ten_bit_addr(
|
pub fn new_ten_bit_addr(
|
||||||
i2c: I2c,
|
i2c: I2c,
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
|
||||||
cfg: SlaveConfig,
|
cfg: SlaveConfig,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||||
Self::new_generic(i2c, sys_cfg, cfg, clocks, speed_mode)
|
Self::new_generic(i2c, cfg, clocks, speed_mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,39 +97,43 @@ pub enum PeripheralSelect {
|
|||||||
pub type PeripheralClock = PeripheralSelect;
|
pub type PeripheralClock = PeripheralSelect;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn enable_peripheral_clock(syscfg: &mut pac::Sysconfig, clock: PeripheralSelect) {
|
pub fn enable_peripheral_clock(clock: PeripheralSelect) {
|
||||||
syscfg
|
// Safety: Only bit of peripheral is modified.
|
||||||
|
unsafe { pac::Sysconfig::steal() }
|
||||||
.peripheral_clk_enable()
|
.peripheral_clk_enable()
|
||||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << clock as u8)) });
|
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << clock as u8)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn disable_peripheral_clock(syscfg: &mut pac::Sysconfig, clock: PeripheralSelect) {
|
pub fn disable_peripheral_clock(clock: PeripheralSelect) {
|
||||||
syscfg
|
// Safety: Only bit of peripheral is modified.
|
||||||
|
unsafe { pac::Sysconfig::steal() }
|
||||||
.peripheral_clk_enable()
|
.peripheral_clk_enable()
|
||||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << clock as u8)) });
|
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << clock as u8)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn assert_periph_reset(syscfg: &mut pac::Sysconfig, periph: PeripheralSelect) {
|
pub fn assert_periph_reset(periph: PeripheralSelect) {
|
||||||
syscfg
|
// Safety: Only reset bit of peripheral is modified.
|
||||||
|
unsafe { pac::Sysconfig::steal() }
|
||||||
.peripheral_reset()
|
.peripheral_reset()
|
||||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph as u8)) });
|
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph as u8)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn deassert_periph_reset(syscfg: &mut pac::Sysconfig, periph: PeripheralSelect) {
|
pub fn deassert_periph_reset(periph: PeripheralSelect) {
|
||||||
syscfg
|
// Safety: Only rest bit of peripheral is modified.
|
||||||
|
unsafe { pac::Sysconfig::steal() }
|
||||||
.peripheral_reset()
|
.peripheral_reset()
|
||||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph as u8)) });
|
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph as u8)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn assert_periph_reset_for_two_cycles(syscfg: &mut pac::Sysconfig, periph: PeripheralSelect) {
|
fn assert_periph_reset_for_two_cycles(periph: PeripheralSelect) {
|
||||||
assert_periph_reset(syscfg, periph);
|
assert_periph_reset(periph);
|
||||||
cortex_m::asm::nop();
|
cortex_m::asm::nop();
|
||||||
cortex_m::asm::nop();
|
cortex_m::asm::nop();
|
||||||
deassert_periph_reset(syscfg, periph);
|
deassert_periph_reset(periph);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
||||||
@ -190,27 +194,27 @@ pub trait SyscfgExt {
|
|||||||
impl SyscfgExt for pac::Sysconfig {
|
impl SyscfgExt for pac::Sysconfig {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn enable_peripheral_clock(&mut self, clock: PeripheralClock) {
|
fn enable_peripheral_clock(&mut self, clock: PeripheralClock) {
|
||||||
enable_peripheral_clock(self, clock)
|
enable_peripheral_clock(clock)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn disable_peripheral_clock(&mut self, clock: PeripheralClock) {
|
fn disable_peripheral_clock(&mut self, clock: PeripheralClock) {
|
||||||
disable_peripheral_clock(self, clock)
|
disable_peripheral_clock(clock)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn assert_periph_reset(&mut self, clock: PeripheralSelect) {
|
fn assert_periph_reset(&mut self, clock: PeripheralSelect) {
|
||||||
assert_periph_reset(self, clock)
|
assert_periph_reset(clock)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deassert_periph_reset(&mut self, clock: PeripheralSelect) {
|
fn deassert_periph_reset(&mut self, clock: PeripheralSelect) {
|
||||||
deassert_periph_reset(self, clock)
|
deassert_periph_reset(clock)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn assert_periph_reset_for_two_cycles(&mut self, periph: PeripheralSelect) {
|
fn assert_periph_reset_for_two_cycles(&mut self, periph: PeripheralSelect) {
|
||||||
assert_periph_reset_for_two_cycles(self, periph)
|
assert_periph_reset_for_two_cycles(periph)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ use crate::{
|
|||||||
pac,
|
pac,
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
typelevel::{NoneT, Sealed},
|
typelevel::{NoneT, Sealed},
|
||||||
PeripheralSelect, SyscfgExt as _,
|
PeripheralSelect,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "va41628"))]
|
#[cfg(not(feature = "va41628"))]
|
||||||
@ -1041,15 +1041,14 @@ where
|
|||||||
/// to be done once.
|
/// to be done once.
|
||||||
/// * `syscfg` - Can be passed optionally to enable the peripheral clock
|
/// * `syscfg` - Can be passed optionally to enable the peripheral clock
|
||||||
pub fn new(
|
pub fn new(
|
||||||
syscfg: &mut pac::Sysconfig,
|
|
||||||
clocks: &crate::clock::Clocks,
|
clocks: &crate::clock::Clocks,
|
||||||
spi: SpiI,
|
spi: SpiI,
|
||||||
pins: (Sck, Miso, Mosi),
|
pins: (Sck, Miso, Mosi),
|
||||||
spi_cfg: SpiConfig,
|
spi_cfg: SpiConfig,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
crate::enable_peripheral_clock(syscfg, SpiI::PERIPH_SEL);
|
crate::enable_peripheral_clock(SpiI::PERIPH_SEL);
|
||||||
// This is done in the C HAL.
|
// This is done in the C HAL.
|
||||||
syscfg.assert_periph_reset_for_two_cycles(SpiI::PERIPH_SEL);
|
crate::assert_periph_reset_for_two_cycles(SpiI::PERIPH_SEL);
|
||||||
let SpiConfig {
|
let SpiConfig {
|
||||||
clk,
|
clk,
|
||||||
init_mode,
|
init_mode,
|
||||||
|
@ -18,7 +18,7 @@ use fugit::RateExtU32;
|
|||||||
use crate::clock::Clocks;
|
use crate::clock::Clocks;
|
||||||
use crate::gpio::PF13;
|
use crate::gpio::PF13;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{disable_nvic_interrupt, enable_nvic_interrupt, PeripheralSelect, SyscfgExt as _};
|
use crate::{disable_nvic_interrupt, enable_nvic_interrupt, PeripheralSelect};
|
||||||
use crate::{
|
use crate::{
|
||||||
gpio::{
|
gpio::{
|
||||||
AltFunc1, AltFunc2, AltFunc3, Pin, PA2, PA3, PB14, PB15, PC14, PC4, PC5, PD11, PD12, PE2,
|
AltFunc1, AltFunc2, AltFunc3, Pin, PA2, PA3, PB14, PB15, PC14, PC4, PC5, PD11, PD12, PE2,
|
||||||
@ -630,15 +630,14 @@ impl<TxPinInst: TxPin<UartInstance>, RxPinInst: RxPin<UartInstance>, UartInstanc
|
|||||||
Uart<UartInstance, (TxPinInst, RxPinInst)>
|
Uart<UartInstance, (TxPinInst, RxPinInst)>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
syscfg: &mut va416xx::Sysconfig,
|
|
||||||
uart: UartInstance,
|
uart: UartInstance,
|
||||||
pins: (TxPinInst, RxPinInst),
|
pins: (TxPinInst, RxPinInst),
|
||||||
config: impl Into<Config>,
|
config: impl Into<Config>,
|
||||||
clocks: &Clocks,
|
clocks: &Clocks,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
crate::enable_peripheral_clock(syscfg, UartInstance::PERIPH_SEL);
|
crate::enable_peripheral_clock(UartInstance::PERIPH_SEL);
|
||||||
// This is done in the C HAL.
|
// This is done in the C HAL.
|
||||||
syscfg.assert_periph_reset_for_two_cycles(UartInstance::PERIPH_SEL);
|
crate::assert_periph_reset_for_two_cycles(UartInstance::PERIPH_SEL);
|
||||||
Uart {
|
Uart {
|
||||||
inner: UartBase {
|
inner: UartBase {
|
||||||
uart,
|
uart,
|
||||||
@ -651,13 +650,12 @@ impl<TxPinInst: TxPin<UartInstance>, RxPinInst: RxPin<UartInstance>, UartInstanc
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_clock_freq(
|
pub fn new_with_clock_freq(
|
||||||
syscfg: &mut va416xx::Sysconfig,
|
|
||||||
uart: UartInstance,
|
uart: UartInstance,
|
||||||
pins: (TxPinInst, RxPinInst),
|
pins: (TxPinInst, RxPinInst),
|
||||||
config: impl Into<Config>,
|
config: impl Into<Config>,
|
||||||
clock: impl Into<Hertz>,
|
clock: impl Into<Hertz>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
crate::enable_peripheral_clock(syscfg, UartInstance::PERIPH_SEL);
|
crate::enable_peripheral_clock(UartInstance::PERIPH_SEL);
|
||||||
Uart {
|
Uart {
|
||||||
inner: UartBase {
|
inner: UartBase {
|
||||||
uart,
|
uart,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user