Skip to main content

dma_api/
array.rs

1use core::{alloc::Layout, ptr::NonNull};
2
3use crate::{DeviceDma, DmaDirection, DmaError, common::DCommon};
4
5/// DMA 可访问的数组容器。
6///
7/// `DArray<T>` 提供固定大小的 DMA 可访问数组,支持自动缓存同步。
8/// 每次访问元素(`read`/`set`)时都会根据 DMA 方向自动处理缓存操作。
9///
10/// # 类型参数
11///
12/// - `T`: 数组元素类型
13///
14/// # 缓存同步
15///
16/// 缓存同步在每次元素访问时自动执行:
17/// - `read(index)`: 读取前使 CPU 缓存失效(FromDevice/Bidirectional)
18/// - `set(index, value)`: 写入后刷新 CPU 缓存(ToDevice/Bidirectional)
19/// - `copy_from_slice(slice)`: 写入后刷新整个范围
20///
21/// # 示例
22///
23/// ```rust,ignore
24/// use dma_api::{DeviceDma, DmaDirection};
25///
26/// let device = DeviceDma::new(0xFFFFFFFF, &my_dma_impl);
27///
28/// // 创建 100 个 u32 的 DMA 数组
29/// let mut dma_array = device
30///     .array_zero_with_align::<u32>(100, 64, DmaDirection::FromDevice)
31///     .expect("Failed to allocate");
32///
33/// dma_array.set(0, 0x12345678);  // 写入(自动刷新缓存)
34/// let value = dma_array.read(0);  // 读取(自动失效缓存)
35///
36/// let dma_addr = dma_array.dma_addr(); // 获取 DMA 地址给硬件
37/// ```
38///
39/// # 生命周期
40///
41/// `DArray` 拥有其分配的 DMA 内存,在离开作用域时自动释放。
42pub struct DArray<T> {
43    data: DCommon,
44    _phantom: core::marker::PhantomData<T>,
45}
46
47unsafe impl<T> Send for DArray<T> where T: Send {}
48
49impl<T> DArray<T> {
50    pub(crate) fn new_zero_with_align(
51        os: &DeviceDma,
52        size: usize,
53        align: usize,
54        direction: DmaDirection,
55    ) -> Result<Self, DmaError> {
56        let layout = Layout::from_size_align(
57            size * core::mem::size_of::<T>(),
58            align.max(core::mem::align_of::<T>()),
59        )?;
60        let data = DCommon::new_zero(os, layout, direction)?;
61        Ok(Self {
62            data,
63            _phantom: core::marker::PhantomData,
64        })
65    }
66
67    pub(crate) fn new_zero(
68        os: &DeviceDma,
69        size: usize,
70        direction: DmaDirection,
71    ) -> Result<Self, DmaError> {
72        Self::new_zero_with_align(os, size, core::mem::align_of::<T>(), direction)
73    }
74
75    /// 获取 DMA 地址。
76    ///
77    /// 返回设备用于访问此 DMA 缓冲区的物理/DMA 地址。
78    /// 将此地址传递给硬件设备以配置 DMA 操作。
79    ///
80    /// # 返回
81    ///
82    /// DMA 地址
83    pub fn dma_addr(&self) -> crate::DmaAddr {
84        self.data.handle.dma_addr
85    }
86
87    /// 获取数组长度(元素个数)。
88    ///
89    /// # 返回
90    ///
91    /// 数组中的元素个数
92    pub fn len(&self) -> usize {
93        self.data.handle.size() / core::mem::size_of::<T>()
94    }
95
96    /// 检查数组是否为空。
97    ///
98    /// # 返回
99    ///
100    /// 如果数组长度为 0 返回 `true`,否则返回 `false`
101    pub fn is_empty(&self) -> bool {
102        self.len() == 0
103    }
104
105    /// 获取数组的字节长度。
106    ///
107    /// # 返回
108    ///
109    /// 数组占用的总字节数
110    pub fn bytes_len(&self) -> usize {
111        self.data.handle.size()
112    }
113
114    /// 读取指定索引的元素。
115    ///
116    /// 根据 DMA 方向自动处理缓存同步:
117    /// - `FromDevice`/`Bidirectional`: 读取前使 CPU 缓存失效
118    /// - `ToDevice`: 无缓存操作
119    ///
120    /// # 参数
121    ///
122    /// - `index`: 元素索引
123    ///
124    /// # 返回
125    ///
126    /// 如果索引有效返回 `Some(T)`,否则返回 `None`
127    pub fn read(&self, index: usize) -> Option<T> {
128        if index >= self.len() {
129            return None;
130        }
131
132        unsafe {
133            let offset = index * core::mem::size_of::<T>();
134            self.data.prepare_read(offset, core::mem::size_of::<T>());
135            Some(self.data.handle.cpu_addr.cast().add(index).read())
136        }
137    }
138
139    /// 设置指定索引的元素值。
140    ///
141    /// 根据 DMA 方向自动处理缓存同步:
142    /// - `ToDevice`/`Bidirectional`: 写入后刷新 CPU 缓存
143    /// - `FromDevice`: 无缓存操作
144    ///
145    /// # 参数
146    ///
147    /// - `index`: 元素索引,必须在范围内
148    /// - `value`: 要写入的值
149    ///
150    /// # Panics
151    ///
152    /// 如果 `index >= self.len()` 则 panic
153    pub fn set(&mut self, index: usize, value: T) {
154        assert!(
155            index < self.len(),
156            "index out of range, index: {},len: {}",
157            index,
158            self.len()
159        );
160
161        unsafe {
162            let offset = index * core::mem::size_of::<T>();
163            let ptr = self.data.handle.cpu_addr.cast::<T>().add(index);
164            ptr.write(value);
165            self.data.confirm_write(offset, core::mem::size_of::<T>());
166        }
167    }
168
169    /// 创建迭代器。
170    ///
171    /// 返回一个迭代器,按顺序读取数组元素。
172    /// 每次读取都会自动处理缓存同步。
173    ///
174    /// # 返回
175    ///
176    /// `DArrayIter` 迭代器
177    pub fn iter(&self) -> DArrayIter<'_, T> {
178        DArrayIter {
179            array: self,
180            index: 0,
181        }
182    }
183
184    /// 从 slice 复制数据到数组。
185    ///
186    /// 复制完成后刷新整个数组的 CPU 缓存(ToDevice/Bidirectional)。
187    ///
188    /// # 参数
189    ///
190    /// - `src`: 源 slice,长度必须 `<= self.len()`
191    ///
192    /// # Panics
193    ///
194    /// 如果 `src.len() > self.len()` 则 panic
195    pub fn copy_from_slice(&mut self, src: &[T]) {
196        assert!(
197            src.len() <= self.len(),
198            "source slice is larger than DArray, src len: {}, DArray len: {}",
199            src.len(),
200            self.len()
201        );
202        unsafe {
203            let dst_ptr = self.data.handle.cpu_addr.as_ptr();
204            let len = core::mem::size_of_val(src);
205            dst_ptr.copy_from_nonoverlapping(src.as_ptr() as *const u8, len);
206        }
207        self.data.confirm_write_all();
208    }
209
210    /// # Safety
211    ///
212    /// slice will not auto do cache sync operations.
213    pub unsafe fn as_mut_slice(&mut self) -> &mut [T] {
214        let ptr = self.data.handle.cpu_addr;
215        unsafe {
216            core::slice::from_raw_parts_mut(
217                ptr.as_ptr() as *mut T,
218                self.bytes_len() / core::mem::size_of::<T>(),
219            )
220        }
221    }
222
223    pub fn as_ptr(&self) -> NonNull<T> {
224        self.data.handle.as_ptr().cast::<T>()
225    }
226}
227
228pub struct DArrayIter<'a, T> {
229    array: &'a DArray<T>,
230    index: usize,
231}
232
233impl<'a, T> Iterator for DArrayIter<'a, T> {
234    type Item = T;
235
236    fn next(&mut self) -> Option<Self::Item> {
237        if self.index >= self.array.len() {
238            return None;
239        }
240        let value = self.array.read(self.index);
241        self.index += 1;
242        value
243    }
244}