1use core::cell::Cell;
8use kernel::utilities::cells::{OptionalCell, TakeCell};
9use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
10use kernel::utilities::registers::{
11 register_bitfields, register_structs, InMemoryRegister, ReadOnly, ReadWrite, WriteOnly,
12};
13use kernel::utilities::StaticRef;
14
15const DMA_BASE: StaticRef<DmaRegisters> =
16 unsafe { StaticRef::new(0x4000_E000 as *const DmaRegisters) };
17
18static DMA_CONFIG: DmaConfigBlock = DmaConfigBlock([
19 DmaChannelControl::const_default(),
22 DmaChannelControl::const_default(),
23 DmaChannelControl::const_default(),
24 DmaChannelControl::const_default(),
25 DmaChannelControl::const_default(),
26 DmaChannelControl::const_default(),
27 DmaChannelControl::const_default(),
28 DmaChannelControl::const_default(),
29 DmaChannelControl::const_default(),
30 DmaChannelControl::const_default(),
31 DmaChannelControl::const_default(),
32 DmaChannelControl::const_default(),
33 DmaChannelControl::const_default(),
34 DmaChannelControl::const_default(),
35 DmaChannelControl::const_default(),
36 DmaChannelControl::const_default(),
37]);
38
39const MAX_SRC_NR: u8 = 7;
44
45pub const AVAILABLE_DMA_CHANNELS: usize = 8;
47
48const MAX_TRANSFERS_LEN: usize = 1024;
50
51register_structs! {
52 DmaRegisters {
54 (0x0000 => device_cfg: ReadOnly<u32, DMA_DEVICE_CFG::Register>),
56 (0x0004 => sw_chtrig: ReadWrite<u32, DMA_SW_CHTRIG::Register>),
58 (0x0008 => _reserved0),
59 (0x0010 => ch_srccfg: [ReadWrite<u32>; 32]),
61 (0x0090 => _reserved1),
62 (0x0100 => int1_srccfg: ReadWrite<u32, DMA_INT1_SRCCFG::Register>),
64 (0x0104 => int2_srccfg: ReadWrite<u32, DMA_INT2_SRCCFG::Register>),
66 (0x0108 => int3_srccfg: ReadWrite<u32, DMA_INT3_SRCCFG::Register>),
68 (0x010C => _reserved2),
69 (0x0110 => int0_srcflg: ReadOnly<u32, DMA_INT0_SRCFLG::Register>),
71 (0x0114 => int0_clrflg: WriteOnly<u32, DMA_INT0_CLRFLG::Register>),
73 (0x0118 => _reserved3),
74 (0x1000 => stat: ReadOnly<u32, DMA_STAT::Register>),
76 (0x1004 => cfg: WriteOnly<u32, DMA_CFG::Register>),
78 (0x1008 => ctlbase: ReadWrite<u32>),
80 (0x100C => altbase: ReadOnly<u32>),
82 (0x1010 => waitstat: ReadOnly<u32>),
84 (0x1014 => wreq: WriteOnly<u32>),
86 (0x1018 => useburstset: ReadWrite<u32>),
88 (0x101C => useburstclr: WriteOnly<u32>),
90 (0x1020 => reqmaskset: ReadWrite<u32>),
92 (0x1024 => reqmaskclr: WriteOnly<u32>),
94 (0x1028 => enaset: ReadWrite<u32>),
96 (0x102C => enaclr: WriteOnly<u32>),
98 (0x1030 => altset: ReadWrite<u32>),
100 (0x1034 => altclr: WriteOnly<u32>),
102 (0x1038 => prioset: ReadWrite<u32>),
104 (0x103C => prioclr: WriteOnly<u32>),
106 (0x1040 => _reserved4),
107 (0x104C => errclr: ReadWrite<u32>),
109 (0x1050 => @END),
110 }
111}
112
113register_bitfields![u32,
114 DMA_DEVICE_CFG [
115 NUM_DMA_CHANNELS OFFSET(0) NUMBITS(8) [],
117 NUM_SRC_PER_CHANNEL OFFSET(8) NUMBITS(8) []
119 ],
120 DMA_SW_CHTRIG [
121 CH0 OFFSET(0) NUMBITS(1) [],
123 CH1 OFFSET(1) NUMBITS(1) [],
125 CH2 OFFSET(2) NUMBITS(1) [],
127 CH3 OFFSET(3) NUMBITS(1) [],
129 CH4 OFFSET(4) NUMBITS(1) [],
131 CH5 OFFSET(5) NUMBITS(1) [],
133 CH6 OFFSET(6) NUMBITS(1) [],
135 CH7 OFFSET(7) NUMBITS(1) [],
137 CH8 OFFSET(8) NUMBITS(1) [],
139 CH9 OFFSET(9) NUMBITS(1) [],
141 CH10 OFFSET(10) NUMBITS(1) [],
143 CH11 OFFSET(11) NUMBITS(1) [],
145 CH12 OFFSET(12) NUMBITS(1) [],
147 CH13 OFFSET(13) NUMBITS(1) [],
149 CH14 OFFSET(14) NUMBITS(1) [],
151 CH15 OFFSET(15) NUMBITS(1) [],
153 CH16 OFFSET(16) NUMBITS(1) [],
155 CH17 OFFSET(17) NUMBITS(1) [],
157 CH18 OFFSET(18) NUMBITS(1) [],
159 CH19 OFFSET(19) NUMBITS(1) [],
161 CH20 OFFSET(20) NUMBITS(1) [],
163 CH21 OFFSET(21) NUMBITS(1) [],
165 CH22 OFFSET(22) NUMBITS(1) [],
167 CH23 OFFSET(23) NUMBITS(1) [],
169 CH24 OFFSET(24) NUMBITS(1) [],
171 CH25 OFFSET(25) NUMBITS(1) [],
173 CH26 OFFSET(26) NUMBITS(1) [],
175 CH27 OFFSET(27) NUMBITS(1) [],
177 CH28 OFFSET(28) NUMBITS(1) [],
179 CH29 OFFSET(29) NUMBITS(1) [],
181 CH30 OFFSET(30) NUMBITS(1) [],
183 CH31 OFFSET(31) NUMBITS(1) []
185 ],
186 DMA_INT1_SRCCFG [
187 INT_SRC OFFSET(0) NUMBITS(5) [],
189 EN OFFSET(5) NUMBITS(1) []
191 ],
192 DMA_INT2_SRCCFG [
193 INT_SRC OFFSET(0) NUMBITS(5) [],
195 EN OFFSET(5) NUMBITS(1) []
197 ],
198 DMA_INT3_SRCCFG [
199 INT_SRC OFFSET(0) NUMBITS(5) [],
201 EN OFFSET(5) NUMBITS(1) []
203 ],
204 DMA_INT0_SRCFLG [
205 CH0 OFFSET(0) NUMBITS(1) [],
207 CH1 OFFSET(1) NUMBITS(1) [],
209 CH2 OFFSET(2) NUMBITS(1) [],
211 CH3 OFFSET(3) NUMBITS(1) [],
213 CH4 OFFSET(4) NUMBITS(1) [],
215 CH5 OFFSET(5) NUMBITS(1) [],
217 CH6 OFFSET(6) NUMBITS(1) [],
219 CH7 OFFSET(7) NUMBITS(1) [],
221 CH8 OFFSET(8) NUMBITS(1) [],
223 CH9 OFFSET(9) NUMBITS(1) [],
225 CH10 OFFSET(10) NUMBITS(1) [],
227 CH11 OFFSET(11) NUMBITS(1) [],
229 CH12 OFFSET(12) NUMBITS(1) [],
231 CH13 OFFSET(13) NUMBITS(1) [],
233 CH14 OFFSET(14) NUMBITS(1) [],
235 CH15 OFFSET(15) NUMBITS(1) [],
237 CH16 OFFSET(16) NUMBITS(1) [],
239 CH17 OFFSET(17) NUMBITS(1) [],
241 CH18 OFFSET(18) NUMBITS(1) [],
243 CH19 OFFSET(19) NUMBITS(1) [],
245 CH20 OFFSET(20) NUMBITS(1) [],
247 CH21 OFFSET(21) NUMBITS(1) [],
249 CH22 OFFSET(22) NUMBITS(1) [],
251 CH23 OFFSET(23) NUMBITS(1) [],
253 CH24 OFFSET(24) NUMBITS(1) [],
255 CH25 OFFSET(25) NUMBITS(1) [],
257 CH26 OFFSET(26) NUMBITS(1) [],
259 CH27 OFFSET(27) NUMBITS(1) [],
261 CH28 OFFSET(28) NUMBITS(1) [],
263 CH29 OFFSET(29) NUMBITS(1) [],
265 CH30 OFFSET(30) NUMBITS(1) [],
267 CH31 OFFSET(31) NUMBITS(1) []
269 ],
270 DMA_INT0_CLRFLG [
271 CH0 OFFSET(0) NUMBITS(1) [],
273 CH1 OFFSET(1) NUMBITS(1) [],
275 CH2 OFFSET(2) NUMBITS(1) [],
277 CH3 OFFSET(3) NUMBITS(1) [],
279 CH4 OFFSET(4) NUMBITS(1) [],
281 CH5 OFFSET(5) NUMBITS(1) [],
283 CH6 OFFSET(6) NUMBITS(1) [],
285 CH7 OFFSET(7) NUMBITS(1) [],
287 CH8 OFFSET(8) NUMBITS(1) [],
289 CH9 OFFSET(9) NUMBITS(1) [],
291 CH10 OFFSET(10) NUMBITS(1) [],
293 CH11 OFFSET(11) NUMBITS(1) [],
295 CH12 OFFSET(12) NUMBITS(1) [],
297 CH13 OFFSET(13) NUMBITS(1) [],
299 CH14 OFFSET(14) NUMBITS(1) [],
301 CH15 OFFSET(15) NUMBITS(1) [],
303 CH16 OFFSET(16) NUMBITS(1) [],
305 CH17 OFFSET(17) NUMBITS(1) [],
307 CH18 OFFSET(18) NUMBITS(1) [],
309 CH19 OFFSET(19) NUMBITS(1) [],
311 CH20 OFFSET(20) NUMBITS(1) [],
313 CH21 OFFSET(21) NUMBITS(1) [],
315 CH22 OFFSET(22) NUMBITS(1) [],
317 CH23 OFFSET(23) NUMBITS(1) [],
319 CH24 OFFSET(24) NUMBITS(1) [],
321 CH25 OFFSET(25) NUMBITS(1) [],
323 CH26 OFFSET(26) NUMBITS(1) [],
325 CH27 OFFSET(27) NUMBITS(1) [],
327 CH28 OFFSET(28) NUMBITS(1) [],
329 CH29 OFFSET(29) NUMBITS(1) [],
331 CH30 OFFSET(30) NUMBITS(1) [],
333 CH31 OFFSET(31) NUMBITS(1) []
335 ],
336 DMA_STAT [
337 MASTEN OFFSET(0) NUMBITS(1) [
339 ControllerDisabled = 0,
341 ControllerEnabled = 1
343 ],
344 STATE OFFSET(4) NUMBITS(4) [
347 Idle = 0,
349 ReadingChannelControllerData = 1,
351 ReadingSourceDataEndPointer = 2,
353 ReadingDestinationDataEndPointer = 3,
355 ReadingSourceData = 4,
357 WritingDestinationData = 5,
359 WaitingForDMARequestToClear = 6,
361 WritingChannelControllerData = 7,
363 Stalled = 8,
365 Done = 9,
367 PeripheralScatterGatherTransition = 10
369 ],
370 DMACHANS OFFSET(16) NUMBITS(5) [
372 ControllerConfiguredToUse1DMAChannel = 0,
374 ControllerConfiguredToUse2DMAChannels = 1,
376 ControllerConfiguredToUse31DMAChannels = 30,
378 ControllerConfiguredToUse32DMAChannels = 31
380 ],
381 TESTSTAT OFFSET(28) NUMBITS(4) [
383 ControllerDoesNotIncludeTheIntegrationTestLogic = 0,
385 ControllerIncludesTheIntegrationTestLogic = 1
387 ]
388 ],
389 DMA_CFG [
390 MASTEN OFFSET(0) NUMBITS(1) [
392 ControllerDisabled = 0,
394 ControllerEnabled = 1
396 ],
397 CHPROTCTRL OFFSET(5) NUMBITS(3) []
399 ]
400];
401
402register_bitfields![u32,
403 DMA_CTRL [
405 CYCLE_CTRL OFFSET(0) NUMBITS(3) [
407 Stop = 0,
409 Basic = 1,
411 Auto = 2,
413 PingPong = 3,
415 MemoryScatterGatherPrimary = 4,
417 MemoryScatterGatherAlternate = 5,
419 PeripheralScatterGatherPrimary = 6,
421 PeripheralScatterGatherAlternate = 7
423 ],
424 NEXT_USEBURST OFFSET(3) NUMBITS(1) [],
426 N_MINUS_1 OFFSET(4) NUMBITS(10) [],
429 R_POWER OFFSET(14) NUMBITS(4) [],
433 SRC_PROT_CTRL OFFSET(18) NUMBITS(3) [],
437 DST_PROT_CTRL OFFSET(21) NUMBITS(3) [],
441 SRC_SIZE OFFSET(24) NUMBITS(2) [
443 Byte = 0,
445 HalfWord = 1,
447 Word = 2
449 ],
450 SRC_INC OFFSET(26) NUMBITS(2) [
452 Byte = 0,
454 HalfWord = 1,
456 Word = 2,
458 NoIncrement = 3
460 ],
461 DST_SIZE OFFSET(28) NUMBITS(2) [
464 Byte = 0,
466 HalfWord = 1,
468 Word = 2
470 ],
471 DST_INC OFFSET(30) NUMBITS(2) [
473 Byte = 0,
475 HalfWord = 1,
477 Word = 2,
479 NoIncrement = 3
481 ]
482 ]
483];
484
485#[repr(align(16))]
491struct DmaChannelControl {
492 src_ptr: InMemoryRegister<u32>,
493 dst_ptr: InMemoryRegister<u32>,
494 ctrl: InMemoryRegister<u32, DMA_CTRL::Register>,
495 _unused: InMemoryRegister<u32>,
496}
497
498#[repr(align(256))]
501struct DmaConfigBlock([DmaChannelControl; 2 * AVAILABLE_DMA_CHANNELS]);
502
503unsafe impl Sync for DmaConfigBlock {}
506
507pub trait DmaClient {
509 fn transfer_done(
510 &self,
511 tx_buf: Option<&'static mut [u8]>,
512 rx_buf: Option<&'static mut [u8]>,
513 transmitted_bytes: usize,
514 );
515}
516
517#[repr(u32)]
518#[derive(Copy, Clone, PartialEq)]
519pub enum DmaMode {
520 Basic = 1,
521 AutoRequest = 2,
522 PingPong = 3,
523 MemoryScatterGather = 4,
524 PeripheralScatterGather = 6,
525}
526
527#[repr(u32)]
528#[derive(Copy, Clone)]
529pub enum DmaDataWidth {
530 Width8Bit,
531 Width16Bit,
532 Width32Bit,
533}
534
535#[repr(u32)]
536#[derive(Copy, Clone, PartialEq)]
537pub enum DmaPtrIncrement {
538 Incr8Bit,
539 Incr16Bit,
540 Incr32Bit,
541 NoIncr,
542}
543
544#[derive(Copy, Clone)]
545pub struct DmaConfig {
546 pub src_chan: u8,
547 pub mode: DmaMode,
548 pub width: DmaDataWidth,
549 pub src_incr: DmaPtrIncrement,
550 pub dst_incr: DmaPtrIncrement,
551}
552
553#[derive(Copy, Clone, PartialEq)]
554enum DmaTransferType {
555 PeripheralToMemory,
556 PeripheralToMemoryPingPong,
557 MemoryToPeripheral,
558 MemoryToMemory,
559 None,
560}
561
562#[derive(Copy, Clone, PartialEq)]
563enum ActiveBuffer {
564 Primary,
565 Alternative,
566}
567
568pub struct DmaChannels<'a> {
569 pub channels: [DmaChannel<'a>; AVAILABLE_DMA_CHANNELS],
570}
571
572impl DmaChannels<'_> {
573 pub fn new() -> Self {
574 Self {
575 channels: [
576 crate::dma::DmaChannel::new(0), crate::dma::DmaChannel::new(1), crate::dma::DmaChannel::new(2),
579 crate::dma::DmaChannel::new(3),
580 crate::dma::DmaChannel::new(4),
581 crate::dma::DmaChannel::new(5),
582 crate::dma::DmaChannel::new(6),
583 crate::dma::DmaChannel::new(7), ],
585 }
586 }
587
588 pub fn handle_interrupt(&self, int_nr: isize) {
589 if int_nr == 0 {
590 let int = self.channels[0].registers.int0_srcflg.get();
593
594 for i in 0..AVAILABLE_DMA_CHANNELS {
595 let bit = (1 << i) as u32;
596 if (bit & int) > 0 {
597 self.channels[i].registers.int0_clrflg.set(bit);
599
600 self.channels[i].handle_interrupt();
601 }
602 }
603 } else if int_nr < 0 {
604 panic!("DMA: error interrupt");
605 } else {
606 panic!("DMA: unhandled interrupt-nr: {}", int_nr);
607 }
608 }
609}
610
611impl<'a> core::ops::Index<usize> for DmaChannels<'a> {
612 type Output = DmaChannel<'a>;
613
614 fn index(&self, idx: usize) -> &Self::Output {
615 &self.channels[idx]
616 }
617}
618
619pub struct DmaChannel<'a> {
620 registers: StaticRef<DmaRegisters>,
621 chan_nr: usize,
622 in_use: Cell<bool>,
623 config: Cell<DmaConfig>,
624 transfer_type: Cell<DmaTransferType>,
625 active_buf: Cell<ActiveBuffer>,
626 tx_buf_prim: TakeCell<'static, [u8]>,
627 rx_buf_prim: TakeCell<'static, [u8]>,
628 tx_buf_alt: TakeCell<'static, [u8]>,
629 rx_buf_alt: TakeCell<'static, [u8]>,
630 bytes_to_transmit_prim: Cell<usize>,
631 bytes_to_transmit_alt: Cell<usize>,
632 remaining_words: Cell<usize>,
633 client: OptionalCell<&'a dyn DmaClient>,
634}
635
636impl DmaChannelControl {
637 const fn const_default() -> Self {
638 Self {
639 src_ptr: InMemoryRegister::new(0),
640 dst_ptr: InMemoryRegister::new(0),
641 ctrl: InMemoryRegister::new(0),
642 _unused: InMemoryRegister::new(0),
643 }
644 }
645}
646
647impl DmaConfig {
648 const fn const_default() -> Self {
649 Self {
650 src_chan: 1,
651 mode: DmaMode::Basic,
652 width: DmaDataWidth::Width8Bit,
653 src_incr: DmaPtrIncrement::NoIncr,
655 dst_incr: DmaPtrIncrement::Incr8Bit,
656 }
657 }
658}
659
660impl<'a> DmaChannel<'a> {
661 pub fn new(chan_nr: usize) -> DmaChannel<'a> {
662 DmaChannel {
663 registers: DMA_BASE,
664 chan_nr,
665 in_use: Cell::new(false),
666 config: Cell::new(DmaConfig::const_default()),
667 transfer_type: Cell::new(DmaTransferType::None),
668 active_buf: Cell::new(ActiveBuffer::Primary),
669 tx_buf_prim: TakeCell::empty(),
670 rx_buf_prim: TakeCell::empty(),
671 tx_buf_alt: TakeCell::empty(),
672 rx_buf_alt: TakeCell::empty(),
673 bytes_to_transmit_prim: Cell::new(0),
674 bytes_to_transmit_alt: Cell::new(0),
675 remaining_words: Cell::new(0),
676 client: OptionalCell::empty(),
677 }
678 }
679
680 fn dma_is_enabled(&self) -> bool {
681 self.registers.stat.is_set(DMA_STAT::MASTEN)
682 }
683
684 fn enable_dma(&self) {
685 self.registers.cfg.write(DMA_CFG::MASTEN::ControllerEnabled);
687
688 let addr = (core::ptr::from_ref::<DmaChannelControl>(&DMA_CONFIG.0[0]) as u32) & (!0xFFu32);
691 self.registers.ctlbase.set(addr);
692 }
693
694 fn apply_config(&self) {
695 let conf = self.config.get();
696
697 if conf.mode == DmaMode::MemoryScatterGather {
698 panic!("DMA: Memory scatter-gather mode currently not supported!");
699 }
700 if conf.mode == DmaMode::PeripheralScatterGather {
701 panic!("DMA: Peripheral scatter-gather mode currently not supported!");
702 }
703
704 DMA_CONFIG.0[self.chan_nr].ctrl.modify(
710 DMA_CTRL::SRC_SIZE.val(conf.width as u32)
711 + DMA_CTRL::DST_SIZE.val(conf.width as u32)
712 + DMA_CTRL::SRC_INC.val(conf.src_incr as u32)
713 + DMA_CTRL::DST_INC.val(conf.dst_incr as u32),
714 );
715
716 self.registers.ch_srccfg[self.chan_nr].set((conf.src_chan % (MAX_SRC_NR + 1)) as u32);
718 }
719
720 fn enable_dma_channel(&self) {
721 self.registers
722 .enaset
723 .set(self.registers.enaset.get() | ((1 << self.chan_nr) as u32));
724 }
725
726 fn setup_transfer_primary_buffer(&self, len: usize) {
727 self.configure_channel(len, self.chan_nr);
728
729 self.bytes_to_transmit_prim.set(len);
731 }
732
733 fn setup_transfer_alternate_buffer(&self, len: usize) {
734 self.configure_channel(len, self.chan_nr + AVAILABLE_DMA_CHANNELS);
735
736 self.bytes_to_transmit_alt.set(len);
738 }
739
740 fn update_buffer_ptr(&self) {
741 let rem_words = self.remaining_words.get();
742 let tt = self.transfer_type.get();
743 let conf = self.config.get();
744 let (len, chan_nr) = if tt == DmaTransferType::PeripheralToMemoryPingPong
745 && self.active_buf.get() == ActiveBuffer::Alternative
746 {
747 (
748 self.bytes_to_transmit_alt.get(),
749 self.chan_nr + AVAILABLE_DMA_CHANNELS,
750 )
751 } else {
752 (self.bytes_to_transmit_prim.get(), self.chan_nr)
753 };
754
755 if tt == DmaTransferType::PeripheralToMemory
757 || tt == DmaTransferType::MemoryToMemory
758 || tt == DmaTransferType::PeripheralToMemoryPingPong
759 {
760 DMA_CONFIG.0[chan_nr].dst_ptr.set(
762 DMA_CONFIG.0[chan_nr].dst_ptr.get()
763 + ((MAX_TRANSFERS_LEN as u32) << (conf.width as u32)),
764 );
765 }
766
767 if (tt == DmaTransferType::MemoryToPeripheral) || (tt == DmaTransferType::MemoryToMemory) {
768 DMA_CONFIG.0[chan_nr].src_ptr.set(
770 DMA_CONFIG.0[chan_nr].src_ptr.get()
771 + ((MAX_TRANSFERS_LEN as u32) << (conf.width as u32)),
772 );
773 }
774
775 if rem_words > MAX_TRANSFERS_LEN {
777 self.remaining_words.set(rem_words - MAX_TRANSFERS_LEN);
778 } else {
779 self.remaining_words.set(0);
780 }
781
782 let r_power = if tt == DmaTransferType::MemoryToMemory {
786 if rem_words > MAX_TRANSFERS_LEN {
787 31 - (MAX_TRANSFERS_LEN as u32).leading_zeros()
788 } else {
789 31 - (len as u32).leading_zeros()
790 }
791 } else {
792 0
793 };
794
795 DMA_CONFIG.0[chan_nr].ctrl.modify(
799 DMA_CTRL::CYCLE_CTRL.val(conf.mode as u32)
800 + DMA_CTRL::N_MINUS_1.val(((rem_words - 1) % MAX_TRANSFERS_LEN) as u32)
801 + DMA_CTRL::R_POWER.val(r_power),
802 );
803 }
804
805 fn calc_remaining_words(&self, bytes_to_transmit: usize) {
806 let transfers = bytes_to_transmit >> (self.config.get().width as usize);
807
808 if transfers > MAX_TRANSFERS_LEN {
810 self.remaining_words.set(transfers - MAX_TRANSFERS_LEN);
811 } else {
812 self.remaining_words.set(0);
813 }
814 }
815
816 fn configure_channel(&self, bytes_to_transmit: usize, chan_nr: usize) {
817 let conf = self.config.get();
818 let transfers = bytes_to_transmit >> (conf.width as usize);
819 DMA_CONFIG.0[chan_nr].ctrl.modify(
823 DMA_CTRL::N_MINUS_1.val(((transfers - 1) % MAX_TRANSFERS_LEN) as u32)
824 + DMA_CTRL::R_POWER.val(0)
825 + DMA_CTRL::CYCLE_CTRL.val(conf.mode as u32),
826 );
827 }
828
829 fn set_primary_buffer(&self, src_end_ptr: u32, dst_end_ptr: u32) {
830 DMA_CONFIG.0[self.chan_nr].src_ptr.set(src_end_ptr);
831 DMA_CONFIG.0[self.chan_nr].dst_ptr.set(dst_end_ptr);
832 }
833
834 fn set_alternative_buffer(&self, src_end_ptr: u32, dst_end_ptr: u32) {
835 DMA_CONFIG.0[self.chan_nr + AVAILABLE_DMA_CHANNELS]
836 .src_ptr
837 .set(src_end_ptr);
838 DMA_CONFIG.0[self.chan_nr + AVAILABLE_DMA_CHANNELS]
839 .dst_ptr
840 .set(dst_end_ptr);
841 }
842
843 fn set_dma_mode(&self, mode: DmaMode) {
844 let mut conf = self.config.get();
845 conf.mode = mode;
846 self.config.set(conf);
847 }
848
849 fn handle_interrupt(&self) {
850 if self.remaining_words.get() > 0 {
851 self.update_buffer_ptr();
852 } else {
853 if self.transfer_type.get() != DmaTransferType::PeripheralToMemoryPingPong {
854 self.registers.enaclr.set((1 << self.chan_nr) as u32);
856 }
857 match self.transfer_type.get() {
859 DmaTransferType::PeripheralToMemory => {
860 self.client.map(|cl| {
861 self.rx_buf_prim.take().map(|rx_buf| {
862 cl.transfer_done(None, Some(rx_buf), self.bytes_to_transmit_prim.get())
863 })
864 });
865 }
866 DmaTransferType::MemoryToPeripheral => {
867 self.client.map(|cl| {
868 self.tx_buf_prim.take().map(|tx_buf| {
869 cl.transfer_done(Some(tx_buf), None, self.bytes_to_transmit_prim.get())
870 })
871 });
872 }
873 DmaTransferType::MemoryToMemory => {
874 self.client.map(|cl| {
875 self.tx_buf_prim.take().map(|tx_buf| {
876 self.rx_buf_prim.take().map(move |rx_buf| {
877 cl.transfer_done(
878 Some(tx_buf),
879 Some(rx_buf),
880 self.bytes_to_transmit_prim.get(),
881 )
882 })
883 })
884 });
885 }
886 DmaTransferType::PeripheralToMemoryPingPong => {
887 let (buf, len) = if self.active_buf.get() == ActiveBuffer::Primary {
888 self.active_buf.set(ActiveBuffer::Alternative);
889 self.calc_remaining_words(self.bytes_to_transmit_alt.get());
890 (self.rx_buf_prim.take(), self.bytes_to_transmit_prim.get())
891 } else {
892 self.active_buf.set(ActiveBuffer::Primary);
893 self.calc_remaining_words(self.bytes_to_transmit_prim.get());
894 (self.rx_buf_alt.take(), self.bytes_to_transmit_alt.get())
895 };
896
897 self.client
898 .map(|cl| buf.map(|buf| cl.transfer_done(None, Some(buf), len)));
899 }
900 _ => {}
901 }
902 }
903 }
904
905 pub fn set_client(&self, client: &'a dyn DmaClient) {
906 if self.client.is_some() {
907 panic!("DMA: channel {} is already in use!", self.chan_nr);
908 }
909 self.client.set(client);
910 }
911
912 pub fn initialize(&self, config: &DmaConfig) {
913 if self.in_use.get() {
914 panic!("DMA: channel {} is already in use!", self.chan_nr);
915 }
916
917 if !self.dma_is_enabled() {
918 self.enable_dma();
919 }
920
921 self.in_use.set(true);
922 self.config.set(*config);
923 self.apply_config();
924 }
925
926 pub fn transfer_mem_to_mem(
928 &self,
929 src_buf: &'static mut [u8],
930 dst_buf: &'static mut [u8],
931 len: usize,
932 ) {
933 let width = self.config.get().width as u32;
937
938 let transfers = len >> width;
940
941 let src_end_ptr = (core::ptr::from_ref::<u8>(&src_buf[0]) as u32) + ((len as u32) - 1);
944 let dst_end_ptr = (core::ptr::from_ref::<u8>(&dst_buf[0]) as u32) + ((len as u32) - 1);
945
946 self.set_dma_mode(DmaMode::Basic);
948 self.set_primary_buffer(src_end_ptr, dst_end_ptr);
949 self.setup_transfer_primary_buffer(len);
950
951 self.calc_remaining_words(len);
953
954 let r_power = if transfers > MAX_TRANSFERS_LEN {
958 31 - (MAX_TRANSFERS_LEN as u32).leading_zeros()
959 } else {
960 31 - (len as u32).leading_zeros()
961 };
962
963 DMA_CONFIG.0[self.chan_nr]
965 .ctrl
966 .modify(DMA_CTRL::R_POWER.val(r_power));
967
968 self.rx_buf_prim.replace(dst_buf);
970 self.tx_buf_prim.replace(src_buf);
971
972 self.transfer_type.set(DmaTransferType::MemoryToMemory);
974
975 self.enable_dma_channel();
977 }
978
979 pub fn transfer_periph_to_mem(&self, src_reg: *const (), buf: &'static mut [u8], len: usize) {
981 let src_end_ptr = src_reg as u32;
984 let dst_end_ptr = (core::ptr::from_ref::<u8>(&buf[0]) as u32) + ((len as u32) - 1);
985
986 self.set_dma_mode(DmaMode::Basic);
988 self.set_primary_buffer(src_end_ptr, dst_end_ptr);
989 self.setup_transfer_primary_buffer(len);
990
991 self.rx_buf_prim.replace(buf);
993
994 self.calc_remaining_words(len);
996
997 self.transfer_type.set(DmaTransferType::PeripheralToMemory);
999
1000 self.enable_dma_channel();
1001 }
1002
1003 pub fn transfer_mem_to_periph(&self, dst_reg: *const (), buf: &'static mut [u8], len: usize) {
1005 let src_end_ptr = (core::ptr::from_ref::<u8>(&buf[0]) as u32) + ((len as u32) - 1);
1008 let dst_end_ptr = dst_reg as u32;
1009
1010 self.set_dma_mode(DmaMode::Basic);
1012 self.set_primary_buffer(src_end_ptr, dst_end_ptr);
1013 self.setup_transfer_primary_buffer(len);
1014
1015 self.tx_buf_prim.replace(buf);
1017
1018 self.calc_remaining_words(len);
1020
1021 self.transfer_type.set(DmaTransferType::MemoryToPeripheral);
1023
1024 self.enable_dma_channel();
1025 }
1026
1027 pub fn transfer_periph_to_mem_pingpong(
1029 &self,
1030 src_reg: *const (),
1031 buf1: &'static mut [u8],
1032 len1: usize,
1033 buf2: &'static mut [u8],
1034 len2: usize,
1035 ) {
1036 let src_end_ptr = src_reg as u32;
1040 let dst_end_ptr1 = (core::ptr::from_ref::<u8>(&buf1[0]) as u32) + ((len1 as u32) - 1);
1041 let dst_end_ptr2 = (core::ptr::from_ref::<u8>(&buf2[0]) as u32) + ((len2 as u32) - 1);
1042
1043 self.set_dma_mode(DmaMode::PingPong);
1045 self.set_primary_buffer(src_end_ptr, dst_end_ptr1);
1046 self.set_alternative_buffer(src_end_ptr, dst_end_ptr2);
1047 self.setup_transfer_primary_buffer(len1);
1048 self.setup_transfer_alternate_buffer(len2);
1049
1050 self.rx_buf_prim.replace(buf1);
1052 self.rx_buf_alt.replace(buf2);
1053
1054 self.calc_remaining_words(len1);
1056
1057 self.transfer_type
1059 .set(DmaTransferType::PeripheralToMemoryPingPong);
1060
1061 self.enable_dma_channel();
1062 }
1063
1064 pub fn provide_new_buffer(&self, buf: &'static mut [u8], len: usize) {
1066 let buf_end_ptr = (core::ptr::from_ref::<u8>(&buf[0]) as u32) + ((len as u32) - 1);
1067
1068 if self.transfer_type.get() == DmaTransferType::PeripheralToMemoryPingPong {
1069 if self.active_buf.get() == ActiveBuffer::Primary {
1070 DMA_CONFIG.0[self.chan_nr + AVAILABLE_DMA_CHANNELS]
1072 .dst_ptr
1073 .set(buf_end_ptr);
1074 self.setup_transfer_alternate_buffer(len);
1075 self.rx_buf_alt.replace(buf);
1076 self.bytes_to_transmit_alt.set(len);
1077 } else {
1078 DMA_CONFIG.0[self.chan_nr].dst_ptr.set(buf_end_ptr);
1080 self.setup_transfer_primary_buffer(len);
1081 self.rx_buf_prim.replace(buf);
1082 self.bytes_to_transmit_prim.set(len);
1083 }
1084 }
1085 }
1086
1087 pub fn stop(
1096 &self,
1097 ) -> (
1098 usize,
1099 Option<&'static mut [u8]>,
1100 Option<&'static mut [u8]>,
1101 Option<&'static mut [u8]>,
1102 Option<&'static mut [u8]>,
1103 ) {
1104 self.registers.enaclr.set((1 << self.chan_nr) as u32);
1106 DMA_CONFIG.0[self.chan_nr]
1108 .ctrl
1109 .modify(DMA_CTRL::CYCLE_CTRL::Stop);
1110
1111 let n_minus_1 = DMA_CONFIG.0[self.chan_nr].ctrl.read(DMA_CTRL::N_MINUS_1) as usize;
1113 let transferred_bytes = if self.active_buf.get() == ActiveBuffer::Primary {
1114 self.bytes_to_transmit_prim.get() - n_minus_1 + 1
1115 } else {
1116 self.bytes_to_transmit_alt.get() - n_minus_1 + 1
1117 };
1118
1119 (
1120 transferred_bytes,
1121 self.tx_buf_prim.take(),
1122 self.rx_buf_prim.take(),
1123 self.tx_buf_alt.take(),
1124 self.rx_buf_alt.take(),
1125 )
1126 }
1127}