Use enumset for DMA interrupts instead of countless functions (#2196)

* [1/x] Use enumset for DMA interrupts instead of countless functions

* [2/x] Remove the countless functions from RegisterAccess

* Use Into

* [3/3] Use enums everywhere in the DMA module

* Remove redundant enum_set!

* Remove `available_` prefix

* Use `pending_` prefix

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
This commit is contained in:
Dominic Fischer 2024-09-23 09:43:56 +01:00 committed by GitHub
parent 89d9de67eb
commit 794cdb0af4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 731 additions and 803 deletions

View File

@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed an issue with DMA transfers potentially not waking up the correct async task (#2065)
- Fixed an issue with LCD_CAM i8080 where it would send double the clocks in 16bit mode (#2085)
- Fix i2c embedded-hal transaction (#2028)
- Fix some inconsistencies in DMA interrupt bits (#2169)
- Fix SPI DMA alternating `write` and `read` for ESP32 and ESP32-S2 (#2131)
- Fix I2C ending up in a state when only re-creating the peripheral makes it useable again (#2141)
- Fix `SpiBus::transfer` transferring data twice in some cases (#2159)

View File

@ -139,10 +139,6 @@ impl<const N: u8> RegisterAccess for Channel<N> {
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn has_out_descriptor_error() -> bool {
Self::out_int().raw().read().out_dscr_err().bit()
}
fn set_out_peripheral(peripheral: u8) {
Self::ch()
.out_peri_sel()
@ -155,34 +151,6 @@ impl<const N: u8> RegisterAccess for Channel<N> {
.modify(|_, w| w.outlink_start().set_bit());
}
fn clear_ch_out_done() {
Self::out_int()
.clr()
.write(|w| w.out_done().clear_bit_by_one());
}
fn is_ch_out_done_set() -> bool {
Self::out_int().raw().read().out_done().bit()
}
fn listen_ch_out_done() {
Self::out_int().ena().modify(|_, w| w.out_done().set_bit())
}
fn unlisten_ch_out_done() {
Self::out_int()
.ena()
.modify(|_, w| w.out_done().clear_bit())
}
fn is_listening_ch_out_done() -> bool {
Self::out_int().ena().read().out_done().bit()
}
fn is_out_done() -> bool {
Self::out_int().raw().read().out_total_eof().bit()
}
fn last_out_dscr_address() -> usize {
Self::ch()
.out_eof_des_addr()
@ -191,16 +159,6 @@ impl<const N: u8> RegisterAccess for Channel<N> {
.bits() as _
}
fn is_out_eof_interrupt_set() -> bool {
Self::out_int().raw().read().out_eof().bit()
}
fn reset_out_eof_interrupt() {
Self::out_int()
.clr()
.write(|w| w.out_eof().clear_bit_by_one());
}
#[cfg(esp32s3)]
fn set_in_ext_mem_block_size(size: DmaExtMemBKSize) {
Self::ch()
@ -259,18 +217,6 @@ impl<const N: u8> RegisterAccess for Channel<N> {
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn has_in_descriptor_error() -> bool {
Self::in_int().raw().read().in_dscr_err().bit()
}
fn has_in_descriptor_error_dscr_empty() -> bool {
Self::in_int().raw().read().in_dscr_empty().bit()
}
fn has_in_descriptor_error_err_eof() -> bool {
Self::in_int().raw().read().in_err_eof().bit()
}
fn set_in_peripheral(peripheral: u8) {
Self::ch()
.in_peri_sel()
@ -283,122 +229,177 @@ impl<const N: u8> RegisterAccess for Channel<N> {
.modify(|_, w| w.inlink_start().set_bit());
}
fn is_in_done() -> bool {
Self::in_int().raw().read().in_suc_eof().bit()
fn listen_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::out_int().ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().set_bit(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().set_bit(),
DmaTxInterrupt::Eof => w.out_eof().set_bit(),
DmaTxInterrupt::Done => w.out_done().set_bit(),
};
}
w
})
}
fn is_listening_in_eof() -> bool {
Self::in_int().ena().read().in_suc_eof().bit_is_set()
fn unlisten_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::out_int().ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit(),
DmaTxInterrupt::Done => w.out_done().clear_bit(),
};
}
w
})
}
fn is_listening_out_eof() -> bool {
Self::out_int().ena().read().out_total_eof().bit_is_set()
fn is_listening_out() -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let int_ena = Self::out_int().ena().read();
if int_ena.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof;
}
if int_ena.out_dscr_err().bit_is_set() {
result |= DmaTxInterrupt::DescriptorError;
}
if int_ena.out_eof().bit_is_set() {
result |= DmaTxInterrupt::Eof;
}
if int_ena.out_done().bit_is_set() {
result |= DmaTxInterrupt::Done;
}
result
}
fn listen_in_eof() {
Self::in_int().ena().modify(|_, w| w.in_suc_eof().set_bit());
fn pending_out_interrupts() -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let int_raw = Self::out_int().raw().read();
if int_raw.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof;
}
if int_raw.out_dscr_err().bit_is_set() {
result |= DmaTxInterrupt::DescriptorError;
}
if int_raw.out_eof().bit_is_set() {
result |= DmaTxInterrupt::Eof;
}
if int_raw.out_done().bit_is_set() {
result |= DmaTxInterrupt::Done;
}
result
}
fn listen_out_eof() {
Self::out_int()
.ena()
.modify(|_, w| w.out_total_eof().set_bit());
fn clear_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::out_int().clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
};
}
w
})
}
fn unlisten_in_eof() {
Self::in_int()
.ena()
.modify(|_, w| w.in_suc_eof().clear_bit());
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
Self::in_int().ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().set_bit(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().set_bit(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().set_bit(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().set_bit(),
DmaRxInterrupt::Done => w.in_done().set_bit(),
};
}
w
})
}
fn unlisten_out_eof() {
Self::out_int()
.ena()
.modify(|_, w| w.out_total_eof().clear_bit());
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
Self::in_int().ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit(),
DmaRxInterrupt::Done => w.in_done().clear_bit(),
};
}
w
})
}
fn listen_ch_in_done() {
Self::in_int().ena().modify(|_, w| w.in_done().set_bit())
fn is_listening_in() -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let int_ena = Self::in_int().ena().read();
if int_ena.in_dscr_err().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError;
}
if int_ena.in_dscr_empty().bit_is_set() {
result |= DmaRxInterrupt::DescriptorEmpty;
}
if int_ena.in_suc_eof().bit_is_set() {
result |= DmaRxInterrupt::SuccessfulEof;
}
if int_ena.in_err_eof().bit_is_set() {
result |= DmaRxInterrupt::ErrorEof;
}
if int_ena.in_done().bit_is_set() {
result |= DmaRxInterrupt::Done;
}
result
}
fn clear_ch_in_done() {
Self::in_int()
.clr()
.write(|w| w.in_done().clear_bit_by_one());
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let int_raw = Self::in_int().raw().read();
if int_raw.in_dscr_err().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError;
}
if int_raw.in_dscr_empty().bit_is_set() {
result |= DmaRxInterrupt::DescriptorEmpty;
}
if int_raw.in_suc_eof().bit_is_set() {
result |= DmaRxInterrupt::SuccessfulEof;
}
if int_raw.in_err_eof().bit_is_set() {
result |= DmaRxInterrupt::ErrorEof;
}
if int_raw.in_done().bit_is_set() {
result |= DmaRxInterrupt::Done;
}
result
}
fn is_ch_in_done_set() -> bool {
Self::in_int().raw().read().in_done().bit()
}
fn unlisten_ch_in_done() {
Self::in_int().ena().modify(|_, w| w.in_done().clear_bit());
}
fn is_listening_ch_in_done() -> bool {
Self::in_int().ena().read().in_done().bit()
}
fn listen_in_descriptor_error() {
Self::in_int()
.ena()
.modify(|_, w| w.in_dscr_err().set_bit())
}
fn unlisten_in_descriptor_error() {
Self::in_int()
.ena()
.modify(|_, w| w.in_dscr_err().clear_bit())
}
fn is_listening_in_descriptor_error() -> bool {
Self::in_int().ena().read().in_dscr_err().bit()
}
fn listen_in_descriptor_error_dscr_empty() {
Self::in_int()
.ena()
.modify(|_, w| w.in_dscr_empty().set_bit())
}
fn unlisten_in_descriptor_error_dscr_empty() {
Self::in_int()
.ena()
.modify(|_, w| w.in_dscr_empty().clear_bit())
}
fn is_listening_in_descriptor_error_dscr_empty() -> bool {
Self::in_int().ena().read().in_dscr_empty().bit()
}
fn listen_in_descriptor_error_err_eof() {
Self::in_int().ena().modify(|_, w| w.in_err_eof().set_bit())
}
fn unlisten_in_descriptor_error_err_eof() {
Self::in_int()
.ena()
.modify(|_, w| w.in_err_eof().clear_bit())
}
fn is_listening_in_descriptor_error_err_eof() -> bool {
Self::in_int().ena().read().in_err_eof().bit()
}
fn listen_out_descriptor_error() {
Self::out_int()
.ena()
.modify(|_, w| w.out_dscr_err().set_bit())
}
fn unlisten_out_descriptor_error() {
Self::out_int()
.ena()
.modify(|_, w| w.out_dscr_err().clear_bit())
}
fn is_listening_out_descriptor_error() -> bool {
Self::out_int().ena().read().out_dscr_err().bit()
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
Self::in_int().clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
};
}
w
})
}
}

View File

@ -302,6 +302,53 @@ pub enum DmaInterrupt {
TxDone,
}
/// Types of interrupts emitted by the TX channel.
#[derive(EnumSetType)]
pub enum DmaTxInterrupt {
/// Triggered when all data corresponding to a linked list (including
/// multiple descriptors) have been sent via transmit channel.
TotalEof,
/// Triggered when an error is detected in a transmit descriptor on transmit
/// channel.
DescriptorError,
/// Triggered when EOF in a transmit descriptor is true and data
/// corresponding to this descriptor have been sent via transmit
/// channel.
Eof,
/// Triggered when all data corresponding to a transmit descriptor have been
/// sent via transmit channel.
Done,
}
/// Types of interrupts emitted by the RX channel.
#[derive(EnumSetType)]
pub enum DmaRxInterrupt {
/// Triggered when the size of the buffer pointed by receive descriptors
/// is smaller than the length of data to be received via receive channel.
DescriptorEmpty,
/// Triggered when an error is detected in a receive descriptor on receive
/// channel.
DescriptorError,
/// Triggered when an error is detected in the data segment corresponding to
/// a descriptor received via receive channel n.
/// This interrupt is used only for UHCI0 peripheral (UART0 or UART1).
ErrorEof,
/// Triggered when the suc_eof bit in a receive descriptor is 1 and the data
/// corresponding to this receive descriptor has been received via receive
/// channel.
SuccessfulEof,
/// Triggered when all data corresponding to a receive descriptor have been
/// received via receive channel.
Done,
}
/// The default chunk size used for DMA transfers.
pub const CHUNK_SIZE: usize = 4092;
@ -983,8 +1030,12 @@ impl TxCircularState {
where
T: TxPrivate,
{
if channel.descriptors_handled() {
channel.reset_descriptors_handled();
if channel
.pending_out_interrupts()
.contains(DmaTxInterrupt::Eof)
{
channel.clear_out(DmaTxInterrupt::Eof);
let descr_address = channel.last_out_dscr_address() as *mut DmaDescriptor;
let mut ptr = self.last_seen_handled_descriptor_ptr;
@ -1226,50 +1277,32 @@ pub trait RxPrivate: crate::private::Sealed {
#[cfg(gdma)]
fn set_mem2mem_mode(&mut self, value: bool);
fn listen_ch_in_done(&self);
fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
fn clear_ch_in_done(&self);
fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
fn is_ch_in_done_set(&self) -> bool;
fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt>;
fn unlisten_ch_in_done(&self);
fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
fn is_listening_ch_in_done(&self) -> bool;
fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt>;
fn is_done(&self) -> bool;
fn is_listening_eof(&self) -> bool;
fn has_error(&self) -> bool {
self.pending_in_interrupts()
.contains(DmaRxInterrupt::DescriptorError)
}
fn listen_eof(&self);
fn has_dscr_empty_error(&self) -> bool {
self.pending_in_interrupts()
.contains(DmaRxInterrupt::DescriptorEmpty)
}
fn unlisten_eof(&self);
/// Descriptor error detected
fn has_error(&self) -> bool;
/// ERR_DSCR_EMPTY error detected
fn has_dscr_empty_error(&self) -> bool;
/// ERR_EOF error detected
fn has_eof_error(&self) -> bool;
fn is_listening_in_descriptor_error(&self) -> bool;
fn listen_in_descriptor_error(&self);
fn unlisten_in_descriptor_error(&self);
fn is_listening_in_descriptor_error_dscr_empty(&self) -> bool;
fn listen_in_descriptor_error_dscr_empty(&self);
fn unlisten_in_descriptor_error_dscr_empty(&self);
fn is_listening_in_descriptor_error_err_eof(&self) -> bool;
fn listen_in_descriptor_error_err_eof(&self);
fn unlisten_in_descriptor_error_err_eof(&self);
fn has_eof_error(&self) -> bool {
self.pending_in_interrupts()
.contains(DmaRxInterrupt::ErrorEof)
}
fn clear_interrupts(&self);
@ -1308,17 +1341,13 @@ where
fn start_transfer(&mut self) -> Result<(), DmaError> {
R::start_in();
if R::has_in_descriptor_error() {
if R::pending_in_interrupts().contains(DmaRxInterrupt::DescriptorError) {
Err(DmaError::DescriptorError)
} else {
Ok(())
}
}
fn is_done(&self) -> bool {
R::is_in_done()
}
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
}
@ -1426,94 +1455,35 @@ where
CH::Channel::set_mem2mem_mode(value);
}
fn listen_ch_in_done(&self) {
CH::Channel::listen_ch_in_done();
fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
CH::Channel::listen_in(interrupts);
}
fn clear_ch_in_done(&self) {
CH::Channel::clear_ch_in_done();
fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
CH::Channel::unlisten_in(interrupts);
}
fn is_ch_in_done_set(&self) -> bool {
CH::Channel::is_ch_in_done_set()
fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt> {
CH::Channel::is_listening_in()
}
fn unlisten_ch_in_done(&self) {
CH::Channel::unlisten_ch_in_done();
fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
CH::Channel::clear_in(interrupts);
}
fn is_listening_ch_in_done(&self) -> bool {
CH::Channel::is_listening_ch_in_done()
fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
CH::Channel::pending_in_interrupts()
}
fn is_done(&self) -> bool {
self.rx_impl.is_done()
self.pending_in_interrupts()
.contains(DmaRxInterrupt::SuccessfulEof)
}
fn init_channel(&mut self) {
CH::Channel::init_channel();
}
fn is_listening_eof(&self) -> bool {
CH::Channel::is_listening_in_eof()
}
fn listen_eof(&self) {
CH::Channel::listen_in_eof()
}
fn unlisten_eof(&self) {
CH::Channel::unlisten_in_eof()
}
fn has_error(&self) -> bool {
CH::Channel::has_in_descriptor_error()
}
fn has_dscr_empty_error(&self) -> bool {
CH::Channel::has_in_descriptor_error_dscr_empty()
}
fn has_eof_error(&self) -> bool {
CH::Channel::has_in_descriptor_error_err_eof()
}
fn is_listening_in_descriptor_error(&self) -> bool {
CH::Channel::is_listening_in_descriptor_error()
}
fn listen_in_descriptor_error(&self) {
CH::Channel::listen_in_descriptor_error();
}
fn unlisten_in_descriptor_error(&self) {
CH::Channel::unlisten_in_descriptor_error();
}
fn is_listening_in_descriptor_error_dscr_empty(&self) -> bool {
CH::Channel::is_listening_in_descriptor_error_dscr_empty()
}
fn listen_in_descriptor_error_dscr_empty(&self) {
CH::Channel::listen_in_descriptor_error_dscr_empty();
}
fn unlisten_in_descriptor_error_dscr_empty(&self) {
CH::Channel::unlisten_in_descriptor_error_dscr_empty();
}
fn is_listening_in_descriptor_error_err_eof(&self) -> bool {
CH::Channel::is_listening_in_descriptor_error_err_eof()
}
fn listen_in_descriptor_error_err_eof(&self) {
CH::Channel::listen_in_descriptor_error_err_eof();
}
fn unlisten_in_descriptor_error_err_eof(&self) {
CH::Channel::unlisten_in_descriptor_error_err_eof();
}
fn clear_interrupts(&self) {
CH::Channel::clear_in_interrupts();
}
@ -1542,45 +1512,35 @@ pub trait TxPrivate: crate::private::Sealed {
buffer: &mut BUF,
) -> Result<(), DmaError>;
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt>;
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt>;
fn start_transfer(&mut self) -> Result<(), DmaError>;
#[cfg(esp32s3)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize);
fn clear_ch_out_done(&self);
fn is_done(&self) -> bool {
self.pending_out_interrupts()
.contains(DmaTxInterrupt::TotalEof)
}
fn is_ch_out_done_set(&self) -> bool;
fn listen_ch_out_done(&self);
fn unlisten_ch_out_done(&self);
fn is_listening_ch_out_done(&self) -> bool;
fn is_done(&self) -> bool;
fn is_listening_eof(&self) -> bool;
fn listen_eof(&self);
fn unlisten_eof(&self);
fn is_listening_out_descriptor_error(&self) -> bool;
fn listen_out_descriptor_error(&self);
fn unlisten_out_descriptor_error(&self);
fn has_error(&self) -> bool;
fn has_error(&self) -> bool {
self.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
}
fn clear_interrupts(&self);
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
fn descriptors_handled(&self) -> bool;
fn reset_descriptors_handled(&self);
fn last_out_dscr_address(&self) -> usize;
}
@ -1612,47 +1572,27 @@ where
fn start_transfer(&mut self) -> Result<(), DmaError> {
R::start_out();
if R::has_out_descriptor_error() {
if R::pending_out_interrupts().contains(DmaTxInterrupt::DescriptorError) {
Err(DmaError::DescriptorError)
} else {
Ok(())
}
}
fn clear_ch_out_done(&self) {
R::clear_ch_out_done();
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
R::listen_out(interrupts)
}
fn is_ch_out_done_set(&self) -> bool {
R::is_ch_out_done_set()
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
R::unlisten_out(interrupts)
}
fn listen_ch_out_done(&self) {
R::listen_ch_out_done();
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> {
R::is_listening_out()
}
fn unlisten_ch_out_done(&self) {
R::unlisten_ch_out_done();
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
R::clear_out(interrupts)
}
fn is_listening_ch_out_done(&self) -> bool {
R::is_listening_ch_out_done()
}
fn is_done(&self) -> bool {
R::is_out_done()
}
fn descriptors_handled(&self) -> bool {
R::is_out_eof_interrupt_set()
}
fn reset_descriptors_handled(&self) {
R::reset_out_eof_interrupt();
}
fn last_out_dscr_address(&self) -> usize {
R::last_out_dscr_address()
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
R::pending_out_interrupts()
}
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
@ -1743,76 +1683,36 @@ where
CH::Channel::set_out_ext_mem_block_size(size);
}
fn clear_ch_out_done(&self) {
self.tx_impl.clear_ch_out_done();
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
CH::Channel::listen_out(interrupts);
}
fn is_ch_out_done_set(&self) -> bool {
self.tx_impl.is_ch_out_done_set()
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
CH::Channel::unlisten_out(interrupts);
}
fn listen_ch_out_done(&self) {
self.tx_impl.listen_ch_out_done();
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> {
CH::Channel::is_listening_out()
}
fn unlisten_ch_out_done(&self) {
self.tx_impl.unlisten_ch_out_done();
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
CH::Channel::clear_out(interrupts);
}
fn is_listening_ch_out_done(&self) -> bool {
self.tx_impl.is_listening_ch_out_done()
}
fn is_done(&self) -> bool {
self.tx_impl.is_done()
}
fn is_listening_eof(&self) -> bool {
CH::Channel::is_listening_out_eof()
}
fn listen_eof(&self) {
CH::Channel::listen_out_eof()
}
fn unlisten_eof(&self) {
CH::Channel::unlisten_out_eof()
}
fn has_error(&self) -> bool {
CH::Channel::has_out_descriptor_error()
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
CH::Channel::pending_out_interrupts()
}
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
CH::Tx::waker()
}
fn is_listening_out_descriptor_error(&self) -> bool {
CH::Channel::is_listening_out_descriptor_error()
}
fn listen_out_descriptor_error(&self) {
CH::Channel::listen_out_descriptor_error();
}
fn unlisten_out_descriptor_error(&self) {
CH::Channel::unlisten_out_descriptor_error();
}
fn clear_interrupts(&self) {
CH::Channel::clear_out_interrupts();
}
fn descriptors_handled(&self) -> bool {
self.tx_impl.descriptors_handled()
}
fn reset_descriptors_handled(&self) {
self.tx_impl.reset_descriptors_handled()
}
fn last_out_dscr_address(&self) -> usize {
self.tx_impl.last_out_dscr_address()
CH::Channel::last_out_dscr_address()
}
}
@ -1828,17 +1728,21 @@ pub trait RegisterAccess: crate::private::Sealed {
fn clear_out_interrupts();
fn reset_out();
fn set_out_descriptors(address: u32);
fn has_out_descriptor_error() -> bool;
fn set_out_peripheral(peripheral: u8);
fn start_out();
fn clear_ch_out_done();
fn is_ch_out_done_set() -> bool;
fn listen_ch_out_done();
fn unlisten_ch_out_done();
fn is_listening_ch_out_done() -> bool;
fn is_out_done() -> bool;
fn is_out_eof_interrupt_set() -> bool;
fn reset_out_eof_interrupt();
fn listen_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
fn unlisten_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
fn is_listening_out() -> EnumSet<DmaTxInterrupt>;
fn clear_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
fn pending_out_interrupts() -> EnumSet<DmaTxInterrupt>;
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
fn is_listening_in() -> EnumSet<DmaRxInterrupt>;
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt>;
fn last_out_dscr_address() -> usize;
#[cfg(esp32s3)]
@ -1848,42 +1752,8 @@ pub trait RegisterAccess: crate::private::Sealed {
fn clear_in_interrupts();
fn reset_in();
fn set_in_descriptors(address: u32);
fn has_in_descriptor_error() -> bool;
fn has_in_descriptor_error_dscr_empty() -> bool;
fn has_in_descriptor_error_err_eof() -> bool;
fn set_in_peripheral(peripheral: u8);
fn start_in();
fn is_in_done() -> bool;
fn is_listening_in_eof() -> bool;
fn is_listening_out_eof() -> bool;
fn listen_in_eof();
fn listen_out_eof();
fn unlisten_in_eof();
fn unlisten_out_eof();
fn listen_in_descriptor_error();
fn unlisten_in_descriptor_error();
fn is_listening_in_descriptor_error() -> bool;
fn listen_in_descriptor_error_dscr_empty();
fn unlisten_in_descriptor_error_dscr_empty();
fn is_listening_in_descriptor_error_dscr_empty() -> bool;
fn listen_in_descriptor_error_err_eof();
fn unlisten_in_descriptor_error_err_eof();
fn is_listening_in_descriptor_error_err_eof() -> bool;
fn listen_out_descriptor_error();
fn unlisten_out_descriptor_error();
fn is_listening_out_descriptor_error() -> bool;
fn listen_ch_in_done();
fn clear_ch_in_done();
fn is_ch_in_done_set() -> bool;
fn unlisten_ch_in_done();
fn is_listening_ch_in_done() -> bool;
}
#[doc(hidden)]
@ -1920,8 +1790,8 @@ where
pub fn listen(&mut self, interrupts: EnumSet<DmaInterrupt>) {
for interrupt in interrupts {
match interrupt {
DmaInterrupt::RxDone => self.rx.listen_ch_in_done(),
DmaInterrupt::TxDone => self.tx.listen_ch_out_done(),
DmaInterrupt::RxDone => self.rx.listen_in(DmaRxInterrupt::Done),
DmaInterrupt::TxDone => self.tx.listen_out(DmaTxInterrupt::Done),
}
}
}
@ -1930,8 +1800,8 @@ where
pub fn unlisten(&mut self, interrupts: EnumSet<DmaInterrupt>) {
for interrupt in interrupts {
match interrupt {
DmaInterrupt::RxDone => self.rx.unlisten_ch_in_done(),
DmaInterrupt::TxDone => self.tx.unlisten_ch_out_done(),
DmaInterrupt::RxDone => self.rx.unlisten_in(DmaRxInterrupt::Done),
DmaInterrupt::TxDone => self.tx.unlisten_out(DmaTxInterrupt::Done),
}
}
}
@ -1952,8 +1822,8 @@ where
pub fn clear_interrupts(&mut self, interrupts: EnumSet<DmaInterrupt>) {
for interrupt in interrupts {
match interrupt {
DmaInterrupt::RxDone => self.rx.clear_ch_in_done(),
DmaInterrupt::TxDone => self.tx.clear_ch_out_done(),
DmaInterrupt::RxDone => self.rx.clear_in(DmaRxInterrupt::Done),
DmaInterrupt::TxDone => self.tx.clear_out(DmaTxInterrupt::Done),
}
}
}
@ -2684,7 +2554,12 @@ where
pub fn wait(self) -> Result<(), DmaError> {
self.instance.peripheral_wait_dma(false, true);
if self.instance.tx().has_error() {
if self
.instance
.tx()
.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
{
Err(DmaError::DescriptorError)
} else {
Ok(())
@ -2732,7 +2607,12 @@ where
pub fn wait(self) -> Result<(), DmaError> {
self.instance.peripheral_wait_dma(true, false);
if self.instance.rx().has_error() {
if self
.instance
.rx()
.pending_in_interrupts()
.contains(DmaRxInterrupt::DescriptorError)
{
Err(DmaError::DescriptorError)
} else {
Ok(())
@ -2781,7 +2661,17 @@ where
pub fn wait(self) -> Result<(), DmaError> {
self.instance.peripheral_wait_dma(true, true);
if self.instance.tx().has_error() || self.instance.rx().has_error() {
if self
.instance
.tx()
.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
|| self
.instance
.rx()
.pending_in_interrupts()
.contains(DmaRxInterrupt::DescriptorError)
{
Err(DmaError::DescriptorError)
} else {
Ok(())
@ -2854,7 +2744,12 @@ where
pub fn stop(self) -> Result<(), DmaError> {
self.instance.peripheral_dma_stop();
if self.instance.tx().has_error() {
if self
.instance
.tx()
.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
{
Err(DmaError::DescriptorError)
} else {
Ok(())
@ -2964,12 +2859,16 @@ pub(crate) mod asynch {
if self.tx.is_done() {
self.tx.clear_interrupts();
Poll::Ready(Ok(()))
} else if self.tx.has_error() {
} else if self
.tx
.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
{
self.tx.clear_interrupts();
Poll::Ready(Err(DmaError::DescriptorError))
} else {
self.tx.listen_eof();
self.tx.listen_out_descriptor_error();
self.tx
.listen_out(DmaTxInterrupt::TotalEof | DmaTxInterrupt::DescriptorError);
Poll::Pending
}
}
@ -2980,8 +2879,8 @@ pub(crate) mod asynch {
TX: Tx,
{
fn drop(&mut self) {
self.tx.unlisten_eof();
self.tx.unlisten_out_descriptor_error();
self.tx
.unlisten_out(DmaTxInterrupt::TotalEof | DmaTxInterrupt::DescriptorError);
}
}
@ -3016,17 +2915,20 @@ pub(crate) mod asynch {
if self.rx.is_done() {
self.rx.clear_interrupts();
Poll::Ready(Ok(()))
} else if self.rx.has_error()
|| self.rx.has_dscr_empty_error()
|| self.rx.has_eof_error()
{
} else if !self.rx.pending_in_interrupts().is_disjoint(
DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
) {
self.rx.clear_interrupts();
Poll::Ready(Err(DmaError::DescriptorError))
} else {
self.rx.listen_eof();
self.rx.listen_in_descriptor_error();
self.rx.listen_in_descriptor_error_dscr_empty();
self.rx.listen_in_descriptor_error_err_eof();
self.rx.listen_in(
DmaRxInterrupt::SuccessfulEof
| DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
);
Poll::Pending
}
}
@ -3037,10 +2939,11 @@ pub(crate) mod asynch {
RX: Rx,
{
fn drop(&mut self) {
self.rx.unlisten_eof();
self.rx.unlisten_in_descriptor_error();
self.rx.unlisten_in_descriptor_error_dscr_empty();
self.rx.unlisten_in_descriptor_error_err_eof();
self.rx.unlisten_in(
DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
);
}
}
@ -3075,15 +2978,23 @@ pub(crate) mod asynch {
cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> {
TX::waker().register(cx.waker());
if self.tx.is_ch_out_done_set() {
self.tx.clear_ch_out_done();
if self
.tx
.pending_out_interrupts()
.contains(DmaTxInterrupt::Done)
{
self.tx.clear_out(DmaTxInterrupt::Done);
Poll::Ready(Ok(()))
} else if self.tx.has_error() {
} else if self
.tx
.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
{
self.tx.clear_interrupts();
Poll::Ready(Err(DmaError::DescriptorError))
} else {
self.tx.listen_ch_out_done();
self.tx.listen_out_descriptor_error();
self.tx
.listen_out(DmaTxInterrupt::Done | DmaTxInterrupt::DescriptorError);
Poll::Pending
}
}
@ -3095,8 +3006,8 @@ pub(crate) mod asynch {
TX: Tx,
{
fn drop(&mut self) {
self.tx.unlisten_ch_out_done();
self.tx.unlisten_out_descriptor_error();
self.tx
.unlisten_out(DmaTxInterrupt::Done | DmaTxInterrupt::DescriptorError);
}
}
@ -3131,20 +3042,27 @@ pub(crate) mod asynch {
cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> {
RX::waker().register(cx.waker());
if self.rx.is_ch_in_done_set() {
self.rx.clear_ch_in_done();
Poll::Ready(Ok(()))
} else if self.rx.has_error()
|| self.rx.has_dscr_empty_error()
|| self.rx.has_eof_error()
if self
.rx
.pending_in_interrupts()
.contains(DmaRxInterrupt::Done)
{
self.rx.clear_in(DmaRxInterrupt::Done);
Poll::Ready(Ok(()))
} else if !self.rx.pending_in_interrupts().is_disjoint(
DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
) {
self.rx.clear_interrupts();
Poll::Ready(Err(DmaError::DescriptorError))
} else {
self.rx.listen_ch_in_done();
self.rx.listen_in_descriptor_error();
self.rx.listen_in_descriptor_error_dscr_empty();
self.rx.listen_in_descriptor_error_err_eof();
self.rx.listen_in(
DmaRxInterrupt::Done
| DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
);
Poll::Pending
}
}
@ -3156,50 +3074,57 @@ pub(crate) mod asynch {
RX: Rx,
{
fn drop(&mut self) {
self.rx.unlisten_ch_in_done();
self.rx.unlisten_in_descriptor_error();
self.rx.unlisten_in_descriptor_error_dscr_empty();
self.rx.unlisten_in_descriptor_error_err_eof();
self.rx.unlisten_in(
DmaRxInterrupt::Done
| DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
);
}
}
fn handle_interrupt<Channel: RegisterAccess, Rx: RxChannel<Channel>, Tx: TxChannel<Channel>>() {
if Channel::has_in_descriptor_error()
|| Channel::has_in_descriptor_error_dscr_empty()
|| Channel::has_in_descriptor_error_err_eof()
if Channel::pending_in_interrupts().is_disjoint(
DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof,
) {
Channel::unlisten_in(
DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof
| DmaRxInterrupt::SuccessfulEof
| DmaRxInterrupt::Done,
);
Rx::waker().wake()
}
if Channel::pending_out_interrupts().contains(DmaTxInterrupt::DescriptorError) {
Channel::unlisten_out(
DmaTxInterrupt::DescriptorError | DmaTxInterrupt::TotalEof | DmaTxInterrupt::Done,
);
Tx::waker().wake()
}
if Channel::pending_in_interrupts().contains(DmaRxInterrupt::SuccessfulEof) {
Channel::unlisten_in(DmaRxInterrupt::SuccessfulEof);
Rx::waker().wake()
}
if Channel::pending_in_interrupts().contains(DmaRxInterrupt::Done) {
Channel::unlisten_in(DmaRxInterrupt::Done);
Rx::waker().wake()
}
if Channel::pending_out_interrupts().contains(DmaTxInterrupt::TotalEof)
&& Channel::is_listening_out().contains(DmaTxInterrupt::TotalEof)
{
Channel::unlisten_in_descriptor_error();
Channel::unlisten_in_descriptor_error_dscr_empty();
Channel::unlisten_in_descriptor_error_err_eof();
Channel::unlisten_in_eof();
Channel::unlisten_ch_in_done();
Rx::waker().wake()
}
if Channel::has_out_descriptor_error() {
Channel::unlisten_out_descriptor_error();
Channel::unlisten_out_eof();
Channel::unlisten_ch_out_done();
Channel::unlisten_out(DmaTxInterrupt::TotalEof);
Tx::waker().wake()
}
if Channel::is_in_done() && Channel::is_listening_in_eof() {
Channel::unlisten_in_eof();
Rx::waker().wake()
}
if Channel::is_ch_in_done_set() {
Channel::unlisten_ch_in_done();
Rx::waker().wake()
}
if Channel::is_out_done() && Channel::is_listening_out_eof() {
Channel::unlisten_out_eof();
Tx::waker().wake()
}
if Channel::is_ch_out_done_set() {
Channel::unlisten_ch_out_done();
if Channel::pending_out_interrupts().contains(DmaTxInterrupt::Done) {
Channel::unlisten_out(DmaTxInterrupt::Done);
Tx::waker().wake()
}
}

View File

@ -83,11 +83,6 @@ macro_rules! ImplSpiChannel {
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn has_out_descriptor_error() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().outlink_dscr_error().bit()
}
fn set_out_peripheral(_peripheral: u8) {
// no-op
}
@ -97,53 +92,11 @@ macro_rules! ImplSpiChannel {
spi.dma_out_link().modify(|_, w| w.outlink_start().set_bit());
}
fn clear_ch_out_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| w.out_done().clear_bit_by_one());
}
fn is_ch_out_done_set() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().out_done().bit()
}
fn listen_ch_out_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_done().set_bit());
}
fn unlisten_ch_out_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_done().clear_bit());
}
fn is_listening_ch_out_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().out_done().bit()
}
fn is_out_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().out_total_eof().bit()
}
fn last_out_dscr_address() -> usize {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize
}
fn is_out_eof_interrupt_set() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().out_eof().bit()
}
fn reset_out_eof_interrupt() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| {
w.out_eof().clear_bit_by_one()
});
}
fn set_in_burstmode(burst_mode: bool) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_conf()
@ -174,21 +127,6 @@ macro_rules! ImplSpiChannel {
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn has_in_descriptor_error() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().inlink_dscr_error().bit()
}
fn has_in_descriptor_error_dscr_empty() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().inlink_dscr_empty().bit()
}
fn has_in_descriptor_error_err_eof() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().in_err_eof().bit()
}
fn set_in_peripheral(_peripheral: u8) {
// no-op
}
@ -198,124 +136,187 @@ macro_rules! ImplSpiChannel {
spi.dma_in_link().modify(|_, w| w.inlink_start().set_bit());
}
fn is_in_done() -> bool {
fn listen_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().in_done().bit()
spi.dma_int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().set_bit(),
DmaTxInterrupt::DescriptorError => w.outlink_dscr_error().set_bit(),
DmaTxInterrupt::Eof => w.out_eof().set_bit(),
DmaTxInterrupt::Done => w.out_done().set_bit(),
};
}
w
})
}
fn is_listening_in_eof() -> bool {
fn unlisten_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().in_suc_eof().bit_is_set()
spi.dma_int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit(),
DmaTxInterrupt::DescriptorError => w.outlink_dscr_error().clear_bit(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit(),
DmaTxInterrupt::Done => w.out_done().clear_bit(),
};
}
w
})
}
fn is_listening_out_eof() -> bool {
fn is_listening_out() -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().out_total_eof().bit_is_set()
let int_ena = spi.dma_int_ena().read();
if int_ena.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof;
}
if int_ena.outlink_dscr_error().bit_is_set() {
result |= DmaTxInterrupt::DescriptorError;
}
if int_ena.out_eof().bit_is_set() {
result |= DmaTxInterrupt::Eof;
}
if int_ena.out_done().bit_is_set() {
result |= DmaTxInterrupt::Done;
}
result
}
fn listen_in_eof() {
fn pending_out_interrupts() -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_suc_eof().set_bit());
let int_raw = spi.dma_int_raw().read();
if int_raw.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof;
}
if int_raw.outlink_dscr_error().bit_is_set() {
result |= DmaTxInterrupt::DescriptorError;
}
if int_raw.out_eof().bit_is_set() {
result |= DmaTxInterrupt::Eof;
}
if int_raw.out_done().bit_is_set() {
result |= DmaTxInterrupt::Done;
}
result
}
fn listen_out_eof() {
fn clear_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_total_eof().set_bit());
spi.dma_int_clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
DmaTxInterrupt::DescriptorError => w.outlink_dscr_error().clear_bit_by_one(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
};
}
w
})
}
fn unlisten_in_eof() {
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_suc_eof().clear_bit());
spi.dma_int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().set_bit(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().set_bit(),
DmaRxInterrupt::DescriptorError => w.inlink_dscr_error().set_bit(),
DmaRxInterrupt::DescriptorEmpty => w.inlink_dscr_empty().set_bit(),
DmaRxInterrupt::Done => w.in_done().set_bit(),
};
}
w
})
}
fn unlisten_out_eof() {
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_total_eof().clear_bit());
spi.dma_int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit(),
DmaRxInterrupt::DescriptorError => w.inlink_dscr_error().clear_bit(),
DmaRxInterrupt::DescriptorEmpty => w.inlink_dscr_empty().clear_bit(),
DmaRxInterrupt::Done => w.in_done().clear_bit(),
};
}
w
})
}
fn listen_ch_in_done(){
fn is_listening_in() -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_done().set_bit());
let int_ena = spi.dma_int_ena().read();
if int_ena.inlink_dscr_error().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError;
}
if int_ena.inlink_dscr_empty().bit_is_set() {
result |= DmaRxInterrupt::DescriptorEmpty;
}
if int_ena.in_suc_eof().bit_is_set() {
result |= DmaRxInterrupt::SuccessfulEof;
}
if int_ena.in_err_eof().bit_is_set() {
result |= DmaRxInterrupt::ErrorEof;
}
if int_ena.in_done().bit_is_set() {
result |= DmaRxInterrupt::Done;
}
result
}
fn clear_ch_in_done(){
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| w.in_done().clear_bit_by_one());
let int_raw = spi.dma_int_raw().read();
if int_raw.inlink_dscr_error().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError;
}
if int_raw.inlink_dscr_empty().bit_is_set() {
result |= DmaRxInterrupt::DescriptorEmpty;
}
if int_raw.in_suc_eof().bit_is_set() {
result |= DmaRxInterrupt::SuccessfulEof;
}
if int_raw.in_err_eof().bit_is_set() {
result |= DmaRxInterrupt::ErrorEof;
}
if int_raw.in_done().bit_is_set() {
result |= DmaRxInterrupt::Done;
}
result
}
fn is_ch_in_done_set() -> bool {
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().in_done().bit()
}
fn unlisten_ch_in_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_done().clear_bit());
}
fn is_listening_ch_in_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().in_done().bit()
}
fn listen_in_descriptor_error() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.inlink_dscr_error().set_bit())
}
fn unlisten_in_descriptor_error() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.inlink_dscr_error().clear_bit())
}
fn is_listening_in_descriptor_error() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().inlink_dscr_error().bit()
}
fn listen_in_descriptor_error_dscr_empty() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.inlink_dscr_empty().set_bit())
}
fn unlisten_in_descriptor_error_dscr_empty() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.inlink_dscr_empty().clear_bit())
}
fn is_listening_in_descriptor_error_dscr_empty() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().inlink_dscr_empty().bit()
}
fn listen_in_descriptor_error_err_eof() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.in_err_eof().set_bit())
}
fn unlisten_in_descriptor_error_err_eof() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.in_err_eof().clear_bit())
}
fn is_listening_in_descriptor_error_err_eof() -> bool{
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().in_err_eof().bit()
}
fn listen_out_descriptor_error() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.outlink_dscr_error().set_bit())
}
fn unlisten_out_descriptor_error() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_,w| w.outlink_dscr_error().clear_bit())
}
fn is_listening_out_descriptor_error() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().outlink_dscr_error().bit()
spi.dma_int_clr().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
DmaRxInterrupt::DescriptorError => w.inlink_dscr_error().clear_bit_by_one(),
DmaRxInterrupt::DescriptorEmpty => w.inlink_dscr_empty().clear_bit_by_one(),
DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
};
}
w
})
}
}
@ -462,11 +463,6 @@ macro_rules! ImplI2sChannel {
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn has_out_descriptor_error() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_dscr_err().bit()
}
fn set_out_peripheral(_peripheral: u8) {
// no-op
}
@ -476,54 +472,11 @@ macro_rules! ImplI2sChannel {
reg_block.out_link().modify(|_, w| w.outlink_start().set_bit());
}
fn clear_ch_out_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| w.out_done().clear_bit_by_one());
}
fn is_ch_out_done_set() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_done().bit()
}
fn listen_ch_out_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.out_done().set_bit());
}
fn unlisten_ch_out_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.out_done().clear_bit());
}
fn is_listening_ch_out_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().out_done().bit()
}
fn is_out_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_eof().bit()
}
fn last_out_dscr_address() -> usize {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.out_eof_des_addr().read().out_eof_des_addr().bits() as usize
}
fn is_out_eof_interrupt_set() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_eof().bit()
}
fn reset_out_eof_interrupt() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| {
w.out_eof()
.clear_bit_by_one()
});
}
fn set_in_burstmode(burst_mode: bool) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.lc_conf()
@ -558,21 +511,6 @@ macro_rules! ImplI2sChannel {
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn has_in_descriptor_error() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_dscr_err().bit()
}
fn has_in_descriptor_error_dscr_empty() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_dscr_empty().bit()
}
fn has_in_descriptor_error_err_eof() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_err_eof().bit()
}
fn set_in_peripheral(_peripheral: u8) {
// no-op
}
@ -582,124 +520,187 @@ macro_rules! ImplI2sChannel {
reg_block.in_link().modify(|_, w| w.inlink_start().set_bit());
}
fn is_in_done() -> bool {
fn listen_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_done().bit()
reg_block.int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().set_bit(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().set_bit(),
DmaTxInterrupt::Eof => w.out_eof().set_bit(),
DmaTxInterrupt::Done => w.out_done().set_bit(),
};
}
w
})
}
fn is_listening_in_eof() -> bool {
fn unlisten_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_suc_eof().bit()
reg_block.int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit(),
DmaTxInterrupt::Done => w.out_done().clear_bit(),
};
}
w
})
}
fn is_listening_out_eof() -> bool {
fn is_listening_out() -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().out_eof().bit()
let int_ena = reg_block.int_ena().read();
if int_ena.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof;
}
if int_ena.out_dscr_err().bit_is_set() {
result |= DmaTxInterrupt::DescriptorError;
}
if int_ena.out_eof().bit_is_set() {
result |= DmaTxInterrupt::Eof;
}
if int_ena.out_done().bit_is_set() {
result |= DmaTxInterrupt::Done;
}
result
}
fn listen_in_eof() {
fn pending_out_interrupts() -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.in_suc_eof().set_bit() );
let int_raw = reg_block.int_raw().read();
if int_raw.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof;
}
if int_raw.out_dscr_err().bit_is_set() {
result |= DmaTxInterrupt::DescriptorError;
}
if int_raw.out_eof().bit_is_set() {
result |= DmaTxInterrupt::Eof;
}
if int_raw.out_done().bit_is_set() {
result |= DmaTxInterrupt::Done;
}
result
}
fn listen_out_eof() {
fn clear_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.out_eof().set_bit() );
reg_block.int_clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
};
}
w
})
}
fn unlisten_in_eof() {
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.in_suc_eof().clear_bit() );
reg_block.int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().set_bit(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().set_bit(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().set_bit(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().set_bit(),
DmaRxInterrupt::Done => w.in_done().set_bit(),
};
}
w
})
}
fn unlisten_out_eof() {
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.out_eof().clear_bit() );
reg_block.int_ena().modify(|_, w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit(),
DmaRxInterrupt::Done => w.in_done().clear_bit(),
};
}
w
})
}
fn listen_ch_in_done(){
fn is_listening_in() -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_done().set_bit());
let int_ena = reg_block.int_ena().read();
if int_ena.in_dscr_err().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError;
}
if int_ena.in_dscr_empty().bit_is_set() {
result |= DmaRxInterrupt::DescriptorEmpty;
}
if int_ena.in_suc_eof().bit_is_set() {
result |= DmaRxInterrupt::SuccessfulEof;
}
if int_ena.in_err_eof().bit_is_set() {
result |= DmaRxInterrupt::ErrorEof;
}
if int_ena.in_done().bit_is_set() {
result |= DmaRxInterrupt::Done;
}
result
}
fn clear_ch_in_done(){
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| w.in_done().clear_bit_by_one());
let int_raw = reg_block.int_raw().read();
if int_raw.in_dscr_err().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError;
}
if int_raw.in_dscr_empty().bit_is_set() {
result |= DmaRxInterrupt::DescriptorEmpty;
}
if int_raw.in_suc_eof().bit_is_set() {
result |= DmaRxInterrupt::SuccessfulEof;
}
if int_raw.in_err_eof().bit_is_set() {
result |= DmaRxInterrupt::ErrorEof;
}
if int_raw.in_done().bit_is_set() {
result |= DmaRxInterrupt::Done;
}
result
}
fn is_ch_in_done_set() -> bool {
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_done().bit()
}
fn unlisten_ch_in_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_done().clear_bit());
}
fn is_listening_ch_in_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_done().bit()
}
fn listen_in_descriptor_error(){
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_dscr_err().set_bit());
}
fn unlisten_in_descriptor_error() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_dscr_err().clear_bit());
}
fn is_listening_in_descriptor_error() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_dscr_err().bit()
}
fn listen_in_descriptor_error_dscr_empty() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_dscr_empty().set_bit());
}
fn unlisten_in_descriptor_error_dscr_empty() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_dscr_empty().clear_bit());
}
fn is_listening_in_descriptor_error_dscr_empty() -> bool{
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_dscr_empty().bit()
}
fn listen_in_descriptor_error_err_eof() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_err_eof().set_bit());
}
fn unlisten_in_descriptor_error_err_eof() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_err_eof().clear_bit());
}
fn is_listening_in_descriptor_error_err_eof() -> bool{
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_err_eof().bit()
}
fn listen_out_descriptor_error() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.out_dscr_err().set_bit());
}
fn unlisten_out_descriptor_error() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.out_dscr_err().clear_bit());
}
fn is_listening_out_descriptor_error() -> bool{
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().out_dscr_err().bit()
reg_block.int_clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
};
}
w
})
}
}