continue CAN support
This commit is contained in:
parent
e8e7ea9b1c
commit
a6c9a6fcdc
@ -25,6 +25,7 @@ typenum = "1"
|
||||
bitflags = "2"
|
||||
bitbybit = "1.3"
|
||||
arbitrary-int = "1.3"
|
||||
derive-mmio = "0.4"
|
||||
fugit = "0.3"
|
||||
delegate = ">=0.12, <=0.13"
|
||||
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.
|
||||
///
|
||||
/// This clock is the reference clock for the following peripherals:
|
||||
///
|
||||
/// - Ethernet
|
||||
/// - SpaceWire
|
||||
/// - IRQ Router
|
||||
/// - DMA
|
||||
/// - Clock Generator
|
||||
pub const fn apb0(&self) -> Hertz {
|
||||
self.sysclk()
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
self.apb1
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
self.apb2
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
//! ## Examples
|
||||
//!
|
||||
//! - [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 embedded_hal::i2c::{self, Operation, SevenBitAddress, TenBitAddress};
|
||||
|
||||
@ -318,13 +320,12 @@ impl<I2C> I2cBase<I2C> {
|
||||
impl<I2c: Instance> I2cBase<I2c> {
|
||||
pub fn new(
|
||||
i2c: I2c,
|
||||
syscfg: &mut pac::Sysconfig,
|
||||
clocks: &Clocks,
|
||||
speed_mode: I2cSpeed,
|
||||
ms_cfg: Option<&MasterConfig>,
|
||||
sl_cfg: Option<&SlaveConfig>,
|
||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||
syscfg.enable_peripheral_clock(I2c::PERIPH_SEL);
|
||||
enable_peripheral_clock(I2c::PERIPH_SEL);
|
||||
|
||||
let mut i2c_base = I2cBase {
|
||||
i2c,
|
||||
@ -476,13 +477,12 @@ pub struct I2cMaster<I2c, Addr = SevenBitAddress> {
|
||||
impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
|
||||
pub fn new(
|
||||
i2c: I2c,
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
cfg: MasterConfig,
|
||||
clocks: &Clocks,
|
||||
speed_mode: I2cSpeed,
|
||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||
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,
|
||||
}
|
||||
.enable_master())
|
||||
@ -737,13 +737,12 @@ pub struct I2cSlave<I2c, Addr = SevenBitAddress> {
|
||||
impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
|
||||
fn new_generic(
|
||||
i2c: I2c,
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
cfg: SlaveConfig,
|
||||
clocks: &Clocks,
|
||||
speed_mode: I2cSpeed,
|
||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||
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,
|
||||
}
|
||||
.enable_slave())
|
||||
@ -884,7 +883,6 @@ impl<I2c: Instance> I2cSlave<I2c, SevenBitAddress> {
|
||||
/// Create a new I2C slave for seven bit addresses
|
||||
pub fn new(
|
||||
i2c: I2c,
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
cfg: SlaveConfig,
|
||||
clocks: &Clocks,
|
||||
speed_mode: I2cSpeed,
|
||||
@ -892,18 +890,17 @@ impl<I2c: Instance> I2cSlave<I2c, SevenBitAddress> {
|
||||
if let I2cAddress::TenBit(_) = cfg.addr {
|
||||
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> {
|
||||
pub fn new_ten_bit_addr(
|
||||
i2c: I2c,
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
cfg: SlaveConfig,
|
||||
clocks: &Clocks,
|
||||
speed_mode: I2cSpeed,
|
||||
) -> 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;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn enable_peripheral_clock(syscfg: &mut pac::Sysconfig, clock: PeripheralSelect) {
|
||||
syscfg
|
||||
pub fn enable_peripheral_clock(clock: PeripheralSelect) {
|
||||
// Safety: Only bit of peripheral is modified.
|
||||
unsafe { pac::Sysconfig::steal() }
|
||||
.peripheral_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << clock as u8)) });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn disable_peripheral_clock(syscfg: &mut pac::Sysconfig, clock: PeripheralSelect) {
|
||||
syscfg
|
||||
pub fn disable_peripheral_clock(clock: PeripheralSelect) {
|
||||
// Safety: Only bit of peripheral is modified.
|
||||
unsafe { pac::Sysconfig::steal() }
|
||||
.peripheral_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << clock as u8)) });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn assert_periph_reset(syscfg: &mut pac::Sysconfig, periph: PeripheralSelect) {
|
||||
syscfg
|
||||
pub fn assert_periph_reset(periph: PeripheralSelect) {
|
||||
// Safety: Only reset bit of peripheral is modified.
|
||||
unsafe { pac::Sysconfig::steal() }
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph as u8)) });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn deassert_periph_reset(syscfg: &mut pac::Sysconfig, periph: PeripheralSelect) {
|
||||
syscfg
|
||||
pub fn deassert_periph_reset(periph: PeripheralSelect) {
|
||||
// Safety: Only rest bit of peripheral is modified.
|
||||
unsafe { pac::Sysconfig::steal() }
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph as u8)) });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn assert_periph_reset_for_two_cycles(syscfg: &mut pac::Sysconfig, periph: PeripheralSelect) {
|
||||
assert_periph_reset(syscfg, periph);
|
||||
fn assert_periph_reset_for_two_cycles(periph: PeripheralSelect) {
|
||||
assert_periph_reset(periph);
|
||||
cortex_m::asm::nop();
|
||||
cortex_m::asm::nop();
|
||||
deassert_periph_reset(syscfg, periph);
|
||||
deassert_periph_reset(periph);
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
||||
@ -190,27 +194,27 @@ pub trait SyscfgExt {
|
||||
impl SyscfgExt for pac::Sysconfig {
|
||||
#[inline(always)]
|
||||
fn enable_peripheral_clock(&mut self, clock: PeripheralClock) {
|
||||
enable_peripheral_clock(self, clock)
|
||||
enable_peripheral_clock(clock)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn disable_peripheral_clock(&mut self, clock: PeripheralClock) {
|
||||
disable_peripheral_clock(self, clock)
|
||||
disable_peripheral_clock(clock)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn assert_periph_reset(&mut self, clock: PeripheralSelect) {
|
||||
assert_periph_reset(self, clock)
|
||||
assert_periph_reset(clock)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn deassert_periph_reset(&mut self, clock: PeripheralSelect) {
|
||||
deassert_periph_reset(self, clock)
|
||||
deassert_periph_reset(clock)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
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,
|
||||
time::Hertz,
|
||||
typelevel::{NoneT, Sealed},
|
||||
PeripheralSelect, SyscfgExt as _,
|
||||
PeripheralSelect,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "va41628"))]
|
||||
@ -1041,15 +1041,14 @@ where
|
||||
/// to be done once.
|
||||
/// * `syscfg` - Can be passed optionally to enable the peripheral clock
|
||||
pub fn new(
|
||||
syscfg: &mut pac::Sysconfig,
|
||||
clocks: &crate::clock::Clocks,
|
||||
spi: SpiI,
|
||||
pins: (Sck, Miso, Mosi),
|
||||
spi_cfg: SpiConfig,
|
||||
) -> Self {
|
||||
crate::enable_peripheral_clock(syscfg, SpiI::PERIPH_SEL);
|
||||
crate::enable_peripheral_clock(SpiI::PERIPH_SEL);
|
||||
// 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 {
|
||||
clk,
|
||||
init_mode,
|
||||
|
@ -18,7 +18,7 @@ use fugit::RateExtU32;
|
||||
use crate::clock::Clocks;
|
||||
use crate::gpio::PF13;
|
||||
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::{
|
||||
gpio::{
|
||||
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)>
|
||||
{
|
||||
pub fn new(
|
||||
syscfg: &mut va416xx::Sysconfig,
|
||||
uart: UartInstance,
|
||||
pins: (TxPinInst, RxPinInst),
|
||||
config: impl Into<Config>,
|
||||
clocks: &Clocks,
|
||||
) -> Self {
|
||||
crate::enable_peripheral_clock(syscfg, UartInstance::PERIPH_SEL);
|
||||
crate::enable_peripheral_clock(UartInstance::PERIPH_SEL);
|
||||
// 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 {
|
||||
inner: UartBase {
|
||||
uart,
|
||||
@ -651,13 +650,12 @@ impl<TxPinInst: TxPin<UartInstance>, RxPinInst: RxPin<UartInstance>, UartInstanc
|
||||
}
|
||||
|
||||
pub fn new_with_clock_freq(
|
||||
syscfg: &mut va416xx::Sysconfig,
|
||||
uart: UartInstance,
|
||||
pins: (TxPinInst, RxPinInst),
|
||||
config: impl Into<Config>,
|
||||
clock: impl Into<Hertz>,
|
||||
) -> Self {
|
||||
crate::enable_peripheral_clock(syscfg, UartInstance::PERIPH_SEL);
|
||||
crate::enable_peripheral_clock(UartInstance::PERIPH_SEL);
|
||||
Uart {
|
||||
inner: UartBase {
|
||||
uart,
|
||||
|
Loading…
x
Reference in New Issue
Block a user