Skip to content

Commit d778a61

Browse files
committed
USB: Check the peripheral frequency for a stable connection
1 parent 997e296 commit d778a61

File tree

6 files changed

+73
-6
lines changed

6 files changed

+73
-6
lines changed

boards/atsame54_xpro/src/devices.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,5 +372,6 @@ pub fn usb_allocator(
372372
let usb_gclk = clocks.get_gclk(Genselect::Gclk2).unwrap();
373373
let usb_clock = &clocks.usb(&usb_gclk).unwrap();
374374
let (dm, dp) = (dm.into(), dp.into());
375-
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb))
375+
/// Safety - V1 clocking API forces a 48Mhz USB clock
376+
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb).unwrap())
376377
}

boards/feather_m4/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,5 +272,6 @@ pub fn usb_allocator(
272272
let usb_gclk = clocks.get_gclk(Genselect::Gclk2).unwrap();
273273
let usb_clock = &clocks.usb(&usb_gclk).unwrap();
274274
let (dm, dp) = (dm.into(), dp.into());
275-
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb))
275+
/// Safety - V1 clocking API forces a 48Mhz USB clock
276+
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb).unwrap())
276277
}

boards/metro_m0/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,5 +336,6 @@ pub fn usb_allocator(
336336
let gclk0 = clocks.gclk0();
337337
let clock = &clocks.usb(&gclk0).unwrap();
338338
let (dm, dp) = (dm.into(), dp.into());
339-
UsbBusAllocator::new(UsbBus::new(clock, pm, dm, dp, usb))
339+
/// Safety - V1 clocking API forces a 48Mhz USB clock
340+
UsbBusAllocator::new(UsbBus::new(clock, pm, dm, dp, usb).unwrap())
340341
}

boards/metro_m4/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,5 +365,6 @@ pub fn usb_allocator(
365365
let usb_gclk = clocks.get_gclk(Genselect::Gclk2).unwrap();
366366
let usb_clock = &clocks.usb(&usb_gclk).unwrap();
367367
let (dm, dp) = (dm.into(), dp.into());
368-
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb))
368+
/// Safety - V1 clocking API forces a 48Mhz USB clock
369+
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb).unwrap())
369370
}

hal/src/peripherals/usb/d11/bus.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,41 @@ impl Inner {
482482
}
483483
}
484484

485+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
486+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
487+
pub enum UsbBusErr {
488+
/// USB clock freq is not valid for a stable connection
489+
InvalidClockFreq,
490+
}
491+
485492
impl UsbBus {
493+
/// Create a new USB Bus, checking the clock frequency of the USB clock for
494+
/// a stable USB link to most hosts. The `clock` freq must be 48Mhz, otherwise
495+
/// [`UsbBusErr::InvalidClockFreq`] will be returned
486496
pub fn new(
487-
_clock: &clock::UsbClock,
497+
clock: &clock::UsbClock,
498+
pm: &mut Pm,
499+
dm_pad: impl AnyPin<Id = PA24>,
500+
dp_pad: impl AnyPin<Id = PA25>,
501+
usb: Usb,
502+
) -> Result<Self, UsbBusErr> {
503+
if clock.freq().to_Hz() != 48_000_000 {
504+
Err(UsbBusErr::InvalidClockFreq)
505+
} else {
506+
let res = unsafe { Self::new_unchecked(clock, pm, dm_pad, dp_pad, usb) };
507+
Ok(res)
508+
}
509+
}
510+
511+
/// Creates a new USB Bus, but does NOT perform the USB clock frequency check.
512+
///
513+
/// SAFETY: For a SAMx to PC connection, the USB clock must be 48Mhz for stability.
514+
/// This function allows you to bypass this check however if you intend to connect multiple SAM chips
515+
/// together with faster running USB clocks for a boost in transfer rate.
516+
///
517+
/// Consult the datasheet for GCLK_USB absolute maximums
518+
pub unsafe fn new_unchecked(
519+
clock: &clock::UsbClock,
488520
pm: &mut Pm,
489521
dm_pad: impl AnyPin<Id = PA24>,
490522
dp_pad: impl AnyPin<Id = PA25>,

hal/src/peripherals/usb/d5x/bus.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,13 +524,44 @@ impl Inner {
524524
}
525525
}
526526

527+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
528+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
529+
pub enum UsbBusErr {
530+
/// USB clock freq is not valid for a stable connection
531+
InvalidClockFreq,
532+
}
533+
527534
impl UsbBus {
535+
/// Create a new USB Bus, checking the clock frequency of the USB clock for
536+
/// a stable USB link to most hosts. The `clock` freq must be 48Mhz, otherwise
537+
/// [`UsbBusErr::InvalidClockFreq`] will be returned
528538
pub fn new(
529-
_clock: &clock::UsbClock,
539+
clock: &clock::UsbClock,
530540
mclk: &mut Mclk,
531541
dm_pad: impl AnyPin<Id = PA24>,
532542
dp_pad: impl AnyPin<Id = PA25>,
533543
_usb: Usb,
544+
) -> Result<Self, UsbBusErr> {
545+
if clock.freq().to_Hz() != 48_000_000 {
546+
Err(UsbBusErr::InvalidClockFreq)
547+
} else {
548+
let res = unsafe { Self::new_unchecked(clock, mclk, dm_pad, dp_pad) };
549+
Ok(res)
550+
}
551+
}
552+
553+
/// Creates a new USB Bus, but does NOT perform the USB clock frequency check.
554+
///
555+
/// SAFETY: For a SAMx to PC connection, the USB clock must be 48Mhz for stability.
556+
/// This function allows you to bypass this check however if you intend to connect multiple SAM chips
557+
/// together with faster running USB clocks for a boost in transfer rate.
558+
///
559+
/// Consult the datasheet for GCLK_USB absolute maximums
560+
pub unsafe fn new_unchecked(
561+
_clock: &clock::UsbClock,
562+
mclk: &mut Mclk,
563+
dm_pad: impl AnyPin<Id = PA24>,
564+
dp_pad: impl AnyPin<Id = PA25>,
534565
) -> Self {
535566
mclk.ahbmask().modify(|_, w| w.usb_().set_bit());
536567
mclk.apbbmask().modify(|_, w| w.usb_().set_bit());

0 commit comments

Comments
 (0)