lpc8xx_hal/dma/
buffer.rs

1use crate::{
2    pac::dma0::channel::xfercfg::{DSTINC_A, SRCINC_A},
3    void::Void,
4};
5
6use super::{Dest, Source};
7
8impl crate::private::Sealed for &'static [u8] {}
9
10impl Source for &'static [u8] {
11    type Error = Void;
12
13    fn is_valid(&self) -> bool {
14        self.len() <= 1024
15    }
16
17    fn is_empty(&self) -> bool {
18        self.len() == 0
19    }
20
21    fn increment(&self) -> SRCINC_A {
22        SRCINC_A::WIDTH_X_1
23    }
24
25    fn transfer_count(&self) -> Option<u16> {
26        if self.is_empty() {
27            None
28        } else {
29            // The cast should be fine, as DMA buffers are restricted to a
30            // length of 1024.
31            Some(self.len() as u16 - 1)
32        }
33    }
34
35    fn end_addr(&self) -> *const u8 {
36        // Sound, as we stay within the bounds of the slice.
37        unsafe { self.as_ptr().add(self.len() - 1) }
38    }
39
40    fn finish(&mut self) -> nb::Result<(), Self::Error> {
41        Ok(())
42    }
43}
44
45impl crate::private::Sealed for &'static mut [u8] {}
46
47impl Dest for &'static mut [u8] {
48    /// The error that can occur while waiting for the destination to be idle
49    type Error = Void;
50
51    fn is_valid(&self) -> bool {
52        self.len() <= 1024
53    }
54
55    fn is_full(&self) -> bool {
56        self.len() == 0
57    }
58
59    fn increment(&self) -> DSTINC_A {
60        DSTINC_A::WIDTH_X_1
61    }
62
63    fn transfer_count(&self) -> Option<u16> {
64        if self.is_full() {
65            None
66        } else {
67            // The cast should be fine, as DMA buffers are restricted to a
68            // length of 1024.
69            Some(self.len() as u16 - 1)
70        }
71    }
72
73    fn end_addr(&mut self) -> *mut u8 {
74        // Sound, as we stay within the bounds of the slice.
75        unsafe { self.as_mut_ptr().add(self.len() - 1) }
76    }
77
78    fn finish(&mut self) -> nb::Result<(), Self::Error> {
79        Ok(())
80    }
81}
82
83pub(crate) struct Buffer {
84    ptr: *mut u8,
85    len: usize,
86}
87
88impl Buffer {
89    /// Create a `Buffer` from a static slice
90    ///
91    /// # Unsafety
92    ///
93    /// The caller must make sure that the create `Buffer` instance is not used
94    /// in a way that would interfere with the nature or usage of the slice. For
95    /// example:
96    ///
97    /// - If the `Buffer` instance is used as a DMA destination, the caller must
98    ///   prevent race conditions by making sure no one else writes to the
99    ///   slice.
100    /// - If the `Buffer` instance is used as a DMA destination, it is the
101    ///   caller's responsibility to only pass a reference to a mutable slice,
102    ///   even though this method accepts references to immutable slices.
103    pub(crate) unsafe fn new(ptr: *mut u8, len: usize) -> Self {
104        Self { ptr, len }
105    }
106}
107
108impl crate::private::Sealed for Buffer {}
109
110impl Source for Buffer {
111    type Error = Void;
112
113    fn is_valid(&self) -> bool {
114        self.len <= 1024
115    }
116
117    fn is_empty(&self) -> bool {
118        self.len == 0
119    }
120
121    fn increment(&self) -> SRCINC_A {
122        SRCINC_A::WIDTH_X_1
123    }
124
125    fn transfer_count(&self) -> Option<u16> {
126        if self.is_empty() {
127            None
128        } else {
129            // The cast should be fine, as DMA buffers are restricted to a
130            // length of 1024.
131            Some(self.len as u16 - 1)
132        }
133    }
134
135    fn end_addr(&self) -> *const u8 {
136        // Sound, as we stay within the bounds of the slice.
137        unsafe { self.ptr.add(self.len - 1) }
138    }
139
140    fn finish(&mut self) -> nb::Result<(), Self::Error> {
141        Ok(())
142    }
143}
144
145impl Dest for Buffer {
146    /// The error that can occur while waiting for the destination to be idle
147    type Error = Void;
148
149    fn is_valid(&self) -> bool {
150        self.len <= 1024
151    }
152
153    fn is_full(&self) -> bool {
154        self.len == 0
155    }
156
157    fn increment(&self) -> DSTINC_A {
158        DSTINC_A::WIDTH_X_1
159    }
160
161    fn transfer_count(&self) -> Option<u16> {
162        if self.is_full() {
163            None
164        } else {
165            // The cast should be fine, as DMA buffers are restricted to a
166            // length of 1024.
167            Some(self.len as u16 - 1)
168        }
169    }
170
171    fn end_addr(&mut self) -> *mut u8 {
172        // Sound, as we stay within the bounds of the slice.
173        unsafe { self.ptr.add(self.len - 1) }
174    }
175
176    fn finish(&mut self) -> nb::Result<(), Self::Error> {
177        Ok(())
178    }
179}