Skip to content

Commit eda436b

Browse files
authored
Merge pull request #16 from stm32-rs/untethered
Remove hal dependencies from the crate
2 parents def1365 + b802384 commit eda436b

File tree

10 files changed

+197
-296
lines changed

10 files changed

+197
-296
lines changed

Cargo.toml

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,19 @@ keywords = ["no-std", "embedded", "usb"]
1212
[dependencies]
1313
vcell = "0.1.2"
1414
cortex-m = "0.6.1"
15-
stm32f0xx-hal = { version = "0.15", features = ["rt"], optional = true }
16-
stm32f1xx-hal = { version = "0.4", features = ["rt"], optional = true }
17-
stm32f3xx-hal = { version = "0.3", features = ["rt"], optional = true }
18-
stm32l0xx-hal = { version = "0.3", features = ["rt"], optional = true }
19-
stm32l4xx-hal = { version = "0.5", features = ["rt"], optional = true }
2015
usb-device = "0.2.3"
2116

22-
[features]
23-
# Device family
24-
stm32f0 = ['stm32f0xx-hal', 'family-selected']
25-
stm32f1 = ['stm32f1xx-hal', 'family-selected']
26-
stm32f3 = ['stm32f3xx-hal', 'family-selected']
27-
stm32l0 = ['stm32l0xx-hal', 'family-selected']
28-
stm32l4 = ['stm32l4xx-hal', 'family-selected']
29-
30-
# Dedicated USB RAM size
31-
ram_size_512 = []
32-
ram_size_1024 = []
17+
[dev-dependencies]
18+
stm32f1xx-hal = { version = "0.4.0", features = ["stm32f103"] }
3319

20+
[features]
3421
# USB RAM access scheme
3522
ram_access_1x16 = []
3623
ram_access_2x16 = []
3724

38-
# USB peripheral features
39-
lpm_support = []
40-
bcd_support = []
41-
dp_pull_up_support = []
42-
43-
# Hacks
44-
ram_addr_40006c00 = []
45-
delay_workaround = [] # deprecated: cortex-m 0.6.1 contains a fix
46-
47-
# Known devices
48-
stm32f042xx = ['stm32f0', 'stm32f0xx-hal/stm32f042', 'new_gen']
49-
stm32f048xx = ['stm32f0', 'stm32f0xx-hal/stm32f048', 'new_gen']
50-
stm32f072xx = ['stm32f0', 'stm32f0xx-hal/stm32f072', 'new_gen']
51-
stm32f078xx = ['stm32f0', 'stm32f0xx-hal/stm32f078', 'new_gen']
52-
stm32f103xx = ['stm32f1', 'stm32f1xx-hal/stm32f103', 'old_gen']
53-
stm32f303xc = ['stm32f3', 'stm32f3xx-hal/stm32f303', 'old_gen']
54-
stm32l0x2xx = ['stm32l0', 'stm32l0xx-hal/stm32l0x2', 'new_gen']
55-
stm32l4x2xx = ['stm32l4', 'stm32l4xx-hal/stm32l4x2', 'new_gen', 'ram_addr_40006c00']
56-
57-
# Auxiliary features
58-
old_gen = ['ram_size_512', 'ram_access_1x16']
59-
new_gen = ['ram_size_1024', 'ram_access_2x16', 'lpm_support', 'bcd_support', 'dp_pull_up_support']
60-
family-selected = []
61-
6225
[package.metadata.docs.rs]
63-
features = ["stm32f103xx"]
26+
features = ["ram_access_2x16"]
27+
28+
[[example]]
29+
name = "hal"
30+
required-features = ["ram_access_1x16"]

README.md

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,57 +21,18 @@ This repository is a fork of the [mvirkkunen/stm32f103xx-usb](https://github.com
2121
* `STM32L4x2xx`
2222
* And others...
2323

24-
## Feature flags
24+
## Usage
2525

26-
To use this crate you need to set proper feature flags.
27-
All the feature flags are listed in `Cargo.toml` under different sections.
28-
29-
If your target MCU matches one of the feature flags listed under the
30-
`Known devices` section of `Cargo.toml`, you can use just that feature flag. For example:
31-
32-
```toml
33-
[dependencies]
34-
stm32-usbd = { version = "0.3", features = ["stm32f103xx"] }
35-
```
36-
37-
For other cases, you have to figure out different properties
38-
of your MCU and USB peripheral implemented in it.
39-
Each property has a corresponding feature flag that you should
40-
set to indicate that property.
41-
42-
Device family:
43-
* `stm32f0`
44-
* `stm32f1`
45-
* `stm32f3`
46-
* `stm32l0`
47-
* `stm32l4`
48-
49-
Size of dedicated packet buffer memory SRAM:
50-
* `ram_size_512`
51-
* `ram_size_1024`
52-
53-
Dedicated packet buffer memory SRAM access scheme:
26+
This driver is intended for use through a device hal library.
27+
Such hal library should implement `UsbPeripheral` for the corresponding USB peripheral object.
28+
This trait declares all the peripheral properties that may vary from one device family to the other.
29+
Additionally, hal should pass `ram_access_1x16` of `ram_access_2x16` feature to the `stm32-usbd` library to
30+
define endpoint memory access scheme:
5431
* `ram_access_1x16` - for "1x16 bits/word" access scheme
5532
* `ram_access_2x16` - for "2x16 bits/word" access scheme
5633

57-
USB peripheral features:
58-
* `lpm_support` - USB 2.0 Link Power Management (LPM) support
59-
* `bcd_support` - Battery Charging Detection (BCD) support
60-
* `dp_pull_up_support` - Embedded pull-up resistor on USB_DP line
61-
62-
Various hacks:
63-
* `ram_addr_40006c00` if dedicated SRAM address is equal to `0x4000_6c00`
64-
instead of `0x4000_6000`
65-
66-
```toml
67-
[dependencies]
68-
# An example feature set for STM32F303CB MCU
69-
stm32-usbd = { version = "0.3", features = ["stm32f3", "ram_size_512", "ram_access_1x16"] }
70-
stm32f3xx-hal = { version = "0.1.4", features = ["rt", "stm32f3xx-hal/stm32f303"] }
71-
```
72-
73-
Note that you also need to set the device feature for `stm32*-hal` crate.
74-
7534
## Examples
7635

7736
See the [stm32-usbd-examples](https://github.com/stm32-rs/stm32-usbd-examples) repo for different device-specific examples.
37+
38+
See the `hal` example for the reference hal implementation.

ci/script.sh

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@
22

33
set -euxo pipefail
44

5-
cargo check --no-default-features --features stm32f042xx
6-
#cargo check --no-default-features --features stm32f048xx
7-
#cargo check --no-default-features --features stm32f072xx
8-
#cargo check --no-default-features --features stm32f078xx
9-
cargo check --no-default-features --features stm32f103xx
10-
cargo check --no-default-features --features stm32f303xc
11-
cargo check --no-default-features --features stm32l0x2xx
12-
cargo check --no-default-features --features stm32l4x2xx
5+
cargo check --features ram_access_1x16
6+
cargo check --features ram_access_2x16
7+
cargo check --example hal --features ram_access_1x16

examples/hal.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! USB peripheral
2+
3+
use stm32_usbd::UsbPeripheral;
4+
use stm32f1xx_hal::pac::{RCC, USB};
5+
6+
pub use stm32_usbd::UsbBus;
7+
use stm32f1xx_hal::gpio::gpioa::{PA11, PA12};
8+
use stm32f1xx_hal::gpio::{Floating, Input};
9+
10+
pub struct Peripheral {
11+
pub usb: USB,
12+
pub pin_dm: PA11<Input<Floating>>,
13+
pub pin_dp: PA12<Input<Floating>>,
14+
}
15+
16+
unsafe impl Sync for Peripheral {}
17+
18+
unsafe impl UsbPeripheral for Peripheral {
19+
const REGISTERS: *const () = USB::ptr() as *const ();
20+
const DP_PULL_UP_FEATURE: bool = false;
21+
const EP_MEMORY: *const () = 0x4000_6000 as _;
22+
const EP_MEMORY_SIZE: usize = 512;
23+
24+
fn enable() {
25+
let rcc = unsafe { (&*RCC::ptr()) };
26+
27+
cortex_m::interrupt::free(|_| {
28+
// Enable USB peripheral
29+
rcc.apb1enr.modify(|_, w| w.usben().set_bit());
30+
31+
// Reset USB peripheral
32+
rcc.apb1rstr.modify(|_, w| w.usbrst().set_bit());
33+
rcc.apb1rstr.modify(|_, w| w.usbrst().clear_bit());
34+
});
35+
}
36+
37+
fn startup_delay() {
38+
// There is a chip specific startup delay. For STM32F103xx it's 1µs and this should wait for
39+
// at least that long.
40+
cortex_m::asm::delay(72);
41+
}
42+
}
43+
44+
pub type UsbBusType = UsbBus<Peripheral>;
45+
46+
fn main() -> ! {
47+
loop {}
48+
}

src/bus.rs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,54 @@
11
//! USB peripheral driver.
22
3-
use core::marker::PhantomData;
4-
use core::mem;
5-
use cortex_m::asm::delay;
3+
use core::mem::{self, MaybeUninit};
64
use cortex_m::interrupt::{self, Mutex};
75
use usb_device::bus::{PollResult, UsbBusAllocator};
86
use usb_device::endpoint::{EndpointAddress, EndpointType};
97
use usb_device::{Result, UsbDirection, UsbError};
108

11-
use crate::endpoint::{calculate_count_rx, Endpoint, EndpointStatus};
9+
use crate::endpoint::{calculate_count_rx, Endpoint, EndpointStatus, NUM_ENDPOINTS};
1210
use crate::endpoint_memory::EndpointMemoryAllocator;
13-
use crate::target::{apb_usb_enable, UsbPins, UsbRegisters, NUM_ENDPOINTS, USB};
11+
use crate::registers::UsbRegisters;
12+
use crate::UsbPeripheral;
1413

1514
/// USB peripheral driver for STM32 microcontrollers.
16-
pub struct UsbBus<PINS> {
17-
regs: Mutex<UsbRegisters>,
18-
endpoints: [Endpoint; NUM_ENDPOINTS],
19-
ep_allocator: EndpointMemoryAllocator,
15+
pub struct UsbBus<USB> {
16+
peripheral: USB,
17+
regs: Mutex<UsbRegisters<USB>>,
18+
endpoints: [Endpoint<USB>; NUM_ENDPOINTS],
19+
ep_allocator: EndpointMemoryAllocator<USB>,
2020
max_endpoint: usize,
21-
pins: PhantomData<PINS>,
2221
}
2322

24-
impl<PINS: UsbPins + Sync> UsbBus<PINS> {
23+
impl<USB: UsbPeripheral> UsbBus<USB> {
2524
/// Constructs a new USB peripheral driver.
26-
pub fn new(regs: USB, _pins: PINS) -> UsbBusAllocator<Self> {
27-
apb_usb_enable();
25+
pub fn new(peripheral: USB) -> UsbBusAllocator<Self> {
26+
USB::enable();
2827

2928
let bus = UsbBus {
30-
regs: Mutex::new(UsbRegisters::new(regs)),
29+
peripheral,
30+
regs: Mutex::new(UsbRegisters::new()),
3131
ep_allocator: EndpointMemoryAllocator::new(),
3232
max_endpoint: 0,
33-
endpoints: unsafe {
34-
let mut endpoints: [Endpoint; NUM_ENDPOINTS] = mem::uninitialized();
33+
endpoints: {
34+
let mut endpoints: [MaybeUninit<Endpoint<USB>>; NUM_ENDPOINTS] =
35+
unsafe { MaybeUninit::uninit().assume_init() };
3536

3637
for i in 0..NUM_ENDPOINTS {
37-
endpoints[i] = Endpoint::new(i as u8);
38+
endpoints[i] = MaybeUninit::new(Endpoint::new(i as u8));
3839
}
3940

40-
endpoints
41+
unsafe { mem::transmute::<_, [Endpoint<USB>; NUM_ENDPOINTS]>(endpoints) }
4142
},
42-
pins: PhantomData,
4343
};
4444

4545
UsbBusAllocator::new(bus)
4646
}
4747

48+
pub fn free(self) -> USB {
49+
self.peripheral
50+
}
51+
4852
/// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the
4953
/// device.
5054
///
@@ -69,7 +73,7 @@ impl<PINS: UsbPins + Sync> UsbBus<PINS> {
6973
}
7074
}
7175

72-
impl<PINS: Send + Sync> usb_device::bus::UsbBus for UsbBus<PINS> {
76+
impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
7377
fn alloc_ep(
7478
&mut self,
7579
ep_dir: UsbDirection,
@@ -136,9 +140,7 @@ impl<PINS: Send + Sync> usb_device::bus::UsbBus for UsbBus<PINS> {
136140

137141
regs.cntr.modify(|_, w| w.pdwn().clear_bit());
138142

139-
// There is a chip specific startup delay. For STM32F103xx it's 1µs and this should wait for
140-
// at least that long.
141-
delay(72);
143+
USB::startup_delay();
142144

143145
regs.btable.modify(|_, w| w.btable().bits(0));
144146
regs.cntr.modify(|_, w| { w
@@ -150,8 +152,9 @@ impl<PINS: Send + Sync> usb_device::bus::UsbBus for UsbBus<PINS> {
150152
});
151153
regs.istr.modify(|_, w| unsafe { w.bits(0) });
152154

153-
#[cfg(feature = "dp_pull_up_support")]
154-
regs.bcdr.modify(|_, w| w.dppu().set_bit());
155+
if USB::DP_PULL_UP_FEATURE {
156+
regs.bcdr.modify(|_, w| w.dppu().set_bit());
157+
}
155158
});
156159
}
157160

src/endpoint.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1-
use crate::endpoint_memory::{BufferDescriptor, EndpointBuffer, EndpointMemoryAllocator};
2-
use crate::target::{usb, UsbAccessType, UsbRegisters};
1+
use crate::endpoint_memory::{BufferDescriptor, EndpointBuffer, EndpointMemoryAllocator, UsbAccessType};
2+
use crate::registers::UsbRegisters;
3+
use crate::UsbPeripheral;
4+
use core::marker::PhantomData;
35
use core::mem;
46
use cortex_m::interrupt::{self, CriticalSection, Mutex};
57
use usb_device::endpoint::EndpointType;
68
use usb_device::{Result, UsbError};
79

10+
// Use bundled register definitions instead of device-specific ones
11+
// This should work because register definitions from newer chips seem to be
12+
// compatible with definitions for older ones.
13+
pub use crate::pac::usb;
14+
15+
pub const NUM_ENDPOINTS: usize = 8;
16+
817
/// Arbitrates access to the endpoint-specific registers and packet buffer memory.
918
#[derive(Default)]
10-
pub struct Endpoint {
19+
pub struct Endpoint<USB> {
1120
out_buf: Option<Mutex<EndpointBuffer>>,
1221
in_buf: Option<Mutex<EndpointBuffer>>,
1322
ep_type: Option<EndpointType>,
1423
index: u8,
24+
_marker: PhantomData<USB>,
1525
}
1626

1727
pub fn calculate_count_rx(mut size: usize) -> Result<(usize, u16)> {
@@ -34,13 +44,14 @@ pub fn calculate_count_rx(mut size: usize) -> Result<(usize, u16)> {
3444
}
3545
}
3646

37-
impl Endpoint {
38-
pub fn new(index: u8) -> Endpoint {
39-
Endpoint {
47+
impl<USB: UsbPeripheral> Endpoint<USB> {
48+
pub fn new(index: u8) -> Self {
49+
Self {
4050
out_buf: None,
4151
in_buf: None,
4252
ep_type: None,
4353
index,
54+
_marker: PhantomData,
4455
}
4556
}
4657

@@ -57,7 +68,7 @@ impl Endpoint {
5768
}
5869

5970
pub fn set_out_buf(&mut self, buffer: EndpointBuffer, size_bits: u16) {
60-
let offset = buffer.offset();
71+
let offset = buffer.offset::<USB>();
6172
self.out_buf = Some(Mutex::new(buffer));
6273

6374
let descr = self.descr();
@@ -70,7 +81,7 @@ impl Endpoint {
7081
}
7182

7283
pub fn set_in_buf(&mut self, buffer: EndpointBuffer) {
73-
let offset = buffer.offset();
84+
let offset = buffer.offset::<USB>();
7485
self.in_buf = Some(Mutex::new(buffer));
7586

7687
let descr = self.descr();
@@ -79,11 +90,11 @@ impl Endpoint {
7990
}
8091

8192
fn descr(&self) -> &'static BufferDescriptor {
82-
EndpointMemoryAllocator::buffer_descriptor(self.index)
93+
EndpointMemoryAllocator::<USB>::buffer_descriptor(self.index)
8394
}
8495

8596
fn reg(&self) -> &'static usb::EPR {
86-
UsbRegisters::ep_register(self.index)
97+
UsbRegisters::<USB>::ep_register(self.index)
8798
}
8899

89100
#[rustfmt::skip]

0 commit comments

Comments
 (0)