1use critical_section::CriticalSection;
18
19use crate::{
20 dma::*,
21 handler,
22 interrupt::Priority,
23 peripheral::{Peripheral, PeripheralRef},
24 peripherals::{pac, Interrupt, DMA},
25};
26
27#[derive(Debug)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30pub struct AnyGdmaChannel(u8);
31
32impl Peripheral for AnyGdmaChannel {
33 type P = Self;
34
35 unsafe fn clone_unchecked(&self) -> Self::P {
36 Self(self.0)
37 }
38}
39
40impl crate::private::Sealed for AnyGdmaChannel {}
41impl DmaChannel for AnyGdmaChannel {
42 type Rx = AnyGdmaRxChannel;
43 type Tx = AnyGdmaTxChannel;
44
45 unsafe fn split_internal(self, _: crate::private::Internal) -> (Self::Rx, Self::Tx) {
46 (AnyGdmaRxChannel(self.0), AnyGdmaTxChannel(self.0))
47 }
48}
49
50#[derive(Debug)]
52#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53pub struct AnyGdmaRxChannel(u8);
54
55impl Peripheral for AnyGdmaRxChannel {
56 type P = Self;
57
58 unsafe fn clone_unchecked(&self) -> Self::P {
59 Self(self.0)
60 }
61}
62
63impl DmaChannelConvert<AnyGdmaRxChannel> for AnyGdmaRxChannel {
64 fn degrade(self) -> AnyGdmaRxChannel {
65 self
66 }
67}
68
69#[derive(Debug)]
71#[cfg_attr(feature = "defmt", derive(defmt::Format))]
72pub struct AnyGdmaTxChannel(u8);
73
74impl Peripheral for AnyGdmaTxChannel {
75 type P = Self;
76
77 unsafe fn clone_unchecked(&self) -> Self::P {
78 Self(self.0)
79 }
80}
81
82impl DmaChannelConvert<AnyGdmaTxChannel> for AnyGdmaTxChannel {
83 fn degrade(self) -> AnyGdmaTxChannel {
84 self
85 }
86}
87
88use crate::asynch::AtomicWaker;
89
90static TX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
91static RX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
92
93cfg_if::cfg_if! {
94 if #[cfg(any(esp32c2, esp32c3))] {
95 use portable_atomic::AtomicBool;
96 static TX_IS_ASYNC: [AtomicBool; CHANNEL_COUNT] = [const { AtomicBool::new(false) }; CHANNEL_COUNT];
97 static RX_IS_ASYNC: [AtomicBool; CHANNEL_COUNT] = [const { AtomicBool::new(false) }; CHANNEL_COUNT];
98 }
99}
100
101impl crate::private::Sealed for AnyGdmaTxChannel {}
102impl DmaTxChannel for AnyGdmaTxChannel {}
103
104impl AnyGdmaTxChannel {
105 #[inline(always)]
106 fn ch(&self) -> &pac::dma::ch::CH {
107 DMA::regs().ch(self.0 as usize)
108 }
109
110 #[cfg(any(esp32c2, esp32c3))]
111 #[inline(always)]
112 fn int(&self) -> &pac::dma::int_ch::INT_CH {
113 DMA::regs().int_ch(self.0 as usize)
114 }
115 #[inline(always)]
116 #[cfg(any(esp32c6, esp32h2))]
117 fn int(&self) -> &pac::dma::out_int_ch::OUT_INT_CH {
118 DMA::regs().out_int_ch(self.0 as usize)
119 }
120 #[cfg(esp32s3)]
121 #[inline(always)]
122 fn int(&self) -> &pac::dma::ch::out_int::OUT_INT {
123 DMA::regs().ch(self.0 as usize).out_int()
124 }
125}
126
127impl RegisterAccess for AnyGdmaTxChannel {
128 fn reset(&self) {
129 let conf0 = self.ch().out_conf0();
130 conf0.modify(|_, w| w.out_rst().set_bit());
131 conf0.modify(|_, w| w.out_rst().clear_bit());
132 }
133
134 fn set_burst_mode(&self, burst_mode: BurstConfig) {
135 self.ch()
136 .out_conf0()
137 .modify(|_, w| w.out_data_burst_en().bit(burst_mode.is_burst_enabled()));
138 }
139
140 fn set_descr_burst_mode(&self, burst_mode: bool) {
141 self.ch()
142 .out_conf0()
143 .modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
144 }
145
146 fn set_priority(&self, priority: DmaPriority) {
147 self.ch()
148 .out_pri()
149 .write(|w| unsafe { w.tx_pri().bits(priority as u8) });
150 }
151
152 fn set_peripheral(&self, peripheral: u8) {
153 self.ch()
154 .out_peri_sel()
155 .modify(|_, w| unsafe { w.peri_out_sel().bits(peripheral) });
156 }
157
158 fn set_link_addr(&self, address: u32) {
159 self.ch()
160 .out_link()
161 .modify(|_, w| unsafe { w.outlink_addr().bits(address) });
162 }
163
164 fn start(&self) {
165 self.ch()
166 .out_link()
167 .modify(|_, w| w.outlink_start().set_bit());
168 }
169
170 fn stop(&self) {
171 self.ch()
172 .out_link()
173 .modify(|_, w| w.outlink_stop().set_bit());
174 }
175
176 fn restart(&self) {
177 self.ch()
178 .out_link()
179 .modify(|_, w| w.outlink_restart().set_bit());
180 }
181
182 fn set_check_owner(&self, check_owner: Option<bool>) {
183 self.ch()
184 .out_conf1()
185 .modify(|_, w| w.out_check_owner().bit(check_owner.unwrap_or(true)));
186 }
187
188 #[cfg(esp32s3)]
189 fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
190 self.ch()
191 .out_conf1()
192 .modify(|_, w| unsafe { w.out_ext_mem_bk_size().bits(size as u8) });
193 }
194
195 #[cfg(psram_dma)]
196 fn can_access_psram(&self) -> bool {
197 true
198 }
199}
200
201impl TxRegisterAccess for AnyGdmaTxChannel {
202 fn is_fifo_empty(&self) -> bool {
203 cfg_if::cfg_if! {
204 if #[cfg(esp32s3)] {
205 self.ch().outfifo_status().read().outfifo_empty_l3().bit_is_set()
206 } else {
207 self.ch().outfifo_status().read().outfifo_empty().bit_is_set()
208 }
209 }
210 }
211
212 fn set_auto_write_back(&self, enable: bool) {
213 self.ch()
214 .out_conf0()
215 .modify(|_, w| w.out_auto_wrback().bit(enable));
216 }
217
218 fn last_dscr_address(&self) -> usize {
219 self.ch()
220 .out_eof_des_addr()
221 .read()
222 .out_eof_des_addr()
223 .bits() as _
224 }
225
226 fn async_handler(&self) -> Option<InterruptHandler> {
227 match self.0 {
228 0 => DmaChannel0::handler_out(),
229 #[cfg(not(esp32c2))]
230 1 => DmaChannel1::handler_out(),
231 #[cfg(not(esp32c2))]
232 2 => DmaChannel2::handler_out(),
233 #[cfg(esp32s3)]
234 3 => DmaChannel3::handler_out(),
235 #[cfg(esp32s3)]
236 4 => DmaChannel4::handler_out(),
237 _ => unreachable!(),
238 }
239 }
240
241 fn peripheral_interrupt(&self) -> Option<Interrupt> {
242 match self.0 {
243 0 => DmaChannel0::isr_out(),
244 #[cfg(not(esp32c2))]
245 1 => DmaChannel1::isr_out(),
246 #[cfg(not(esp32c2))]
247 2 => DmaChannel2::isr_out(),
248 #[cfg(esp32s3)]
249 3 => DmaChannel3::isr_out(),
250 #[cfg(esp32s3)]
251 4 => DmaChannel4::isr_out(),
252 _ => unreachable!(),
253 }
254 }
255}
256
257impl InterruptAccess<DmaTxInterrupt> for AnyGdmaTxChannel {
258 fn enable_listen(&self, interrupts: EnumSet<DmaTxInterrupt>, enable: bool) {
259 self.int().ena().modify(|_, w| {
260 for interrupt in interrupts {
261 match interrupt {
262 DmaTxInterrupt::TotalEof => w.out_total_eof().bit(enable),
263 DmaTxInterrupt::DescriptorError => w.out_dscr_err().bit(enable),
264 DmaTxInterrupt::Eof => w.out_eof().bit(enable),
265 DmaTxInterrupt::Done => w.out_done().bit(enable),
266 };
267 }
268 w
269 });
270 }
271
272 fn is_listening(&self) -> EnumSet<DmaTxInterrupt> {
273 let mut result = EnumSet::new();
274
275 let int_ena = self.int().ena().read();
276 if int_ena.out_total_eof().bit_is_set() {
277 result |= DmaTxInterrupt::TotalEof;
278 }
279 if int_ena.out_dscr_err().bit_is_set() {
280 result |= DmaTxInterrupt::DescriptorError;
281 }
282 if int_ena.out_eof().bit_is_set() {
283 result |= DmaTxInterrupt::Eof;
284 }
285 if int_ena.out_done().bit_is_set() {
286 result |= DmaTxInterrupt::Done;
287 }
288
289 result
290 }
291
292 fn clear(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
293 self.int().clr().write(|w| {
294 for interrupt in interrupts.into() {
295 match interrupt {
296 DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
297 DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
298 DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
299 DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
300 };
301 }
302 w
303 });
304 }
305
306 fn pending_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
307 let mut result = EnumSet::new();
308
309 let int_raw = self.int().raw().read();
310 if int_raw.out_total_eof().bit_is_set() {
311 result |= DmaTxInterrupt::TotalEof;
312 }
313 if int_raw.out_dscr_err().bit_is_set() {
314 result |= DmaTxInterrupt::DescriptorError;
315 }
316 if int_raw.out_eof().bit_is_set() {
317 result |= DmaTxInterrupt::Eof;
318 }
319 if int_raw.out_done().bit_is_set() {
320 result |= DmaTxInterrupt::Done;
321 }
322
323 result
324 }
325
326 fn waker(&self) -> &'static AtomicWaker {
327 &TX_WAKERS[self.0 as usize]
328 }
329
330 fn is_async(&self) -> bool {
331 cfg_if::cfg_if! {
332 if #[cfg(any(esp32c2, esp32c3))] {
333 TX_IS_ASYNC[self.0 as usize].load(portable_atomic::Ordering::Acquire)
334 } else {
335 true
336 }
337 }
338 }
339
340 fn set_async(&self, _is_async: bool) {
341 cfg_if::cfg_if! {
342 if #[cfg(any(esp32c2, esp32c3))] {
343 TX_IS_ASYNC[self.0 as usize].store(_is_async, portable_atomic::Ordering::Release);
344 }
345 }
346 }
347}
348
349impl crate::private::Sealed for AnyGdmaRxChannel {}
350impl DmaRxChannel for AnyGdmaRxChannel {}
351
352impl AnyGdmaRxChannel {
353 #[inline(always)]
354 fn ch(&self) -> &pac::dma::ch::CH {
355 DMA::regs().ch(self.0 as usize)
356 }
357
358 #[cfg(any(esp32c2, esp32c3))]
359 #[inline(always)]
360 fn int(&self) -> &pac::dma::int_ch::INT_CH {
361 DMA::regs().int_ch(self.0 as usize)
362 }
363
364 #[inline(always)]
365 #[cfg(any(esp32c6, esp32h2))]
366 fn int(&self) -> &pac::dma::in_int_ch::IN_INT_CH {
367 DMA::regs().in_int_ch(self.0 as usize)
368 }
369
370 #[cfg(esp32s3)]
371 #[inline(always)]
372 fn int(&self) -> &pac::dma::ch::in_int::IN_INT {
373 DMA::regs().ch(self.0 as usize).in_int()
374 }
375}
376
377impl RegisterAccess for AnyGdmaRxChannel {
378 fn reset(&self) {
379 let conf0 = self.ch().in_conf0();
380 conf0.modify(|_, w| w.in_rst().set_bit());
381 conf0.modify(|_, w| w.in_rst().clear_bit());
382 }
383
384 fn set_burst_mode(&self, burst_mode: BurstConfig) {
385 self.ch()
386 .in_conf0()
387 .modify(|_, w| w.in_data_burst_en().bit(burst_mode.is_burst_enabled()));
388 }
389
390 fn set_descr_burst_mode(&self, burst_mode: bool) {
391 self.ch()
392 .in_conf0()
393 .modify(|_, w| w.indscr_burst_en().bit(burst_mode));
394 }
395
396 fn set_priority(&self, priority: DmaPriority) {
397 self.ch()
398 .in_pri()
399 .write(|w| unsafe { w.rx_pri().bits(priority as u8) });
400 }
401
402 fn set_peripheral(&self, peripheral: u8) {
403 self.ch()
404 .in_peri_sel()
405 .modify(|_, w| unsafe { w.peri_in_sel().bits(peripheral) });
406 }
407
408 fn set_link_addr(&self, address: u32) {
409 self.ch()
410 .in_link()
411 .modify(|_, w| unsafe { w.inlink_addr().bits(address) });
412 }
413
414 fn start(&self) {
415 self.ch()
416 .in_link()
417 .modify(|_, w| w.inlink_start().set_bit());
418 }
419
420 fn stop(&self) {
421 self.ch().in_link().modify(|_, w| w.inlink_stop().set_bit());
422 }
423
424 fn restart(&self) {
425 self.ch()
426 .in_link()
427 .modify(|_, w| w.inlink_restart().set_bit());
428 }
429
430 fn set_check_owner(&self, check_owner: Option<bool>) {
431 self.ch()
432 .in_conf1()
433 .modify(|_, w| w.in_check_owner().bit(check_owner.unwrap_or(true)));
434 }
435
436 #[cfg(esp32s3)]
437 fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
438 self.ch()
439 .in_conf1()
440 .modify(|_, w| unsafe { w.in_ext_mem_bk_size().bits(size as u8) });
441 }
442
443 #[cfg(psram_dma)]
444 fn can_access_psram(&self) -> bool {
445 true
446 }
447}
448
449impl RxRegisterAccess for AnyGdmaRxChannel {
450 fn set_mem2mem_mode(&self, value: bool) {
451 self.ch()
452 .in_conf0()
453 .modify(|_, w| w.mem_trans_en().bit(value));
454 }
455
456 fn async_handler(&self) -> Option<InterruptHandler> {
457 match self.0 {
458 0 => DmaChannel0::handler_in(),
459 #[cfg(not(esp32c2))]
460 1 => DmaChannel1::handler_in(),
461 #[cfg(not(esp32c2))]
462 2 => DmaChannel2::handler_in(),
463 #[cfg(esp32s3)]
464 3 => DmaChannel3::handler_in(),
465 #[cfg(esp32s3)]
466 4 => DmaChannel4::handler_in(),
467 _ => unreachable!(),
468 }
469 }
470
471 fn peripheral_interrupt(&self) -> Option<Interrupt> {
472 match self.0 {
473 0 => DmaChannel0::isr_in(),
474 #[cfg(not(esp32c2))]
475 1 => DmaChannel1::isr_in(),
476 #[cfg(not(esp32c2))]
477 2 => DmaChannel2::isr_in(),
478 #[cfg(esp32s3)]
479 3 => DmaChannel3::isr_in(),
480 #[cfg(esp32s3)]
481 4 => DmaChannel4::isr_in(),
482 _ => unreachable!(),
483 }
484 }
485}
486
487impl InterruptAccess<DmaRxInterrupt> for AnyGdmaRxChannel {
488 fn enable_listen(&self, interrupts: EnumSet<DmaRxInterrupt>, enable: bool) {
489 self.int().ena().modify(|_, w| {
490 for interrupt in interrupts {
491 match interrupt {
492 DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().bit(enable),
493 DmaRxInterrupt::ErrorEof => w.in_err_eof().bit(enable),
494 DmaRxInterrupt::DescriptorError => w.in_dscr_err().bit(enable),
495 DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().bit(enable),
496 DmaRxInterrupt::Done => w.in_done().bit(enable),
497 };
498 }
499 w
500 });
501 }
502
503 fn is_listening(&self) -> EnumSet<DmaRxInterrupt> {
504 let mut result = EnumSet::new();
505
506 let int_ena = self.int().ena().read();
507 if int_ena.in_dscr_err().bit_is_set() {
508 result |= DmaRxInterrupt::DescriptorError;
509 }
510 if int_ena.in_dscr_empty().bit_is_set() {
511 result |= DmaRxInterrupt::DescriptorEmpty;
512 }
513 if int_ena.in_suc_eof().bit_is_set() {
514 result |= DmaRxInterrupt::SuccessfulEof;
515 }
516 if int_ena.in_err_eof().bit_is_set() {
517 result |= DmaRxInterrupt::ErrorEof;
518 }
519 if int_ena.in_done().bit_is_set() {
520 result |= DmaRxInterrupt::Done;
521 }
522
523 result
524 }
525
526 fn clear(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
527 self.int().clr().write(|w| {
528 for interrupt in interrupts.into() {
529 match interrupt {
530 DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
531 DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
532 DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
533 DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
534 DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
535 };
536 }
537 w
538 });
539 }
540
541 fn pending_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
542 let mut result = EnumSet::new();
543
544 let int_raw = self.int().raw().read();
545 if int_raw.in_dscr_err().bit_is_set() {
546 result |= DmaRxInterrupt::DescriptorError;
547 }
548 if int_raw.in_dscr_empty().bit_is_set() {
549 result |= DmaRxInterrupt::DescriptorEmpty;
550 }
551 if int_raw.in_suc_eof().bit_is_set() {
552 result |= DmaRxInterrupt::SuccessfulEof;
553 }
554 if int_raw.in_err_eof().bit_is_set() {
555 result |= DmaRxInterrupt::ErrorEof;
556 }
557 if int_raw.in_done().bit_is_set() {
558 result |= DmaRxInterrupt::Done;
559 }
560
561 result
562 }
563
564 fn waker(&self) -> &'static AtomicWaker {
565 &RX_WAKERS[self.0 as usize]
566 }
567
568 fn is_async(&self) -> bool {
569 cfg_if::cfg_if! {
570 if #[cfg(any(esp32c2, esp32c3))] {
571 RX_IS_ASYNC[self.0 as usize].load(portable_atomic::Ordering::Acquire)
572 } else {
573 true
574 }
575 }
576 }
577
578 fn set_async(&self, _is_async: bool) {
579 cfg_if::cfg_if! {
580 if #[cfg(any(esp32c2, esp32c3))] {
581 RX_IS_ASYNC[self.0 as usize].store(_is_async, portable_atomic::Ordering::Release);
582 }
583 }
584 }
585}
586
587impl<CH: DmaChannel, Dm: DriverMode> Channel<'_, Dm, CH> {
588 pub fn runtime_ensure_compatible<P: DmaEligible>(&self, _peripheral: &PeripheralRef<'_, P>) {
590 }
592}
593
594macro_rules! impl_channel {
595 ($num:literal, $interrupt_in:ident $(, $interrupt_out:ident)? ) => {
596 paste::paste! {
597 #[non_exhaustive]
599 #[derive(Debug, PartialEq, Eq)]
600 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
601 pub struct [<DmaChannel $num>] {}
602
603 impl $crate::private::Sealed for [<DmaChannel $num>] {}
604
605 impl Peripheral for [<DmaChannel $num>] {
606 type P = Self;
607
608 unsafe fn clone_unchecked(&self) -> Self::P {
609 Self::steal()
610 }
611 }
612
613 impl [<DmaChannel $num>] {
614 pub unsafe fn steal() -> Self {
620 Self {}
621 }
622 }
623
624 impl [<DmaChannel $num>] {
625 fn handler_in() -> Option<InterruptHandler> {
626 $crate::if_set! {
627 $({
628 #[handler(priority = Priority::max())]
630 fn interrupt_handler_in() {
631 $crate::ignore!($interrupt_out);
632 super::asynch::handle_in_interrupt::<[< DmaChannel $num >]>();
633 }
634 Some(interrupt_handler_in)
635 })?,
636 {
637 #[handler(priority = Priority::max())]
638 fn interrupt_handler() {
639 super::asynch::handle_in_interrupt::<[< DmaChannel $num >]>();
640 super::asynch::handle_out_interrupt::<[< DmaChannel $num >]>();
641 }
642 Some(interrupt_handler)
643 }
644 }
645 }
646
647 fn isr_in() -> Option<Interrupt> {
648 Some(Interrupt::$interrupt_in)
649 }
650
651 fn handler_out() -> Option<InterruptHandler> {
652 $crate::if_set! {
653 $({
654 #[handler(priority = Priority::max())]
655 fn interrupt_handler_out() {
656 $crate::ignore!($interrupt_out);
657 super::asynch::handle_out_interrupt::<[< DmaChannel $num >]>();
658 }
659 Some(interrupt_handler_out)
660 })?,
661 None
662 }
663 }
664
665 fn isr_out() -> Option<Interrupt> {
666 $crate::if_set! { $(Some(Interrupt::$interrupt_out))?, None }
667 }
668 }
669
670 impl DmaChannel for [<DmaChannel $num>] {
671 type Rx = AnyGdmaRxChannel;
672 type Tx = AnyGdmaTxChannel;
673
674 unsafe fn split_internal(self, _: $crate::private::Internal) -> (Self::Rx, Self::Tx) {
675 (AnyGdmaRxChannel($num), AnyGdmaTxChannel($num))
676 }
677 }
678
679 impl DmaChannelConvert<AnyGdmaChannel> for [<DmaChannel $num>] {
680 fn degrade(self) -> AnyGdmaChannel {
681 AnyGdmaChannel($num)
682 }
683 }
684
685 impl DmaChannelConvert<AnyGdmaRxChannel> for [<DmaChannel $num>] {
686 fn degrade(self) -> AnyGdmaRxChannel {
687 AnyGdmaRxChannel($num)
688 }
689 }
690
691 impl DmaChannelConvert<AnyGdmaTxChannel> for [<DmaChannel $num>] {
692 fn degrade(self) -> AnyGdmaTxChannel {
693 AnyGdmaTxChannel($num)
694 }
695 }
696
697 impl DmaChannelExt for [<DmaChannel $num>] {
698 fn rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
699 AnyGdmaRxChannel($num)
700 }
701
702 fn tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt> {
703 AnyGdmaTxChannel($num)
704 }
705 }
706 }
707 };
708}
709
710cfg_if::cfg_if! {
711 if #[cfg(esp32c2)] {
712 const CHANNEL_COUNT: usize = 1;
713 impl_channel!(0, DMA_CH0);
714 } else if #[cfg(esp32c3)] {
715 const CHANNEL_COUNT: usize = 3;
716 impl_channel!(0, DMA_CH0);
717 impl_channel!(1, DMA_CH1);
718 impl_channel!(2, DMA_CH2);
719 } else if #[cfg(any(esp32c6, esp32h2))] {
720 const CHANNEL_COUNT: usize = 3;
721 impl_channel!(0, DMA_IN_CH0, DMA_OUT_CH0);
722 impl_channel!(1, DMA_IN_CH1, DMA_OUT_CH1);
723 impl_channel!(2, DMA_IN_CH2, DMA_OUT_CH2);
724 } else if #[cfg(esp32s3)] {
725 const CHANNEL_COUNT: usize = 5;
726 impl_channel!(0, DMA_IN_CH0, DMA_OUT_CH0);
727 impl_channel!(1, DMA_IN_CH1, DMA_OUT_CH1);
728 impl_channel!(2, DMA_IN_CH2, DMA_OUT_CH2);
729 impl_channel!(3, DMA_IN_CH3, DMA_OUT_CH3);
730 impl_channel!(4, DMA_IN_CH4, DMA_OUT_CH4);
731 }
732}
733
734crate::dma::impl_dma_eligible! {
735 AnyGdmaChannel {
736 #[cfg(spi2)]
737 SPI2 => Spi2,
738
739 #[cfg(spi3)]
740 SPI3 => Spi3,
741
742 #[cfg(uhci0)]
743 UHCI0 => Uhci0,
744
745 #[cfg(i2s0)]
746 I2S0 => I2s0,
747
748 #[cfg(i2s1)]
749 I2S1 => I2s1,
750
751 #[cfg(esp32s3)]
752 LCD_CAM => LcdCam,
753
754 #[cfg(all(gdma, aes))]
755 AES => Aes,
756
757 #[cfg(all(gdma, sha))]
758 SHA => Sha,
759
760 #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
761 ADC1 => Adc,
762
763 #[cfg(any(esp32c3, esp32s3))]
764 ADC2 => Adc,
765
766 #[cfg(esp32s3)]
767 RMT => Rmt,
768
769 #[cfg(parl_io)]
770 PARL_IO => ParlIo,
771
772 #[cfg(any(esp32c2, esp32c6, esp32h2))]
773 MEM2MEM1 => Mem2Mem1,
774 }
775}
776
777#[cfg(any(esp32c6, esp32h2))]
778crate::dma::impl_dma_eligible! {
779 AnyGdmaChannel {
780 MEM2MEM4 => Mem2Mem4,
781 MEM2MEM5 => Mem2Mem5,
782 MEM2MEM10 => Mem2Mem10,
783 MEM2MEM11 => Mem2Mem11,
784 MEM2MEM12 => Mem2Mem12,
785 MEM2MEM13 => Mem2Mem13,
786 MEM2MEM14 => Mem2Mem14,
787 MEM2MEM15 => Mem2Mem15,
788 }
789}
790
791pub(super) fn init_dma(_cs: CriticalSection<'_>) {
792 DMA::regs()
793 .misc_conf()
794 .modify(|_, w| w.ahbm_rst_inter().set_bit());
795 DMA::regs()
796 .misc_conf()
797 .modify(|_, w| w.ahbm_rst_inter().clear_bit());
798 DMA::regs().misc_conf().modify(|_, w| w.clk_en().set_bit());
799}