rust-embedded-community / usb-device

Experimental device-side USB framework for microcontrollers in Rust.
MIT License
413 stars 77 forks source link

Usage with global allocator #110

Closed hacknus closed 1 year ago

hacknus commented 1 year ago

I have been using this library on my STM32F405 and it has work flawlessly with interrupt polling: The setup is as follows:

// Make USB serial device globally available
pub static G_USB_SERIAL: Mutex<RefCell<Option<SerialPort<UsbBus<USB>>>>> =
    Mutex::new(RefCell::new(None));

// Make USB device globally available
pub static G_USB_DEVICE: Mutex<RefCell<Option<UsbDevice<UsbBus<USB>>>>> =
    Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {

  unsafe {
          static mut EP_MEMORY: [u32; 1024] = [0; 1024];
          static mut USB_BUS: Option<UsbBusAllocator<stm32f4xx_hal::otg_fs::UsbBusType>> = None;
          USB_BUS = Some(stm32f4xx_hal::otg_fs::UsbBusType::new(usb, &mut EP_MEMORY));
          let mut usb_bus = USB_BUS.as_ref().unwrap();
          let mut serial_port = SerialPort::new(&usb_bus);
          cortex_m::interrupt::free(|cs| {
              *G_USB_SERIAL.borrow(cs).borrow_mut() = Some(serial_port);
              *G_USB_DEVICE.borrow(cs).borrow_mut() = Some(
                  UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
                      .manufacturer("University of Bern")
                      .product("Emanuel")
                      .serial_number("007")
                      .device_class(usbd_serial::USB_CLASS_CDC)
                      .build(),
              );
          });
          cortex_m::peripheral::NVIC::unmask(Interrupt::OTG_FS);
          // Enable the external interrupt in the NVIC by passing the button interrupt number
          cortex_m::peripheral::NVIC::unmask(sw.interrupt());
      }
      loop {
           // do stuff
     }

}

However, now I am trying to use it with a FreeRTOS wrapper for rust which requires nightly build with a global allocator:

#[global_allocator]
static GLOBAL: FreeRtosAllocator = FreeRtosAllocator;

and now the USB setup fails, I assume the allocations conflict? Does anybody have an idea on how to mitigate this?

Disasm commented 1 year ago

usb-device doesn't use allocator, so the problem is located somewhere else.

hacknus commented 1 year ago

Ok, I found out that with the debugger, it hangs in this line:

while read_reg!(otg_global, regs.global(), GRSTCTL, AHBIDL) == 0 {}

line 365 in .cargo/registry/src/github.com-1ecc6299db9ec823/synopsys-usb-otg-0.3.1/src/bus.rs

full output of the debugger:

synopsys_usb_otg::bus::{impl#2}::enable::{closure#0}<stm32f4xx_hal::otg_fs::USB> (cs=<optimized out>)
    at /Users/linus/.cargo/registry/src/github.com-1ecc6299db9ec823/synopsys-usb-otg-0.3.1/src/bus.rs:365
365             while read_reg!(otg_global, regs.global(), GRSTCTL, AHBIDL) == 0 {}
(gdb) 
halted: PC: 0x08002ace
halted: PC: 0x08002ac6
synopsys_usb_otg::ral::register::RWRegister<u32>::read<u32> (self=<optimized out>)
    at /Users/linus/.cargo/registry/src/github.com-1ecc6299db9ec823/synopsys-usb-otg-0.3.1/src/ral/register.rs:23
23          unsafe { ::core::ptr::read_volatile(self.register.get()) }
(gdb) step
0x08002ac6 in core::ptr::read_volatile<u32> (src=<optimized out>) at /rustc/659e169d37990b9c730a59a96081f2ef7afbe8f1/library/core/src/ptr/mod.rs:1521
1521    /rustc/659e169d37990b9c730a59a96081f2ef7afbe8f1/library/core/src/ptr/mod.rs: No such file or directory.
(gdb) step
halted: PC: 0x08002aca
synopsys_usb_otg::bus::{impl#2}::enable::{closure#0}<stm32f4xx_hal::otg_fs::USB> (cs=<optimized out>)
    at /Users/linus/.cargo/registry/src/github.com-1ecc6299db9ec823/synopsys-usb-otg-0.3.1/src/bus.rs:365
365             while read_reg!(otg_global, regs.global(), GRSTCTL, AHBIDL) == 0 {}
(gdb) 
halted: PC: 0x08002ace
halted: PC: 0x08002ac6
Disasm commented 1 year ago

Please check that clocks are correct and 48MHz clock is supplied to the USB peripheral.

hacknus commented 1 year ago

I agree, it looks like there is a clock issue.. I'm looking into this and I'll come back to you. Thanks!

hacknus commented 1 year ago

It appears that usb-device works when compiled with default rust, but it fails when compiled with nightly (no changes in the code, just added '+nightly' to the cargo build command). Should I open another issue for that? (FreeRTOS requires nightly because of the allocator, that's why I noticed it)

Disasm commented 1 year ago

I think the best approach is to reduce the software to a minimal version which reveals the difference between stable and nightly and then file a bug to rust-lang.

hacknus commented 1 year ago

Yes, I did that. I tried these examples; poll and interrupt and both work with rust stable but hang with nightly. rust-lang seems a bit overkill, it seems that the AHB clock is not ready/setup in nightly. I guess that is an issue in the stm32f4xx-hal?

antonok-edm commented 1 year ago

I ran into this as well.

Linking the related issue chain for reference, in case anyone else has the same issue: https://github.com/stm32-rs/stm32f4xx-hal/issues/567

Disasm commented 1 year ago

Fixed in https://github.com/stm32-rs/synopsys-usb-otg/pull/34