From 62fdd309c55286222d1add4ca3051353da0e11b8 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Wed, 31 Mar 2021 17:40:53 +0200 Subject: Enable USB CDC ACM for eval-clock-cw-tx --- sw/eval-clock-cw-tx/Cargo.lock | 31 ++++++++++++++ sw/eval-clock-cw-tx/Cargo.toml | 4 +- sw/eval-clock-cw-tx/Makefile | 2 +- sw/eval-clock-cw-tx/src/main.rs | 14 +++++++ sw/eval-clock-cw-tx/src/usb.rs | 91 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 sw/eval-clock-cw-tx/src/usb.rs (limited to 'sw') diff --git a/sw/eval-clock-cw-tx/Cargo.lock b/sw/eval-clock-cw-tx/Cargo.lock index 8007053..e0152f2 100644 --- a/sw/eval-clock-cw-tx/Cargo.lock +++ b/sw/eval-clock-cw-tx/Cargo.lock @@ -146,6 +146,8 @@ dependencies = [ "shared-bus", "si5351", "stm32f1xx-hal", + "usb-device", + "usbd-serial", ] [[package]] @@ -280,6 +282,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "stm32-usbd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d13eca735cae37df697f599777b000cc0ee924df8452f2b4bfaa6798ab0338" +dependencies = [ + "cortex-m 0.6.7", + "usb-device", + "vcell", +] + [[package]] name = "stm32f1" version = "0.11.0" @@ -304,6 +317,7 @@ dependencies = [ "embedded-dma", "embedded-hal", "nb 0.1.3", + "stm32-usbd", "stm32f1", "void", ] @@ -331,6 +345,23 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "usb-device" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6be90410d4772074ea49525e2e753b65920b94b57eee21a6ef7b6a6fe6296245" + +[[package]] +name = "usbd-serial" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe" +dependencies = [ + "embedded-hal", + "nb 0.1.3", + "usb-device", +] + [[package]] name = "vcell" version = "0.1.3" diff --git a/sw/eval-clock-cw-tx/Cargo.toml b/sw/eval-clock-cw-tx/Cargo.toml index b56ac96..ebf3e20 100644 --- a/sw/eval-clock-cw-tx/Cargo.toml +++ b/sw/eval-clock-cw-tx/Cargo.toml @@ -15,11 +15,13 @@ cortex-m-semihosting = "0.3" panic-semihosting = "0.5" nb = "1.0" #stm32h7 = { version = "0.9", features = ["stm32h743", "rt"] } -stm32f1xx-hal = { version = "0.7", features = ["rt", "stm32f103", "medium"] } +stm32f1xx-hal = { version = "0.7", features = ["rt", "stm32f103", "medium", "stm32-usbd"] } embedded-hal = { version = "0.2", features = [] } shared-bus = { version = "0.2", features = ["cortex-m"] } hd44780-driver = { path = "../deps/hd44780-driver"} si5351 = { path = "../deps/si5351" } +usb-device = { version = "0.2" } +usbd-serial = { version = "0.1" } [profile.dev] codegen-units = 1 diff --git a/sw/eval-clock-cw-tx/Makefile b/sw/eval-clock-cw-tx/Makefile index 8c5fc79..1679b79 100644 --- a/sw/eval-clock-cw-tx/Makefile +++ b/sw/eval-clock-cw-tx/Makefile @@ -1,7 +1,7 @@ .PHONY: all openocd debug OPENOCD := openocd -OPENOCD_OPT := -f interface/stlink-v2.cfg -f target/stm32f1x.cfg +OPENOCD_OPT := -f interface/stlink.cfg -f target/stm32f1x.cfg BIN := target/thumbv7m-none-eabi/debug/picardy # Build and flash in release mode diff --git a/sw/eval-clock-cw-tx/src/main.rs b/sw/eval-clock-cw-tx/src/main.rs index c91c545..d30318b 100644 --- a/sw/eval-clock-cw-tx/src/main.rs +++ b/sw/eval-clock-cw-tx/src/main.rs @@ -46,6 +46,7 @@ use embedded_hal::digital::v2::InputPin; use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780}; pub mod ui; +pub mod usb; pub mod cw; pub mod state; pub mod si_clock; @@ -92,8 +93,14 @@ fn main() -> ! { let mut rcc = dp.RCC.constrain(); let mut afio = dp.AFIO.constrain(&mut rcc.apb2); let clocks = rcc.cfgr + .use_hse(16.mhz()) + .sysclk(48.mhz()) + .pclk1(24.mhz()) .adcclk(2.mhz()) .freeze(&mut flash.acr); + + assert!(clocks.usbclk_valid()); + let mut delay = Delay::new(cp.SYST, clocks); delay.delay_ms(200u16); @@ -102,6 +109,10 @@ fn main() -> ! { let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); + let usb_dm = gpioa.pa11; + let usb_dp = gpioa.pa12.into_floating_input(&mut gpioa.crh); + let usb = usb::USB::new(dp.USB, usb_dm, usb_dp); + // Buttons as analog inputs (multi-level) let pb0 = gpiob.pb0.into_floating_input(&mut gpiob.crl); // BTN1 Button B, has external pullup let pb1 = gpiob.pb1.into_floating_input(&mut gpiob.crl); // BTN0 Button A, has external pullup @@ -173,6 +184,7 @@ fn main() -> ! { lcd.write_str(" 30m CW TX 2021 ", &mut delay).unwrap(); delay.delay_ms(1_500u16); + usb.enable_interrupts(); let mut siclock = { let shared = unsafe { &mut *SHARED.as_mut_ptr() }; @@ -349,6 +361,7 @@ fn TIM2() { } } +#[allow(non_snake_case)] #[cortex_m_rt::exception] fn HardFault(ef: &ExceptionFrame) -> ! { let periph = unsafe { cortex_m::Peripherals::steal() }; @@ -360,6 +373,7 @@ fn HardFault(ef: &ExceptionFrame) -> ! { loop { } } +#[allow(non_snake_case)] #[cortex_m_rt::exception] fn DefaultHandler(irqn: i16) { hprintln!("Unhandled exception (IRQn = {})", irqn).unwrap(); diff --git a/sw/eval-clock-cw-tx/src/usb.rs b/sw/eval-clock-cw-tx/src/usb.rs new file mode 100644 index 0000000..941a024 --- /dev/null +++ b/sw/eval-clock-cw-tx/src/usb.rs @@ -0,0 +1,91 @@ + +use stm32f1xx_hal::gpio; +use stm32f1xx_hal::pac; +use stm32f1xx_hal::pac::{interrupt, Interrupt}; +use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType}; +use usb_device::{bus::UsbBusAllocator, prelude::*}; +use usbd_serial::{SerialPort, USB_CLASS_CDC}; + +static mut USB_BUS: Option> = None; +static mut USB_SERIAL: Option> = None; +static mut USB_DEVICE: Option> = None; + +pub struct USB { +} + +impl USB { + pub fn new( + usb: stm32f1xx_hal::pac::USB, + pin_dm: gpio::gpioa::PA11>, + pin_dp: gpio::gpioa::PA12>) -> Self { + + let peripheral = Peripheral { + usb, + pin_dm, + pin_dp, + }; + + unsafe { + let bus = UsbBus::new(peripheral); + + USB_BUS = Some(bus); + + USB_SERIAL = Some(SerialPort::new(USB_BUS.as_ref().unwrap())); + + let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x1d50, 0x5120)) // Openmoko Neo1973 serial + .manufacturer("HB9EGM") + .product("Beep Machine") + .serial_number("1") + .device_class(USB_CLASS_CDC) + .build(); + + USB_DEVICE = Some(usb_dev); + } + + USB{} + } + + pub fn enable_interrupts(&self) { + unsafe { + pac::NVIC::unmask(Interrupt::USB_HP_CAN_TX); + pac::NVIC::unmask(Interrupt::USB_LP_CAN_RX0); + } + } +} + +#[allow(non_snake_case)] +#[interrupt] +fn USB_HP_CAN_TX() { + usb_interrupt(); +} + +#[allow(non_snake_case)] +#[interrupt] +fn USB_LP_CAN_RX0() { + usb_interrupt(); +} + +fn usb_interrupt() { + let usb_dev = unsafe { USB_DEVICE.as_mut().unwrap() }; + let serial = unsafe { USB_SERIAL.as_mut().unwrap() }; + + if !usb_dev.poll(&mut [serial]) { + return; + } + + let mut buf = [0u8; 8]; + + match serial.read(&mut buf) { + Ok(count) if count > 0 => { + // Echo back in upper case + for c in buf[0..count].iter_mut() { + if 0x61 <= *c && *c <= 0x7a { + *c &= !0x20; + } + } + + serial.write(&buf[0..count]).ok(); + } + _ => {} + } +} -- cgit v1.2.3