Skip to content
Open
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
2 changes: 1 addition & 1 deletion embassy-nrf/src/usb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl<'d, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, V> {
))
}

fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
fn start(self, control_max_packet_size: u16, _enable_sof_interrupts: bool) -> (Self::Bus, Self::ControlPipe) {
(
Bus {
regs: self.regs,
Expand Down
2 changes: 1 addition & 1 deletion embassy-rp/src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}

fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
fn start(self, control_max_packet_size: u16, _enable_sof_interrupts: bool) -> (Self::Bus, Self::ControlPipe) {
let regs = T::regs();
regs.inte().write(|w| {
w.set_bus_reset(true);
Expand Down
4 changes: 2 additions & 2 deletions embassy-stm32/src/usb/otg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
}

fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
let (bus, cp) = self.inner.start(control_max_packet_size);
fn start(self, control_max_packet_size: u16, enable_sof_interrupts: bool) -> (Self::Bus, Self::ControlPipe) {
let (bus, cp) = self.inner.start(control_max_packet_size, enable_sof_interrupts);

(
Bus {
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/usb/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}

fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
fn start(mut self, control_max_packet_size: u16, _enable_sof_interrupts: bool) -> (Self::Bus, Self::ControlPipe) {
let ep_out = self
.alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
.unwrap();
Expand Down
5 changes: 4 additions & 1 deletion embassy-usb-driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ pub trait Driver<'a> {
///
/// This consumes the `Driver` instance, so it's no longer possible to allocate more
/// endpoints.
fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe);
fn start(self, control_max_packet_size: u16, enable_sof_interrupts: bool) -> (Self::Bus, Self::ControlPipe);
}

/// USB bus trait.
Expand Down Expand Up @@ -402,6 +402,9 @@ pub enum Event {

/// The USB power has been removed. Not supported by all devices.
PowerRemoved,

/// A Start of Frame token has been received
SOF,
}

/// Allocating an endpoint failed.
Expand Down
21 changes: 19 additions & 2 deletions embassy-usb-synopsys-otg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@ pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(r: Otg, state: &State<MAX_
trace!("irq");

let ints = r.gintsts().read();
if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
if ints.wkupint()
|| ints.usbsusp()
|| ints.usbrst()
|| ints.enumdne()
|| ints.otgint()
|| ints.srqint()
|| ints.sof()
{
// Mask interrupts and notify `Bus` to process them
r.gintmsk().write(|w| {
w.set_iepint(true);
Expand Down Expand Up @@ -479,7 +486,7 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}

fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
fn start(mut self, control_max_packet_size: u16, enable_sof_interrupts: bool) -> (Self::Bus, Self::ControlPipe) {
let ep_out = self
.alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
.unwrap();
Expand All @@ -500,6 +507,7 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d
ep_out: self.ep_out,
inited: false,
instance: self.instance,
enable_sof_interrupts,
},
ControlPipe {
max_packet_size: control_max_packet_size,
Expand All @@ -519,6 +527,7 @@ pub struct Bus<'d, const MAX_EP_COUNT: usize> {
ep_out: [Option<EndpointData>; MAX_EP_COUNT],
instance: OtgInstance<'d, MAX_EP_COUNT>,
inited: bool,
enable_sof_interrupts: bool,
}

impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
Expand All @@ -533,6 +542,7 @@ impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
w.set_rxflvlm(true);
w.set_srqim(true);
w.set_otgint(true);
w.set_sofm(self.enable_sof_interrupts);
});
}

Expand Down Expand Up @@ -868,6 +878,13 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Bus for Bus<'d, MAX_EP_C
return Poll::Ready(Event::Resume);
}

if ints.sof() {
trace!("sof");
regs.gintsts().write(|w| w.set_sof(true)); // clear
self.restore_irqs();
return Poll::Ready(Event::SOF);
}

Poll::Pending
})
.await
Expand Down
13 changes: 13 additions & 0 deletions embassy-usb/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ pub struct Config<'a> {
/// Default: 100mA
/// Max: 500mA
pub max_power: u16,

/// Whether to enable SOF interrupts
///
/// Start of Frame can be a useful event on the bus, happening either every
/// 1ms for USB LS and FS, or every 125µs for USB HS. This can be used as a
/// free extra timer in a lot of cases, and as a way to process events at
/// the end of the frame if things needed deferring. However, this can be
/// a significant amount of interrupt traffic, so only enable this if you
/// really need this style of handling.
///
/// Default: `false`
pub enable_sof_interrupts: bool,
}

impl<'a> Config<'a> {
Expand All @@ -138,6 +150,7 @@ impl<'a> Config<'a> {
supports_remote_wakeup: false,
composite_with_iads: true,
max_power: 100,
enable_sof_interrupts: false,
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion embassy-usb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ pub trait Handler {
let _ = alternate_setting;
}

/// Called when a SOF token is processed.
fn sof(&mut self) {}

/// Called when a control request is received with direction HostToDevice.
///
/// # Arguments
Expand Down Expand Up @@ -225,7 +228,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
) -> UsbDevice<'d, D> {
// Start the USB bus.
// This prevent further allocation by consuming the driver.
let (bus, control) = driver.start(config.max_packet_size_0 as u16);
let (bus, control) = driver.start(config.max_packet_size_0 as u16, config.enable_sof_interrupts);
let device_descriptor = descriptor::device_descriptor(&config);
let device_qualifier_descriptor = descriptor::device_qualifier_descriptor(&config);

Expand Down Expand Up @@ -495,6 +498,12 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
h.enabled(false);
}
}
Event::SOF => {
trace!("usb: start of frame");
for h in &mut self.handlers {
h.sof();
}
}
}
}

Expand Down