mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00
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:
parent
89d9de67eb
commit
794cdb0af4
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
fn listen_in_eof() {
|
||||
Self::in_int().ena().modify(|_, w| w.in_suc_eof().set_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn listen_out_eof() {
|
||||
Self::out_int()
|
||||
.ena()
|
||||
.modify(|_, w| w.out_total_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;
|
||||
}
|
||||
|
||||
fn unlisten_in_eof() {
|
||||
Self::in_int()
|
||||
.ena()
|
||||
.modify(|_, w| w.in_suc_eof().clear_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn unlisten_out_eof() {
|
||||
Self::out_int()
|
||||
.ena()
|
||||
.modify(|_, w| w.out_total_eof().clear_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 listen_ch_in_done() {
|
||||
Self::in_int().ena().modify(|_, w| w.in_done().set_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 clear_ch_in_done() {
|
||||
Self::in_int()
|
||||
.clr()
|
||||
.write(|w| w.in_done().clear_bit_by_one());
|
||||
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 is_ch_in_done_set() -> bool {
|
||||
Self::in_int().raw().read().in_done().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;
|
||||
}
|
||||
|
||||
fn unlisten_ch_in_done() {
|
||||
Self::in_int().ena().modify(|_, w| w.in_done().clear_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn is_listening_ch_in_done() -> bool {
|
||||
Self::in_int().ena().read().in_done().bit()
|
||||
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;
|
||||
}
|
||||
|
||||
fn listen_in_descriptor_error() {
|
||||
Self::in_int()
|
||||
.ena()
|
||||
.modify(|_, w| w.in_dscr_err().set_bit())
|
||||
result
|
||||
}
|
||||
|
||||
fn unlisten_in_descriptor_error() {
|
||||
Self::in_int()
|
||||
.ena()
|
||||
.modify(|_, w| w.in_dscr_err().clear_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(),
|
||||
};
|
||||
}
|
||||
|
||||
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()
|
||||
w
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
fn listen_in_eof() {
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_ena().modify(|_, w| w.in_suc_eof().set_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn listen_out_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.out_total_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;
|
||||
}
|
||||
|
||||
fn unlisten_in_eof() {
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_ena().modify(|_, w| w.in_suc_eof().clear_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn unlisten_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().clear_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 listen_ch_in_done(){
|
||||
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_ena().modify(|_, w| w.in_done().set_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 clear_ch_in_done(){
|
||||
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_clr().write(|w| w.in_done().clear_bit_by_one());
|
||||
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 is_ch_in_done_set() -> bool {
|
||||
fn is_listening_in() -> EnumSet<DmaRxInterrupt> {
|
||||
let mut result = EnumSet::new();
|
||||
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_raw().read().in_done().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;
|
||||
}
|
||||
|
||||
fn unlisten_ch_in_done() {
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_ena().modify(|_, w| w.in_done().clear_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn is_listening_ch_in_done() -> bool {
|
||||
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt> {
|
||||
let mut result = EnumSet::new();
|
||||
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_ena().read().in_done().bit()
|
||||
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;
|
||||
}
|
||||
|
||||
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())
|
||||
result
|
||||
}
|
||||
|
||||
fn unlisten_in_descriptor_error() {
|
||||
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
|
||||
spi.dma_int_ena().modify(|_,w| w.inlink_dscr_error().clear_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(),
|
||||
};
|
||||
}
|
||||
|
||||
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()
|
||||
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;
|
||||
}
|
||||
|
||||
fn listen_in_eof() {
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_ena().modify(|_,w| w.in_suc_eof().set_bit() );
|
||||
result
|
||||
}
|
||||
|
||||
fn listen_out_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.out_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;
|
||||
}
|
||||
|
||||
fn unlisten_in_eof() {
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_ena().modify(|_,w| w.in_suc_eof().clear_bit() );
|
||||
result
|
||||
}
|
||||
|
||||
fn unlisten_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().clear_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 listen_ch_in_done(){
|
||||
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_ena().modify(|_, w| w.in_done().set_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 clear_ch_in_done(){
|
||||
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_clr().write(|w| w.in_done().clear_bit_by_one());
|
||||
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 is_ch_in_done_set() -> bool {
|
||||
fn is_listening_in() -> EnumSet<DmaRxInterrupt> {
|
||||
let mut result = EnumSet::new();
|
||||
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_raw().read().in_done().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;
|
||||
}
|
||||
|
||||
fn unlisten_ch_in_done() {
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_ena().modify(|_, w| w.in_done().clear_bit());
|
||||
result
|
||||
}
|
||||
|
||||
fn is_listening_ch_in_done() -> bool {
|
||||
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt> {
|
||||
let mut result = EnumSet::new();
|
||||
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_ena().read().in_done().bit()
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
result
|
||||
}
|
||||
|
||||
fn unlisten_in_descriptor_error() {
|
||||
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
|
||||
reg_block.int_ena().modify(|_, w| w.in_dscr_err().clear_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(),
|
||||
};
|
||||
}
|
||||
|
||||
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()
|
||||
w
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user