stm32_usbd/
endpoint_memory.rs1use crate::endpoint::NUM_ENDPOINTS;
2use crate::UsbPeripheral;
3use core::slice;
4use core::{marker::PhantomData, mem};
5use usb_device::{Result, UsbError};
6use vcell::VolatileCell;
7
8#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10#[non_exhaustive]
11pub enum MemoryAccess {
12 Word16x1,
16 Word16x2,
20 Word32x1,
22}
23
24impl MemoryAccess {
25 #[inline(always)]
27 const fn offset_multiplier(self) -> usize {
28 match self {
29 MemoryAccess::Word16x1 => 2,
30 MemoryAccess::Word16x2 | MemoryAccess::Word32x1 => 1,
31 }
32 }
33
34 #[inline(always)]
36 const fn unit_size(self) -> usize {
37 match self {
38 MemoryAccess::Word16x1 | MemoryAccess::Word16x2 => 2,
39 MemoryAccess::Word32x1 => 4,
40 }
41 }
42}
43
44pub struct EndpointBuffer<USB> {
45 mem_ptr: *mut (),
46 mem_len: usize,
47 marker: PhantomData<USB>,
48}
49
50unsafe impl<USB> Send for EndpointBuffer<USB> {}
51
52impl<USB: UsbPeripheral> EndpointBuffer<USB> {
53 pub fn new(offset_bytes: usize, size_bytes: usize) -> Self {
54 let mem_offset_bytes = offset_bytes * USB::EP_MEMORY_ACCESS.offset_multiplier();
55 let mem_len = size_bytes * USB::EP_MEMORY_ACCESS.offset_multiplier() / USB::EP_MEMORY_ACCESS.unit_size();
56
57 let mem_ptr = unsafe { USB::EP_MEMORY.byte_add(mem_offset_bytes).cast_mut() };
58 Self {
59 mem_ptr,
60 mem_len,
61 marker: PhantomData,
62 }
63 }
64
65 #[inline(always)]
69 unsafe fn get_mem_slice<T>(&self) -> &[VolatileCell<T>] {
70 unsafe { slice::from_raw_parts(self.mem_ptr.cast(), self.mem_len) }
71 }
72
73 pub fn read(&self, mut buf: &mut [u8]) {
74 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
75 let mem = unsafe { self.get_mem_slice::<u32>() };
76
77 let mut index = 0;
78
79 while buf.len() >= 4 {
80 let value = mem[index].get().to_ne_bytes();
81 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
82
83 buf[0..4].copy_from_slice(&value);
84 buf = &mut buf[4..];
85 }
86
87 if buf.len() > 0 {
88 let value = mem[index].get().to_ne_bytes();
89 buf.copy_from_slice(&value[0..buf.len()]);
90 }
91 } else {
92 let mem = unsafe { self.get_mem_slice::<u16>() };
93
94 let mut index = 0;
95
96 while buf.len() >= 2 {
97 let value = mem[index].get().to_ne_bytes();
98 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
99
100 buf[0..2].copy_from_slice(&value);
101 buf = &mut buf[2..];
102 }
103
104 if buf.len() > 0 {
105 let value = mem[index].get().to_ne_bytes();
106 buf.copy_from_slice(&value[0..buf.len()]);
107 }
108 }
109 }
110
111 pub fn write(&self, mut buf: &[u8]) {
112 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
113 let mem = unsafe { self.get_mem_slice::<u32>() };
114
115 let mut index = 0;
116
117 while buf.len() >= 4 {
118 let mut value = [0; 4];
119 value.copy_from_slice(&buf[0..4]);
120 buf = &buf[4..];
121
122 mem[index].set(u32::from_ne_bytes(value));
123 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
124 }
125
126 if buf.len() > 0 {
127 let mut value = [0; 4];
128 value[0..buf.len()].copy_from_slice(buf);
129 mem[index].set(u32::from_ne_bytes(value));
130 }
131 } else {
132 let mem = unsafe { self.get_mem_slice::<u16>() };
133
134 let mut index = 0;
135
136 while buf.len() >= 2 {
137 let mut value = [0; 2];
138 value.copy_from_slice(&buf[0..2]);
139 buf = &buf[2..];
140
141 mem[index].set(u16::from_ne_bytes(value));
142 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
143 }
144
145 if buf.len() > 0 {
146 let mut value = [0; 2];
147 value[0..buf.len()].copy_from_slice(buf);
148 mem[index].set(u16::from_ne_bytes(value));
149 }
150 }
151 }
152
153 pub fn offset(&self) -> u16 {
154 let offset_bytes = self.mem_ptr as usize - USB::EP_MEMORY as usize;
155 (offset_bytes / USB::EP_MEMORY_ACCESS.offset_multiplier()) as u16
156 }
157
158 pub fn capacity(&self) -> usize {
159 self.mem_len * USB::EP_MEMORY_ACCESS.unit_size() / USB::EP_MEMORY_ACCESS.offset_multiplier()
160 }
161}
162
163pub struct Field<USB> {
164 ptr: *const (),
165 marker: PhantomData<USB>,
166}
167
168impl<USB: UsbPeripheral> Field<USB> {
169 #[inline(always)]
170 pub fn get(&self) -> u16 {
171 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
172 let unaligned_offset = self.ptr as usize & 0b11;
173 let cell: &VolatileCell<u32> = unsafe { &*self.ptr.byte_sub(unaligned_offset).cast() };
174 let value: [u16; 2] = unsafe { mem::transmute(cell.get()) };
175 value[unaligned_offset >> 1]
176 } else {
177 let cell: &VolatileCell<u16> = unsafe { &*self.ptr.cast() };
178 cell.get()
179 }
180 }
181
182 #[inline(always)]
183 pub fn set(&self, value: u16) {
184 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
185 let unaligned_offset = self.ptr as usize & 0b11;
186 let cell: &VolatileCell<u32> = unsafe { &*self.ptr.byte_sub(unaligned_offset).cast() };
187 let mut previous_value: [u16; 2] = unsafe { mem::transmute(cell.get()) };
188 previous_value[unaligned_offset >> 1] = value;
189 cell.set(unsafe { mem::transmute(previous_value) });
190 } else {
191 let cell: &VolatileCell<u16> = unsafe { &*self.ptr.cast() };
192 cell.set(value);
193 }
194 }
195}
196
197#[repr(C)]
198pub struct BufferDescriptor<USB> {
199 ptr: *const (),
200 marker: PhantomData<USB>,
201}
202
203impl<USB: UsbPeripheral> BufferDescriptor<USB> {
204 #[inline(always)]
205 fn field(&self, index: usize) -> Field<USB> {
206 let mul = USB::EP_MEMORY_ACCESS.offset_multiplier();
207 let ptr = unsafe { self.ptr.byte_add(index * 2 * mul) };
208 Field {
209 ptr,
210 marker: PhantomData,
211 }
212 }
213
214 #[inline(always)]
215 pub fn addr_tx(&self) -> Field<USB> {
216 self.field(0)
217 }
218
219 #[inline(always)]
220 pub fn count_tx(&self) -> Field<USB> {
221 self.field(1)
222 }
223
224 #[inline(always)]
225 pub fn addr_rx(&self) -> Field<USB> {
226 self.field(2)
227 }
228
229 #[inline(always)]
230 pub fn count_rx(&self) -> Field<USB> {
231 self.field(3)
232 }
233}
234
235pub struct EndpointMemoryAllocator<USB> {
236 next_free_offset: usize,
237 _marker: PhantomData<USB>,
238}
239
240impl<USB: UsbPeripheral> EndpointMemoryAllocator<USB> {
241 pub fn new() -> Self {
242 Self {
243 next_free_offset: NUM_ENDPOINTS * 8,
244 _marker: PhantomData,
245 }
246 }
247
248 pub fn allocate_buffer(&mut self, size: usize) -> Result<EndpointBuffer<USB>> {
249 assert_eq!(size & 1, 0);
250 assert!(size < USB::EP_MEMORY_SIZE);
251
252 let offset = self.next_free_offset;
253 if offset as usize + size > USB::EP_MEMORY_SIZE {
254 return Err(UsbError::EndpointMemoryOverflow);
255 }
256
257 self.next_free_offset += size;
258
259 Ok(EndpointBuffer::new(offset, size))
260 }
261
262 pub fn buffer_descriptor(index: u8) -> BufferDescriptor<USB> {
263 let mul = USB::EP_MEMORY_ACCESS.offset_multiplier();
264 let ptr = unsafe { USB::EP_MEMORY.byte_add((index as usize) * 8 * mul).cast() };
265 BufferDescriptor {
266 ptr,
267 marker: Default::default(),
268 }
269 }
270}