use super::*;
use crate::RegisterToggle;
impl AhbGdmaTxChannel<'_> {
#[inline(always)]
pub(super) fn ch(&self) -> &pac::dma::ch::CH {
DMA::regs().ch(self.0.info.channel as usize)
}
#[cfg(any(esp32c2, esp32c3))]
#[inline(always)]
pub(super) fn int(&self) -> &pac::dma::int_ch::INT_CH {
DMA::regs().int_ch(self.0.info.channel as usize)
}
#[inline(always)]
#[cfg(any(esp32c6, esp32h2))]
pub(super) fn int(&self) -> &pac::dma::out_int_ch::OUT_INT_CH {
DMA::regs().out_int_ch(self.0.info.channel as usize)
}
#[cfg(esp32s3)]
#[inline(always)]
pub(super) fn int(&self) -> &pac::dma::ch::out_int::OUT_INT {
DMA::regs().ch(self.0.info.channel as usize).out_int()
}
}
impl RegisterAccess for AhbGdmaTxChannel<'_> {
#[allow(private_interfaces)]
fn enable(&self) -> Option<PeripheralGuard> {
Some(PeripheralGuard::new_with(
Peripheral::AhbGdma,
init_dma_racey,
))
}
fn reset(&self) {
self.ch().out_conf0().toggle(|w, bit| w.out_rst().bit(bit));
}
fn set_burst_mode(&self, burst_mode: BurstConfig) {
self.ch()
.out_conf0()
.modify(|_, w| w.out_data_burst_en().bit(burst_mode.is_burst_enabled()));
}
fn set_descr_burst_mode(&self, burst_mode: bool) {
self.ch()
.out_conf0()
.modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
}
fn set_priority(&self, priority: DmaPriority) {
self.ch()
.out_pri()
.write(|w| unsafe { w.tx_pri().bits(priority as u8) });
}
fn set_peripheral(&self, peripheral: u8) {
self.ch()
.out_peri_sel()
.modify(|_, w| unsafe { w.peri_out_sel().bits(peripheral) });
}
fn set_link_addr(&self, address: u32) {
self.ch()
.out_link()
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn start(&self) {
self.ch()
.out_link()
.modify(|_, w| w.outlink_start().set_bit());
}
fn stop(&self) {
self.ch()
.out_link()
.modify(|_, w| w.outlink_stop().set_bit());
}
fn restart(&self) {
self.ch()
.out_link()
.modify(|_, w| w.outlink_restart().set_bit());
}
fn set_check_owner(&self, check_owner: Option<bool>) {
self.ch()
.out_conf1()
.modify(|_, w| w.out_check_owner().bit(check_owner.unwrap_or(true)));
}
#[cfg(dma_ext_mem_configurable_block_size)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
self.ch()
.out_conf1()
.modify(|_, w| unsafe { w.out_ext_mem_bk_size().bits(size as u8) });
}
#[cfg(dma_can_access_psram)]
fn can_access_psram(&self) -> bool {
true
}
fn compatible_peripherals(&self) -> &[u8] {
self.0.info.compatible_peripherals
}
}
impl TxRegisterAccess for AhbGdmaTxChannel<'_> {
fn is_fifo_empty(&self) -> bool {
cfg_select! {
esp32s3 => self
.ch()
.outfifo_status()
.read()
.outfifo_empty_l3()
.bit_is_set(),
_ => self
.ch()
.outfifo_status()
.read()
.outfifo_empty()
.bit_is_set(),
}
}
fn set_auto_write_back(&self, enable: bool) {
self.ch()
.out_conf0()
.modify(|_, w| w.out_auto_wrback().bit(enable));
}
fn last_dscr_address(&self) -> usize {
self.ch()
.out_eof_des_addr()
.read()
.out_eof_des_addr()
.bits() as _
}
fn async_handler(&self) -> Option<InterruptHandler> {
self.0.info.handler_out
}
fn peripheral_interrupt(&self) -> Option<Interrupt> {
self.0.info.isr_out
}
}
impl InterruptAccess<DmaTxInterrupt> for AhbGdmaTxChannel<'_> {
fn enable_listen(&self, interrupts: EnumSet<DmaTxInterrupt>, enable: bool) {
self.int().ena().modify(|_, w| {
for interrupt in interrupts {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().bit(enable),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().bit(enable),
DmaTxInterrupt::Eof => w.out_eof().bit(enable),
DmaTxInterrupt::Done => w.out_done().bit(enable),
};
}
w
});
}
fn is_listening(&self) -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let int_ena = self.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 clear(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
self.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 pending_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new();
let int_raw = self.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 waker(&self) -> &'static AtomicWaker {
&self.0.state.tx_waker
}
fn is_async(&self) -> bool {
cfg_select! {
any(esp32c2, esp32c3) => self
.0
.state
.tx_is_async
.load(portable_atomic::Ordering::Acquire),
_ => true,
}
}
fn set_async(&self, _is_async: bool) {
#[cfg(any(esp32c2, esp32c3))]
{
self.0
.state
.tx_is_async
.store(_is_async, portable_atomic::Ordering::Release);
}
}
}
impl AhbGdmaRxChannel<'_> {
#[inline(always)]
fn ch(&self) -> &pac::dma::ch::CH {
DMA::regs().ch(self.0.info.channel as usize)
}
#[cfg(any(esp32c2, esp32c3))]
#[inline(always)]
fn int(&self) -> &pac::dma::int_ch::INT_CH {
DMA::regs().int_ch(self.0.info.channel as usize)
}
#[inline(always)]
#[cfg(any(esp32c6, esp32h2))]
fn int(&self) -> &pac::dma::in_int_ch::IN_INT_CH {
DMA::regs().in_int_ch(self.0.info.channel as usize)
}
#[cfg(esp32s3)]
#[inline(always)]
fn int(&self) -> &pac::dma::ch::in_int::IN_INT {
DMA::regs().ch(self.0.info.channel as usize).in_int()
}
}
impl RegisterAccess for AhbGdmaRxChannel<'_> {
#[allow(private_interfaces)]
fn enable(&self) -> Option<PeripheralGuard> {
Some(PeripheralGuard::new_with(
Peripheral::AhbGdma,
init_dma_racey,
))
}
fn reset(&self) {
self.ch().in_conf0().toggle(|w, bit| w.in_rst().bit(bit));
}
fn set_burst_mode(&self, burst_mode: BurstConfig) {
self.ch()
.in_conf0()
.modify(|_, w| w.in_data_burst_en().bit(burst_mode.is_burst_enabled()));
}
fn set_descr_burst_mode(&self, burst_mode: bool) {
self.ch()
.in_conf0()
.modify(|_, w| w.indscr_burst_en().bit(burst_mode));
}
fn set_priority(&self, priority: DmaPriority) {
self.ch()
.in_pri()
.write(|w| unsafe { w.rx_pri().bits(priority as u8) });
}
fn set_peripheral(&self, peripheral: u8) {
self.ch()
.in_peri_sel()
.modify(|_, w| unsafe { w.peri_in_sel().bits(peripheral) });
}
fn set_link_addr(&self, address: u32) {
self.ch()
.in_link()
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn start(&self) {
self.ch()
.in_link()
.modify(|_, w| w.inlink_start().set_bit());
}
fn stop(&self) {
self.ch().in_link().modify(|_, w| w.inlink_stop().set_bit());
}
fn restart(&self) {
self.ch()
.in_link()
.modify(|_, w| w.inlink_restart().set_bit());
}
fn set_check_owner(&self, check_owner: Option<bool>) {
self.ch()
.in_conf1()
.modify(|_, w| w.in_check_owner().bit(check_owner.unwrap_or(true)));
}
#[cfg(dma_ext_mem_configurable_block_size)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
self.ch()
.in_conf1()
.modify(|_, w| unsafe { w.in_ext_mem_bk_size().bits(size as u8) });
}
#[cfg(dma_can_access_psram)]
fn can_access_psram(&self) -> bool {
true
}
fn compatible_peripherals(&self) -> &[u8] {
self.0.info.compatible_peripherals
}
}
impl RxRegisterAccess for AhbGdmaRxChannel<'_> {
#[cfg(dma_supports_mem2mem)]
fn set_mem2mem_mode(&self, value: bool) {
self.ch()
.in_conf0()
.modify(|_, w| w.mem_trans_en().bit(value));
}
fn async_handler(&self) -> Option<InterruptHandler> {
self.0.info.handler_in
}
fn peripheral_interrupt(&self) -> Option<Interrupt> {
self.0.info.isr_in
}
}
impl InterruptAccess<DmaRxInterrupt> for AhbGdmaRxChannel<'_> {
fn enable_listen(&self, interrupts: EnumSet<DmaRxInterrupt>, enable: bool) {
self.int().ena().modify(|_, w| {
for interrupt in interrupts {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().bit(enable),
DmaRxInterrupt::ErrorEof => w.in_err_eof().bit(enable),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().bit(enable),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().bit(enable),
DmaRxInterrupt::Done => w.in_done().bit(enable),
};
}
w
});
}
fn is_listening(&self) -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let int_ena = self.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(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
self.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
});
}
fn pending_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new();
let int_raw = self.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 waker(&self) -> &'static AtomicWaker {
&self.0.state.rx_waker
}
fn is_async(&self) -> bool {
cfg_select! {
any(esp32c2, esp32c3) => self
.0
.state
.rx_is_async
.load(portable_atomic::Ordering::Acquire),
_ => true,
}
}
fn set_async(&self, _is_async: bool) {
#[cfg(any(esp32c2, esp32c3))]
{
self.0
.state
.rx_is_async
.store(_is_async, portable_atomic::Ordering::Release);
}
}
}
pub(crate) fn setup() {}