HAL update
This commit is contained in:
parent
fc894bc421
commit
ae8467a6dd
@ -137,15 +137,12 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TestCase::DelayGpio => {
|
TestCase::DelayGpio => {
|
||||||
let mut out_0 = pinsa
|
let mut out_0 = pinsa.pa0.into_readable_push_pull_output();
|
||||||
.pa0
|
out_0.configure_delay(true, false);
|
||||||
.into_readable_push_pull_output()
|
let mut out_1 = pinsa.pa1.into_readable_push_pull_output();
|
||||||
.configure_delay(true, false);
|
out_1.configure_delay(false, true);
|
||||||
let mut out_1 = pinsa
|
let mut out_2 = pinsa.pa3.into_readable_push_pull_output();
|
||||||
.pa1
|
out_2.configure_delay(true, true);
|
||||||
.into_readable_push_pull_output()
|
|
||||||
.configure_delay(false, true);
|
|
||||||
let mut out_2 = pinsa.pa3.into_readable_push_pull_output().configure_delay(true, true);
|
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
out_0.toggle().unwrap();
|
out_0.toggle().unwrap();
|
||||||
out_1.toggle().unwrap();
|
out_1.toggle().unwrap();
|
||||||
|
@ -8,6 +8,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
|
|
||||||
|
## [v0.10.0]
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- A lot of missing `defmt::Format` implementations.
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Missing GPIO API replacements from `x` to `configure_x`
|
||||||
|
|
||||||
## [v0.9.0]
|
## [v0.9.0]
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
@ -42,7 +42,7 @@ portable-atomic = "1"
|
|||||||
[features]
|
[features]
|
||||||
default = ["rt"]
|
default = ["rt"]
|
||||||
rt = ["va108xx/rt"]
|
rt = ["va108xx/rt"]
|
||||||
defmt = ["dep:defmt", "fugit/defmt"]
|
defmt = ["dep:defmt", "fugit/defmt", "embedded-hal/defmt-03"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
@ -486,11 +486,6 @@ impl<I: PinId, M: PinMode> Pin<I, M> {
|
|||||||
self.inner.regs.write_pin(false)
|
self.inner.regs.write_pin(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn _toggle_with_toggle_reg(&mut self) {
|
|
||||||
self.inner.regs.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn _is_low(&self) -> bool {
|
pub(crate) fn _is_low(&self) -> bool {
|
||||||
!self.inner.regs.read_pin()
|
!self.inner.regs.read_pin()
|
||||||
@ -626,13 +621,13 @@ impl<I: PinId, C: OutputConfig> Pin<I, Output<C>> {
|
|||||||
/// - Delay 2: 2
|
/// - Delay 2: 2
|
||||||
/// - Delay 1 + Delay 2: 3
|
/// - Delay 1 + Delay 2: 3
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||||
self.inner.regs.configure_delay(delay_1, delay_2);
|
self.inner.regs.configure_delay(delay_1, delay_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn toggle_with_toggle_reg(&mut self) {
|
pub fn toggle_with_toggle_reg(&mut self) {
|
||||||
self._toggle_with_toggle_reg()
|
self.inner.regs.toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
|
@ -36,8 +36,6 @@ pub struct InvalidTimingParamsError;
|
|||||||
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
|
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
//#[error("Invalid timing parameters")]
|
|
||||||
//InvalidTimingParams,
|
|
||||||
#[error("arbitration lost")]
|
#[error("arbitration lost")]
|
||||||
ArbitrationLost,
|
ArbitrationLost,
|
||||||
#[error("nack address")]
|
#[error("nack address")]
|
||||||
@ -82,6 +80,7 @@ impl embedded_hal::i2c::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
enum I2cCmd {
|
enum I2cCmd {
|
||||||
Start = 0b00,
|
Start = 0b00,
|
||||||
Stop = 0b10,
|
Stop = 0b10,
|
||||||
@ -252,6 +251,8 @@ impl Default for MasterConfig {
|
|||||||
|
|
||||||
impl Sealed for MasterConfig {}
|
impl Sealed for MasterConfig {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SlaveConfig {
|
pub struct SlaveConfig {
|
||||||
pub tx_fe_mode: FifoEmptyMode,
|
pub tx_fe_mode: FifoEmptyMode,
|
||||||
pub rx_fe_mode: FifoEmptyMode,
|
pub rx_fe_mode: FifoEmptyMode,
|
||||||
@ -455,13 +456,6 @@ impl<I2c: Instance> I2cBase<I2c> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unique mode to use the loopback functionality
|
|
||||||
// pub struct I2cLoopback<I2C> {
|
|
||||||
// i2c_base: I2cBase<I2C>,
|
|
||||||
// master_cfg: MasterConfig,
|
|
||||||
// slave_cfg: SlaveConfig,
|
|
||||||
// }
|
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// I2C Master
|
// I2C Master
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -673,275 +667,6 @@ impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
macro_rules! i2c_master {
|
|
||||||
($($I2CX:path: ($i2cx:ident, $clk_enb:path),)+) => {
|
|
||||||
$(
|
|
||||||
impl<ADDR> I2cMaster<$I2CX, ADDR> {
|
|
||||||
pub fn $i2cx(
|
|
||||||
i2c: $I2CX,
|
|
||||||
cfg: MasterConfig,
|
|
||||||
sys_clk: impl Into<Hertz> + Copy,
|
|
||||||
speed_mode: I2cSpeed,
|
|
||||||
sys_cfg: Option<&mut pac::Sysconfig>,
|
|
||||||
) -> Self {
|
|
||||||
I2cMaster {
|
|
||||||
i2c_base: I2cBase::$i2cx(
|
|
||||||
i2c,
|
|
||||||
sys_clk,
|
|
||||||
speed_mode,
|
|
||||||
Some(&cfg),
|
|
||||||
None,
|
|
||||||
sys_cfg
|
|
||||||
),
|
|
||||||
_addr: PhantomData,
|
|
||||||
}
|
|
||||||
.enable_master()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cancel_transfer(&self) {
|
|
||||||
self.i2c_base
|
|
||||||
.i2c
|
|
||||||
.cmd()
|
|
||||||
.write(|w| unsafe { w.bits(I2cCmd::Cancel as u32) });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn clear_tx_fifo(&self) {
|
|
||||||
self.i2c_base.i2c.fifo_clr().write(|w| w.txfifo().set_bit());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn clear_rx_fifo(&self) {
|
|
||||||
self.i2c_base.i2c.fifo_clr().write(|w| w.rxfifo().set_bit());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn enable_master(self) -> Self {
|
|
||||||
self.i2c_base.i2c.ctrl().modify(|_, w| w.enable().set_bit());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn disable_master(self) -> Self {
|
|
||||||
self.i2c_base.i2c.ctrl().modify(|_, w| w.enable().clear_bit());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn load_fifo(&self, word: u8) {
|
|
||||||
self.i2c_base
|
|
||||||
.i2c
|
|
||||||
.data()
|
|
||||||
.write(|w| unsafe { w.bits(word as u32) });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn read_fifo(&self) -> u8 {
|
|
||||||
self.i2c_base.i2c.data().read().bits() as u8
|
|
||||||
}
|
|
||||||
|
|
||||||
fn error_handler_write(&mut self, init_cmd: &I2cCmd) {
|
|
||||||
self.clear_tx_fifo();
|
|
||||||
if *init_cmd == I2cCmd::Start {
|
|
||||||
self.i2c_base.stop_cmd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_base(
|
|
||||||
&mut self,
|
|
||||||
addr: I2cAddress,
|
|
||||||
init_cmd: I2cCmd,
|
|
||||||
bytes: impl IntoIterator<Item = u8>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut iter = bytes.into_iter();
|
|
||||||
// Load address
|
|
||||||
let (addr, addr_mode_bit) = I2cBase::<$I2CX>::unwrap_addr(addr);
|
|
||||||
self.i2c_base.i2c.address().write(|w| unsafe {
|
|
||||||
w.bits(I2cDirection::Send as u32 | (addr << 1) as u32 | addr_mode_bit)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.i2c_base
|
|
||||||
.i2c
|
|
||||||
.cmd()
|
|
||||||
.write(|w| unsafe { w.bits(init_cmd as u32) });
|
|
||||||
let mut load_if_next_available = || {
|
|
||||||
if let Some(next_byte) = iter.next() {
|
|
||||||
self.load_fifo(next_byte);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loop {
|
|
||||||
let status_reader = self.i2c_base.i2c.status().read();
|
|
||||||
if status_reader.arblost().bit_is_set() {
|
|
||||||
self.error_handler_write(&init_cmd);
|
|
||||||
return Err(Error::ArbitrationLost);
|
|
||||||
} else if status_reader.nackaddr().bit_is_set() {
|
|
||||||
self.error_handler_write(&init_cmd);
|
|
||||||
return Err(Error::NackAddr);
|
|
||||||
} else if status_reader.nackdata().bit_is_set() {
|
|
||||||
self.error_handler_write(&init_cmd);
|
|
||||||
return Err(Error::NackData);
|
|
||||||
} else if status_reader.idle().bit_is_set() {
|
|
||||||
return Ok(());
|
|
||||||
} else {
|
|
||||||
while !status_reader.txnfull().bit_is_set() {
|
|
||||||
load_if_next_available();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_from_buffer(
|
|
||||||
&mut self,
|
|
||||||
init_cmd: I2cCmd,
|
|
||||||
addr: I2cAddress,
|
|
||||||
output: &[u8],
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let len = output.len();
|
|
||||||
// It should theoretically possible to transfer larger data sizes by tracking
|
|
||||||
// the number of sent words and setting it to 0x7fe as soon as only that many
|
|
||||||
// bytes are remaining. However, large transfer like this are not common. This
|
|
||||||
// feature will therefore not be supported for now.
|
|
||||||
if len > 0x7fe {
|
|
||||||
return Err(Error::DataTooLarge);
|
|
||||||
}
|
|
||||||
// Load number of words
|
|
||||||
self.i2c_base
|
|
||||||
.i2c
|
|
||||||
.words()
|
|
||||||
.write(|w| unsafe { w.bits(len as u32) });
|
|
||||||
let mut bytes = output.iter();
|
|
||||||
// FIFO has a depth of 16. We load slightly above the trigger level
|
|
||||||
// but not all of it because the transaction might fail immediately
|
|
||||||
const FILL_DEPTH: usize = 12;
|
|
||||||
|
|
||||||
// load the FIFO
|
|
||||||
for _ in 0..core::cmp::min(FILL_DEPTH, len) {
|
|
||||||
self.load_fifo(*bytes.next().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.write_base(addr, init_cmd, output.iter().cloned())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_internal(&mut self, addr: I2cAddress, buffer: &mut [u8]) -> Result<(), Error> {
|
|
||||||
let len = buffer.len();
|
|
||||||
// It should theoretically possible to transfer larger data sizes by tracking
|
|
||||||
// the number of sent words and setting it to 0x7fe as soon as only that many
|
|
||||||
// bytes are remaining. However, large transfer like this are not common. This
|
|
||||||
// feature will therefore not be supported for now.
|
|
||||||
if len > 0x7fe {
|
|
||||||
return Err(Error::DataTooLarge);
|
|
||||||
}
|
|
||||||
// Clear the receive FIFO
|
|
||||||
self.clear_rx_fifo();
|
|
||||||
|
|
||||||
// Load number of words
|
|
||||||
self.i2c_base
|
|
||||||
.i2c
|
|
||||||
.words()
|
|
||||||
.write(|w| unsafe { w.bits(len as u32) });
|
|
||||||
let (addr, addr_mode_bit) = match addr {
|
|
||||||
I2cAddress::Regular(addr) => (addr as u16, 0 << 15),
|
|
||||||
I2cAddress::TenBit(addr) => (addr, 1 << 15),
|
|
||||||
};
|
|
||||||
// Load address
|
|
||||||
self.i2c_base.i2c.address().write(|w| unsafe {
|
|
||||||
w.bits(I2cDirection::Read as u32 | (addr << 1) as u32 | addr_mode_bit)
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut buf_iter = buffer.iter_mut();
|
|
||||||
let mut read_bytes = 0;
|
|
||||||
// Start receive transfer
|
|
||||||
self.i2c_base
|
|
||||||
.i2c
|
|
||||||
.cmd()
|
|
||||||
.write(|w| unsafe { w.bits(I2cCmd::StartWithStop as u32) });
|
|
||||||
let mut read_if_next_available = || {
|
|
||||||
if let Some(next_byte) = buf_iter.next() {
|
|
||||||
*next_byte = self.read_fifo();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loop {
|
|
||||||
let status_reader = self.i2c_base.i2c.status().read();
|
|
||||||
if status_reader.arblost().bit_is_set() {
|
|
||||||
self.clear_rx_fifo();
|
|
||||||
return Err(Error::ArbitrationLost);
|
|
||||||
} else if status_reader.nackaddr().bit_is_set() {
|
|
||||||
self.clear_rx_fifo();
|
|
||||||
return Err(Error::NackAddr);
|
|
||||||
} else if status_reader.idle().bit_is_set() {
|
|
||||||
if read_bytes != len {
|
|
||||||
return Err(Error::InsufficientDataReceived);
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
} else if status_reader.rxnempty().bit_is_set() {
|
|
||||||
read_if_next_available();
|
|
||||||
read_bytes += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//======================================================================================
|
|
||||||
// Embedded HAL I2C implementations
|
|
||||||
//======================================================================================
|
|
||||||
|
|
||||||
impl embedded_hal::i2c::ErrorType for I2cMaster<$I2CX, SevenBitAddress> {
|
|
||||||
type Error = Error;
|
|
||||||
}
|
|
||||||
impl embedded_hal::i2c::I2c for I2cMaster<$I2CX, SevenBitAddress> {
|
|
||||||
fn transaction(
|
|
||||||
&mut self,
|
|
||||||
address: SevenBitAddress,
|
|
||||||
operations: &mut [Operation<'_>],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
for operation in operations {
|
|
||||||
match operation {
|
|
||||||
Operation::Read(buf) => self.read_internal(I2cAddress::Regular(address), buf)?,
|
|
||||||
Operation::Write(buf) => self.write_from_buffer(
|
|
||||||
I2cCmd::StartWithStop,
|
|
||||||
I2cAddress::Regular(address),
|
|
||||||
buf,
|
|
||||||
)?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl embedded_hal::i2c::ErrorType for I2cMaster<$I2CX, TenBitAddress> {
|
|
||||||
type Error = Error;
|
|
||||||
}
|
|
||||||
impl embedded_hal::i2c::I2c<TenBitAddress> for I2cMaster<$I2CX, TenBitAddress> {
|
|
||||||
fn transaction(
|
|
||||||
&mut self,
|
|
||||||
address: TenBitAddress,
|
|
||||||
operations: &mut [Operation<'_>],
|
|
||||||
) -> Result<(), Self::Error> {
|
|
||||||
for operation in operations {
|
|
||||||
match operation {
|
|
||||||
Operation::Read(buf) => self.read_internal(I2cAddress::TenBit(address), buf)?,
|
|
||||||
Operation::Write(buf) => self.write_from_buffer(
|
|
||||||
I2cCmd::StartWithStop,
|
|
||||||
I2cAddress::TenBit(address),
|
|
||||||
buf,
|
|
||||||
)?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_master!(
|
|
||||||
pac::I2ca: (i2ca, PeripheralClocks::I2c0),
|
|
||||||
pac::I2cb: (i2cb, PeripheralClocks::I2c1),
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
//======================================================================================
|
//======================================================================================
|
||||||
// Embedded HAL I2C implementations
|
// Embedded HAL I2C implementations
|
||||||
//======================================================================================
|
//======================================================================================
|
||||||
|
@ -31,7 +31,7 @@ pub enum PortSel {
|
|||||||
PortB,
|
PortB,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum PeripheralSelect {
|
pub enum PeripheralSelect {
|
||||||
PortA = 0,
|
PortA = 0,
|
||||||
@ -54,6 +54,7 @@ pub enum PeripheralSelect {
|
|||||||
/// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might want to
|
/// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might want to
|
||||||
/// perform those steps themselves.
|
/// perform those steps themselves.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct InterruptConfig {
|
pub struct InterruptConfig {
|
||||||
/// Interrupt target vector. Should always be set, might be required for disabling IRQs
|
/// Interrupt target vector. Should always be set, might be required for disabling IRQs
|
||||||
pub id: pac::Interrupt,
|
pub id: pac::Interrupt,
|
||||||
|
@ -33,6 +33,7 @@ use embedded_hal::spi::{Mode, MODE_0};
|
|||||||
const FILL_DEPTH: usize = 12;
|
const FILL_DEPTH: usize = 12;
|
||||||
|
|
||||||
pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31;
|
pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31;
|
||||||
|
pub const BMSKIPDATA_MASK: u32 = 1 << 30;
|
||||||
|
|
||||||
pub const DEFAULT_CLK_DIV: u16 = 2;
|
pub const DEFAULT_CLK_DIV: u16 = 2;
|
||||||
|
|
||||||
@ -288,6 +289,7 @@ pub trait TransferConfigProvider {
|
|||||||
/// This struct contains all configuration parameter which are transfer specific
|
/// This struct contains all configuration parameter which are transfer specific
|
||||||
/// and might change for transfers to different SPI slaves
|
/// and might change for transfers to different SPI slaves
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TransferConfigWithHwcs<HwCs> {
|
pub struct TransferConfigWithHwcs<HwCs> {
|
||||||
pub hw_cs: Option<HwCs>,
|
pub hw_cs: Option<HwCs>,
|
||||||
pub cfg: TransferConfig,
|
pub cfg: TransferConfig,
|
||||||
@ -296,6 +298,7 @@ pub struct TransferConfigWithHwcs<HwCs> {
|
|||||||
/// Type erased variant of the transfer configuration. This is required to avoid generics in
|
/// Type erased variant of the transfer configuration. This is required to avoid generics in
|
||||||
/// the SPI constructor.
|
/// the SPI constructor.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct TransferConfig {
|
pub struct TransferConfig {
|
||||||
pub clk_cfg: Option<SpiClkConfig>,
|
pub clk_cfg: Option<SpiClkConfig>,
|
||||||
pub mode: Option<Mode>,
|
pub mode: Option<Mode>,
|
||||||
@ -383,6 +386,8 @@ impl<HwCs: HwCsProvider> TransferConfigProvider for TransferConfigWithHwcs<HwCs>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details
|
/// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SpiConfig {
|
pub struct SpiConfig {
|
||||||
clk: SpiClkConfig,
|
clk: SpiClkConfig,
|
||||||
// SPI mode configuration
|
// SPI mode configuration
|
||||||
@ -532,6 +537,7 @@ pub struct Spi<SpiInstance, Pins, Word = u8> {
|
|||||||
pins: Pins,
|
pins: Pins,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) {
|
pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) {
|
||||||
match mode {
|
match mode {
|
||||||
embedded_hal::spi::MODE_0 => (false, false),
|
embedded_hal::spi::MODE_0 => (false, false),
|
||||||
@ -575,6 +581,7 @@ impl SpiClkConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum SpiClkConfigError {
|
pub enum SpiClkConfigError {
|
||||||
#[error("division by zero")]
|
#[error("division by zero")]
|
||||||
DivIsZero,
|
DivIsZero,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user