Skip to content

Commit 665f88b

Browse files
committed
Update to allow 32bit sram access mode
1 parent c54d5fa commit 665f88b

File tree

4 files changed

+176
-72
lines changed

4 files changed

+176
-72
lines changed

examples/hal.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! USB peripheral
22
3-
use stm32_usbd::UsbPeripheral;
3+
use stm32_usbd::{U16Bits, UsbPeripheral};
44
use stm32f1xx_hal::pac::{RCC, USB};
55

66
pub use stm32_usbd::UsbBus;
@@ -20,7 +20,7 @@ unsafe impl UsbPeripheral for Peripheral {
2020
const DP_PULL_UP_FEATURE: bool = false;
2121
const EP_MEMORY: *const () = 0x4000_6000 as _;
2222
const EP_MEMORY_SIZE: usize = 512;
23-
const EP_MEMORY_ACCESS_2X16: bool = false;
23+
type SramAccessScheme = U16Bits;
2424

2525
fn enable() {
2626
let rcc = unsafe { &*RCC::ptr() };

src/endpoint.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::endpoint_memory::{BufferDescriptor, EndpointBuffer, EndpointMemoryAllocator};
1+
use crate::endpoint_memory::{BufferDescriptor, DescriptorPart, EndpointBuffer, EndpointMemoryAllocator};
22
use crate::registers::UsbRegisters;
33
use crate::UsbPeripheral;
44
use core::marker::PhantomData;
@@ -72,8 +72,7 @@ impl<USB: UsbPeripheral> Endpoint<USB> {
7272
self.out_buf = Some(Mutex::new(buffer));
7373

7474
let descr = self.descr();
75-
descr.addr_rx().set(offset.into());
76-
descr.count_rx().set(size_bits.into());
75+
descr.set_rx(offset, size_bits);
7776
}
7877

7978
pub fn is_in_buf_set(&self) -> bool {
@@ -85,8 +84,7 @@ impl<USB: UsbPeripheral> Endpoint<USB> {
8584
self.in_buf = Some(Mutex::new(buffer));
8685

8786
let descr = self.descr();
88-
descr.addr_tx().set(offset.into());
89-
descr.count_tx().set(0.into());
87+
descr.set_tx(offset, 0);
9088
}
9189

9290
fn descr(&self) -> BufferDescriptor<USB> {
@@ -151,7 +149,8 @@ impl<USB: UsbPeripheral> Endpoint<USB> {
151149
};
152150

153151
in_buf.write(buf);
154-
self.descr().count_tx().set((buf.len() as u16).into());
152+
let DescriptorPart { address, count: _ } = self.descr().get_tx();
153+
self.descr().set_tx(address, buf.len() as u16);
155154

156155
self.set_stat_tx(cs, EndpointStatus::Valid);
157156

@@ -173,7 +172,7 @@ impl<USB: UsbPeripheral> Endpoint<USB> {
173172

174173
self.clear_ctr_rx(cs);
175174

176-
let count = (self.descr().count_rx().get().into() & 0x3ff) as usize;
175+
let count = (self.descr().get_rx().count & 0x3ff) as usize;
177176
if count > buf.len() {
178177
return Err(UsbError::BufferOverflow);
179178
}

src/endpoint_memory.rs

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,55 @@
11
use crate::endpoint::NUM_ENDPOINTS;
2-
use crate::{UsbPeripheral, Word};
2+
use crate::{SramAccessScheme, UsbPeripheral, Word};
33
use core::marker::PhantomData;
4-
use core::slice;
4+
use core::mem;
55
use usb_device::{Result, UsbError};
6-
use vcell::VolatileCell;
76

87
pub struct EndpointBuffer<USB: UsbPeripheral> {
9-
mem: &'static mut [VolatileCell<USB::Word>],
8+
ptr: *mut <USB::SramAccessScheme as SramAccessScheme>::Word,
9+
word_count: usize,
1010
marker: PhantomData<USB>,
1111
}
1212

13+
unsafe impl<USB: UsbPeripheral> Send for EndpointBuffer<USB> {}
14+
1315
impl<USB: UsbPeripheral> EndpointBuffer<USB> {
1416
pub fn new(offset_bytes: usize, size_bytes: usize) -> Self {
15-
let ep_mem_ptr = USB::EP_MEMORY as *mut VolatileCell<_>;
16-
17-
let offset_words = offset_bytes >> 1;
18-
let count_words = size_bytes >> 1;
19-
let offset_u16_words;
20-
let count_u16_words;
21-
if USB::EP_MEMORY_ACCESS_2X16 {
22-
offset_u16_words = offset_words;
23-
count_u16_words = count_words;
24-
} else {
25-
offset_u16_words = offset_words * 2;
26-
count_u16_words = count_words * 2;
27-
};
17+
let ep_mem_ptr = USB::EP_MEMORY as *mut <USB::SramAccessScheme as SramAccessScheme>::Word;
18+
19+
let word_size = Self::word_size();
20+
let offset_words = offset_bytes / word_size;
21+
let word_count = size_bytes / word_size;
22+
23+
let offset_words = offset_words * USB::SramAccessScheme::ADDRESS_MULTIPLIER;
24+
let word_count = word_count * USB::SramAccessScheme::ADDRESS_MULTIPLIER;
2825

2926
unsafe {
30-
let mem = slice::from_raw_parts_mut(ep_mem_ptr.add(offset_u16_words), count_u16_words);
27+
let ptr = ep_mem_ptr.add(offset_words);
3128
Self {
32-
mem,
29+
ptr,
30+
word_count,
3331
marker: PhantomData,
3432
}
3533
}
3634
}
3735

36+
fn word_size() -> usize {
37+
mem::size_of::<<USB::SramAccessScheme as SramAccessScheme>::Word>()
38+
}
39+
3840
#[inline(always)]
39-
fn read_word(&self, index: usize) -> USB::Word {
40-
if USB::EP_MEMORY_ACCESS_2X16 {
41-
self.mem[index].get()
42-
} else {
43-
self.mem[index * 2].get()
44-
}
41+
fn read_word(&self, index: usize) -> <USB::SramAccessScheme as SramAccessScheme>::Word {
42+
let index = index * USB::SramAccessScheme::ADDRESS_MULTIPLIER;
43+
assert!(index < self.word_count);
44+
unsafe { self.ptr.add(index).read_volatile() }
4545
}
4646

4747
#[inline(always)]
48-
fn write_word(&self, index: usize, value: USB::Word) {
49-
if USB::EP_MEMORY_ACCESS_2X16 {
50-
self.mem[index].set(value);
51-
} else {
52-
self.mem[index * 2].set(value);
48+
fn write_word(&self, index: usize, value: <USB::SramAccessScheme as SramAccessScheme>::Word) {
49+
let index = index * USB::SramAccessScheme::ADDRESS_MULTIPLIER;
50+
assert!(index < self.word_count);
51+
unsafe {
52+
self.ptr.add(index).write_volatile(value);
5353
}
5454
}
5555

@@ -75,45 +75,57 @@ impl<USB: UsbPeripheral> EndpointBuffer<USB> {
7575
}
7676

7777
pub fn offset(&self) -> u16 {
78-
let buffer_address = self.mem.as_ptr() as usize;
79-
let word_size = if USB::EP_MEMORY_ACCESS_2X16 { 2 } else { 4 };
80-
let index = (buffer_address - USB::EP_MEMORY as usize) / word_size;
81-
(index << 1) as u16
78+
let buffer_address = self.ptr as usize;
79+
let word_size = Self::word_size();
80+
let offset_per_word = word_size * USB::SramAccessScheme::ADDRESS_MULTIPLIER;
81+
let index = (buffer_address - USB::EP_MEMORY as usize) / offset_per_word;
82+
(index * word_size) as u16
8283
}
8384

85+
/// Capacity in bytes
8486
pub fn capacity(&self) -> usize {
85-
let len_words = if USB::EP_MEMORY_ACCESS_2X16 {
86-
self.mem.len()
87-
} else {
88-
self.mem.len() / 2
89-
};
90-
len_words << 1
87+
let len_words = self.word_count / USB::SramAccessScheme::ADDRESS_MULTIPLIER;
88+
let word_size = Self::word_size();
89+
len_words * word_size
9190
}
9291
}
9392

9493
#[repr(C)]
9594
pub struct BufferDescriptor<USB: UsbPeripheral> {
96-
ptr: *const VolatileCell<USB::Word>,
95+
ptr: *mut <USB::SramAccessScheme as SramAccessScheme>::Word,
9796
marker: PhantomData<USB>,
9897
}
9998

99+
pub struct DescriptorPart {
100+
pub address: u16,
101+
pub count: u16,
102+
}
103+
100104
impl<USB: UsbPeripheral> BufferDescriptor<USB> {
101105
#[inline(always)]
102-
fn field(&self, index: usize) -> &'static VolatileCell<USB::Word> {
103-
let mul = if USB::EP_MEMORY_ACCESS_2X16 { 1 } else { 2 };
104-
unsafe { &*(self.ptr.add(index * mul)) }
106+
pub fn set_tx(&self, address: u16, count: u16) {
107+
unsafe {
108+
USB::SramAccessScheme::set(self.ptr, crate::AccessType::Tx, address, count);
109+
}
105110
}
106111

107112
#[inline(always)]
108-
pub fn set_tx(&self, address: u16, count: u16) {
109-
self.field(0) // addr
110-
self.field(1) // count (msb in 32bit)
113+
pub fn get_tx(&self) -> DescriptorPart {
114+
let (address, count) = unsafe { USB::SramAccessScheme::read(self.ptr, crate::AccessType::Tx) };
115+
DescriptorPart { address, count }
116+
}
117+
118+
#[inline(always)]
119+
pub fn set_rx(&self, address: u16, count: u16) {
120+
unsafe {
121+
USB::SramAccessScheme::set(self.ptr, crate::AccessType::Rx, address, count);
122+
}
111123
}
112124

113125
#[inline(always)]
114-
pub fn get_rx(&self) -> (u16, u16) {
115-
self.field(2) // addr
116-
self.field(3) // count(msb in 32bit)
126+
pub fn get_rx(&self) -> DescriptorPart {
127+
let (address, count) = unsafe { USB::SramAccessScheme::read(self.ptr, crate::AccessType::Rx) };
128+
DescriptorPart { address, count }
117129
}
118130
}
119131

@@ -145,10 +157,15 @@ impl<USB: UsbPeripheral> EndpointMemoryAllocator<USB> {
145157
}
146158

147159
pub fn buffer_descriptor(index: u8) -> BufferDescriptor<USB> {
148-
let mul = if USB::EP_MEMORY_ACCESS_2X16 { 1 } else { 2 };
160+
let mul = USB::SramAccessScheme::ADDRESS_MULTIPLIER;
161+
let word_size = mem::size_of::<<USB::SramAccessScheme as SramAccessScheme>::Word>();
149162

163+
// 4xu16=8Bytes worth of data per descriptor
164+
let descriptor_size_bytes = 8;
165+
let offset_per_descriptor = descriptor_size_bytes * mul / word_size;
150166
unsafe {
151-
let ptr = (USB::EP_MEMORY as *const VolatileCell<USB::Word>).add((index as usize) * 4 * mul);
167+
let ptr = (USB::EP_MEMORY as *mut <USB::SramAccessScheme as SramAccessScheme>::Word)
168+
.add((index as usize) * offset_per_descriptor);
152169
BufferDescriptor {
153170
ptr,
154171
marker: Default::default(),

src/lib.rs

Lines changed: 99 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod bus;
99
mod endpoint;
1010
mod endpoint_memory;
1111
mod registers;
12+
1213
pub use crate::bus::UsbBus;
1314

1415
mod pac;
@@ -32,10 +33,11 @@ pub unsafe trait UsbPeripheral: Send + Sync {
3233
/// Endpoint memory access scheme
3334
///
3435
/// Check Reference Manual for details.
35-
/// Set to `true` if "2x16 bits/word" access scheme is used, otherwise set to `false`.
36-
const EP_MEMORY_ACCESS_2X16: bool;
37-
38-
type Word: Word;
36+
/// Can be any of:
37+
/// * U16Bits
38+
/// * U16BitsX2
39+
/// * U32Bits
40+
type SramAccessScheme: SramAccessScheme;
3941

4042
/// Enables USB device on its peripheral bus
4143
fn enable();
@@ -47,18 +49,82 @@ pub unsafe trait UsbPeripheral: Send + Sync {
4749
fn startup_delay();
4850
}
4951

50-
pub trait Word: From<u16> + Into<u32> + Copy + Send + 'static
51-
{
52+
pub struct U16Bits;
53+
pub struct U16BitsX2;
54+
pub struct U32Bits;
55+
56+
pub enum AccessType {
57+
Tx = 0,
58+
Rx = 1,
59+
}
60+
61+
pub trait SramAccessScheme {
62+
type Word: Word;
63+
const ADDRESS_MULTIPLIER: usize = 1;
64+
65+
unsafe fn set(ptr: *mut Self::Word, t: AccessType, address: u16, count: u16);
66+
unsafe fn read(ptr: *const Self::Word, t: AccessType) -> (u16, u16);
67+
}
68+
69+
impl SramAccessScheme for U16Bits {
70+
type Word = u16;
71+
const ADDRESS_MULTIPLIER: usize = 2;
72+
73+
unsafe fn set(ptr: *mut Self::Word, t: AccessType, address: u16, count: u16) {
74+
set(ptr, t, Self::ADDRESS_MULTIPLIER, address, count);
75+
}
76+
77+
unsafe fn read(ptr: *const Self::Word, t: AccessType) -> (u16, u16) {
78+
read(ptr, t, Self::ADDRESS_MULTIPLIER)
79+
}
80+
}
81+
82+
impl SramAccessScheme for U16BitsX2 {
83+
type Word = u16;
84+
85+
unsafe fn set(ptr: *mut Self::Word, t: AccessType, address: u16, count: u16) {
86+
set(ptr, t, Self::ADDRESS_MULTIPLIER, address, count);
87+
}
88+
89+
unsafe fn read(ptr: *const Self::Word, t: AccessType) -> (u16, u16) {
90+
read(ptr, t, Self::ADDRESS_MULTIPLIER)
91+
}
92+
}
93+
impl SramAccessScheme for U32Bits {
94+
type Word = u32;
95+
96+
unsafe fn set(ptr: *mut Self::Word, t: AccessType, address: u16, count: u16) {
97+
assert!(count < (1 << 10));
98+
99+
let offset = t as usize;
100+
101+
let bits = u32::from(count) << 16 | u32::from(address);
102+
unsafe {
103+
ptr.add(offset).write_volatile(bits);
104+
}
105+
}
106+
107+
unsafe fn read(ptr: *const Self::Word, t: AccessType) -> (u16, u16) {
108+
let offset = t as usize;
109+
110+
unsafe {
111+
let bits = ptr.add(offset).read_volatile();
112+
let address = bits as u16;
113+
let count = (bits >> 16) as u16;
114+
115+
(address, count)
116+
}
117+
}
118+
}
119+
120+
pub trait Word: From<u16> + Into<u32> + Copy + Send + 'static {
52121
fn from_iter_le<'a>(it: &mut impl Iterator<Item = &'a u8>) -> Self;
53122
fn write_to_iter_le<'a>(self, it: &mut impl Iterator<Item = &'a mut u8>);
54123
}
55124

56125
impl Word for u16 {
57126
fn from_iter_le<'a>(it: &mut impl Iterator<Item = &'a u8>) -> Self {
58-
Self::from_le_bytes([
59-
*it.next().unwrap_or(&0),
60-
*it.next().unwrap_or(&0),
61-
])
127+
Self::from_le_bytes([*it.next().unwrap_or(&0), *it.next().unwrap_or(&0)])
62128
}
63129

64130
fn write_to_iter_le<'a>(self, it: &mut impl Iterator<Item = &'a mut u8>) {
@@ -83,4 +149,26 @@ impl Word for u32 {
83149
*w = r;
84150
}
85151
}
86-
}
152+
}
153+
154+
fn set(ptr: *mut u16, t: AccessType, mul: usize, address: u16, count: u16) {
155+
assert!(count < (1 << 10));
156+
157+
let offset = t as usize;
158+
159+
unsafe {
160+
ptr.add(offset * mul).write_volatile(address);
161+
ptr.add((offset + 1) * mul).write_volatile(count);
162+
}
163+
}
164+
165+
fn read(ptr: *const u16, t: AccessType, mul: usize) -> (u16, u16) {
166+
let offset = t as usize;
167+
168+
unsafe {
169+
let address = ptr.add(offset * mul).read_volatile();
170+
let count = ptr.add((offset + 1) * mul).read_volatile();
171+
172+
(address, count)
173+
}
174+
}

0 commit comments

Comments
 (0)