move to updated API
This commit is contained in:
@ -2,24 +2,13 @@
|
||||
//!
|
||||
//! This also includes functionality to enable the peripheral clocks
|
||||
use crate::time::Hertz;
|
||||
use crate::PeripheralSelect;
|
||||
use cortex_m::interrupt::{self, Mutex};
|
||||
use once_cell::unsync::OnceCell;
|
||||
|
||||
static SYS_CLOCK: Mutex<OnceCell<Hertz>> = Mutex::new(OnceCell::new());
|
||||
pub use vorago_shared_periphs::gpio::FilterClkSel;
|
||||
pub use vorago_shared_periphs::sysconfig::{disable_peripheral_clock, enable_peripheral_clock};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum FilterClkSel {
|
||||
SysClk = 0,
|
||||
Clk1 = 1,
|
||||
Clk2 = 2,
|
||||
Clk3 = 3,
|
||||
Clk4 = 4,
|
||||
Clk5 = 5,
|
||||
Clk6 = 6,
|
||||
Clk7 = 7,
|
||||
}
|
||||
static SYS_CLOCK: Mutex<OnceCell<Hertz>> = Mutex::new(OnceCell::new());
|
||||
|
||||
/// The Vorago in powered by an external clock which might have different frequencies.
|
||||
/// The clock can be set here so it can be used by other software components as well.
|
||||
@ -61,5 +50,3 @@ pub fn set_clk_div_register(syscfg: &mut va108xx::Sysconfig, clk_sel: FilterClkS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use vorago_shared_periphs::sysconfig::{disable_peripheral_clock, enable_peripheral_clock};
|
||||
|
@ -307,7 +307,7 @@ impl<I2C> I2cBase<I2C> {
|
||||
|
||||
impl<I2c: Instance> I2cBase<I2c> {
|
||||
pub fn new(
|
||||
sysclk: Hertz,
|
||||
sys_clk: Hertz,
|
||||
i2c: I2c,
|
||||
speed_mode: I2cSpeed,
|
||||
ms_cfg: Option<&MasterConfig>,
|
||||
@ -315,10 +315,7 @@ impl<I2c: Instance> I2cBase<I2c> {
|
||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||
enable_peripheral_clock(I2c::PERIPH_SEL);
|
||||
|
||||
let mut i2c_base = I2cBase {
|
||||
i2c,
|
||||
sys_clk: sysclk.into(),
|
||||
};
|
||||
let mut i2c_base = I2cBase { i2c, sys_clk };
|
||||
if let Some(ms_cfg) = ms_cfg {
|
||||
i2c_base.cfg_master(ms_cfg);
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
pub use vorago_shared_periphs::gpio::{Pin, PinId, PinMarker, Port};
|
||||
use vorago_shared_periphs::sysconfig::reset_peripheral_for_cycles;
|
||||
|
||||
use crate::{sysconfig::reset_peripheral_for_cycles, PeripheralSelect};
|
||||
pub use crate::gpio::{Pin, PinId, PinIdProvider, Port};
|
||||
|
||||
use crate::sealed::Sealed;
|
||||
use crate::PeripheralSelect;
|
||||
|
||||
pub trait PinMarker: Sealed {
|
||||
const ID: PinId;
|
||||
}
|
||||
|
||||
macro_rules! pin_id {
|
||||
($Id:ident, $Port:path, $num:literal) => {
|
||||
@ -11,14 +18,18 @@ macro_rules! pin_id {
|
||||
pub enum $Id {}
|
||||
|
||||
impl $crate::sealed::Sealed for $Id {}
|
||||
impl PinMarker for $Id {
|
||||
const ID: PinId = PinId::new($Port, $num);
|
||||
impl PinIdProvider for $Id {
|
||||
const ID: PinId = PinId::new_unchecked($Port, $num);
|
||||
}
|
||||
|
||||
impl PinMarker for Pin<$Id> {
|
||||
const ID: PinId = $Id::ID;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<I: PinMarker + crate::sealed::Sealed> crate::sealed::Sealed for Pin<I> {}
|
||||
impl<I: PinIdProvider + Sealed> Sealed for Pin<I> {}
|
||||
|
||||
pin_id!(Pa0, Port::A, 0);
|
||||
pin_id!(Pa1, Port::A, 1);
|
||||
|
@ -8,10 +8,11 @@
|
||||
use core::convert::Infallible;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use vorago_shared_periphs::PeripheralSelect;
|
||||
|
||||
use crate::clock::enable_peripheral_clock;
|
||||
use crate::pac;
|
||||
use crate::time::Hertz;
|
||||
use crate::timer::{TimId, TimPeripheralMarker, TimPin, TimRegInterface};
|
||||
use crate::timer::{TimId, TimMarker, TimPin, TimRegInterface};
|
||||
|
||||
const DUTY_MAX: u16 = u16::MAX;
|
||||
|
||||
@ -56,9 +57,8 @@ pub struct PwmPin<Mode = PwmA> {
|
||||
|
||||
impl<Mode> PwmPin<Mode> {
|
||||
/// Create a new strongly typed PWM pin
|
||||
pub fn new<Pin: TimPin, Tim: TimPeripheralMarker + TimRegInterface>(
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
sys_clk: impl Into<Hertz> + Copy,
|
||||
pub fn new<Pin: TimPin, Tim: TimMarker + TimRegInterface>(
|
||||
sys_clk: Hertz,
|
||||
pin_and_tim: (Pin, Tim),
|
||||
initial_period: impl Into<Hertz> + Copy,
|
||||
) -> Result<Self, TimMissmatchError> {
|
||||
@ -74,12 +74,13 @@ impl<Mode> PwmPin<Mode> {
|
||||
current_lower_limit: 0,
|
||||
current_period: initial_period.into(),
|
||||
current_rst_val: 0,
|
||||
sys_clk: sys_clk.into(),
|
||||
sys_clk,
|
||||
mode: PhantomData,
|
||||
};
|
||||
enable_peripheral_clock(crate::clock::PeripheralClocks::Gpio);
|
||||
enable_peripheral_clock(crate::clock::PeripheralClocks::Ioconfig);
|
||||
sys_cfg
|
||||
enable_peripheral_clock(PeripheralSelect::Gpio);
|
||||
enable_peripheral_clock(PeripheralSelect::Ioconfig);
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.tim_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | pin_and_tim.1.mask_32()) });
|
||||
pin.enable_pwm_a();
|
||||
|
@ -9,13 +9,22 @@
|
||||
//! - [Blocking SPI example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/simple/examples/spi.rs)
|
||||
//! - [REB1 ADC example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/max11519-adc.rs)
|
||||
//! - [REB1 EEPROM library](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/src/m95m01.rs)
|
||||
use crate::{clock::enable_peripheral_clock, pac, time::Hertz, PeripheralSelect};
|
||||
use crate::{
|
||||
clock::enable_peripheral_clock, pac, pins::PinMarker, sealed::Sealed, time::Hertz,
|
||||
PeripheralSelect,
|
||||
};
|
||||
use core::{convert::Infallible, fmt::Debug, marker::PhantomData, ops::Deref};
|
||||
use embedded_hal::spi::{Mode, MODE_0};
|
||||
use pins::{HwCsProvider, PinMiso, PinMosi, PinSck};
|
||||
use vorago_shared_periphs::gpio::IoPeriphPin;
|
||||
|
||||
pub mod pins;
|
||||
|
||||
pub fn configure_pin_as_hw_cs_pin<P: PinMarker + HwCsProvider>(_pin: P) -> HwChipSelectId {
|
||||
IoPeriphPin::new(P::ID, P::FUN_SEL, None);
|
||||
P::CS_ID
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Defintions
|
||||
//==================================================================================================
|
||||
@ -41,7 +50,7 @@ pub enum HwChipSelectId {
|
||||
Id7 = 7,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum SpiId {
|
||||
A,
|
||||
@ -80,7 +89,7 @@ pub type SpiRegBlock = pac::spia::RegisterBlock;
|
||||
|
||||
/// Common trait implemented by all PAC peripheral access structures. The register block
|
||||
/// format is the same for all SPI blocks.
|
||||
pub trait SpiPeripheralMarker: Deref<Target = SpiRegBlock> {
|
||||
pub trait SpiMarker: Deref<Target = SpiRegBlock> + Sealed {
|
||||
const ID: SpiId;
|
||||
const PERIPH_SEL: PeripheralSelect;
|
||||
|
||||
@ -92,7 +101,7 @@ pub trait SpiPeripheralMarker: Deref<Target = SpiRegBlock> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SpiPeripheralMarker for pac::Spia {
|
||||
impl SpiMarker for pac::Spia {
|
||||
const ID: SpiId = SpiId::A;
|
||||
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi0;
|
||||
|
||||
@ -101,8 +110,9 @@ impl SpiPeripheralMarker for pac::Spia {
|
||||
Self::ptr()
|
||||
}
|
||||
}
|
||||
impl Sealed for pac::Spia {}
|
||||
|
||||
impl SpiPeripheralMarker for pac::Spib {
|
||||
impl SpiMarker for pac::Spib {
|
||||
const ID: SpiId = SpiId::B;
|
||||
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi1;
|
||||
|
||||
@ -111,8 +121,9 @@ impl SpiPeripheralMarker for pac::Spib {
|
||||
Self::ptr()
|
||||
}
|
||||
}
|
||||
impl Sealed for pac::Spib {}
|
||||
|
||||
impl SpiPeripheralMarker for pac::Spic {
|
||||
impl SpiMarker for pac::Spic {
|
||||
const ID: SpiId = SpiId::C;
|
||||
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi2;
|
||||
|
||||
@ -121,6 +132,7 @@ impl SpiPeripheralMarker for pac::Spic {
|
||||
Self::ptr()
|
||||
}
|
||||
}
|
||||
impl Sealed for pac::Spic {}
|
||||
|
||||
//==================================================================================================
|
||||
// Config
|
||||
@ -134,17 +146,6 @@ pub trait TransferConfigProvider {
|
||||
fn hw_cs_id(&self) -> u8;
|
||||
}
|
||||
|
||||
/*
|
||||
/// This struct contains all configuration parameter which are transfer specific
|
||||
/// and might change for transfers to different SPI slaves
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct TransferConfigWithHwcs<HwCs> {
|
||||
pub hw_cs: Option<HwCs>,
|
||||
pub cfg: TransferConfig,
|
||||
}
|
||||
*/
|
||||
|
||||
/// Type erased variant of the transfer configuration. This is required to avoid generics in
|
||||
/// the SPI constructor.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -163,80 +164,26 @@ pub struct TransferConfig {
|
||||
pub hw_cs: Option<HwChipSelectId>,
|
||||
}
|
||||
|
||||
/*
|
||||
impl TransferConfigWithHwcs<NoneT> {
|
||||
pub fn new_no_hw_cs(
|
||||
impl TransferConfig {
|
||||
pub fn new_with_hw_cs(
|
||||
clk_cfg: Option<SpiClkConfig>,
|
||||
mode: Option<Mode>,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
sod: bool,
|
||||
hw_cs_id: HwChipSelectId,
|
||||
) -> Self {
|
||||
TransferConfigWithHwcs {
|
||||
hw_cs: None,
|
||||
cfg: TransferConfig {
|
||||
clk_cfg,
|
||||
mode,
|
||||
sod,
|
||||
blockmode,
|
||||
bmstall,
|
||||
hw_cs: HwChipSelectId::Invalid,
|
||||
},
|
||||
TransferConfig {
|
||||
clk_cfg,
|
||||
mode,
|
||||
sod,
|
||||
blockmode,
|
||||
bmstall,
|
||||
hw_cs: Some(hw_cs_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<HwCs: HwCsProvider> TransferConfigWithHwcs<HwCs> {
|
||||
pub fn new(
|
||||
clk_cfg: Option<SpiClkConfig>,
|
||||
mode: Option<Mode>,
|
||||
hw_cs: Option<HwCs>,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
sod: bool,
|
||||
) -> Self {
|
||||
TransferConfigWithHwcs {
|
||||
hw_cs,
|
||||
cfg: TransferConfig {
|
||||
clk_cfg,
|
||||
mode,
|
||||
sod,
|
||||
blockmode,
|
||||
bmstall,
|
||||
hw_cs: HwCs::CS_ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downgrade(self) -> TransferConfig {
|
||||
self.cfg
|
||||
}
|
||||
}
|
||||
|
||||
impl<HwCs: HwCsProvider> TransferConfigProvider for TransferConfigWithHwcs<HwCs> {
|
||||
/// Slave Output Disable
|
||||
fn sod(&mut self, sod: bool) {
|
||||
self.cfg.sod = sod;
|
||||
}
|
||||
|
||||
fn blockmode(&mut self, blockmode: bool) {
|
||||
self.cfg.blockmode = blockmode;
|
||||
}
|
||||
|
||||
fn mode(&mut self, mode: Mode) {
|
||||
self.cfg.mode = Some(mode);
|
||||
}
|
||||
|
||||
fn clk_cfg(&mut self, clk_cfg: SpiClkConfig) {
|
||||
self.cfg.clk_cfg = Some(clk_cfg);
|
||||
}
|
||||
|
||||
fn hw_cs_id(&self) -> u8 {
|
||||
HwCs::CS_ID as u8
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@ -373,25 +320,6 @@ pub trait SpiLowLevel {
|
||||
fn read_fifo_unchecked(&mut self) -> u32;
|
||||
}
|
||||
|
||||
pub struct Spi<Word = u8> {
|
||||
id: SpiId,
|
||||
reg_block: *mut SpiRegBlock,
|
||||
cfg: SpiConfig,
|
||||
sys_clk: Hertz,
|
||||
/// Fill word for read-only SPI transactions.
|
||||
pub fill_word: Word,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
word: PhantomData<Word>,
|
||||
}
|
||||
|
||||
/*
|
||||
pub struct Spi<, Pins, Word = u8> {
|
||||
inner: SpiBase<SpiInstance, Word>,
|
||||
pins: Pins,
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline(always)]
|
||||
pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) {
|
||||
match mode {
|
||||
@ -510,28 +438,69 @@ pub fn clk_div_for_target_clock(
|
||||
Some(rounded_div as u16)
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("peripheral or peripheral pin ID is not consistent")]
|
||||
pub struct SpiIdMissmatchError;
|
||||
|
||||
/// SPI peripheral driver structure.
|
||||
pub struct Spi<Word = u8> {
|
||||
id: SpiId,
|
||||
reg_block: *mut SpiRegBlock,
|
||||
cfg: SpiConfig,
|
||||
sys_clk: Hertz,
|
||||
/// Fill word for read-only SPI transactions.
|
||||
fill_word: Word,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
word: PhantomData<Word>,
|
||||
}
|
||||
|
||||
impl<Word: WordProvider> Spi<Word>
|
||||
where
|
||||
<Word as TryFrom<u32>>::Error: core::fmt::Debug,
|
||||
{
|
||||
/// Create a new SPI struct
|
||||
///
|
||||
/// You can delete the pin type information by calling the
|
||||
/// [`downgrade`](Self::downgrade) function
|
||||
/// Create a new SPI struct.
|
||||
///
|
||||
/// ## Arguments
|
||||
/// * `syscfg` - Can be passed optionally to enable the peripheral clock
|
||||
/// * `sys_clk` - System clock
|
||||
/// * `spi` - SPI bus to use
|
||||
/// * `pins` - Pins to be used for SPI transactions. These pins are consumed
|
||||
/// to ensure the pins can not be used for other purposes anymore
|
||||
/// * `spi_cfg` - Configuration specific to the SPI bus
|
||||
pub fn new<SpiI: SpiPeripheralMarker, Sck: PinSck, Miso: PinMiso, Mosi: PinMosi>(
|
||||
sys_clk: impl Into<Hertz>,
|
||||
pub fn new_for_rom<SpiI: SpiMarker>(
|
||||
sys_clk: Hertz,
|
||||
spi: SpiI,
|
||||
spi_cfg: SpiConfig,
|
||||
) -> Result<Self, SpiIdMissmatchError> {
|
||||
if SpiI::ID != SpiId::C {
|
||||
return Err(SpiIdMissmatchError);
|
||||
}
|
||||
Ok(Self::new_generic(sys_clk, spi, spi_cfg))
|
||||
}
|
||||
/// Create a new SPI struct.
|
||||
///
|
||||
/// ## Arguments
|
||||
/// * `sys_clk` - System clock
|
||||
/// * `spi` - SPI bus to use
|
||||
/// * `pins` - Pins to be used for SPI transactions. These pins are consumed
|
||||
/// to ensure the pins can not be used for other purposes anymore
|
||||
/// * `spi_cfg` - Configuration specific to the SPI bus
|
||||
pub fn new<SpiI: SpiMarker, Sck: PinSck, Miso: PinMiso, Mosi: PinMosi>(
|
||||
sys_clk: Hertz,
|
||||
spi: SpiI,
|
||||
_pins: (Sck, Miso, Mosi),
|
||||
spi_cfg: SpiConfig,
|
||||
) -> Self {
|
||||
) -> Result<Self, SpiIdMissmatchError> {
|
||||
if SpiI::ID != Sck::SPI_ID || SpiI::ID != Miso::SPI_ID || SpiI::ID != Mosi::SPI_ID {
|
||||
return Err(SpiIdMissmatchError);
|
||||
}
|
||||
IoPeriphPin::new(Sck::ID, Sck::FUN_SEL, None);
|
||||
IoPeriphPin::new(Miso::ID, Miso::FUN_SEL, None);
|
||||
IoPeriphPin::new(Mosi::ID, Mosi::FUN_SEL, None);
|
||||
Ok(Self::new_generic(sys_clk, spi, spi_cfg))
|
||||
}
|
||||
|
||||
pub fn new_generic<SpiI: SpiMarker>(sys_clk: Hertz, spi: SpiI, spi_cfg: SpiConfig) -> Self {
|
||||
enable_peripheral_clock(SpiI::PERIPH_SEL);
|
||||
let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(spi_cfg.init_mode);
|
||||
spi.ctrl0().write(|w| {
|
||||
@ -568,7 +537,7 @@ where
|
||||
id: SpiI::ID,
|
||||
reg_block: spi.reg_block(),
|
||||
cfg: spi_cfg,
|
||||
sys_clk: sys_clk.into(),
|
||||
sys_clk,
|
||||
fill_word: Default::default(),
|
||||
bmstall: spi_cfg.bmstall,
|
||||
blockmode: spi_cfg.blockmode,
|
||||
@ -596,6 +565,10 @@ where
|
||||
.write(|w| unsafe { w.bits(cfg.prescale_val as u32) });
|
||||
}
|
||||
|
||||
pub fn set_fill_word(&mut self, fill_word: Word) {
|
||||
self.fill_word = fill_word;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cfg_clock_from_div(&mut self, div: u16) -> Result<(), SpiClkConfigError> {
|
||||
let val = spi_clk_config_from_div(div)?;
|
||||
@ -633,6 +606,10 @@ where
|
||||
}
|
||||
|
||||
/// Configure the hardware chip select given a hardware chip select ID.
|
||||
///
|
||||
/// The pin also needs to be configured to be used as a HW CS pin. This can be done
|
||||
/// by using the [configure_pin_as_hw_cs_pin] function which also returns the
|
||||
/// corresponding [HwChipSelectId].
|
||||
#[inline]
|
||||
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId) {
|
||||
self.reg_block_mut().ctrl1().modify(|_, w| {
|
||||
@ -644,13 +621,6 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
/// Configure the hardware chip select given a physical hardware CS pin.
|
||||
#[inline]
|
||||
pub fn cfg_hw_cs_with_pin<HwCs: HwCsProvider>(&mut self, _: &HwCs) {
|
||||
// TODO: Error handling.
|
||||
self.cfg_hw_cs(HwCs::CS_ID);
|
||||
}
|
||||
|
||||
/// Disables the hardware chip select functionality. This can be used when performing
|
||||
/// external chip select handling, for example with GPIO pins.
|
||||
#[inline]
|
||||
|
@ -1,32 +1,33 @@
|
||||
use vorago_shared_periphs::gpio::{PinId, PinIdProvider};
|
||||
use vorago_shared_periphs::FunSel;
|
||||
|
||||
use crate::{
|
||||
pins::{
|
||||
Pa10, Pa11, Pa12, Pa13, Pa14, Pa15, Pa16, Pa17, Pa18, Pa19, Pa20, Pa21, Pa22, Pa23, Pa24,
|
||||
Pa25, Pa26, Pa27, Pa28, Pa29, Pa30, Pa31, Pb0, Pb1, Pb10, Pb11, Pb12, Pb13, Pb14, Pb15,
|
||||
Pb16, Pb17, Pb18, Pb19, Pb2, Pb22, Pb23, Pb3, Pb4, Pb5, Pb6, Pb7, Pb8, Pb9, Pin,
|
||||
Pb16, Pb17, Pb18, Pb19, Pb2, Pb22, Pb23, Pb3, Pb4, Pb5, Pb6, Pb7, Pb8, Pb9, Pin, PinMarker,
|
||||
},
|
||||
sealed::Sealed,
|
||||
};
|
||||
|
||||
use super::{HwChipSelectId, SpiId};
|
||||
|
||||
pub trait PinSck: Sealed {
|
||||
pub trait PinSck: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
|
||||
pub trait PinMosi: Sealed {
|
||||
pub trait PinMosi: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
|
||||
pub trait PinMiso: Sealed {
|
||||
pub trait PinMiso: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
|
||||
pub trait HwCsProvider: Sealed {
|
||||
pub trait HwCsProvider: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
const CS_ID: HwChipSelectId;
|
||||
@ -48,7 +49,7 @@ macro_rules! hw_cs_multi_pin {
|
||||
// name of the newtype wrapper struct
|
||||
$name:ident,
|
||||
// Pb0
|
||||
$pin_id:path,
|
||||
$pin_id:ident,
|
||||
// SpiId::B
|
||||
$spi_id:path,
|
||||
// FunSel::Sel1
|
||||
@ -71,6 +72,10 @@ macro_rules! hw_cs_multi_pin {
|
||||
|
||||
impl Sealed for $name {}
|
||||
|
||||
impl PinMarker for $name {
|
||||
const ID: PinId = <$pin_id as PinIdProvider>::ID;
|
||||
}
|
||||
|
||||
impl HwCsProvider for $name {
|
||||
const SPI_ID: SpiId = $spi_id;
|
||||
const FUN_SEL: FunSel = $fun_sel;
|
||||
@ -185,7 +190,7 @@ impl PinMosi for Pin<Pa19> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel2;
|
||||
}
|
||||
impl PinMosi for Pin<Pa18> {
|
||||
impl PinMiso for Pin<Pa18> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel2;
|
||||
}
|
||||
@ -202,7 +207,7 @@ impl PinMosi for Pin<Pb18> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
impl PinMosi for Pin<Pb17> {
|
||||
impl PinMiso for Pin<Pb17> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
@ -215,7 +220,7 @@ impl PinMosi for Pin<Pb4> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
impl PinMosi for Pin<Pb3> {
|
||||
impl PinMiso for Pin<Pb3> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
@ -330,6 +335,7 @@ hw_cs_multi_pin!(
|
||||
|
||||
// SPIC
|
||||
|
||||
/*
|
||||
// Dummy pin defintion for the ROM SCK.
|
||||
pub struct RomSck;
|
||||
// Dummy pin defintion for the ROM MOSI.
|
||||
@ -358,6 +364,7 @@ impl PinMiso for RomMiso {
|
||||
const FUN_SEL: FunSel = FunSel::Sel0;
|
||||
}
|
||||
impl Sealed for RomCs {}
|
||||
*/
|
||||
|
||||
hw_cs_pins!(
|
||||
SpiId::C,
|
||||
@ -408,9 +415,11 @@ hw_cs_multi_pin!(
|
||||
HwChipSelectId::Id4
|
||||
);
|
||||
|
||||
/*
|
||||
impl HwCsProvider for RomCs {
|
||||
const CS_ID: HwChipSelectId = HwChipSelectId::Id0;
|
||||
const SPI_ID: SpiId = SpiId::C;
|
||||
/// Function select does not make sense here, just select default value.
|
||||
const FUN_SEL: FunSel = FunSel::Sel0;
|
||||
}
|
||||
*/
|
||||
|
@ -1,5 +1,3 @@
|
||||
use crate::PeripheralSelect;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct InvalidCounterResetVal(pub(crate) ());
|
||||
@ -40,26 +38,6 @@ pub fn disable_ram_scrubbing() {
|
||||
syscfg.ram_scrub().write(|w| unsafe { w.bits(0) });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_peripheral_reset(periph_sel: PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn deassert_peripheral_reset(periph_sel: PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
pub fn reset_peripheral_for_cycles(periph_sel: PeripheralSelect, cycles: u32) {
|
||||
assert_peripheral_reset(periph_sel);
|
||||
cortex_m::asm::delay(cycles);
|
||||
deassert_peripheral_reset(periph_sel);
|
||||
}
|
||||
|
||||
pub use vorago_shared_periphs::sysconfig::{disable_peripheral_clock, enable_peripheral_clock};
|
||||
pub use vorago_shared_periphs::sysconfig::{
|
||||
assert_peripheral_reset, disable_peripheral_clock, enable_peripheral_clock,
|
||||
};
|
||||
|
@ -16,17 +16,13 @@ use crate::{
|
||||
sealed::Sealed,
|
||||
time::Hertz,
|
||||
};
|
||||
use core::cell::Cell;
|
||||
use critical_section::Mutex;
|
||||
use fugit::RateExtU32;
|
||||
use vorago_shared_periphs::{
|
||||
gpio::{Pin, PinMarker},
|
||||
gpio::{Pin, PinIdProvider},
|
||||
ioconfig::regs::FunSel,
|
||||
Port,
|
||||
};
|
||||
|
||||
pub static MS_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
|
||||
|
||||
/// Get the peripheral block of a TIM peripheral given the index.
|
||||
///
|
||||
/// This function panics if the given index is greater than 23.
|
||||
@ -170,17 +166,23 @@ pub trait TimPin: Sealed {
|
||||
const TIM_ID: TimId;
|
||||
}
|
||||
|
||||
pub trait TimPeripheralMarker: Sealed {
|
||||
pub trait TimMarker: Sealed {
|
||||
// TIM ID ranging from 0 to 23 for 24 TIM peripherals
|
||||
const ID: TimId;
|
||||
}
|
||||
|
||||
macro_rules! tim_marker {
|
||||
($TIMX:path, $ID:expr) => {
|
||||
impl TimPeripheralMarker for $TIMX {
|
||||
impl TimMarker for $TIMX {
|
||||
const ID: TimId = TimId($ID);
|
||||
}
|
||||
|
||||
unsafe impl TimRegInterface for $TIMX {
|
||||
fn raw_id(&self) -> u8 {
|
||||
Self::ID.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Sealed for $TIMX {}
|
||||
};
|
||||
}
|
||||
@ -210,13 +212,13 @@ tim_marker!(pac::Tim21, 21);
|
||||
tim_marker!(pac::Tim22, 22);
|
||||
tim_marker!(pac::Tim23, 23);
|
||||
|
||||
pub trait ValidTimAndPin<Pin: TimPin, Tim: TimPeripheralMarker>: Sealed {}
|
||||
pub trait ValidTimAndPin<Pin: TimPin, Tim: TimMarker>: Sealed {}
|
||||
|
||||
macro_rules! pin_and_tim {
|
||||
($Px:ident, $FunSel:path, $ID:expr) => {
|
||||
impl TimPin for Pin<$Px>
|
||||
where
|
||||
$Px: PinMarker,
|
||||
$Px: PinIdProvider,
|
||||
{
|
||||
const PORT: Port = $Px::ID.port();
|
||||
const OFFSET: usize = $Px::ID.offset();
|
||||
@ -368,7 +370,7 @@ unsafe impl TimRegInterface for CountdownTimer {
|
||||
|
||||
impl CountdownTimer {
|
||||
/// Configures a TIM peripheral as a periodic count down timer
|
||||
pub fn new<Tim: TimPeripheralMarker>(sys_clk: Hertz, _tim: Tim) -> Self {
|
||||
pub fn new<Tim: TimMarker>(sys_clk: Hertz, _tim: Tim) -> Self {
|
||||
enable_tim_clk(Tim::ID.raw_id());
|
||||
let cd_timer = CountdownTimer {
|
||||
tim: Tim::ID,
|
||||
@ -593,6 +595,10 @@ impl CountdownTimer {
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Delay implementations
|
||||
//==================================================================================================
|
||||
//
|
||||
impl embedded_hal::delay::DelayNs for CountdownTimer {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
let ticks = (u64::from(ns)) * (u64::from(self.sys_clk.raw())) / 1_000_000_000;
|
||||
@ -647,59 +653,6 @@ impl embedded_hal::delay::DelayNs for CountdownTimer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_up_ms_delay_provider(sys_clk: Hertz, tim: impl TimPeripheralMarker) -> CountdownTimer {
|
||||
let mut provider = CountdownTimer::new(sys_clk, tim);
|
||||
provider.start(1000.Hz());
|
||||
provider
|
||||
}
|
||||
|
||||
/// This function can be called in a specified interrupt handler to increment
|
||||
/// the MS counter
|
||||
pub fn default_ms_irq_handler() {
|
||||
critical_section::with(|cs| {
|
||||
let mut ms = MS_COUNTER.borrow(cs).get();
|
||||
ms += 1;
|
||||
MS_COUNTER.borrow(cs).set(ms);
|
||||
});
|
||||
}
|
||||
|
||||
/// Get the current MS tick count
|
||||
pub fn get_ms_ticks() -> u32 {
|
||||
critical_section::with(|cs| MS_COUNTER.borrow(cs).get())
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Delay implementations
|
||||
//==================================================================================================
|
||||
|
||||
/*
|
||||
pub struct DelayMs(CountdownTimer<pac::Tim0>);
|
||||
|
||||
impl DelayMs {
|
||||
pub fn new(timer: CountdownTimer<pac::Tim0>) -> Option<Self> {
|
||||
if timer.curr_freq() != Hertz::from_raw(1000) || !timer.listening() {
|
||||
return None;
|
||||
}
|
||||
Some(Self(timer))
|
||||
}
|
||||
}
|
||||
|
||||
/// This assumes that the user has already set up a MS tick timer in TIM0 as a system tick
|
||||
/// with [`set_up_ms_delay_provider`]
|
||||
impl embedded_hal::delay::DelayNs for DelayMs {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
let ns_as_ms = ns / 1_000_000;
|
||||
if self.0.curr_freq() != Hertz::from_raw(1000) || !self.0.listening() {
|
||||
return;
|
||||
}
|
||||
let start_time = get_ms_ticks();
|
||||
while get_ms_ticks() - start_time < ns_as_ms {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline(always)]
|
||||
pub fn enable_tim_clk(idx: u8) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
|
@ -14,7 +14,10 @@
|
||||
//! - [Flashloader exposing a CCSDS interface via UART](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/flashloader)
|
||||
use core::{convert::Infallible, ops::Deref};
|
||||
use fugit::RateExtU32;
|
||||
use vorago_shared_periphs::{gpio::Pin, FunSel, InterruptConfig};
|
||||
use vorago_shared_periphs::{
|
||||
gpio::{IoPeriphPin, Pin},
|
||||
FunSel, InterruptConfig,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
clock::enable_peripheral_clock,
|
||||
@ -22,7 +25,7 @@ use crate::{
|
||||
pac::{self, uarta as uart_base},
|
||||
pins::{
|
||||
Pa16, Pa17, Pa18, Pa19, Pa2, Pa26, Pa27, Pa3, Pa30, Pa31, Pa8, Pa9, Pb18, Pb19, Pb20, Pb21,
|
||||
Pb22, Pb23, Pb6, Pb7, Pb8, Pb9,
|
||||
Pb22, Pb23, Pb6, Pb7, Pb8, Pb9, PinMarker,
|
||||
},
|
||||
time::Hertz,
|
||||
PeripheralSelect,
|
||||
@ -55,11 +58,11 @@ impl UartId {
|
||||
// Type-Level support
|
||||
//==================================================================================================
|
||||
|
||||
pub trait TxPin {
|
||||
pub trait TxPin: PinMarker {
|
||||
const UART_ID: UartId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
pub trait RxPin {
|
||||
pub trait RxPin: PinMarker {
|
||||
const UART_ID: UartId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
@ -557,6 +560,8 @@ impl Uart {
|
||||
if UartI::ID != TxPinI::UART_ID || UartI::ID != RxPinI::UART_ID {
|
||||
return Err(UartIdMissmatchError);
|
||||
}
|
||||
IoPeriphPin::new(TxPinI::ID, TxPinI::FUN_SEL, None);
|
||||
IoPeriphPin::new(RxPinI::ID, TxPinI::FUN_SEL, None);
|
||||
crate::clock::enable_peripheral_clock(UartI::PERIPH_SEL);
|
||||
|
||||
let reg_block = unsafe { UartI::reg_block() };
|
||||
|
@ -411,10 +411,10 @@ impl<const N: usize> embedded_io_async::Read for RxAsyncOverwriting<N> {
|
||||
critical_section::with(|cs| {
|
||||
let queue = inner.shared_consumer.borrow(cs);
|
||||
if queue.borrow().as_ref().unwrap().len() == 0 {
|
||||
RX_HAS_DATA[id as usize].store(false, Ordering::Relaxed);
|
||||
RX_HAS_DATA[id].store(false, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
let _guard = ActiveReadGuard(id as usize);
|
||||
let _guard = ActiveReadGuard(id);
|
||||
let mut handle_data_in_queue = |inner: &mut RxAsyncOverwritingInner<N>| {
|
||||
critical_section::with(|cs| {
|
||||
let mut consumer_ref = inner.shared_consumer.borrow(cs).borrow_mut();
|
||||
|
Reference in New Issue
Block a user