Skip to content
Draft
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
1 change: 1 addition & 0 deletions boards/grand_central_m4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ optional = true
[dependencies.atsamd-hal]
default-features = false
version = "0.22.0"
path = "../../hal"

[dependencies.usb-device]
version = "0.3.2"
Expand Down
46 changes: 32 additions & 14 deletions boards/grand_central_m4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,22 @@
//! an ATSAMD51-based board in an Arduino Mega form factor.

pub use atsamd_hal as hal;
pub use hal::ehal;
pub use hal::pac;
pub use hal::{
clock::v2::{
self as clock,
ahb::{AhbClk, AhbToken},
apb::{ApbClk, ApbToken},
dfll::{self, Dfll},
gclk::{Gclk, GclkId, GclkToken},
pclk::{Pclk, PclkToken},
types::Usb,
Enabled,
},
ehal,
gpio::{AnyPin, PA24, PA25},
pac,
sercom::spi::lengths::U1,
};

#[cfg(feature = "rt")]
pub use cortex_m_rt::entry;
Expand Down Expand Up @@ -595,18 +609,22 @@ pub fn uart(

#[cfg(feature = "usb")]
/// Convenience function for setting up USB
pub fn usb_allocator(
pub fn usb_allocator<G: GclkId>(
usb: pac::Usb,
clocks: &mut GenericClockController,
mclk: &mut pac::Mclk,
dm: impl Into<UsbDm>,
dp: impl Into<UsbDp>,
) -> UsbBusAllocator<UsbBus> {
use pac::gclk::{genctrl::Srcselect, pchctrl::Genselect};
dfll: Enabled<Dfll, U1>,
gclk_token: GclkToken<G>,
pclk_token: PclkToken<Usb>,
ahb_clk: AhbClk<clock::types::Usb>,
apb_clk: ApbClk<clock::types::Usb>,
dm: impl AnyPin<Id = PA24>,
dp: impl AnyPin<Id = PA25>,
) -> UsbBusAllocator<UsbBus<G>> {
// SWITCH DFLL INTO USB CLOCK RECOVERY MODE - THIS ALLOWS FOR MORE ACCURATE USB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving the comment about clock recovery mode in to the docstring for the method, so that it shows up in docs (or Rust Analyzer etc). Also, I'm pretty sure it's required to use USBCRM if running USB with the DFLL clock source, so not sure "more accurate" is the right way to describe it.

let (dfll_usb, _) = dfll.into_mode(dfll::FromUsb, |_| {});
// GCLK3 comes from DFLL, outputs to USB
let (gclk_n, _) = Gclk::from_source(gclk_token, dfll_usb);
let gclk_n_48mhz = gclk_n.enable();
let (pclk_usb, _) = Pclk::enable(pclk_token, gclk_n_48mhz);

clocks.configure_gclk_divider_and_source(Genselect::Gclk2, 1, Srcselect::Dfll, false);
let usb_gclk = clocks.get_gclk(Genselect::Gclk2).unwrap();
let usb_clock = &clocks.usb(&usb_gclk).unwrap();
let (dm, dp) = (dm.into(), dp.into());
UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb))
return UsbBusAllocator::new(UsbBus::new(pclk_usb, ahb_clk, apb_clk, dm, dp, usb));
}
2 changes: 1 addition & 1 deletion hal/src/peripherals/clock/d5x/v2/gclk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ pub enum DynGclkId {
///
/// [type-level programming]: crate::typelevel
/// [type-level enums]: crate::typelevel#type-level-enums
pub trait GclkId: Sealed {
pub trait GclkId: Sealed + Send {
/// Corresponding variant of [`DynGclkId`]
const DYN: DynGclkId;
/// Corresponding numeric index (0..12)
Expand Down
65 changes: 47 additions & 18 deletions hal/src/peripherals/usb/d5x/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@

use super::Descriptors;
use crate::calibration::{usb_transn_cal, usb_transp_cal, usb_trim_cal};
use crate::clock;
use crate::gpio::{AlternateH, AnyPin, Pin, PA24, PA25};
use crate::clock::v2::{
self as clock,
ahb::AhbClk,
apb::ApbClk,
pclk::{Pclk, PclkSourceId},
};
use crate::gpio::{AlternateH, AnyPin, PA24, PA25, Pin};
use crate::pac;
use crate::pac::Usb;
use crate::pac::usb::Device;
use crate::pac::{Mclk, Usb};
use crate::usb::devicedesc::DeviceDescBank;
use core::cell::{Ref, RefCell, RefMut};
use core::marker::PhantomData;
use core::mem;
use cortex_m::singleton;
use critical_section::{with as disable_interrupts, Mutex};
use critical_section::{Mutex, with as disable_interrupts};
use usb_device::bus::PollResult;
use usb_device::endpoint::{EndpointAddress, EndpointType};
use usb_device::{Result as UsbResult, UsbDirection, UsbError};
Expand Down Expand Up @@ -191,16 +196,19 @@ impl BufferAllocator {
}
}

struct Inner {
struct Inner<S: PclkSourceId> {
desc: RefCell<Descriptors>,
_dm_pad: Pin<PA24, AlternateH>,
_dp_pad: Pin<PA25, AlternateH>,
endpoints: RefCell<AllEndpoints>,
buffers: RefCell<BufferAllocator>,
pclk: Pclk<clock::types::Usb, S>,
ahb_clk: AhbClk<clock::types::Usb>,
apb_clk: ApbClk<clock::types::Usb>,
}

pub struct UsbBus {
inner: Mutex<RefCell<Inner>>,
pub struct UsbBus<S: PclkSourceId> {
inner: Mutex<RefCell<Inner<S>>>,
}

struct Bank<'a, T> {
Expand Down Expand Up @@ -469,7 +477,7 @@ impl<T> Bank<'_, T> {
}
}

impl Inner {
impl<S: PclkSourceId> Inner<S> {
#[inline]
fn epcfg(&self, endpoint: usize) -> &pac::usb::device::device_endpoint::Epcfg {
self.usb().device_endpoint(endpoint).epcfg()
Expand Down Expand Up @@ -524,17 +532,15 @@ impl Inner {
}
}

impl UsbBus {
impl<S: PclkSourceId> UsbBus<S> {
pub fn new(
_clock: &clock::UsbClock,
mclk: &mut Mclk,
pclk: Pclk<clock::types::Usb, S>,
ahb_clk: AhbClk<clock::types::Usb>,
apb_clk: ApbClk<clock::types::Usb>,
dm_pad: impl AnyPin<Id = PA24>,
dp_pad: impl AnyPin<Id = PA25>,
_usb: Usb,
) -> Self {
mclk.ahbmask().modify(|_, w| w.usb_().set_bit());
mclk.apbbmask().modify(|_, w| w.usb_().set_bit());

let desc = RefCell::new(Descriptors::new());

let inner = Inner {
Expand All @@ -543,15 +549,38 @@ impl UsbBus {
desc,
buffers: RefCell::new(BufferAllocator::new()),
endpoints: RefCell::new(AllEndpoints::new()),
pclk,
ahb_clk,
apb_clk,
};

Self {
inner: Mutex::new(RefCell::new(inner)),
}
}

pub fn free(
self,
) -> (
Pclk<clock::types::Usb, S>,
AhbClk<clock::types::Usb>,
ApbClk<clock::types::Usb>,
Pin<PA24, AlternateH>,
Pin<PA25, AlternateH>,
) {
// Unwrap the Mutex and RefCell to get the Inner
let inner = self.inner.into_inner().into_inner();
(
inner.pclk,
inner.ahb_clk,
inner.apb_clk,
inner._dm_pad,
inner._dp_pad,
)
}
}

impl Inner {
impl<S: PclkSourceId> Inner<S> {
fn usb(&self) -> &Device {
unsafe { (*Usb::ptr()).device() }
}
Expand All @@ -576,7 +605,7 @@ enum FlushConfigMode {
ProtocolReset,
}

impl Inner {
impl<S: PclkSourceId> Inner<S> {
fn enable(&mut self) {
let usb = self.usb();
usb.ctrla().modify(|_, w| w.swrst().set_bit());
Expand Down Expand Up @@ -884,7 +913,7 @@ impl Inner {
}
}

impl UsbBus {
impl<S: PclkSourceId> UsbBus<S> {
/// Enables the Start Of Frame (SOF) interrupt
pub fn enable_sof_interrupt(&self) {
disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().sof_interrupt(true))
Expand All @@ -901,7 +930,7 @@ impl UsbBus {
}
}

impl usb_device::bus::UsbBus for UsbBus {
impl<S: PclkSourceId> usb_device::bus::UsbBus for UsbBus<S> {
fn enable(&mut self) {
disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().enable())
}
Expand Down
Loading