You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello Everyone!
It's my first post here. I'm trying to learn Rust programming for embedded devices, and I'd like to set up USB communication for my Nucleo F413ZH board.
I've managed to set up everything correctly and I've tested a simple Blink program, which is working. I've tried moving on to USB communication, writing the following two files:
main.rs
#![deny(unsafe_code)]#![allow(clippy::empty_loop)]#![no_main]#![no_std]mod usb;// dev profile: easier to debug panics; can put a breakpoint on `rust_begin_unwind`#[cfg(debug_assertions)]use panic_halt as _;// release profile: minimize the binary size of the application#[cfg(not(debug_assertions))]use panic_abort as _;use cortex_m_rt::entry;use stm32f4xx_hal as hal;usecrate::hal::{pac, prelude::*};fninitialize_clocks(rcc: hal::rcc::Rcc) -> hal::rcc::Clocks{return rcc
.cfgr// We will use the external 8MHz HSE oscillator.use_hse(8.MHz())// We will run the internal clock at 64MHz.sysclk(64.MHz()).pclk1((8).MHz()).freeze();}use stm32f4xx_hal::otg_fs::{USB};#[entry]fnmain() -> ! {let dp = pac::Peripherals::take().unwrap();let cp = cortex_m::Peripherals::take().unwrap();// Initialize clockslet clocks = initialize_clocks(dp.RCC.constrain());// Initialize USBlet gpioa = dp.GPIOA.split();let usb_configuration = USB{usb_global: dp.OTG_FS_GLOBAL,usb_device: dp.OTG_FS_DEVICE,usb_pwrclk: dp.OTG_FS_PWRCLK,pin_dm: gpioa.pa11.into_alternate(),pin_dp: gpioa.pa12.into_alternate(),hclk: clocks.hclk(),};
usb::initialize_usb(usb_configuration);// Create an the LED abstraction. On the Nucleo-401RE it's connected to pin PA5.let gpiob = dp.GPIOB.split();letmut led = gpiob.pb7.into_push_pull_output();// Create a delay abstraction based on SysTickletmut delay = cp.SYST.delay(&clocks);loop{// On for 1s, off for 1s.
led.set_high();
delay.delay_ms(1000_u32);
led.set_low();
delay.delay_ms(1000_u32);}}
usb.rs
#![allow(unsafe_code)]use core::cell::RefCell;use cortex_m::interrupt::Mutex;use stm32f4xx_hal::otg_fs::{UsbBus,USB};use stm32f4xx_hal::pac::{interrupt,Interrupt};use usb_device::class_prelude::UsbBusAllocator;use usb_device::prelude::*;use usbd_serial::SerialPort;// Make USB serial device globally availablestaticG_USB_SERIAL:Mutex<RefCell<Option<SerialPort<UsbBus<USB>>>>> =
Mutex::new(RefCell::new(None));// Make USB device globally availablestaticG_USB_DEVICE:Mutex<RefCell<Option<UsbDevice<UsbBus<USB>>>>> =
Mutex::new(RefCell::new(None));pubfninitialize_usb(usb:USB){staticmutEP_MEMORY:[u32;1024] = [0;1024];staticmutUSB_BUS:Option<UsbBusAllocator<stm32f4xx_hal::otg_fs::UsbBusType>> = None;unsafe{USB_BUS = Some(stm32f4xx_hal::otg_fs::UsbBusType::new(usb,EP_MEMORY.as_mut()));let usb_bus = USB_BUS.as_ref().unwrap();
cortex_m::interrupt::free(|cs| {*G_USB_SERIAL.borrow(cs).borrow_mut() = Some(SerialPort::new(usb_bus));*G_USB_DEVICE.borrow(cs).borrow_mut() = Some(UsbDeviceBuilder::new(usb_bus,UsbVidPid(0x16c0,0x27dd)).manufacturer("Fake company").product("Serial port").serial_number("TEST").device_class(usbd_serial::USB_CLASS_CDC).build(),);});
cortex_m::peripheral::NVIC::unmask(Interrupt::OTG_FS);}}#[interrupt]unsafefnOTG_FS(){staticmutUSB_SERIAL:Option<SerialPort<UsbBus<USB>>> = None;staticmutUSB_DEVICE:Option<UsbDevice<UsbBus<USB>>> = None;let usb_dev = USB_DEVICE.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {// Move USB device here, leaving a None in its placeG_USB_DEVICE.borrow(cs).replace(None).unwrap()})});let serial = USB_SERIAL.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {// Move USB serial device here, leaving a None in its placeG_USB_SERIAL.borrow(cs).replace(None).unwrap()})});if usb_dev.poll(&mut[serial]){letmut buf = [0u8;64];match serial.read(&mut buf){Ok(count)if count > 0 => {// Echo back in upper casefor c in buf[0..count].iter_mut(){if0x61 <= *c && *c <= 0x7a{*c &= !0x20;}}letmut write_offset = 0;while write_offset < count {match serial.write(&buf[write_offset..count]){Ok(len)if len > 0 => {
write_offset += len;}
_ => {}}}}
_ => {}}}}
However, whenever I run lsusb in my terminal, after connecting the board to my PC, nothing shows up. I should be able to hear a notification and see a Fake CompanySerial Port usb device.
Why is that (not) happening?
Thank you very much,
Riccardo
The text was updated successfully, but these errors were encountered:
I'm not sure if USB interrupts work at all with this chip. And there is a bug for a different one: stm32-rs/synopsys-usb-otg#13
Polling in main loop should still work, though.
I have a similar issue with a STM32f405. The interrupts fire when a windows or macOS machine is on the host side, but when I connect it to a linux machine (ubuntu), the interrupts never fire and I have to poll in the main loop... Does anybody have an idea on where the problem could lie?
Hello Everyone!
It's my first post here. I'm trying to learn Rust programming for embedded devices, and I'd like to set up USB communication for my Nucleo F413ZH board.
I've managed to set up everything correctly and I've tested a simple Blink program, which is working. I've tried moving on to USB communication, writing the following two files:
main.rs
usb.rs
However, whenever I run
lsusb
in my terminal, after connecting the board to my PC, nothing shows up. I should be able to hear a notification and see a Fake Company Serial Port usb device.Why is that (not) happening?
Thank you very much,
Riccardo
The text was updated successfully, but these errors were encountered: