Skip to content

Remove hal dependencies from the crate #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Nov 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 8 additions & 41 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,19 @@ keywords = ["no-std", "embedded", "usb"]
[dependencies]
vcell = "0.1.2"
cortex-m = "0.6.1"
stm32f0xx-hal = { version = "0.15", features = ["rt"], optional = true }
stm32f1xx-hal = { version = "0.4", features = ["rt"], optional = true }
stm32f3xx-hal = { version = "0.3", features = ["rt"], optional = true }
stm32l0xx-hal = { version = "0.3", features = ["rt"], optional = true }
stm32l4xx-hal = { version = "0.5", features = ["rt"], optional = true }
usb-device = "0.2.3"

[features]
# Device family
stm32f0 = ['stm32f0xx-hal', 'family-selected']
stm32f1 = ['stm32f1xx-hal', 'family-selected']
stm32f3 = ['stm32f3xx-hal', 'family-selected']
stm32l0 = ['stm32l0xx-hal', 'family-selected']
stm32l4 = ['stm32l4xx-hal', 'family-selected']

# Dedicated USB RAM size
ram_size_512 = []
ram_size_1024 = []
[dev-dependencies]
stm32f1xx-hal = { version = "0.4.0", features = ["stm32f103"] }

[features]
# USB RAM access scheme
ram_access_1x16 = []
ram_access_2x16 = []

# USB peripheral features
lpm_support = []
bcd_support = []
dp_pull_up_support = []

# Hacks
ram_addr_40006c00 = []
delay_workaround = [] # deprecated: cortex-m 0.6.1 contains a fix

# Known devices
stm32f042xx = ['stm32f0', 'stm32f0xx-hal/stm32f042', 'new_gen']
stm32f048xx = ['stm32f0', 'stm32f0xx-hal/stm32f048', 'new_gen']
stm32f072xx = ['stm32f0', 'stm32f0xx-hal/stm32f072', 'new_gen']
stm32f078xx = ['stm32f0', 'stm32f0xx-hal/stm32f078', 'new_gen']
stm32f103xx = ['stm32f1', 'stm32f1xx-hal/stm32f103', 'old_gen']
stm32f303xc = ['stm32f3', 'stm32f3xx-hal/stm32f303', 'old_gen']
stm32l0x2xx = ['stm32l0', 'stm32l0xx-hal/stm32l0x2', 'new_gen']
stm32l4x2xx = ['stm32l4', 'stm32l4xx-hal/stm32l4x2', 'new_gen', 'ram_addr_40006c00']

# Auxiliary features
old_gen = ['ram_size_512', 'ram_access_1x16']
new_gen = ['ram_size_1024', 'ram_access_2x16', 'lpm_support', 'bcd_support', 'dp_pull_up_support']
family-selected = []

[package.metadata.docs.rs]
features = ["stm32f103xx"]
features = ["ram_access_2x16"]

[[example]]
name = "hal"
required-features = ["ram_access_1x16"]
55 changes: 8 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,57 +21,18 @@ This repository is a fork of the [mvirkkunen/stm32f103xx-usb](https://github.com
* `STM32L4x2xx`
* And others...

## Feature flags
## Usage

To use this crate you need to set proper feature flags.
All the feature flags are listed in `Cargo.toml` under different sections.

If your target MCU matches one of the feature flags listed under the
`Known devices` section of `Cargo.toml`, you can use just that feature flag. For example:

```toml
[dependencies]
stm32-usbd = { version = "0.3", features = ["stm32f103xx"] }
```

For other cases, you have to figure out different properties
of your MCU and USB peripheral implemented in it.
Each property has a corresponding feature flag that you should
set to indicate that property.

Device family:
* `stm32f0`
* `stm32f1`
* `stm32f3`
* `stm32l0`
* `stm32l4`

Size of dedicated packet buffer memory SRAM:
* `ram_size_512`
* `ram_size_1024`

Dedicated packet buffer memory SRAM access scheme:
This driver is intended for use through a device hal library.
Such hal library should implement `UsbPeripheral` for the corresponding USB peripheral object.
This trait declares all the peripheral properties that may vary from one device family to the other.
Additionally, hal should pass `ram_access_1x16` of `ram_access_2x16` feature to the `stm32-usbd` library to
define endpoint memory access scheme:
* `ram_access_1x16` - for "1x16 bits/word" access scheme
* `ram_access_2x16` - for "2x16 bits/word" access scheme

USB peripheral features:
* `lpm_support` - USB 2.0 Link Power Management (LPM) support
* `bcd_support` - Battery Charging Detection (BCD) support
* `dp_pull_up_support` - Embedded pull-up resistor on USB_DP line

Various hacks:
* `ram_addr_40006c00` if dedicated SRAM address is equal to `0x4000_6c00`
instead of `0x4000_6000`

```toml
[dependencies]
# An example feature set for STM32F303CB MCU
stm32-usbd = { version = "0.3", features = ["stm32f3", "ram_size_512", "ram_access_1x16"] }
stm32f3xx-hal = { version = "0.1.4", features = ["rt", "stm32f3xx-hal/stm32f303"] }
```

Note that you also need to set the device feature for `stm32*-hal` crate.

## Examples

See the [stm32-usbd-examples](https://github.com/stm32-rs/stm32-usbd-examples) repo for different device-specific examples.

See the `hal` example for the reference hal implementation.
11 changes: 3 additions & 8 deletions ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@

set -euxo pipefail

cargo check --no-default-features --features stm32f042xx
#cargo check --no-default-features --features stm32f048xx
#cargo check --no-default-features --features stm32f072xx
#cargo check --no-default-features --features stm32f078xx
cargo check --no-default-features --features stm32f103xx
cargo check --no-default-features --features stm32f303xc
cargo check --no-default-features --features stm32l0x2xx
cargo check --no-default-features --features stm32l4x2xx
cargo check --features ram_access_1x16
cargo check --features ram_access_2x16
cargo check --example hal --features ram_access_1x16
48 changes: 48 additions & 0 deletions examples/hal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! USB peripheral

use stm32_usbd::UsbPeripheral;
use stm32f1xx_hal::pac::{RCC, USB};

pub use stm32_usbd::UsbBus;
use stm32f1xx_hal::gpio::gpioa::{PA11, PA12};
use stm32f1xx_hal::gpio::{Floating, Input};

pub struct Peripheral {
pub usb: USB,
pub pin_dm: PA11<Input<Floating>>,
pub pin_dp: PA12<Input<Floating>>,
}

unsafe impl Sync for Peripheral {}

unsafe impl UsbPeripheral for Peripheral {
const REGISTERS: *const () = USB::ptr() as *const ();
const DP_PULL_UP_FEATURE: bool = false;
const EP_MEMORY: *const () = 0x4000_6000 as _;
const EP_MEMORY_SIZE: usize = 512;

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

cortex_m::interrupt::free(|_| {
// Enable USB peripheral
rcc.apb1enr.modify(|_, w| w.usben().set_bit());

// Reset USB peripheral
rcc.apb1rstr.modify(|_, w| w.usbrst().set_bit());
rcc.apb1rstr.modify(|_, w| w.usbrst().clear_bit());
});
}

fn startup_delay() {
// There is a chip specific startup delay. For STM32F103xx it's 1µs and this should wait for
// at least that long.
cortex_m::asm::delay(72);
}
}

pub type UsbBusType = UsbBus<Peripheral>;

fn main() -> ! {
loop {}
}
53 changes: 28 additions & 25 deletions src/bus.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,54 @@
//! USB peripheral driver.

use core::marker::PhantomData;
use core::mem;
use cortex_m::asm::delay;
use core::mem::{self, MaybeUninit};
use cortex_m::interrupt::{self, Mutex};
use usb_device::bus::{PollResult, UsbBusAllocator};
use usb_device::endpoint::{EndpointAddress, EndpointType};
use usb_device::{Result, UsbDirection, UsbError};

use crate::endpoint::{calculate_count_rx, Endpoint, EndpointStatus};
use crate::endpoint::{calculate_count_rx, Endpoint, EndpointStatus, NUM_ENDPOINTS};
use crate::endpoint_memory::EndpointMemoryAllocator;
use crate::target::{apb_usb_enable, UsbPins, UsbRegisters, NUM_ENDPOINTS, USB};
use crate::registers::UsbRegisters;
use crate::UsbPeripheral;

/// USB peripheral driver for STM32 microcontrollers.
pub struct UsbBus<PINS> {
regs: Mutex<UsbRegisters>,
endpoints: [Endpoint; NUM_ENDPOINTS],
ep_allocator: EndpointMemoryAllocator,
pub struct UsbBus<USB> {
peripheral: USB,
regs: Mutex<UsbRegisters<USB>>,
endpoints: [Endpoint<USB>; NUM_ENDPOINTS],
ep_allocator: EndpointMemoryAllocator<USB>,
max_endpoint: usize,
pins: PhantomData<PINS>,
}

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

let bus = UsbBus {
regs: Mutex::new(UsbRegisters::new(regs)),
peripheral,
regs: Mutex::new(UsbRegisters::new()),
ep_allocator: EndpointMemoryAllocator::new(),
max_endpoint: 0,
endpoints: unsafe {
let mut endpoints: [Endpoint; NUM_ENDPOINTS] = mem::uninitialized();
endpoints: {
let mut endpoints: [MaybeUninit<Endpoint<USB>>; NUM_ENDPOINTS] =
unsafe { MaybeUninit::uninit().assume_init() };

for i in 0..NUM_ENDPOINTS {
endpoints[i] = Endpoint::new(i as u8);
endpoints[i] = MaybeUninit::new(Endpoint::new(i as u8));
}

endpoints
unsafe { mem::transmute::<_, [Endpoint<USB>; NUM_ENDPOINTS]>(endpoints) }
},
pins: PhantomData,
};

UsbBusAllocator::new(bus)
}

pub fn free(self) -> USB {
self.peripheral
}

/// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the
/// device.
///
Expand All @@ -69,7 +73,7 @@ impl<PINS: UsbPins + Sync> UsbBus<PINS> {
}
}

impl<PINS: Send + Sync> usb_device::bus::UsbBus for UsbBus<PINS> {
impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
fn alloc_ep(
&mut self,
ep_dir: UsbDirection,
Expand Down Expand Up @@ -136,9 +140,7 @@ impl<PINS: Send + Sync> usb_device::bus::UsbBus for UsbBus<PINS> {

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

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

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

#[cfg(feature = "dp_pull_up_support")]
regs.bcdr.modify(|_, w| w.dppu().set_bit());
if USB::DP_PULL_UP_FEATURE {
regs.bcdr.modify(|_, w| w.dppu().set_bit());
}
});
}

Expand Down
31 changes: 21 additions & 10 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
use crate::endpoint_memory::{BufferDescriptor, EndpointBuffer, EndpointMemoryAllocator};
use crate::target::{usb, UsbAccessType, UsbRegisters};
use crate::endpoint_memory::{BufferDescriptor, EndpointBuffer, EndpointMemoryAllocator, UsbAccessType};
use crate::registers::UsbRegisters;
use crate::UsbPeripheral;
use core::marker::PhantomData;
use core::mem;
use cortex_m::interrupt::{self, CriticalSection, Mutex};
use usb_device::endpoint::EndpointType;
use usb_device::{Result, UsbError};

// Use bundled register definitions instead of device-specific ones
// This should work because register definitions from newer chips seem to be
// compatible with definitions for older ones.
pub use crate::pac::usb;

pub const NUM_ENDPOINTS: usize = 8;

/// Arbitrates access to the endpoint-specific registers and packet buffer memory.
#[derive(Default)]
pub struct Endpoint {
pub struct Endpoint<USB> {
out_buf: Option<Mutex<EndpointBuffer>>,
in_buf: Option<Mutex<EndpointBuffer>>,
ep_type: Option<EndpointType>,
index: u8,
_marker: PhantomData<USB>,
}

pub fn calculate_count_rx(mut size: usize) -> Result<(usize, u16)> {
Expand All @@ -34,13 +44,14 @@ pub fn calculate_count_rx(mut size: usize) -> Result<(usize, u16)> {
}
}

impl Endpoint {
pub fn new(index: u8) -> Endpoint {
Endpoint {
impl<USB: UsbPeripheral> Endpoint<USB> {
pub fn new(index: u8) -> Self {
Self {
out_buf: None,
in_buf: None,
ep_type: None,
index,
_marker: PhantomData,
}
}

Expand All @@ -57,7 +68,7 @@ impl Endpoint {
}

pub fn set_out_buf(&mut self, buffer: EndpointBuffer, size_bits: u16) {
let offset = buffer.offset();
let offset = buffer.offset::<USB>();
self.out_buf = Some(Mutex::new(buffer));

let descr = self.descr();
Expand All @@ -70,7 +81,7 @@ impl Endpoint {
}

pub fn set_in_buf(&mut self, buffer: EndpointBuffer) {
let offset = buffer.offset();
let offset = buffer.offset::<USB>();
self.in_buf = Some(Mutex::new(buffer));

let descr = self.descr();
Expand All @@ -79,11 +90,11 @@ impl Endpoint {
}

fn descr(&self) -> &'static BufferDescriptor {
EndpointMemoryAllocator::buffer_descriptor(self.index)
EndpointMemoryAllocator::<USB>::buffer_descriptor(self.index)
}

fn reg(&self) -> &'static usb::EPR {
UsbRegisters::ep_register(self.index)
UsbRegisters::<USB>::ep_register(self.index)
}

#[rustfmt::skip]
Expand Down
Loading