Skip to content

Commit dade3d9

Browse files
committed
Implement endpoint size with generics
Signed-off-by: Arthur Heymans <[email protected]>
1 parent 07687b9 commit dade3d9

File tree

8 files changed

+98
-67
lines changed

8 files changed

+98
-67
lines changed

examples/ch32v307/src/bin/usb_hs_serial.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use panic_halt as _;
55
use embassy_executor::Spawner;
66
use embassy_futures::join::join;
7-
use ch32_hal::usb::EndpointDataBuffer;
7+
use ch32_hal::usb::EndpointDataBuffer512;
88
use ch32_hal::usbhs::{Driver};
99
use ch32_hal::{self as hal, bind_interrupts, peripherals, Config};
1010
use ch32_hal::usbhs::{InterruptHandler, WakeupInterruptHandler, Instance};
@@ -27,7 +27,7 @@ async fn main(_spawner: Spawner) {
2727

2828

2929
// Create the driver, from the HAL.
30-
let mut buffer: [EndpointDataBuffer; 4] = core::array::from_fn(|_| EndpointDataBuffer::default());
30+
let mut buffer: [EndpointDataBuffer512; 4] = core::array::from_fn(|_| EndpointDataBuffer512::default());
3131
let driver = Driver::new(p.USBHS, Irq, p.PB7, p.PB6, &mut buffer);
3232

3333
// Create embassy-usb Config
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
5555
);
5656

5757
// Create classes on the builder.
58-
let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
58+
let mut class = CdcAcmClass::new(&mut builder, &mut state, 512);
5959

6060
// Build the builder.
6161
let mut usb = builder.build();
@@ -87,8 +87,8 @@ impl From<EndpointError> for Disconnected {
8787
}
8888
}
8989

90-
async fn echo<'d, T: Instance + 'd, const NR_EP: usize>(class: &mut CdcAcmClass<'d, Driver<'d, T, NR_EP>>) -> Result<(), Disconnected> {
91-
let mut buf = [0; 64];
90+
async fn echo<'d, T: Instance + 'd, const NR_EP: usize, const SIZE: usize>(class: &mut CdcAcmClass<'d, Driver<'d, T, NR_EP, SIZE>>) -> Result<(), Disconnected> {
91+
let mut buf = [0; 512];
9292
loop {
9393
let n = class.read_packet(&mut buf).await?;
9494
let data = &buf[..n];

examples/ch32v307/src/bin/usbfs_dfu.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![no_main]
33

44
use panic_halt as _;
5-
use ch32_hal::usb::EndpointDataBuffer;
5+
use ch32_hal::usb::EndpointDataBuffer512;
66
use ch32_hal::otg_fs::{self, Driver};
77
use ch32_hal::{self as hal, bind_interrupts, peripherals, Config};
88
use embassy_executor::Spawner;
@@ -47,7 +47,7 @@ async fn main(spawner: Spawner) -> ! {
4747
let p = hal::init(cfg);
4848

4949
/* USB DRIVER SECION */
50-
let mut buffer: [EndpointDataBuffer; 1] = core::array::from_fn(|_| EndpointDataBuffer::default());
50+
let mut buffer: [EndpointDataBuffer512; 1] = core::array::from_fn(|_| EndpointDataBuffer512::default());
5151
let driver = Driver::new(p.OTG_FS, p.PA12, p.PA11, &mut buffer);
5252

5353
// Create embassy-usb Config

src/otg_fs/endpoint.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ use crate::interrupt::typelevel::Interrupt;
1010
use crate::usb::{Dir, EndpointData, In, Out};
1111

1212
/// USB endpoint.
13-
pub struct Endpoint<'d, T, D> {
13+
pub struct Endpoint<'d, T, D, const SIZE: usize> {
1414
_phantom: PhantomData<&'d (T, D)>,
1515
info: EndpointInfo,
16-
data: EndpointData<'d>,
16+
data: EndpointData<'d, SIZE>,
1717
}
1818

19-
impl<'d, T: Instance, D: Dir> Endpoint<'d, T, D> {
20-
pub(crate) fn new(info: EndpointInfo, data: EndpointData<'d>) -> Self {
19+
impl<'d, T: Instance, D: Dir, const SIZE: usize> Endpoint<'d, T, D, SIZE> {
20+
pub(crate) fn new(info: EndpointInfo, data: EndpointData<'d, SIZE>) -> Self {
2121
T::regs()
2222
.uep_dma(info.addr.index() as usize)
2323
.write_value(data.buffer.addr() as u32);
@@ -67,7 +67,7 @@ impl<'d, T: Instance, D: Dir> Endpoint<'d, T, D> {
6767
}
6868
}
6969

70-
impl<'d, T: Instance, D: Dir> embassy_usb_driver::Endpoint for Endpoint<'d, T, D> {
70+
impl<'d, T: Instance, D: Dir, const SIZE: usize> embassy_usb_driver::Endpoint for Endpoint<'d, T, D, SIZE> {
7171
fn info(&self) -> &EndpointInfo {
7272
&self.info
7373
}
@@ -77,7 +77,7 @@ impl<'d, T: Instance, D: Dir> embassy_usb_driver::Endpoint for Endpoint<'d, T, D
7777
}
7878
}
7979

80-
impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
80+
impl<'d, T: Instance, const SIZE: usize> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In, SIZE> {
8181
async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
8282
trace!("endpoint {} IN", self.info.addr.index());
8383
if !self.is_enabled() {
@@ -133,7 +133,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
133133
}
134134
}
135135

136-
impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> {
136+
impl<'d, T: Instance, const SIZE: usize> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out, SIZE> {
137137
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
138138
trace!("endpoint {} OUT", self.info.addr.index());
139139
if !self.is_enabled() {
@@ -192,21 +192,21 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> {
192192
}
193193
}
194194

195-
pub struct ControlPipe<'d, T> {
196-
ep0_buf: EndpointData<'d>,
195+
pub struct ControlPipe<'d, T, const SIZE: usize> {
196+
ep0_buf: EndpointData<'d, SIZE>,
197197
_phantom: PhantomData<T>,
198198
}
199199

200-
impl<'d, T: Instance> ControlPipe<'d, T> {
201-
pub(crate) fn new(ep0_buf: EndpointData<'d>) -> Self {
200+
impl<'d, T: Instance, const SIZE: usize> ControlPipe<'d, T, SIZE> {
201+
pub(crate) fn new(ep0_buf: EndpointData<'d, SIZE>) -> Self {
202202
Self {
203203
ep0_buf,
204204
_phantom: PhantomData,
205205
}
206206
}
207207
}
208208

209-
impl<'d, T> embassy_usb_driver::ControlPipe for ControlPipe<'d, T>
209+
impl<'d, T, const SIZE: usize> embassy_usb_driver::ControlPipe for ControlPipe<'d, T, SIZE>
210210
where
211211
T: Instance,
212212
{

src/otg_fs/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
101101
}
102102
}
103103

104-
pub struct Driver<'d, T: Instance, const NR_EP: usize> {
104+
pub struct Driver<'d, T: Instance, const NR_EP: usize, const SIZE: usize> {
105105
phantom: PhantomData<&'d mut T>,
106-
allocator: EndpointBufferAllocator<'d, NR_EP>,
106+
allocator: EndpointBufferAllocator<'d, NR_EP, SIZE>,
107107
allocated: Bitmap<MAX_NR_EP>,
108108
}
109109

110-
impl<'d, T, const NR_EP: usize> Driver<'d, T, NR_EP>
110+
impl<'d, T, const NR_EP: usize, const SIZE: usize> Driver<'d, T, NR_EP, SIZE>
111111
where
112112
T: Instance,
113113
{
@@ -116,7 +116,7 @@ where
116116
// _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
117117
dp: impl Peripheral<P = impl crate::gpio::Pin> + 'd,
118118
dm: impl Peripheral<P = impl crate::gpio::Pin> + 'd,
119-
ep_buffer: &'d mut [EndpointDataBuffer; NR_EP],
119+
ep_buffer: &'d mut [EndpointDataBuffer<SIZE>; NR_EP],
120120
) -> Self {
121121
assert!(ep_buffer.len() > 0);
122122
let dp = dp.into_ref();
@@ -151,7 +151,7 @@ where
151151
max_packet_size: u16,
152152
interval_ms: u8,
153153
dir: Direction,
154-
) -> Result<Endpoint<'d, T, D>, embassy_usb_driver::EndpointAllocError> {
154+
) -> Result<Endpoint<'d, T, D, SIZE>, embassy_usb_driver::EndpointAllocError> {
155155
let addr = match ep_addr {
156156
Some(addr) => {
157157
// Use the provided endpoint address
@@ -198,12 +198,14 @@ where
198198
}
199199
}
200200

201-
impl<'d, T: Instance, const NR_EP: usize> embassy_usb_driver::Driver<'d> for Driver<'d, T, NR_EP> {
202-
type EndpointOut = Endpoint<'d, T, Out>;
201+
impl<'d, T: Instance, const NR_EP: usize, const SIZE: usize> embassy_usb_driver::Driver<'d>
202+
for Driver<'d, T, NR_EP, SIZE>
203+
{
204+
type EndpointOut = Endpoint<'d, T, Out, SIZE>;
203205

204-
type EndpointIn = Endpoint<'d, T, In>;
206+
type EndpointIn = Endpoint<'d, T, In, SIZE>;
205207

206-
type ControlPipe = ControlPipe<'d, T>;
208+
type ControlPipe = ControlPipe<'d, T, SIZE>;
207209

208210
type Bus = Bus<'d, T>;
209211

src/usb/mod.rs

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
use embassy_usb_driver::EndpointAllocError;
22

3-
pub(crate) struct EndpointBufferAllocator<'d, const NR_EP: usize> {
4-
ep_buffer: &'d mut [EndpointDataBuffer; NR_EP],
3+
pub(crate) struct EndpointBufferAllocator<'d, const NR_EP: usize, const SIZE: usize> {
4+
ep_buffer: &'d mut [EndpointDataBuffer<SIZE>; NR_EP],
55
ep_next: usize,
66
}
77

8-
impl<'d, const NR_EP: usize> EndpointBufferAllocator<'d, NR_EP> {
9-
pub fn new(ep_buffer: &'d mut [EndpointDataBuffer; NR_EP]) -> Self {
8+
/// Compile-time validation for buffer sizes
9+
const fn validate_buffer_size(size: usize) -> bool {
10+
matches!(size, 8 | 16 | 32 | 64 | 512)
11+
}
12+
13+
impl<'d, const NR_EP: usize, const SIZE: usize> EndpointBufferAllocator<'d, NR_EP, SIZE> {
14+
pub fn new(ep_buffer: &'d mut [EndpointDataBuffer<SIZE>; NR_EP]) -> Self {
15+
const { assert!(validate_buffer_size(SIZE), "Invalid buffer size") };
1016
Self { ep_buffer, ep_next: 0 }
1117
}
1218

1319
pub fn alloc_endpoint(
1420
&mut self,
1521
max_packet_size: u16,
16-
) -> Result<EndpointData<'d>, embassy_usb_driver::EndpointAllocError> {
22+
) -> Result<EndpointData<'d, SIZE>, embassy_usb_driver::EndpointAllocError> {
1723
if self.ep_next >= NR_EP {
1824
error!("out of endpoint buffers");
1925
return Err(EndpointAllocError);
@@ -22,37 +28,39 @@ impl<'d, const NR_EP: usize> EndpointBufferAllocator<'d, NR_EP> {
2228
let ep_buf_idx = self.ep_next;
2329
self.ep_next += 1;
2430

25-
// TODO: Fix this, and allow variable buffer sizes
26-
assert!(max_packet_size as usize <= ENDPOINT_DATA_BUFFER_SIZE);
31+
assert!(
32+
max_packet_size as usize <= SIZE,
33+
"max_packet_size {} exceeds buffer size {}",
34+
max_packet_size,
35+
SIZE
36+
);
2737

2838
Ok(EndpointData {
2939
max_packet_size,
30-
buffer: unsafe { core::mem::transmute(&self.ep_buffer[ep_buf_idx] as *const EndpointDataBuffer) },
40+
buffer: unsafe { core::mem::transmute(&self.ep_buffer[ep_buf_idx] as *const EndpointDataBuffer<SIZE>) },
3141
})
3242
}
3343
}
3444

35-
pub struct EndpointData<'d> {
45+
pub struct EndpointData<'d, const SIZE: usize> {
3646
pub max_packet_size: u16,
37-
pub buffer: &'d mut EndpointDataBuffer,
47+
pub buffer: &'d mut EndpointDataBuffer<SIZE>,
3848
}
3949

40-
impl<'d> EndpointData<'d> {
50+
impl<'d, const SIZE: usize> EndpointData<'d, SIZE> {
4151
pub fn addr(&self) -> usize {
4252
self.buffer.addr()
4353
}
4454
}
4555

46-
// todo generic
47-
const ENDPOINT_DATA_BUFFER_SIZE: usize = 64;
48-
4956
#[repr(C, align(4))]
50-
pub struct EndpointDataBuffer {
51-
data: [u8; ENDPOINT_DATA_BUFFER_SIZE as usize],
57+
pub struct EndpointDataBuffer<const SIZE: usize> {
58+
data: [u8; SIZE],
5259
}
5360

54-
impl Default for EndpointDataBuffer {
61+
impl<const SIZE: usize> Default for EndpointDataBuffer<SIZE> {
5562
fn default() -> Self {
63+
const { assert!(validate_buffer_size(SIZE), "Invalid buffer size") };
5664
unsafe {
5765
EndpointDataBuffer {
5866
data: core::mem::zeroed(),
@@ -61,7 +69,7 @@ impl Default for EndpointDataBuffer {
6169
}
6270
}
6371

64-
impl EndpointDataBuffer {
72+
impl<const SIZE: usize> EndpointDataBuffer<SIZE> {
6573
pub(crate) fn read_volatile(&self, buf: &mut [u8]) {
6674
assert!(buf.len() <= self.data.len());
6775
let len = buf.len();
@@ -85,6 +93,25 @@ impl EndpointDataBuffer {
8593
}
8694
}
8795

96+
// Type aliases for common buffer sizes
97+
pub type EndpointDataBuffer8 = EndpointDataBuffer<8>;
98+
pub type EndpointDataBuffer16 = EndpointDataBuffer<16>;
99+
pub type EndpointDataBuffer32 = EndpointDataBuffer<32>;
100+
pub type EndpointDataBuffer64 = EndpointDataBuffer<64>;
101+
pub type EndpointDataBuffer512 = EndpointDataBuffer<512>;
102+
103+
pub type EndpointData8<'d> = EndpointData<'d, 8>;
104+
pub type EndpointData16<'d> = EndpointData<'d, 16>;
105+
pub type EndpointData32<'d> = EndpointData<'d, 32>;
106+
pub type EndpointData64<'d> = EndpointData<'d, 64>;
107+
pub type EndpointData512<'d> = EndpointData<'d, 512>;
108+
109+
pub type EndpointBufferAllocator8<'d, const NR_EP: usize> = EndpointBufferAllocator<'d, NR_EP, 8>;
110+
pub type EndpointBufferAllocator16<'d, const NR_EP: usize> = EndpointBufferAllocator<'d, NR_EP, 16>;
111+
pub type EndpointBufferAllocator32<'d, const NR_EP: usize> = EndpointBufferAllocator<'d, NR_EP, 32>;
112+
pub type EndpointBufferAllocator64<'d, const NR_EP: usize> = EndpointBufferAllocator<'d, NR_EP, 64>;
113+
pub type EndpointBufferAllocator512<'d, const NR_EP: usize> = EndpointBufferAllocator<'d, NR_EP, 512>;
114+
88115
/// USB Direction Trait
89116
pub trait Dir {}
90117

src/usbhs/control.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ use super::endpoint::Endpoint;
99
use super::{Instance, EP_WAKERS};
1010
use crate::usb::InOut;
1111

12-
pub struct ControlPipe<'d, T: Instance> {
12+
pub struct ControlPipe<'d, T: Instance, const SIZE: usize> {
1313
_phantom: PhantomData<&'d mut T>,
14-
ep0: Endpoint<'d, T, InOut>,
14+
ep0: Endpoint<'d, T, InOut, SIZE>,
1515
}
1616

17-
impl<'d, T: Instance> ControlPipe<'d, T> {
18-
pub(crate) fn new(ep0: Endpoint<'d, T, InOut>) -> Self {
17+
impl<'d, T: Instance, const SIZE: usize> ControlPipe<'d, T, SIZE> {
18+
pub(crate) fn new(ep0: Endpoint<'d, T, InOut, SIZE>) -> Self {
1919
Self {
2020
_phantom: PhantomData,
2121
ep0,
2222
}
2323
}
2424
}
2525

26-
impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> {
26+
impl<'d, T: Instance, const SIZE: usize> embassy_usb_driver::ControlPipe for ControlPipe<'d, T, SIZE> {
2727
fn max_packet_size(&self) -> usize {
2828
use embassy_usb_driver::Endpoint;
2929

src/usbhs/endpoint.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ use embassy_usb_driver::{Direction, EndpointError, EndpointIn, EndpointInfo, End
88
use super::{EndpointData, Instance, EP_WAKERS};
99
use crate::usb::{Dir, In, Out};
1010

11-
pub struct Endpoint<'d, T: Instance, D: Dir> {
11+
pub struct Endpoint<'d, T: Instance, D: Dir, const SIZE: usize> {
1212
_phantom: PhantomData<(&'d mut T, D)>,
1313
info: EndpointInfo,
14-
pub(crate) data: EndpointData<'d>,
14+
pub(crate) data: EndpointData<'d, SIZE>,
1515
}
1616

17-
impl<'d, T: Instance, D: Dir> Endpoint<'d, T, D> {
18-
pub(crate) fn new(info: EndpointInfo, data: EndpointData<'d>) -> Self {
17+
impl<'d, T: Instance, D: Dir, const SIZE: usize> Endpoint<'d, T, D, SIZE> {
18+
pub(crate) fn new(info: EndpointInfo, data: EndpointData<'d, SIZE>) -> Self {
1919
let index = info.addr.index();
2020
T::dregs().ep_max_len(index).write(|v| v.set_len(info.max_packet_size));
2121
if info.ep_type != EndpointType::Control {
@@ -152,7 +152,7 @@ impl<'d, T: Instance, D: Dir> Endpoint<'d, T, D> {
152152
}
153153
}
154154

155-
impl<'d, T: Instance, D: Dir> embassy_usb_driver::Endpoint for Endpoint<'d, T, D> {
155+
impl<'d, T: Instance, D: Dir, const SIZE: usize> embassy_usb_driver::Endpoint for Endpoint<'d, T, D, SIZE> {
156156
fn info(&self) -> &EndpointInfo {
157157
&self.info
158158
}
@@ -162,7 +162,7 @@ impl<'d, T: Instance, D: Dir> embassy_usb_driver::Endpoint for Endpoint<'d, T, D
162162
}
163163
}
164164

165-
impl<'d, T: Instance> EndpointOut for Endpoint<'d, T, Out> {
165+
impl<'d, T: Instance, const SIZE: usize> EndpointOut for Endpoint<'d, T, Out, SIZE> {
166166
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
167167
if !self.is_enabled() {
168168
error!("read from disabled ep {}", self.info.addr.index());
@@ -184,7 +184,7 @@ impl<'d, T: Instance> EndpointOut for Endpoint<'d, T, Out> {
184184
}
185185
}
186186

187-
impl<'d, T: Instance> EndpointIn for Endpoint<'d, T, In> {
187+
impl<'d, T: Instance, const SIZE: usize> EndpointIn for Endpoint<'d, T, In, SIZE> {
188188
async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
189189
if !self.is_enabled() {
190190
error!("write to disabled ep {}", self.info.addr.index());

0 commit comments

Comments
 (0)