I am developing firmware for a stm32h7 device with usb, and I want to make a struct for the usb-related stuff (with a read/write function exposed typically). My first attempt looked like this (there is a UsbDeviceBuilder involved as well, but it does the same as SerialPort so removed for simplicity):
use synopsys_usb_otg::UsbPeripheral;
use usb_device::prelude::*;
use usbd_serial::SerialPort;
static mut USB_MEMORY: [u32; 1024] = [0u32; 1024];
pub struct Usb<'a, USB: UsbPeripheral> {
usb_bus: UsbBusAllocator<UsbBus<USB>>,
usb_serial: SerialPort<'a, UsbBus<USB>>,
}
impl <USB: UsbPeripheral> Usb<'_, USB> {
pub fn new(usb: USB) -> Self {
let usb_bus = UsbBus::new(usb, unsafe { &mut USB_MEMORY });
let usb_serial = usbd_serial::SerialPort::new(&usb_bus);
Usb {
usb_bus,
usb_serial,
}
}
}
The problem is that SerialPort::new stores the reference to usb_bus, and since this is moved when returning from the function, the compiler chokes:
pub fn new(usb: USB) -> Self {
| ---- return type is Usb<'1, USB>
17 | let usb_bus = UsbBus::new(usb, unsafe { &mut USB_MEMORY });
18 | let usb_serial = usbd_serial::SerialPort::new(&usb_bus);
| -------- borrow of `usb_bus` occurs here
19 |
20 | / Usb {
21 | | usb_bus,
| | ^^^^^^^ move out of `usb_bus` occurs here
22 | | usb_serial,
23 | | }
| |_________- returning this value requires that `usb_bus` is borrowed for `'1`
Usb is instantiated from my Board struct (where I do Peripherals::take and setup everything), so I was thinking about sending in the usb_bus from there, but even that won't help since it would again be moved when board is instantiated from main.
fn main() {
let board = Board::new();
}
impl Board {
pub fn new() {
let p = Peripherals::take();
let usb_bus = UsbBus::new(p.USB1, ...);
let usb = Usb::new(&usb_bus);
Board {
usb // <- Moved here as well
}
}
}
And since it takes the usb-peripheral as input, I also don't want to instantiate usbbus on main, since I would have to take Peripherals there instead of in board.
How can I organize this in a proper way?