Skip to content

Commit

Permalink
Implement is_reg_synced on sercom registers
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaizen Wolf committed Dec 27, 2021
1 parent c86f731 commit b76a5a5
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 126 deletions.
8 changes: 8 additions & 0 deletions hal/src/sercom/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ pub mod uart;
#[cfg(feature = "dma")]
pub mod dma;

/// Register synchronization flags
pub enum reg_sync {
CtrlB,
Length,
Enable,
SwRst,
}

//==============================================================================
// Sercom
//==============================================================================
Expand Down
51 changes: 22 additions & 29 deletions hal/src/sercom/v2/spi/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::pac::sercom0::spi::ctrla::MODE_A;
#[cfg(feature = "min-samd51g")]
use crate::pac::sercom0::spim::ctrla::MODE_A;

use crate::sercom::v2::Sercom;
use crate::sercom::v2::{reg_sync, Sercom};
use crate::time::Hertz;

use super::{BitOrder, DataWidth, Error, Flags, Phase, Polarity, Status};
Expand Down Expand Up @@ -52,10 +52,7 @@ impl<S: Sercom> Registers<S> {
#[inline]
pub fn reset(&mut self) {
self.spi().ctrla.write(|w| w.swrst().set_bit());
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().swrst().bit_is_set() {}
while !self.is_register_synced(reg_sync::SwRst) {}
}

#[cfg(feature = "dma")]
Expand All @@ -74,6 +71,20 @@ impl<S: Sercom> Registers<S> {
});
}

/// Wait for the registers synchronization
#[inline]
fn is_register_synced(&mut self, synced_reg: reg_sync) -> bool {
#[cfg(feature = "samd20")]
return !self.spi().status.read().syncbusy().bit_is_set();
#[cfg(not(feature = "samd20"))]
match synced_reg {
reg_sync::CtrlB => !self.spi().syncbusy.read().ctrlb().bit_is_set(),
reg_sync::Length => !self.spi().syncbusy.read().length().bit_is_set(),
reg_sync::Enable => !self.spi().syncbusy.read().enable().bit_is_set(),
reg_sync::SwRst => !self.spi().syncbusy.read().swrst().bit_is_set(),
}
}

/// Configure the SPI operating mode
///
/// For maximum flexibility, this module chooses to always operate in 32-bit
Expand All @@ -90,10 +101,7 @@ impl<S: Sercom> Registers<S> {
w.data32b().data_trans_32bit();
w.icspace().bits(1)
});
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().ctrlb().bit_is_set() {}
while !self.is_register_synced(reg_sync::CtrlB) {}
}

/// Return the current transaction length
Expand All @@ -112,10 +120,7 @@ impl<S: Sercom> Registers<S> {
w.len().bits(length);
w.lenen().set_bit()
});
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().length().bit_is_set() {}
while !self.is_register_synced(reg_sync::Length) {}
}

/// Set the character size
Expand Down Expand Up @@ -284,40 +289,28 @@ impl<S: Sercom> Registers<S> {
#[inline]
pub fn rx_enable(&mut self) {
self.spi().ctrlb.modify(|_, w| w.rxen().set_bit());
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().ctrlb().bit_is_set() {}
while !self.is_register_synced(reg_sync::CtrlB) {}
}

/// Disable the receiver
#[inline]
pub fn rx_disable(&mut self) {
self.spi().ctrlb.modify(|_, w| w.rxen().clear_bit());
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().ctrlb().bit_is_set() {}
while !self.is_register_synced(reg_sync::CtrlB) {}
}

/// Enable the peripheral
#[inline]
pub fn enable(&mut self) {
self.spi().ctrla.modify(|_, w| w.enable().set_bit());
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().enable().bit_is_set() {}
while !self.is_register_synced(reg_sync::Enable) {}
}

/// Disable the peripheral
#[inline]
pub fn disable(&mut self) {
self.spi().ctrla.modify(|_, w| w.enable().clear_bit());
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().enable().bit_is_set() {}
while !self.is_register_synced(reg_sync::Enable) {}
}

/// Read from the `DATA` register
Expand Down
90 changes: 41 additions & 49 deletions hal/src/sercom/v2/uart/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,26 @@ impl<S: Sercom> Registers<S> {
self.sercom
}

/// Wait for the registers synchronization
#[inline]
pub fn is_register_synced(&mut self, synced_reg: reg_sync) -> bool {
#[cfg(feature = "samd20")]
return !self.usart().status.read().syncbusy().bit_is_set();
#[cfg(not(feature = "samd20"))]
match synced_reg {
reg_sync::CtrlB => !self.usart().syncbusy.read().ctrlb().bit_is_set(),
reg_sync::Length => !self.usart().syncbusy.read().length().bit_is_set(),
reg_sync::Enable => !self.usart().syncbusy.read().enable().bit_is_set(),
reg_sync::SwRst => !self.usart().syncbusy.read().swrst().bit_is_set(),
}
}

/// Reset the SERCOM peripheral
#[inline]
pub(super) fn swrst(&mut self) {
self.usart().ctrla.write(|w| w.swrst().set_bit());

#[cfg(feature = "samd20")]
while self.usart().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.usart().syncbusy.read().swrst().bit_is_set() {}
while !self.is_register_synced(reg_sync::SwRst) {}
}

/// Configure the SERCOM to use internal clock mode
Expand Down Expand Up @@ -291,24 +302,24 @@ impl<S: Sercom> Registers<S> {
use Oversampling::*;

#[cfg(feature = "samd20")]
let baud = self.usart().baud.read().bits();
#[cfg(feature = "samd20")]
let mode = Arithmetic(Bits16);

#[cfg(not(feature = "samd20"))]
let baud = self.usart().baud_usartfp_mode().read().bits();
#[cfg(not(feature = "samd20"))]
let sampr = self.usart().ctrla.read().sampr().bits();
{
let baud = self.usart().baud.read().bits();
let mode = Arithmetic(Bits16);
return (baud, mode);
}
#[cfg(not(feature = "samd20"))]
let mode = match sampr {
0 => Arithmetic(Bits16),
1 => Fractional(Bits16),
2 => Arithmetic(Bits8),
3 => Fractional(Bits8),
_ => unreachable!(),
};

(baud, mode)
{
let baud = self.usart().baud_usartfp_mode().read().bits();
let sampr = self.usart().ctrla.read().sampr().bits();
let mode = match sampr {
0 => Arithmetic(Bits16),
1 => Fractional(Bits16),
2 => Arithmetic(Bits8),
3 => Fractional(Bits8),
_ => unreachable!(),
};
(baud, mode)
}
}

/// Control the buffer overflow notification
Expand Down Expand Up @@ -433,24 +444,16 @@ impl<S: Sercom> Registers<S> {
/// UART transactions are not possible until the peripheral is enabled.
#[inline]
pub(super) fn enable(&mut self, rxen: bool, txen: bool) {
let usart = self.usart();

// Enable RX
if rxen {
usart.ctrlb.modify(|_, w| w.rxen().set_bit());
#[cfg(feature = "samd20")]
while usart.status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while usart.syncbusy.read().ctrlb().bit_is_set() {}
self.usart().ctrlb.modify(|_, w| w.rxen().set_bit());
while !self.is_register_synced(reg_sync::CtrlB) {}
}

// Enable TX
if txen {
usart.ctrlb.modify(|_, w| w.txen().set_bit());
#[cfg(feature = "samd20")]
while usart.status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while usart.syncbusy.read().ctrlb().bit_is_set() {}
self.usart().ctrlb.modify(|_, w| w.txen().set_bit());
while !self.is_register_synced(reg_sync::CtrlB) {}
}

// Globally enable peripheral
Expand All @@ -459,21 +462,13 @@ impl<S: Sercom> Registers<S> {

#[inline]
pub(super) fn disable(&mut self) {
let usart = self.usart();

// Disable RX
usart.ctrlb.modify(|_, w| w.rxen().clear_bit());
#[cfg(feature = "samd20")]
while usart.status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while usart.syncbusy.read().ctrlb().bit_is_set() {}
self.usart().ctrlb.modify(|_, w| w.rxen().clear_bit());
while !self.is_register_synced(reg_sync::CtrlB) {}

// Disable TX
usart.ctrlb.modify(|_, w| w.txen().clear_bit());
#[cfg(feature = "samd20")]
while usart.status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while usart.syncbusy.read().ctrlb().bit_is_set() {}
self.usart().ctrlb.modify(|_, w| w.txen().clear_bit());
while !self.is_register_synced(reg_sync::CtrlB) {}

self.enable_peripheral(false);
}
Expand All @@ -482,10 +477,7 @@ impl<S: Sercom> Registers<S> {
/// synchronize.
pub(super) fn enable_peripheral(&mut self, enable: bool) {
self.usart().ctrla.modify(|_, w| w.enable().bit(enable));
#[cfg(feature = "samd20")]
while self.usart().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.usart().syncbusy.read().enable().bit_is_set() {}
while !self.is_register_synced(reg_sync::Enable) {}
}
}

Expand Down
19 changes: 11 additions & 8 deletions hal/src/spi_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,27 @@ pub trait CommonSpi {
/// Helper for accessing the spi member of the sercom instance
fn spi_mut(&mut self) -> &SPI;

/// Wait for the registers synchronization
#[inline]
fn is_register_synced(&mut self) -> bool {
#[cfg(feature = "samd20")]
return !self.spi().status.read().syncbusy().bit_is_set();
#[cfg(not(feature = "samd20"))]
!self.spi().syncbusy.read().enable().bit_is_set()
}

/// Disable the SPI
fn disable(&mut self) {
self.spi_mut().ctrla.modify(|_, w| w.enable().clear_bit());
// wait for configuration to take effect
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().enable().bit_is_set() {}
while !self.is_register_synced() {}
}

/// Enable the SPI
fn enable(&mut self) {
self.spi_mut().ctrla.modify(|_, w| w.enable().set_bit());
// wait for configuration to take effect
#[cfg(feature = "samd20")]
while self.spi().status.read().syncbusy().bit_is_set() {}
#[cfg(not(feature = "samd20"))]
while self.spi().syncbusy.read().enable().bit_is_set() {}
while !self.is_register_synced() {}
}

/// Set the polarity (CPOL) and phase (CPHA) of the SPI
Expand Down
7 changes: 3 additions & 4 deletions hal/src/thumbv6m/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,11 @@ impl GenericClockController {
}

// Feed 32khz into the DFLL48
state.enable_clock_generator(ClockId::DFLL48, GCLK1);
state.enable_clock_generator(DFLL48, GCLK1);
// Enable the DFLL48
configure_and_enable_dfll48m(sysctrl, use_external_crystal);
// Feed DFLL48 into the main clock
state.set_gclk_divider_and_source(GCLK0, 1, ClockSource::DFLL48M, true);
state.set_gclk_divider_and_source(GCLK0, 1, DFLL48M, true);
// We are now running at 48Mhz

// Reset various dividers back to 1
Expand All @@ -202,7 +202,6 @@ impl GenericClockController {
pm.apbbsel.write(|w| w.apbbdiv().div1());
pm.apbcsel.write(|w| w.apbcdiv().div1());

let used_clocks = 1u64 << u8::from(ClockId::DFLL48);
Self {
state,
gclks: [
Expand All @@ -215,7 +214,7 @@ impl GenericClockController {
Hertz(0),
Hertz(0),
],
used_clocks,
used_clocks: 1u64 << u8::from(ClockId::DFLL48),
}
}

Expand Down
Loading

0 comments on commit b76a5a5

Please sign in to comment.