stm32_usbd2/
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)]
66 fn get_mem_slice<T>(&self) -> &mut [VolatileCell<T>] {
67 unsafe { slice::from_raw_parts_mut(self.mem_ptr.cast(), self.mem_len) }
68 }
69
70 pub fn read(&self, mut buf: &mut [u8]) {
71 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
72 let mem = self.get_mem_slice::<u32>();
73
74 let mut index = 0;
75
76 while buf.len() >= 4 {
77 let value = mem[index].get().to_ne_bytes();
78 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
79
80 buf[0..4].copy_from_slice(&value);
81 buf = &mut buf[4..];
82 }
83
84 if buf.len() > 0 {
85 let value = mem[index].get().to_ne_bytes();
86 buf.copy_from_slice(&value[0..buf.len()]);
87 }
88 } else {
89 let mem = self.get_mem_slice::<u16>();
90
91 let mut index = 0;
92
93 while buf.len() >= 2 {
94 let value = mem[index].get().to_ne_bytes();
95 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
96
97 buf[0..2].copy_from_slice(&value);
98 buf = &mut buf[2..];
99 }
100
101 if buf.len() > 0 {
102 let value = mem[index].get().to_ne_bytes();
103 buf.copy_from_slice(&value[0..buf.len()]);
104 }
105 }
106 }
107
108 pub fn write(&self, mut buf: &[u8]) {
109 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
110 let mem = self.get_mem_slice::<u32>();
111
112 let mut index = 0;
113
114 while buf.len() >= 4 {
115 let mut value = [0; 4];
116 value.copy_from_slice(&buf[0..4]);
117 buf = &buf[4..];
118
119 mem[index].set(u32::from_ne_bytes(value));
120 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
121 }
122
123 if buf.len() > 0 {
124 let mut value = [0; 4];
125 value[0..buf.len()].copy_from_slice(buf);
126 mem[index].set(u32::from_ne_bytes(value));
127 }
128 } else {
129 let mem = self.get_mem_slice::<u16>();
130
131 let mut index = 0;
132
133 while buf.len() >= 2 {
134 let mut value = [0; 2];
135 value.copy_from_slice(&buf[0..2]);
136 buf = &buf[2..];
137
138 mem[index].set(u16::from_ne_bytes(value));
139 index += USB::EP_MEMORY_ACCESS.offset_multiplier();
140 }
141
142 if buf.len() > 0 {
143 let mut value = [0; 2];
144 value[0..buf.len()].copy_from_slice(buf);
145 mem[index].set(u16::from_ne_bytes(value));
146 }
147 }
148 }
149
150 pub fn offset(&self) -> u16 {
151 let offset_bytes = self.mem_ptr as usize - USB::EP_MEMORY as usize;
152 (offset_bytes / USB::EP_MEMORY_ACCESS.offset_multiplier()) as u16
153 }
154
155 pub fn capacity(&self) -> usize {
156 self.mem_len * USB::EP_MEMORY_ACCESS.unit_size() / USB::EP_MEMORY_ACCESS.offset_multiplier()
157 }
158}
159
160pub struct Field<USB> {
161 ptr: *const (),
162 marker: PhantomData<USB>,
163}
164
165impl<USB: UsbPeripheral> Field<USB> {
166 #[inline(always)]
167 pub fn get(&self) -> u16 {
168 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
169 let unaligned_offset = self.ptr as usize & 0b11;
170 let cell: &VolatileCell<u32> = unsafe { &*self.ptr.byte_sub(unaligned_offset).cast() };
171 let value: [u16; 2] = unsafe { mem::transmute(cell.get()) };
172 value[unaligned_offset >> 1]
173 } else {
174 let cell: &VolatileCell<u16> = unsafe { &*self.ptr.cast() };
175 cell.get()
176 }
177 }
178
179 #[inline(always)]
180 pub fn set(&self, value: u16) {
181 if USB::EP_MEMORY_ACCESS == MemoryAccess::Word32x1 {
182 let unaligned_offset = self.ptr as usize & 0b11;
183 let cell: &VolatileCell<u32> = unsafe { &*self.ptr.byte_sub(unaligned_offset).cast() };
184 let mut previous_value: [u16; 2] = unsafe { mem::transmute(cell.get()) };
185 previous_value[unaligned_offset >> 1] = value;
186 cell.set(unsafe { mem::transmute(previous_value) });
187 } else {
188 let cell: &VolatileCell<u16> = unsafe { &*self.ptr.cast() };
189 cell.set(value);
190 }
191 }
192}
193
194#[repr(C)]
195pub struct BufferDescriptor<USB> {
196 ptr: *const (),
197 marker: PhantomData<USB>,
198}
199
200impl<USB: UsbPeripheral> BufferDescriptor<USB> {
201 #[inline(always)]
202 fn field(&self, index: usize) -> Field<USB> {
203 let mul = USB::EP_MEMORY_ACCESS.offset_multiplier();
204 let ptr = unsafe { self.ptr.byte_add(index * 2 * mul) };
205 Field {
206 ptr,
207 marker: PhantomData,
208 }
209 }
210
211 #[inline(always)]
212 pub fn addr_tx(&self) -> Field<USB> {
213 self.field(0)
214 }
215
216 #[inline(always)]
217 pub fn count_tx(&self) -> Field<USB> {
218 self.field(1)
219 }
220
221 #[inline(always)]
222 pub fn addr_rx(&self) -> Field<USB> {
223 self.field(2)
224 }
225
226 #[inline(always)]
227 pub fn count_rx(&self) -> Field<USB> {
228 self.field(3)
229 }
230}
231
232pub struct EndpointMemoryAllocator<USB> {
233 next_free_offset: usize,
234 _marker: PhantomData<USB>,
235}
236
237impl<USB: UsbPeripheral> EndpointMemoryAllocator<USB> {
238 pub fn new() -> Self {
239 Self {
240 next_free_offset: NUM_ENDPOINTS * 8,
241 _marker: PhantomData,
242 }
243 }
244
245 pub fn allocate_buffer(&mut self, size: usize) -> Result<EndpointBuffer<USB>> {
246 assert_eq!(size & 1, 0);
247 assert!(size < USB::EP_MEMORY_SIZE);
248
249 let offset = self.next_free_offset;
250 if offset as usize + size > USB::EP_MEMORY_SIZE {
251 return Err(UsbError::EndpointMemoryOverflow);
252 }
253
254 self.next_free_offset += size;
255
256 Ok(EndpointBuffer::new(offset, size))
257 }
258
259 pub fn buffer_descriptor(index: u8) -> BufferDescriptor<USB> {
260 let mul = USB::EP_MEMORY_ACCESS.offset_multiplier();
261 let ptr = unsafe { USB::EP_MEMORY.byte_add((index as usize) * 8 * mul).cast() };
262 BufferDescriptor {
263 ptr,
264 marker: Default::default(),
265 }
266 }
267}