stm32_usbd2/
endpoint_memory.rs

1use 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/// Different endpoint memory access schemes
9#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10#[non_exhaustive]
11pub enum MemoryAccess {
12    /// 16x1 bits per word. Each 32-bit word is accessed as one 16-bit half-word. The second half-word of the word is ignored.
13    ///
14    /// This matches the behavior of `EP_MEMORY_ACCESS_2X16 = false` from previous versions of this library.
15    Word16x1,
16    /// 16x2 bits per word. Each 32-bit word is accessed as two 16-bit half-words.
17    ///
18    /// This matches the behavior of `EP_MEMORY_ACCESS_2X16 = true` from previous versions of this library.
19    Word16x2,
20    /// 32x1 bits per word. Each 32-bit word is accessed as one 32-bit word.
21    Word32x1,
22}
23
24impl MemoryAccess {
25    /// Value to multiply offsets within the EP memory by when calculating address to read or write to.
26    #[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    /// Size of unit used when reading and writing EP memory, in bytes.
35    #[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}