1use crate::{common::wrap_trait::*, pac, rcc::Rcc, Steal};
4
5pub use crate::common::dma::*;
6pub type DmaPriority = pac::dma1::ch::cr::PL;
7
8pub trait DmaInit {
9 type Channels;
10
11 fn split(self, rcc: &mut Rcc) -> Self::Channels;
12}
13
14macro_rules! dma {
15 ($DMAX:ty: ($dmaX:ident, {
16 $($CX:ident: ($ch: literal),)+
17 }),) => {
18 pub mod $dmaX {
19 use super::*;
20
21 #[non_exhaustive]
22 #[allow(clippy::manual_non_exhaustive)]
23 pub struct Channels((), $(pub $CX),+);
24
25 $(
26 pub type $CX = super::Ch<$DMAX, $ch>;
27 )+
28
29 impl DmaInit for $DMAX {
30 type Channels = Channels;
31
32 fn split(self, rcc: &mut Rcc) -> Channels {
33 rcc.enable(&self);
34
35 $(
37 self.ch($ch).cr().reset();
38 )+
39
40 Channels((), $(Ch::<$DMAX, $ch>{ dma: unsafe { self.steal() }}),+)
41 }
42 }
43 }
44 }
45}
46
47dma! {
48 pac::DMA1: (dma1, {
49 C1: (0),
50 C2: (1),
51 C3: (2),
52 C4: (3),
53 C5: (4),
54 C6: (5),
55 C7: (6),
56 }),
57}
58
59dma! {
60 pac::DMA2: (dma2, {
61 C1: (0),
62 C2: (1),
63 C3: (2),
64 C4: (3),
65 C5: (4),
66 }),
67}
68
69wrap_trait_deref! {
70 (pac::DMA1, pac::DMA2,),
71 pub trait RegisterBlock {
72 fn isr(&self) -> &pac::dma1::ISR;
73 fn ifcr(&self) -> &pac::dma1::IFCR;
74 fn ch(&self, n: usize) -> &pac::dma1::CH;
75 }
76}
77
78pub struct Ch<DMA, const C: u8> {
81 dma: DMA,
82}
83
84impl<DMA, const C: u8> Ch<DMA, C>
85where
86 DMA: RegisterBlock,
87{
88 #[inline]
89 pub fn set_priority(&mut self, priority: DmaPriority) {
90 self.ch().cr().modify(|_, w| w.pl().variant(priority));
91 }
92
93 #[inline(always)]
94 fn ch(&self) -> &pac::dma1::CH {
95 self.dma.ch(C as usize)
96 }
97}
98
99impl<DMA, const C: u8> DmaChannel for Ch<DMA, C>
100where
101 DMA: RegisterBlock,
102{
103 #[inline]
104 fn start(&mut self) {
105 self.dma.ifcr().write(|w| w.cgif(C).set_bit());
106 self.ch().cr().modify(|_, w| w.en().set_bit());
107 }
108
109 #[inline]
110 fn stop(&mut self) {
111 self.ch().cr().modify(|_, w| w.en().clear_bit());
112 self.dma.ifcr().write(|w| w.cgif(C).set_bit());
113 self.set_transfer_length(0);
114 }
115
116 #[inline]
117 fn set_peripheral_address<T: Sized>(
118 &mut self,
119 address: usize,
120 mem_to_periph: bool,
121 increase: bool,
122 circular: bool,
123 ) {
124 self.ch()
125 .par()
126 .write(|w| unsafe { w.pa().bits(address as u32) });
127 self.ch().cr().modify(|_, w| {
128 w.mem2mem()
129 .clear_bit()
130 .pinc()
131 .bit(increase)
132 .circ()
133 .bit(circular)
134 .dir()
135 .bit(mem_to_periph);
136
137 match core::mem::size_of::<T>() {
138 2 => {
139 w.msize().bits16();
140 w.psize().bits16()
141 }
142 4 => {
143 w.msize().bits32();
144 w.psize().bits32()
145 }
146 _ => {
147 w.msize().bits8();
148 w.psize().bits8()
149 }
150 }
151 });
152 }
153
154 #[inline(always)]
155 fn set_memory_address(&mut self, address: usize, increase: bool) {
156 self.ch()
157 .mar()
158 .write(|w| unsafe { w.ma().bits(address as u32) });
159 self.ch().cr().modify(|_, w| w.minc().bit(increase));
160 }
161
162 #[inline(always)]
163 fn set_transfer_length(&mut self, len: usize) {
164 self.ch()
165 .ndtr()
166 .write(|w| w.ndt().set(u16::try_from(len).unwrap()));
167 }
168
169 #[inline]
170 fn set_memory_to_memory<T: Sized>(&mut self, _src_addr: usize, _dst_addr: usize, _len: usize) {
171 todo!()
172 }
173
174 #[inline]
175 fn get_left_len(&self) -> usize {
176 self.ch().ndtr().read().bits() as usize
177 }
178
179 #[inline]
180 fn in_progress(&self) -> bool {
181 self.get_left_len() != 0 && self.dma.isr().read().tcif(C).bit_is_clear()
182 }
183
184 #[inline]
185 fn set_interrupt(&mut self, event: DmaEvent, enable: bool) {
186 match event {
187 DmaEvent::HalfTransfer => self.ch().cr().modify(|_, w| w.htie().bit(enable)),
188 DmaEvent::TransferComplete => self.ch().cr().modify(|_, w| w.tcie().bit(enable)),
189 };
190 }
191
192 #[inline]
193 fn is_interrupted(&mut self, event: DmaEvent) -> bool {
194 match event {
195 DmaEvent::TransferComplete => {
196 if self.dma.isr().read().tcif(C).bit_is_set() {
197 self.dma.ifcr().write(|w| w.ctcif(C).set_bit());
198 true
199 } else {
200 false
201 }
202 }
203 DmaEvent::HalfTransfer => {
204 if self.dma.isr().read().htif(C).bit_is_set() {
205 self.dma.ifcr().write(|w| w.chtif(C).set_bit());
206 true
207 } else {
208 false
209 }
210 }
211 }
212 }
213}
214
215pub trait DmaBindTx<U>: DmaChannel {}
216pub trait DmaBindRx<U>: DmaChannel {}
217
218impl DmaBindTx<pac::USART3> for dma1::C2 {}
223impl DmaBindRx<pac::USART3> for dma1::C3 {}
224impl DmaBindTx<pac::USART1> for dma1::C4 {}
225impl DmaBindRx<pac::USART1> for dma1::C5 {}
226impl DmaBindRx<pac::USART2> for dma1::C6 {}
227impl DmaBindTx<pac::USART2> for dma1::C7 {}
228impl DmaBindRx<pac::UART4> for dma2::C3 {}
229impl DmaBindTx<pac::UART4> for dma2::C5 {}
230
231impl DmaBindRx<pac::SPI1> for dma1::C2 {}
232impl DmaBindTx<pac::SPI1> for dma1::C3 {}
233impl DmaBindRx<pac::SPI2> for dma1::C4 {}
234impl DmaBindTx<pac::SPI2> for dma1::C5 {}
235impl DmaBindRx<pac::SPI3> for dma2::C1 {}
236impl DmaBindTx<pac::SPI3> for dma2::C2 {}
237
238impl DmaBindTx<pac::I2C2> for dma1::C4 {}
239impl DmaBindRx<pac::I2C2> for dma1::C5 {}
240impl DmaBindTx<pac::I2C1> for dma1::C6 {}
241impl DmaBindRx<pac::I2C1> for dma1::C7 {}