aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/usb
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-04-06 18:50:53 +0200
committerDario Nieuwenhuis <[email protected]>2023-04-06 18:59:37 +0200
commit9f28d8097704f51fb7d7dcc8d459ce86aaf07eff (patch)
tree42e60061bee4284d3dd400547b38505f1655ab03 /embassy-stm32/src/usb
parent52cab3a9f4f1a14b47454d38a96f01b14e688c9f (diff)
stm32/usb: add support for 32bit usbram.
Diffstat (limited to 'embassy-stm32/src/usb')
-rw-r--r--embassy-stm32/src/usb/usb.rs131
1 files changed, 85 insertions, 46 deletions
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 0355c5f14..e6ee39549 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -12,22 +12,29 @@ use embassy_usb_driver as driver;
12use embassy_usb_driver::{ 12use embassy_usb_driver::{
13 Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, 13 Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
14}; 14};
15use pac::common::{Reg, RW};
16use pac::usb::vals::{EpType, Stat};
17 15
18use super::{DmPin, DpPin, Instance}; 16use super::{DmPin, DpPin, Instance};
19use crate::gpio::sealed::AFType; 17use crate::gpio::sealed::AFType;
20use crate::interrupt::InterruptExt; 18use crate::interrupt::InterruptExt;
21use crate::pac::usb::regs; 19use crate::pac::usb::regs;
20use crate::pac::usb::vals::{EpType, Stat};
21use crate::pac::USBRAM;
22use crate::rcc::sealed::RccPeripheral; 22use crate::rcc::sealed::RccPeripheral;
23use crate::{pac, Peripheral}; 23use crate::Peripheral;
24 24
25const EP_COUNT: usize = 8; 25const EP_COUNT: usize = 8;
26 26
27#[cfg(any(usb_v1_x1, usb_v1_x2))] 27#[cfg(any(usbram_16x1_512, usbram_16x2_512))]
28const EP_MEMORY_SIZE: usize = 512; 28const USBRAM_SIZE: usize = 512;
29#[cfg(not(any(usb_v1_x1, usb_v1_x2)))] 29#[cfg(usbram_16x2_1024)]
30const EP_MEMORY_SIZE: usize = 1024; 30const USBRAM_SIZE: usize = 1024;
31#[cfg(usbram_32_2048)]
32const USBRAM_SIZE: usize = 2048;
33
34#[cfg(not(usbram_32_2048))]
35const USBRAM_ALIGN: usize = 2;
36#[cfg(usbram_32_2048)]
37const USBRAM_ALIGN: usize = 4;
31 38
32const NEW_AW: AtomicWaker = AtomicWaker::new(); 39const NEW_AW: AtomicWaker = AtomicWaker::new();
33static BUS_WAKER: AtomicWaker = NEW_AW; 40static BUS_WAKER: AtomicWaker = NEW_AW;
@@ -57,25 +64,60 @@ fn invariant(mut r: regs::Epr) -> regs::Epr {
57 r 64 r
58} 65}
59 66
67fn align_len_up(len: u16) -> u16 {
68 ((len as usize + USBRAM_ALIGN - 1) / USBRAM_ALIGN * USBRAM_ALIGN) as u16
69}
70
60// Returns (actual_len, len_bits) 71// Returns (actual_len, len_bits)
61fn calc_out_len(len: u16) -> (u16, u16) { 72fn calc_out_len(len: u16) -> (u16, u16) {
62 match len { 73 match len {
63 2..=62 => ((len + 1) / 2 * 2, ((len + 1) / 2) << 10), 74 // NOTE: this could be 2..=62 with 16bit USBRAM, but not with 32bit. Limit it to 60 for simplicity.
64 63..=480 => ((len + 31) / 32 * 32, (((len + 31) / 32 - 1) << 10) | 0x8000), 75 2..=60 => (align_len_up(len), align_len_up(len) / 2 << 10),
76 61..=1024 => ((len + 31) / 32 * 32, (((len + 31) / 32 - 1) << 10) | 0x8000),
65 _ => panic!("invalid OUT length {}", len), 77 _ => panic!("invalid OUT length {}", len),
66 } 78 }
67} 79}
68fn ep_in_addr<T: Instance>(index: usize) -> Reg<u16, RW> { 80
69 T::regs().ep_mem(index * 4 + 0) 81#[cfg(not(usbram_32_2048))]
70} 82mod btable {
71fn ep_in_len<T: Instance>(index: usize) -> Reg<u16, RW> { 83 use super::*;
72 T::regs().ep_mem(index * 4 + 1) 84
73} 85 pub(super) unsafe fn write_in<T: Instance>(index: usize, addr: u16) {
74fn ep_out_addr<T: Instance>(index: usize) -> Reg<u16, RW> { 86 USBRAM.mem(index * 4 + 0).write_value(addr);
75 T::regs().ep_mem(index * 4 + 2) 87 }
88
89 pub(super) unsafe fn write_in_len<T: Instance>(index: usize, _addr: u16, len: u16) {
90 USBRAM.mem(index * 4 + 1).write_value(len);
91 }
92
93 pub(super) unsafe fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
94 USBRAM.mem(index * 4 + 2).write_value(addr);
95 USBRAM.mem(index * 4 + 3).write_value(max_len_bits);
96 }
97
98 pub(super) unsafe fn read_out_len<T: Instance>(index: usize) -> u16 {
99 USBRAM.mem(index * 4 + 3).read()
100 }
76} 101}
77fn ep_out_len<T: Instance>(index: usize) -> Reg<u16, RW> { 102#[cfg(usbram_32_2048)]
78 T::regs().ep_mem(index * 4 + 3) 103mod btable {
104 use super::*;
105
106 pub(super) unsafe fn write_in<T: Instance>(_index: usize, _addr: u16) {}
107
108 pub(super) unsafe fn write_in_len<T: Instance>(index: usize, addr: u16, len: u16) {
109 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16));
110 }
111
112 pub(super) unsafe fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
113 USBRAM
114 .mem(index * 2 + 1)
115 .write_value((addr as u32) | ((max_len_bits as u32) << 16));
116 }
117
118 pub(super) unsafe fn read_out_len<T: Instance>(index: usize) -> u16 {
119 (USBRAM.mem(index * 2 + 1).read() >> 16) as u16
120 }
79} 121}
80 122
81struct EndpointBuffer<T: Instance> { 123struct EndpointBuffer<T: Instance> {
@@ -87,23 +129,25 @@ struct EndpointBuffer<T: Instance> {
87impl<T: Instance> EndpointBuffer<T> { 129impl<T: Instance> EndpointBuffer<T> {
88 fn read(&mut self, buf: &mut [u8]) { 130 fn read(&mut self, buf: &mut [u8]) {
89 assert!(buf.len() <= self.len as usize); 131 assert!(buf.len() <= self.len as usize);
90 for i in 0..((buf.len() + 1) / 2) { 132 for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN {
91 let val = unsafe { T::regs().ep_mem(self.addr as usize / 2 + i).read() }; 133 let val = unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).read() };
92 buf[i * 2] = val as u8; 134 let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN);
93 if i * 2 + 1 < buf.len() { 135 buf[i * USBRAM_ALIGN..][..n].copy_from_slice(&val.to_le_bytes()[..n]);
94 buf[i * 2 + 1] = (val >> 8) as u8;
95 }
96 } 136 }
97 } 137 }
98 138
99 fn write(&mut self, buf: &[u8]) { 139 fn write(&mut self, buf: &[u8]) {
100 assert!(buf.len() <= self.len as usize); 140 assert!(buf.len() <= self.len as usize);
101 for i in 0..((buf.len() + 1) / 2) { 141 for i in 0..(buf.len() + USBRAM_ALIGN - 1) / USBRAM_ALIGN {
102 let mut val = buf[i * 2] as u16; 142 let mut val = [0u8; USBRAM_ALIGN];
103 if i * 2 + 1 < buf.len() { 143 let n = USBRAM_ALIGN.min(buf.len() - i * USBRAM_ALIGN);
104 val |= (buf[i * 2 + 1] as u16) << 8; 144 val[..n].copy_from_slice(&buf[i * USBRAM_ALIGN..][..n]);
105 } 145
106 unsafe { T::regs().ep_mem(self.addr as usize / 2 + i).write_value(val) }; 146 #[cfg(not(usbram_32_2048))]
147 let val = u16::from_le_bytes(val);
148 #[cfg(usbram_32_2048)]
149 let val = u32::from_le_bytes(val);
150 unsafe { USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val) };
107 } 151 }
108 } 152 }
109} 153}
@@ -139,8 +183,7 @@ impl<'d, T: Instance> Driver<'d, T> {
139 #[cfg(stm32l5)] 183 #[cfg(stm32l5)]
140 unsafe { 184 unsafe {
141 crate::peripherals::PWR::enable(); 185 crate::peripherals::PWR::enable();
142 186 crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
143 pac::PWR.cr2().modify(|w| w.set_usv(true));
144 } 187 }
145 188
146 unsafe { 189 unsafe {
@@ -256,8 +299,9 @@ impl<'d, T: Instance> Driver<'d, T> {
256 } 299 }
257 300
258 fn alloc_ep_mem(&mut self, len: u16) -> u16 { 301 fn alloc_ep_mem(&mut self, len: u16) -> u16 {
302 assert!(len as usize % USBRAM_ALIGN == 0);
259 let addr = self.ep_mem_free; 303 let addr = self.ep_mem_free;
260 if addr + len > EP_MEMORY_SIZE as _ { 304 if addr + len > USBRAM_SIZE as _ {
261 panic!("Endpoint memory full"); 305 panic!("Endpoint memory full");
262 } 306 }
263 self.ep_mem_free += len; 307 self.ep_mem_free += len;
@@ -306,10 +350,7 @@ impl<'d, T: Instance> Driver<'d, T> {
306 let addr = self.alloc_ep_mem(len); 350 let addr = self.alloc_ep_mem(len);
307 351
308 trace!(" len_bits = {:04x}", len_bits); 352 trace!(" len_bits = {:04x}", len_bits);
309 unsafe { 353 unsafe { btable::write_out::<T>(index, addr, len_bits) }
310 ep_out_addr::<T>(index).write_value(addr);
311 ep_out_len::<T>(index).write_value(len_bits);
312 }
313 354
314 EndpointBuffer { 355 EndpointBuffer {
315 addr, 356 addr,
@@ -321,13 +362,11 @@ impl<'d, T: Instance> Driver<'d, T> {
321 assert!(!ep.used_in); 362 assert!(!ep.used_in);
322 ep.used_in = true; 363 ep.used_in = true;
323 364
324 let len = (max_packet_size + 1) / 2 * 2; 365 let len = align_len_up(max_packet_size);
325 let addr = self.alloc_ep_mem(len); 366 let addr = self.alloc_ep_mem(len);
326 367
327 unsafe { 368 // ep_in_len is written when actually TXing packets.
328 ep_in_addr::<T>(index).write_value(addr); 369 unsafe { btable::write_in::<T>(index, addr) }
329 // ep_in_len is written when actually TXing packets.
330 }
331 370
332 EndpointBuffer { 371 EndpointBuffer {
333 addr, 372 addr,
@@ -398,7 +437,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
398 w.set_ctrm(true); 437 w.set_ctrm(true);
399 }); 438 });
400 439
401 #[cfg(usb_v3)] 440 #[cfg(any(usb_v3, usb_v4))]
402 regs.bcdr().write(|w| w.set_dppu(true)) 441 regs.bcdr().write(|w| w.set_dppu(true))
403 } 442 }
404 443
@@ -633,12 +672,12 @@ impl<'d, T: Instance, D> Endpoint<'d, T, D> {
633 fn write_data(&mut self, buf: &[u8]) { 672 fn write_data(&mut self, buf: &[u8]) {
634 let index = self.info.addr.index(); 673 let index = self.info.addr.index();
635 self.buf.write(buf); 674 self.buf.write(buf);
636 unsafe { ep_in_len::<T>(index).write_value(buf.len() as _) }; 675 unsafe { btable::write_in_len::<T>(index, self.buf.addr, buf.len() as _) }
637 } 676 }
638 677
639 fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { 678 fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
640 let index = self.info.addr.index(); 679 let index = self.info.addr.index();
641 let rx_len = unsafe { ep_out_len::<T>(index).read() as usize } & 0x3FF; 680 let rx_len = unsafe { btable::read_out_len::<T>(index) as usize } & 0x3FF;
642 trace!("READ DONE, rx_len = {}", rx_len); 681 trace!("READ DONE, rx_len = {}", rx_len);
643 if rx_len > buf.len() { 682 if rx_len > buf.len() {
644 return Err(EndpointError::BufferOverflow); 683 return Err(EndpointError::BufferOverflow);