msp432/
dma.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Direct Memory Access (DMA)
6
7use 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    // Unfortunately the Default-trait does not support constant functions and the InMemoryRegister
20    // structs do not implement the copy-trait, so it's necessary to initialize this array by hand.
21    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
39/// Although there are 8bits reserved for selecting a source for the DMA trigger, the
40/// MSP432P4x family only supports numbers from 1 to 7. 0 doesn't cause an error, but it's
41/// marked as reserved. According to the device-specific datasheet 'reserved' can be used for
42/// transfering data from one location in the RAM to another one.
43const MAX_SRC_NR: u8 = 7;
44
45/// The MSP432 chips contain 8 DMA channels
46pub const AVAILABLE_DMA_CHANNELS: usize = 8;
47
48/// The DMA can perform up to 1024 transfers before it needs to rearbitrate the bus
49const MAX_TRANSFERS_LEN: usize = 1024;
50
51register_structs! {
52    /// DMA
53    DmaRegisters {
54        /// Device Configuration Status
55        (0x0000 => device_cfg: ReadOnly<u32, DMA_DEVICE_CFG::Register>),
56        /// Software Channel Trigger Register
57        (0x0004 => sw_chtrig: ReadWrite<u32, DMA_SW_CHTRIG::Register>),
58        (0x0008 => _reserved0),
59        /// Channel n Source Configuration Registers
60        (0x0010 => ch_srccfg: [ReadWrite<u32>; 32]),
61        (0x0090 => _reserved1),
62        /// Interrupt 1 Source Channel Configuration
63        (0x0100 => int1_srccfg: ReadWrite<u32, DMA_INT1_SRCCFG::Register>),
64        /// Interrupt 2 Source Channel Configuration Register
65        (0x0104 => int2_srccfg: ReadWrite<u32, DMA_INT2_SRCCFG::Register>),
66        /// Interrupt 3 Source Channel Configuration Register
67        (0x0108 => int3_srccfg: ReadWrite<u32, DMA_INT3_SRCCFG::Register>),
68        (0x010C => _reserved2),
69        /// Interrupt 0 Source Channel Flag Register
70        (0x0110 => int0_srcflg: ReadOnly<u32, DMA_INT0_SRCFLG::Register>),
71        /// Interrupt 0 Source Channel Clear Flag Register
72        (0x0114 => int0_clrflg: WriteOnly<u32, DMA_INT0_CLRFLG::Register>),
73        (0x0118 => _reserved3),
74        /// Status Register
75        (0x1000 => stat: ReadOnly<u32, DMA_STAT::Register>),
76        /// Configuration Register
77        (0x1004 => cfg: WriteOnly<u32, DMA_CFG::Register>),
78        /// Channel Control Data Base Pointer Register
79        (0x1008 => ctlbase: ReadWrite<u32>),
80        /// Channel Alternate Control Data Base Pointer Register
81        (0x100C => altbase: ReadOnly<u32>),
82        /// Channel Wait on Request Status Register
83        (0x1010 => waitstat: ReadOnly<u32>),
84        /// Channel Software Request Register
85        (0x1014 => wreq: WriteOnly<u32>),
86        /// Channel Useburst Set Register
87        (0x1018 => useburstset: ReadWrite<u32>),
88        /// Channel Useburst Clear Register
89        (0x101C => useburstclr: WriteOnly<u32>),
90        /// Channel Request Mask Set Register
91        (0x1020 => reqmaskset: ReadWrite<u32>),
92        /// Channel Request Mask Clear Register
93        (0x1024 => reqmaskclr: WriteOnly<u32>),
94        /// Channel Enable Set Register
95        (0x1028 => enaset: ReadWrite<u32>),
96        /// Channel Enable Clear Register
97        (0x102C => enaclr: WriteOnly<u32>),
98        /// Channel Primary-Alternate Set Register
99        (0x1030 => altset: ReadWrite<u32>),
100        /// Channel Primary-Alternate Clear Register
101        (0x1034 => altclr: WriteOnly<u32>),
102        /// Channel Priority Set Register
103        (0x1038 => prioset: ReadWrite<u32>),
104        /// Channel Priority Clear Register
105        (0x103C => prioclr: WriteOnly<u32>),
106        (0x1040 => _reserved4),
107        /// Bus Error Clear Register
108        (0x104C => errclr: ReadWrite<u32>),
109        (0x1050 => @END),
110    }
111}
112
113register_bitfields![u32,
114    DMA_DEVICE_CFG [
115        /// Number of DMA channels available
116        NUM_DMA_CHANNELS OFFSET(0) NUMBITS(8) [],
117        /// Number of DMA sources per channel
118        NUM_SRC_PER_CHANNEL OFFSET(8) NUMBITS(8) []
119    ],
120    DMA_SW_CHTRIG [
121        /// Write 1, triggers DMA_CHANNEL0
122        CH0 OFFSET(0) NUMBITS(1) [],
123        /// Write 1, triggers DMA_CHANNEL1
124        CH1 OFFSET(1) NUMBITS(1) [],
125        /// Write 1, triggers DMA_CHANNEL2
126        CH2 OFFSET(2) NUMBITS(1) [],
127        /// Write 1, triggers DMA_CHANNEL3
128        CH3 OFFSET(3) NUMBITS(1) [],
129        /// Write 1, triggers DMA_CHANNEL4
130        CH4 OFFSET(4) NUMBITS(1) [],
131        /// Write 1, triggers DMA_CHANNEL5
132        CH5 OFFSET(5) NUMBITS(1) [],
133        /// Write 1, triggers DMA_CHANNEL6
134        CH6 OFFSET(6) NUMBITS(1) [],
135        /// Write 1, triggers DMA_CHANNEL7
136        CH7 OFFSET(7) NUMBITS(1) [],
137        /// Write 1, triggers DMA_CHANNEL8
138        CH8 OFFSET(8) NUMBITS(1) [],
139        /// Write 1, triggers DMA_CHANNEL9
140        CH9 OFFSET(9) NUMBITS(1) [],
141        /// Write 1, triggers DMA_CHANNEL10
142        CH10 OFFSET(10) NUMBITS(1) [],
143        /// Write 1, triggers DMA_CHANNEL11
144        CH11 OFFSET(11) NUMBITS(1) [],
145        /// Write 1, triggers DMA_CHANNEL12
146        CH12 OFFSET(12) NUMBITS(1) [],
147        /// Write 1, triggers DMA_CHANNEL13
148        CH13 OFFSET(13) NUMBITS(1) [],
149        /// Write 1, triggers DMA_CHANNEL14
150        CH14 OFFSET(14) NUMBITS(1) [],
151        /// Write 1, triggers DMA_CHANNEL15
152        CH15 OFFSET(15) NUMBITS(1) [],
153        /// Write 1, triggers DMA_CHANNEL16
154        CH16 OFFSET(16) NUMBITS(1) [],
155        /// Write 1, triggers DMA_CHANNEL17
156        CH17 OFFSET(17) NUMBITS(1) [],
157        /// Write 1, triggers DMA_CHANNEL18
158        CH18 OFFSET(18) NUMBITS(1) [],
159        /// Write 1, triggers DMA_CHANNEL19
160        CH19 OFFSET(19) NUMBITS(1) [],
161        /// Write 1, triggers DMA_CHANNEL20
162        CH20 OFFSET(20) NUMBITS(1) [],
163        /// Write 1, triggers DMA_CHANNEL21
164        CH21 OFFSET(21) NUMBITS(1) [],
165        /// Write 1, triggers DMA_CHANNEL22
166        CH22 OFFSET(22) NUMBITS(1) [],
167        /// Write 1, triggers DMA_CHANNEL23
168        CH23 OFFSET(23) NUMBITS(1) [],
169        /// Write 1, triggers DMA_CHANNEL24
170        CH24 OFFSET(24) NUMBITS(1) [],
171        /// Write 1, triggers DMA_CHANNEL25
172        CH25 OFFSET(25) NUMBITS(1) [],
173        /// Write 1, triggers DMA_CHANNEL26
174        CH26 OFFSET(26) NUMBITS(1) [],
175        /// Write 1, triggers DMA_CHANNEL27
176        CH27 OFFSET(27) NUMBITS(1) [],
177        /// Write 1, triggers DMA_CHANNEL28
178        CH28 OFFSET(28) NUMBITS(1) [],
179        /// Write 1, triggers DMA_CHANNEL29
180        CH29 OFFSET(29) NUMBITS(1) [],
181        /// Write 1, triggers DMA_CHANNEL30
182        CH30 OFFSET(30) NUMBITS(1) [],
183        /// Write 1, triggers DMA_CHANNEL31
184        CH31 OFFSET(31) NUMBITS(1) []
185    ],
186    DMA_INT1_SRCCFG [
187        /// Controls which channel's completion event is mapped as a source of this Interrup
188        INT_SRC OFFSET(0) NUMBITS(5) [],
189        /// Enables DMA_INT1 mapping
190        EN OFFSET(5) NUMBITS(1) []
191    ],
192    DMA_INT2_SRCCFG [
193        /// Controls which channel's completion event is mapped as a source of this Interrup
194        INT_SRC OFFSET(0) NUMBITS(5) [],
195        /// Enables DMA_INT2 mapping
196        EN OFFSET(5) NUMBITS(1) []
197    ],
198    DMA_INT3_SRCCFG [
199        /// Controls which channel's completion event is mapped as a source of this Interrup
200        INT_SRC OFFSET(0) NUMBITS(5) [],
201        /// Enables DMA_INT3 mapping
202        EN OFFSET(5) NUMBITS(1) []
203    ],
204    DMA_INT0_SRCFLG [
205        /// Channel 0 was the source of DMA_INT0
206        CH0 OFFSET(0) NUMBITS(1) [],
207        /// Channel 1 was the source of DMA_INT0
208        CH1 OFFSET(1) NUMBITS(1) [],
209        /// Channel 2 was the source of DMA_INT0
210        CH2 OFFSET(2) NUMBITS(1) [],
211        /// Channel 3 was the source of DMA_INT0
212        CH3 OFFSET(3) NUMBITS(1) [],
213        /// Channel 4 was the source of DMA_INT0
214        CH4 OFFSET(4) NUMBITS(1) [],
215        /// Channel 5 was the source of DMA_INT0
216        CH5 OFFSET(5) NUMBITS(1) [],
217        /// Channel 6 was the source of DMA_INT0
218        CH6 OFFSET(6) NUMBITS(1) [],
219        /// Channel 7 was the source of DMA_INT0
220        CH7 OFFSET(7) NUMBITS(1) [],
221        /// Channel 8 was the source of DMA_INT0
222        CH8 OFFSET(8) NUMBITS(1) [],
223        /// Channel 9 was the source of DMA_INT0
224        CH9 OFFSET(9) NUMBITS(1) [],
225        /// Channel 10 was the source of DMA_INT0
226        CH10 OFFSET(10) NUMBITS(1) [],
227        /// Channel 11 was the source of DMA_INT0
228        CH11 OFFSET(11) NUMBITS(1) [],
229        /// Channel 12 was the source of DMA_INT0
230        CH12 OFFSET(12) NUMBITS(1) [],
231        /// Channel 13 was the source of DMA_INT0
232        CH13 OFFSET(13) NUMBITS(1) [],
233        /// Channel 14 was the source of DMA_INT0
234        CH14 OFFSET(14) NUMBITS(1) [],
235        /// Channel 15 was the source of DMA_INT0
236        CH15 OFFSET(15) NUMBITS(1) [],
237        /// Channel 16 was the source of DMA_INT0
238        CH16 OFFSET(16) NUMBITS(1) [],
239        /// Channel 17 was the source of DMA_INT0
240        CH17 OFFSET(17) NUMBITS(1) [],
241        /// Channel 18 was the source of DMA_INT0
242        CH18 OFFSET(18) NUMBITS(1) [],
243        /// Channel 19 was the source of DMA_INT0
244        CH19 OFFSET(19) NUMBITS(1) [],
245        /// Channel 20 was the source of DMA_INT0
246        CH20 OFFSET(20) NUMBITS(1) [],
247        /// Channel 21 was the source of DMA_INT0
248        CH21 OFFSET(21) NUMBITS(1) [],
249        /// Channel 22 was the source of DMA_INT0
250        CH22 OFFSET(22) NUMBITS(1) [],
251        /// Channel 23 was the source of DMA_INT0
252        CH23 OFFSET(23) NUMBITS(1) [],
253        /// Channel 24 was the source of DMA_INT0
254        CH24 OFFSET(24) NUMBITS(1) [],
255        /// Channel 25 was the source of DMA_INT0
256        CH25 OFFSET(25) NUMBITS(1) [],
257        /// Channel 26 was the source of DMA_INT0
258        CH26 OFFSET(26) NUMBITS(1) [],
259        /// Channel 27 was the source of DMA_INT0
260        CH27 OFFSET(27) NUMBITS(1) [],
261        /// Channel 28 was the source of DMA_INT0
262        CH28 OFFSET(28) NUMBITS(1) [],
263        /// Channel 29 was the source of DMA_INT0
264        CH29 OFFSET(29) NUMBITS(1) [],
265        /// Channel 30 was the source of DMA_INT0
266        CH30 OFFSET(30) NUMBITS(1) [],
267        /// Channel 31 was the source of DMA_INT0
268        CH31 OFFSET(31) NUMBITS(1) []
269    ],
270    DMA_INT0_CLRFLG [
271        /// Clear corresponding DMA_INT0_SRCFLG_REG
272        CH0 OFFSET(0) NUMBITS(1) [],
273        /// Clear corresponding DMA_INT0_SRCFLG_REG
274        CH1 OFFSET(1) NUMBITS(1) [],
275        /// Clear corresponding DMA_INT0_SRCFLG_REG
276        CH2 OFFSET(2) NUMBITS(1) [],
277        /// Clear corresponding DMA_INT0_SRCFLG_REG
278        CH3 OFFSET(3) NUMBITS(1) [],
279        /// Clear corresponding DMA_INT0_SRCFLG_REG
280        CH4 OFFSET(4) NUMBITS(1) [],
281        /// Clear corresponding DMA_INT0_SRCFLG_REG
282        CH5 OFFSET(5) NUMBITS(1) [],
283        /// Clear corresponding DMA_INT0_SRCFLG_REG
284        CH6 OFFSET(6) NUMBITS(1) [],
285        /// Clear corresponding DMA_INT0_SRCFLG_REG
286        CH7 OFFSET(7) NUMBITS(1) [],
287        /// Clear corresponding DMA_INT0_SRCFLG_REG
288        CH8 OFFSET(8) NUMBITS(1) [],
289        /// Clear corresponding DMA_INT0_SRCFLG_REG
290        CH9 OFFSET(9) NUMBITS(1) [],
291        /// Clear corresponding DMA_INT0_SRCFLG_REG
292        CH10 OFFSET(10) NUMBITS(1) [],
293        /// Clear corresponding DMA_INT0_SRCFLG_REG
294        CH11 OFFSET(11) NUMBITS(1) [],
295        /// Clear corresponding DMA_INT0_SRCFLG_REG
296        CH12 OFFSET(12) NUMBITS(1) [],
297        /// Clear corresponding DMA_INT0_SRCFLG_REG
298        CH13 OFFSET(13) NUMBITS(1) [],
299        /// Clear corresponding DMA_INT0_SRCFLG_REG
300        CH14 OFFSET(14) NUMBITS(1) [],
301        /// Clear corresponding DMA_INT0_SRCFLG_REG
302        CH15 OFFSET(15) NUMBITS(1) [],
303        /// Clear corresponding DMA_INT0_SRCFLG_REG
304        CH16 OFFSET(16) NUMBITS(1) [],
305        /// Clear corresponding DMA_INT0_SRCFLG_REG
306        CH17 OFFSET(17) NUMBITS(1) [],
307        /// Clear corresponding DMA_INT0_SRCFLG_REG
308        CH18 OFFSET(18) NUMBITS(1) [],
309        /// Clear corresponding DMA_INT0_SRCFLG_REG
310        CH19 OFFSET(19) NUMBITS(1) [],
311        /// Clear corresponding DMA_INT0_SRCFLG_REG
312        CH20 OFFSET(20) NUMBITS(1) [],
313        /// Clear corresponding DMA_INT0_SRCFLG_REG
314        CH21 OFFSET(21) NUMBITS(1) [],
315        /// Clear corresponding DMA_INT0_SRCFLG_REG
316        CH22 OFFSET(22) NUMBITS(1) [],
317        /// Clear corresponding DMA_INT0_SRCFLG_REG
318        CH23 OFFSET(23) NUMBITS(1) [],
319        /// Clear corresponding DMA_INT0_SRCFLG_REG
320        CH24 OFFSET(24) NUMBITS(1) [],
321        /// Clear corresponding DMA_INT0_SRCFLG_REG
322        CH25 OFFSET(25) NUMBITS(1) [],
323        /// Clear corresponding DMA_INT0_SRCFLG_REG
324        CH26 OFFSET(26) NUMBITS(1) [],
325        /// Clear corresponding DMA_INT0_SRCFLG_REG
326        CH27 OFFSET(27) NUMBITS(1) [],
327        /// Clear corresponding DMA_INT0_SRCFLG_REG
328        CH28 OFFSET(28) NUMBITS(1) [],
329        /// Clear corresponding DMA_INT0_SRCFLG_REG
330        CH29 OFFSET(29) NUMBITS(1) [],
331        /// Clear corresponding DMA_INT0_SRCFLG_REG
332        CH30 OFFSET(30) NUMBITS(1) [],
333        /// Clear corresponding DMA_INT0_SRCFLG_REG
334        CH31 OFFSET(31) NUMBITS(1) []
335    ],
336    DMA_STAT [
337        /// Enable status of the controller
338        MASTEN OFFSET(0) NUMBITS(1) [
339            /// Controller disabled
340            ControllerDisabled = 0,
341            /// Controller enabled
342            ControllerEnabled = 1
343        ],
344        /// Current state of the control state machine.
345        /// State can be one of the following:
346        STATE OFFSET(4) NUMBITS(4) [
347            /// idle
348            Idle = 0,
349            /// reading channel controller data
350            ReadingChannelControllerData = 1,
351            /// reading source data end pointer
352            ReadingSourceDataEndPointer = 2,
353            /// reading destination data end pointer
354            ReadingDestinationDataEndPointer = 3,
355            /// reading source data
356            ReadingSourceData = 4,
357            /// writing destination data
358            WritingDestinationData = 5,
359            /// waiting for DMA request to clear
360            WaitingForDMARequestToClear = 6,
361            /// writing channel controller data
362            WritingChannelControllerData = 7,
363            /// stalled
364            Stalled = 8,
365            /// done
366            Done = 9,
367            /// peripheral scatter-gather transition
368            PeripheralScatterGatherTransition = 10
369        ],
370        /// Number of available DMA channels minus one.
371        DMACHANS OFFSET(16) NUMBITS(5) [
372            /// Controller configured to use 1 DMA channel
373            ControllerConfiguredToUse1DMAChannel = 0,
374            /// Controller configured to use 2 DMA channels
375            ControllerConfiguredToUse2DMAChannels = 1,
376            /// Controller configured to use 31 DMA channels
377            ControllerConfiguredToUse31DMAChannels = 30,
378            /// Controller configured to use 32 DMA channels
379            ControllerConfiguredToUse32DMAChannels = 31
380        ],
381        /// To reduce the gate count the controller can be configured to exclude the integra
382        TESTSTAT OFFSET(28) NUMBITS(4) [
383            /// Controller does not include the integration test logic
384            ControllerDoesNotIncludeTheIntegrationTestLogic = 0,
385            /// Controller includes the integration test logic
386            ControllerIncludesTheIntegrationTestLogic = 1
387        ]
388    ],
389    DMA_CFG [
390        /// Enable status of the controller
391        MASTEN OFFSET(0) NUMBITS(1) [
392            /// Controller disabled
393            ControllerDisabled = 0,
394            /// Controller enabled
395            ControllerEnabled = 1
396        ],
397        /// Sets the AHB-Lite protection by controlling the HPROT[3:1] signal levels as fol
398        CHPROTCTRL OFFSET(5) NUMBITS(3) []
399    ]
400];
401
402register_bitfields![u32,
403    /// DMA control data configuration
404    DMA_CTRL [
405        /// Cycle control
406        CYCLE_CTRL OFFSET(0) NUMBITS(3) [
407            /// Stop. indicates that the data-structure is invalid
408            Stop = 0,
409            /// Basic transfer mode
410            Basic = 1,
411            /// Auto-request mode
412            Auto = 2,
413            /// Ping-pong mode
414            PingPong = 3,
415            /// Memory scatter-gather mode, which uses the primary data-structure
416            MemoryScatterGatherPrimary = 4,
417            /// Memory scatter-gather mode, which uses the alternate data-structure
418            MemoryScatterGatherAlternate = 5,
419            /// Peripheral scatter-gather mode, which uses the primary data-structure
420            PeripheralScatterGatherPrimary = 6,
421            /// Peripheral scatter-gather mode, which uses the alternate data-structure
422            PeripheralScatterGatherAlternate = 7
423        ],
424        /// Controls if the chnl_useburst_set bit is is set to 1
425        NEXT_USEBURST OFFSET(3) NUMBITS(1) [],
426        /// These bits represent the total number of DMA transfers minus 1
427        /// that the DMA cycle contains.
428        N_MINUS_1 OFFSET(4) NUMBITS(10) [],
429        /// These bits control how many DMA transfers can occur before the controller rearbitrates
430        /// the bus. The register-value is the 'ld' of the number of cycles. E.g. 128 cycles ->
431        /// regval = ld(128) = 7. The maximum number of cycles is 1024 -> regval = 10
432        R_POWER OFFSET(14) NUMBITS(4) [],
433        /// These bits set the control state of HPROT[3:1] when the controller reads data. For the
434        /// MSP432 family these bits can be ignored, because they have no effect. The DMA in the
435        /// MSP432-devices can access all memory, no matter how these bits are set.
436        SRC_PROT_CTRL OFFSET(18) NUMBITS(3) [],
437        /// These bits set the control state of HPROT[3:1] when the controller writes data. For the
438        /// MSP432 family these bits can be ignored, because they have no effect. The DMA in the
439        /// MSP432-devices can access all memory, no matter how these bits are set.
440        DST_PROT_CTRL OFFSET(21) NUMBITS(3) [],
441        /// These bits control the size of the source-data
442        SRC_SIZE OFFSET(24) NUMBITS(2) [
443            /// Byte -> 8bit
444            Byte = 0,
445            /// Half-word -> 16bit
446            HalfWord = 1,
447            /// Word -> 32bit
448            Word = 2
449        ],
450        /// These bits set the source address-increment
451        SRC_INC OFFSET(26) NUMBITS(2) [
452            /// Byte -> +1
453            Byte = 0,
454            /// Half-word -> +2
455            HalfWord = 1,
456            /// Word -> +4
457            Word = 2,
458            /// No increment -> +0
459            NoIncrement = 3
460        ],
461        /// These bits control the size of the destination-data.
462        /// NOTE: DST_SIZE must be the same as SRC_SIZE!
463        DST_SIZE OFFSET(28) NUMBITS(2) [
464            /// Byte -> 8bit
465            Byte = 0,
466            /// Half-word -> 16bit
467            HalfWord = 1,
468            /// Word -> 32bit
469            Word = 2
470        ],
471        /// These bits set the destination address-increment
472        DST_INC OFFSET(30) NUMBITS(2) [
473            /// Byte -> +1
474            Byte = 0,
475            /// Half-word -> +2
476            HalfWord = 1,
477            /// Word -> +4
478            Word = 2,
479            /// No increment -> +0
480            NoIncrement = 3
481        ]
482    ]
483];
484
485/// The uDMA of the MSP432 family don't offer own registers where the configuration of the
486/// individual DMA channels is stored, they require a pointer to a block of memory in the RAM
487/// where the actual configuration is stored. Within this block of memory the pointer to the
488/// data-source, the pointer to the destination and the configuration is stored. Probably due to
489/// alignment reasons the 4th word is unused.
490#[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/// It's necessary to allocate twice as much buffers as DMA channels are available. This is because
499/// the DMA supports modes where a primary buffer and an alternative one can be used.
500#[repr(align(256))]
501struct DmaConfigBlock([DmaChannelControl; 2 * AVAILABLE_DMA_CHANNELS]);
502
503/// It's necessary to implement `Sync`, otherwise the `DMA_CONFIG` array cannot be instantiated
504/// because static variables require the `Sync` trait, otherwise they are not threadsafe.
505unsafe impl Sync for DmaConfigBlock {}
506
507/// Trait for handling the callbacks if a DMA transfer finished
508pub 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), // Used for UART0 TX
577                crate::dma::DmaChannel::new(1), // Used for UART0 RX
578                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), // Used for ADC
584            ],
585        }
586    }
587
588    pub fn handle_interrupt(&self, int_nr: isize) {
589        if int_nr == 0 {
590            // For now only use the INT0 because I don't know how to prioritize the channels in order
591            // to give them 1 out of 3 'own' interrupts.
592            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                    // Clear interrupt-bit
598                    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            // Default is to copy data from a hardware to a buffer
654            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        // Enable the DMA module
686        self.registers.cfg.write(DMA_CFG::MASTEN::ControllerEnabled);
687
688        // Set the pointer to the configuration-memory
689        // Since the config needs exactly 256 bytes, mask out the lower 256 bytes
690        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        // The memory acces protection fields 'dst_prot_ctrl' and 'src_prot_ctrl' are not necessary
705        // to configure for the MSP432P4x chips because they don't affect the privileges of the
706        // DMA module. In other words, the DMA can access every memory and register at every time.
707        // For more information see datasheet p. 625 section 11.2.2.3.
708
709        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        // Set the source-peripheral for the DMA channel
717        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        // Store to transmitting bytes
730        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        // Store to transmitting bytes
737        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        // Update the buffer-pointers
756        if tt == DmaTransferType::PeripheralToMemory
757            || tt == DmaTransferType::MemoryToMemory
758            || tt == DmaTransferType::PeripheralToMemoryPingPong
759        {
760            // Update the destination-buffer pointer
761            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            // Update the source-buffer pointer
769            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        // Update the remaining words
776        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        // If the transfer type is MemoryToMemory, the R_POWER register can have a different
783        // value than 0, since the source- and destination address are incremented and it's not
784        // necessary to wait for any hardware module to process or 'generate' data.
785        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        // Set the DMA mode since the DMA module sets it back to stop after every cycle
796        // Set the DMA cycles to the amount of remaining words
797        // Set the number of DMA-transfers after the DMA has to rearbitrate the bus
798        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        // Store the remaining words
809        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        // The DMA can only transmit 1024 words with 1 transfer
820        // Reset the bits in case they were set before to a different value
821        // Set the DMA mode since it the DMA module sets it back to to stop after every cycle
822        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                // Disable the DMA channel since the data transfer has finished
855                self.registers.enaclr.set((1 << self.chan_nr) as u32);
856            }
857            // Fire the callback and return the buffer-references
858            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    /// Start a DMA transfer where one buffer is copied into another one
927    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        // Note: This function is currently entirely untested, since there is currently no driver
934        // available where this function might be used.
935
936        let width = self.config.get().width as u32;
937
938        // Divide the byte-length by the width to get the number of necessary transfers
939        let transfers = len >> width;
940
941        // The pointers must point to the end of the buffer, for detailed calculation see
942        // datasheet p. 646, section 11.2.4.4.
943        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        // Setup the DMA configuration
947        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        // Store remaining words
952        self.calc_remaining_words(len);
953
954        // Set the the number of cycles after the module rearbitrates the bus.
955        // The 'register-value' for this is ld(cycles), e.g. cycles = 256 -> ld(256) = 8
956        // In order to get the number of cycles, just get the closest 2^n value of transfers
957        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        // Set the number of cycles before a bus rearbitration
964        DMA_CONFIG.0[self.chan_nr]
965            .ctrl
966            .modify(DMA_CTRL::R_POWER.val(r_power));
967
968        // Store the buffers
969        self.rx_buf_prim.replace(dst_buf);
970        self.tx_buf_prim.replace(src_buf);
971
972        // Store transfer-type
973        self.transfer_type.set(DmaTransferType::MemoryToMemory);
974
975        // Enable the DMA channel
976        self.enable_dma_channel();
977    }
978
979    /// Start a DMA transfer where the contents of any register will be copied into a provided buffer
980    pub fn transfer_periph_to_mem(&self, src_reg: *const (), buf: &'static mut [u8], len: usize) {
981        // The pointers must point to the end of the buffer, for detailed calculation see
982        // datasheet p. 646, section 11.2.4.4.
983        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        // Setup the DMA configuration
987        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        // Store the buffer
992        self.rx_buf_prim.replace(buf);
993
994        // Store remaining words
995        self.calc_remaining_words(len);
996
997        // Store transfer-type
998        self.transfer_type.set(DmaTransferType::PeripheralToMemory);
999
1000        self.enable_dma_channel();
1001    }
1002
1003    /// Start a DMA transfer where the contents of a buffer will be copied into a register
1004    pub fn transfer_mem_to_periph(&self, dst_reg: *const (), buf: &'static mut [u8], len: usize) {
1005        // The pointers must point to the end of the buffer, for detailed calculation see
1006        // datasheet p. 646, section 11.2.4.4.
1007        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        // Setup the DMA configuration
1011        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        // Store the buffer
1016        self.tx_buf_prim.replace(buf);
1017
1018        // Store remaining words
1019        self.calc_remaining_words(len);
1020
1021        // Store transfer-type
1022        self.transfer_type.set(DmaTransferType::MemoryToPeripheral);
1023
1024        self.enable_dma_channel();
1025    }
1026
1027    /// Start a ping-pong transfer from a peripheral to a certain location in memory
1028    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        // The pointers must point to the end of the buffer, for detailed calculation see
1037        // datasheet p. 646, section 11.2.4.4.
1038
1039        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        // Setup the DMA configuration
1044        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        // Store the buffers
1051        self.rx_buf_prim.replace(buf1);
1052        self.rx_buf_alt.replace(buf2);
1053
1054        // Store remaining words
1055        self.calc_remaining_words(len1);
1056
1057        // Store transfer-type
1058        self.transfer_type
1059            .set(DmaTransferType::PeripheralToMemoryPingPong);
1060
1061        self.enable_dma_channel();
1062    }
1063
1064    /// Provide a new buffer for a ping-pong transfer
1065    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                // Replace alternative buffer, overwrite only destination pointer!
1071                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                // Replace primary buffer, overwrite only destination pointer!
1079                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    /// Stop any ongoing DMA transfer
1088    ///
1089    /// Returnvalues:
1090    /// usize:                      Number of transferred bytes until the transfer was stopped
1091    /// Option<&'static mut [u8]>:  Option to the primary TX buffer
1092    /// Option<&'static mut [u8]>:  Option to the primary RX buffer
1093    /// Option<&'static mut [u8]>:  Option to the alternate TX buffer
1094    /// Option<&'static mut [u8]>:  Option to the alternate RX buffer
1095    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        // Disable the channel
1105        self.registers.enaclr.set((1 << self.chan_nr) as u32);
1106        // Set cycle-ctrl to stop in order to cancel an ongoing transaction
1107        DMA_CONFIG.0[self.chan_nr]
1108            .ctrl
1109            .modify(DMA_CTRL::CYCLE_CTRL::Stop);
1110
1111        // Calculate the already transferred bytes
1112        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}