Skip to content

Add USB driver #74

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 4 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Enabled commented out and now available GPIOE support for 07x and 09x families
- Extract register block address only once
- Add DAC driver
- Added USB driver

## [v0.15.1] - 2019-08-11

Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ embedded-hal = { version = "0.2", features = ["unproven"] }
stm32f0 = "0.8"
nb = "0.1"
void = { version = "1.0", default-features = false }
stm32-usbd = { version = "0.5.0", features = ["ram_access_2x16"], optional = true }

[dev-dependencies]
panic-halt = "0.2"
usb-device = "0.2.3"
usbd-serial = "0.1.0"

[features]
device-selected = []
Expand Down Expand Up @@ -80,3 +83,7 @@ required-features = ["stm32f042", "rt"]
[[example]]
name = "dac"
required-features = ["stm32f072"]

[[example]]
name = "usb_serial"
required-features = ["rt", "stm32f042", "stm32-usbd"]
90 changes: 90 additions & 0 deletions examples/usb_serial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//! CDC-ACM serial port example using polling in a busy loop.
//! Target board: NUCLEO-F042K6
#![no_std]
#![no_main]

extern crate panic_halt;

use cortex_m_rt::entry;
use stm32f0xx_hal::usb::{Peripheral, UsbBus};
use stm32f0xx_hal::{prelude::*, stm32};
use usb_device::prelude::*;
use usbd_serial::{SerialPort, USB_CLASS_CDC};

#[entry]
fn main() -> ! {
let mut dp = stm32::Peripherals::take().unwrap();

/* Uncomment the following lines if you have a chip in TSSOP20 (STM32F042F)
or UFQFPN28 (STM32F042G) package
This code enables clock for SYSCFG and remaps USB pins to PA9 and PA10.
*/
//dp.RCC.apb2enr.modify(|_, w| w.syscfgen().set_bit());
//dp.SYSCFG.cfgr1.modify(|_, w| w.pa11_pa12_rmp().remapped());

let mut rcc = dp
.RCC
.configure()
.hsi48()
.enable_crs(dp.CRS)
.sysclk(48.mhz())
.pclk(24.mhz())
.freeze(&mut dp.FLASH);

// Configure the on-board LED (LD3, green)
let gpiob = dp.GPIOB.split(&mut rcc);
let mut led = cortex_m::interrupt::free(|cs| gpiob.pb3.into_push_pull_output(cs));
led.set_low(); // Turn off

let gpioa = dp.GPIOA.split(&mut rcc);

let usb = Peripheral {
usb: dp.USB,
pin_dm: gpioa.pa11,
pin_dp: gpioa.pa12,
};
let usb_bus = UsbBus::new(usb);

let mut serial = SerialPort::new(&usb_bus);

let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(USB_CLASS_CDC)
.build();

loop {
if !usb_dev.poll(&mut [&mut serial]) {
continue;
}

let mut buf = [0u8; 64];

match serial.read(&mut buf) {
Ok(count) if count > 0 => {
led.set_high(); // Turn on

// Echo back in upper case
for c in buf[0..count].iter_mut() {
if 0x61 <= *c && *c <= 0x7a {
*c &= !0x20;
}
}

let mut write_offset = 0;
while write_offset < count {
match serial.write(&buf[write_offset..count]) {
Ok(len) if len > 0 => {
write_offset += len;
}
_ => {}
}
}
}
_ => {}
}

led.set_low(); // Turn off
}
}
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,17 @@ pub mod timers;
feature = "stm32f098",
))]
pub mod tsc;
#[cfg(all(
feature = "stm32-usbd",
any(
feature = "stm32f042",
feature = "stm32f048",
feature = "stm32f072",
feature = "stm32f078",
feature = "stm32f070x6",
feature = "stm32f070xb",
)
))]
pub mod usb;
#[cfg(feature = "device-selected")]
pub mod watchdog;
44 changes: 44 additions & 0 deletions src/usb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! USB peripheral

use crate::stm32::{RCC, USB};
use stm32_usbd::UsbPeripheral;

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

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 = true;
const EP_MEMORY: *const () = 0x4000_6000 as _;
const EP_MEMORY_SIZE: usize = 1024;

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>;