diff --git a/boards/atsame54_xpro/Cargo.toml b/boards/atsame54_xpro/Cargo.toml index eafd323a3089..cb9c87497493 100644 --- a/boards/atsame54_xpro/Cargo.toml +++ b/boards/atsame54_xpro/Cargo.toml @@ -26,15 +26,12 @@ default-features = false path = "../../hal" version = "0.22.2" -[dependencies.usb-device] -optional = true -version = "0.3.1" - [dev-dependencies] mcan = "0.2" panic-rtt-target = {version = "0.1", features = ["cortex-m"]} rtic = {version = "2.1.2", features = ["thumbv7-backend"]} rtt-target = {version = "0.3", features = ["cortex-m"]} +usb-device = "0.3.1" [features] default = ["rt", "atsamd-hal/same54p"] @@ -44,7 +41,7 @@ max-channels = ["dma", "atsamd-hal/max-channels"] async = ["atsamd-hal/async"] can = ["atsamd-hal/can"] rt = ["cortex-m-rt", "atsamd-hal/same54p-rt"] -usb = ["atsamd-hal/usb", "usb-device"] +usb = ["atsamd-hal/usb"] # Enable rtic support from atsamd-hal rtic = ["atsamd-hal/rtic"] diff --git a/boards/atsame54_xpro/src/devices.rs b/boards/atsame54_xpro/src/devices.rs index a5a3c760df0f..0ff6e18e6c07 100644 --- a/boards/atsame54_xpro/src/devices.rs +++ b/boards/atsame54_xpro/src/devices.rs @@ -12,9 +12,6 @@ use hal::sercom::{i2c, spi, uart}; use hal::time::Hertz; use uart::{BaudMode, Oversampling}; -#[cfg(feature = "usb")] -use hal::usb::{usb_device::bus::UsbBusAllocator, UsbBus}; - hal::bsp_peripherals!( Sercom0 { Ext1UartSercom } Sercom1 { Ext3UartSercom } @@ -356,21 +353,3 @@ pub fn dgi_i2c( .baud(baud) .enable() } - -/// Convenience for setting up the USB -#[cfg(feature = "usb")] -pub fn usb_allocator( - usb: pac::Usb, - clocks: &mut GenericClockController, - mclk: &mut pac::Mclk, - dm: impl Into, - dp: impl Into, -) -> UsbBusAllocator { - use pac::gclk::{genctrl::Srcselect, pchctrl::Genselect}; - - 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)) -} diff --git a/boards/feather_m4/Cargo.toml b/boards/feather_m4/Cargo.toml index cb9e61f21f5f..3634c19a3c10 100644 --- a/boards/feather_m4/Cargo.toml +++ b/boards/feather_m4/Cargo.toml @@ -28,10 +28,6 @@ default-features = false path = "../../hal" version = "0.22.2" -[dependencies.usb-device] -optional = true -version = "0.3.1" - [dev-dependencies] heapless = "0.7" panic-halt = "0.2" @@ -40,6 +36,7 @@ panic-semihosting = "0.5" rtic = {version = "2.1.1", features = ["thumbv7-backend"]} smart-leds = "0.3" usbd-serial = "0.2" +usb-device = "0.3.1" ws2812-timer-delay = "0.3" [features] @@ -49,7 +46,7 @@ dma = ["atsamd-hal/dma"] max-channels = ["dma", "atsamd-hal/dma"] rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"] rtic = ["atsamd-hal/rtic"] -usb = ["atsamd-hal/usb", "usb-device"] +usb = ["atsamd-hal/usb"] # Enable async support from atsamd-hal async = ["atsamd-hal/async"] use_semihosting = [] diff --git a/boards/feather_m4/examples/nvm_dsu.rs b/boards/feather_m4/examples/nvm_dsu.rs index e73f2f0d0913..8a16cf1a65c4 100644 --- a/boards/feather_m4/examples/nvm_dsu.rs +++ b/boards/feather_m4/examples/nvm_dsu.rs @@ -13,7 +13,11 @@ use panic_semihosting as _; use bsp::entry; use ehal::digital::StatefulOutputPin; -use hal::clock::GenericClockController; +use hal::clock::v2::{ + clock_system_at_reset, dfll, + gclk::{Gclk, Gclk1Id}, + pclk::Pclk, +}; use hal::dsu::Dsu; use hal::nvm::{retrieve_bank_size, Bank, Nvm, WriteGranularity, BLOCKSIZE}; use hal::pac::{interrupt, CorePeripherals, Peripherals}; @@ -32,11 +36,11 @@ use core::sync::atomic; fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_external_32kosc( + let (mut buses, clocks, tokens) = clock_system_at_reset( + peripherals.oscctrl, + peripherals.osc32kctrl, peripherals.gclk, - &mut peripherals.mclk, - &mut peripherals.osc32kctrl, - &mut peripherals.oscctrl, + peripherals.mclk, &mut peripherals.nvmctrl, ); let pins = bsp::Pins::new(peripherals.port); @@ -44,21 +48,32 @@ fn main() -> ! { let mut nvm = Nvm::new(peripherals.nvmctrl); let mut dsu = Dsu::new(peripherals.dsu, &peripherals.pac).unwrap(); + // Set up USB clocking + let (dfll_usb, _) = clocks.dfll.into_mode(dfll::FromUsb, |_| {}); + // GCLK1 comes from DFLL, outputs to USB + let (gclk_1, _) = Gclk::from_source(tokens.gclks.gclk1, dfll_usb); + let gclk_1_48mhz = gclk_1.enable(); + let (pclk_usb, _) = Pclk::enable(tokens.pclks.usb, gclk_1_48mhz); + + let usb_bus = UsbBus::new( + pclk_usb, + clocks.ahbs.usb, + buses.apb.enable(tokens.apbs.usb), + pins.usb_dm, + pins.usb_dp, + peripherals.usb, + ) + .unwrap(); + let bus_allocator = unsafe { - USB_ALLOCATOR = Some(bsp::usb_allocator( - pins.usb_dm, - pins.usb_dp, - peripherals.usb, - &mut clocks, - &mut peripherals.mclk, - )); + USB_ALLOCATOR = Some(UsbBusAllocator::new(usb_bus)); USB_ALLOCATOR.as_ref().unwrap() }; unsafe { USB_SERIAL = Some(SerialPort::new(bus_allocator)); USB_BUS = Some( - UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x16c0, 0x27dd)) + UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x1209, 0x0001)) .strings(&[StringDescriptors::new(LangID::EN) .manufacturer("Fake company") .product("Serial port") @@ -130,9 +145,9 @@ fn main() -> ! { } } -static mut USB_ALLOCATOR: Option> = None; -static mut USB_BUS: Option> = None; -static mut USB_SERIAL: Option> = None; +static mut USB_ALLOCATOR: Option>> = None; +static mut USB_BUS: Option>> = None; +static mut USB_SERIAL: Option>> = None; static USER_PRESENT: atomic::AtomicBool = atomic::AtomicBool::new(false); @@ -152,7 +167,7 @@ static USER_PRESENT: atomic::AtomicBool = atomic::AtomicBool::new(false); /// singleton `UsbSerial`, we will panic. fn usbserial_get(borrower: T) -> R where - T: Fn(&mut SerialPort) -> R, + T: Fn(&mut SerialPort>) -> R, { usb_free(|_| unsafe { let usb_serial = USB_SERIAL.as_mut().expect("UsbSerial not initialized"); diff --git a/boards/feather_m4/examples/pukcc_test.rs b/boards/feather_m4/examples/pukcc_test.rs index fc74d9ebc1f5..3293e8a6cff7 100644 --- a/boards/feather_m4/examples/pukcc_test.rs +++ b/boards/feather_m4/examples/pukcc_test.rs @@ -13,7 +13,11 @@ use panic_semihosting as _; use bsp::entry; use ehal::digital::StatefulOutputPin; -use hal::clock::GenericClockController; +use hal::clock::v2::{ + clock_system_at_reset, dfll, + gclk::{Gclk, Gclk1Id}, + pclk::Pclk, +}; use hal::pac::{interrupt, CorePeripherals, Peripherals}; use hal::{pukcc::*, usb::UsbBus}; @@ -28,31 +32,45 @@ use cortex_m::peripheral::NVIC; fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_external_32kosc( + + let pukcc = Pukcc::enable(&mut peripherals.mclk).unwrap(); + + let (mut buses, clocks, tokens) = clock_system_at_reset( + peripherals.oscctrl, + peripherals.osc32kctrl, peripherals.gclk, - &mut peripherals.mclk, - &mut peripherals.osc32kctrl, - &mut peripherals.oscctrl, + peripherals.mclk, &mut peripherals.nvmctrl, ); let pins = bsp::Pins::new(peripherals.port); let mut red_led = pins.d13.into_push_pull_output(); + // Set up USB clocking + let (dfll_usb, _) = clocks.dfll.into_mode(dfll::FromUsb, |_| {}); + // GCLK1 comes from DFLL, outputs to USB + let (gclk_1, _) = Gclk::from_source(tokens.gclks.gclk1, dfll_usb); + let gclk_1_48mhz = gclk_1.enable(); + let (pclk_usb, _) = Pclk::enable(tokens.pclks.usb, gclk_1_48mhz); + + let usb_bus = UsbBus::new( + pclk_usb, + clocks.ahbs.usb, + buses.apb.enable(tokens.apbs.usb), + pins.usb_dm, + pins.usb_dp, + peripherals.usb, + ) + .unwrap(); + let bus_allocator = unsafe { - USB_ALLOCATOR = Some(bsp::usb_allocator( - pins.usb_dm, - pins.usb_dp, - peripherals.usb, - &mut clocks, - &mut peripherals.mclk, - )); + USB_ALLOCATOR = Some(UsbBusAllocator::new(usb_bus)); USB_ALLOCATOR.as_ref().unwrap() }; unsafe { USB_SERIAL = Some(SerialPort::new(bus_allocator)); USB_BUS = Some( - UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x16c0, 0x27dd)) + UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x1209, 0x0001)) .strings(&[StringDescriptors::new(LangID::EN) .manufacturer("Fake company") .product("Serial port") @@ -72,8 +90,6 @@ fn main() -> ! { NVIC::unmask(interrupt::USB_TRCPT1); } - let pukcc = Pukcc::enable(&mut peripherals.mclk).unwrap(); - loop { serial_writeln!("ECDSA Test"); serial_writeln!("Column 1: Is generated signature identical to a reference signature?"); @@ -220,9 +236,9 @@ fn main() -> ! { } } -static mut USB_ALLOCATOR: Option> = None; -static mut USB_BUS: Option> = None; -static mut USB_SERIAL: Option> = None; +static mut USB_ALLOCATOR: Option>> = None; +static mut USB_BUS: Option>> = None; +static mut USB_SERIAL: Option>> = None; /// Borrows the global singleton `UsbSerial` for a brief period with interrupts /// disabled @@ -240,7 +256,7 @@ static mut USB_SERIAL: Option> = None; /// singleton `UsbSerial`, we will panic. fn usbserial_get(borrower: T) -> R where - T: Fn(&mut SerialPort) -> R, + T: Fn(&mut SerialPort>) -> R, { usb_free(|_| unsafe { let usb_serial = USB_SERIAL.as_mut().expect("UsbSerial not initialized"); diff --git a/boards/feather_m4/examples/smart_eeprom.rs b/boards/feather_m4/examples/smart_eeprom.rs index 9a487468aca1..a92878433023 100644 --- a/boards/feather_m4/examples/smart_eeprom.rs +++ b/boards/feather_m4/examples/smart_eeprom.rs @@ -13,7 +13,11 @@ use panic_semihosting as _; use bsp::entry; use ehal::digital::StatefulOutputPin; -use hal::clock::GenericClockController; +use hal::clock::v2::{ + clock_system_at_reset, dfll, + gclk::{Gclk, Gclk1Id}, + pclk::Pclk, +}; use hal::nvm::{smart_eeprom, Nvm}; use hal::pac::{interrupt, CorePeripherals, Peripherals}; use hal::usb::UsbBus; @@ -31,32 +35,43 @@ use core::sync::atomic; fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_external_32kosc( + let (mut buses, clocks, tokens) = clock_system_at_reset( + peripherals.oscctrl, + peripherals.osc32kctrl, peripherals.gclk, - &mut peripherals.mclk, - &mut peripherals.osc32kctrl, - &mut peripherals.oscctrl, + peripherals.mclk, &mut peripherals.nvmctrl, ); let pins = bsp::Pins::new(peripherals.port); let mut red_led = pins.d13.into_push_pull_output(); let mut nvm = Nvm::new(peripherals.nvmctrl); + // Set up USB clocking + let (dfll_usb, _) = clocks.dfll.into_mode(dfll::FromUsb, |_| {}); + // GCLK1 comes from DFLL, outputs to USB + let (gclk_1, _) = Gclk::from_source(tokens.gclks.gclk1, dfll_usb); + let gclk_1_48mhz = gclk_1.enable(); + let (pclk_usb, _) = Pclk::enable(tokens.pclks.usb, gclk_1_48mhz); + + let usb_bus = UsbBus::new( + pclk_usb, + clocks.ahbs.usb, + buses.apb.enable(tokens.apbs.usb), + pins.usb_dm, + pins.usb_dp, + peripherals.usb, + ) + .unwrap(); + let bus_allocator = unsafe { - USB_ALLOCATOR = Some(bsp::usb_allocator( - pins.usb_dm, - pins.usb_dp, - peripherals.usb, - &mut clocks, - &mut peripherals.mclk, - )); + USB_ALLOCATOR = Some(UsbBusAllocator::new(usb_bus)); USB_ALLOCATOR.as_ref().unwrap() }; unsafe { USB_SERIAL = Some(SerialPort::new(bus_allocator)); USB_BUS = Some( - UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x16c0, 0x27dd)) + UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x1209, 0x0001)) .strings(&[StringDescriptors::new(LangID::EN) .manufacturer("Fake company") .product("Serial port") @@ -113,9 +128,9 @@ fn main() -> ! { } } -static mut USB_ALLOCATOR: Option> = None; -static mut USB_BUS: Option> = None; -static mut USB_SERIAL: Option> = None; +static mut USB_ALLOCATOR: Option>> = None; +static mut USB_BUS: Option>> = None; +static mut USB_SERIAL: Option>> = None; static USER_PRESENT: atomic::AtomicBool = atomic::AtomicBool::new(false); @@ -135,7 +150,7 @@ static USER_PRESENT: atomic::AtomicBool = atomic::AtomicBool::new(false); /// singleton `UsbSerial`, we will panic. fn usbserial_get(borrower: T) -> R where - T: Fn(&mut SerialPort) -> R, + T: Fn(&mut SerialPort>) -> R, { usb_free(|_| unsafe { let usb_serial = USB_SERIAL.as_mut().expect("UsbSerial not initialized"); diff --git a/boards/feather_m4/examples/usb_echo.rs b/boards/feather_m4/examples/usb_echo.rs index acce79335e41..721fba7b3d66 100644 --- a/boards/feather_m4/examples/usb_echo.rs +++ b/boards/feather_m4/examples/usb_echo.rs @@ -10,7 +10,12 @@ use panic_halt as _; use panic_semihosting as _; use bsp::entry; -use hal::clock::GenericClockController; +use bsp::pin_alias; +use hal::clock::v2::{ + clock_system_at_reset, dfll, + gclk::{Gclk, Gclk1Id}, + pclk::Pclk, +}; use hal::pac::{interrupt, CorePeripherals, Peripherals}; use hal::prelude::*; use hal::usb::UsbBus; @@ -26,31 +31,42 @@ use cortex_m::peripheral::NVIC; fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_external_32kosc( + let (mut buses, clocks, tokens) = clock_system_at_reset( + peripherals.oscctrl, + peripherals.osc32kctrl, peripherals.gclk, - &mut peripherals.mclk, - &mut peripherals.osc32kctrl, - &mut peripherals.oscctrl, + peripherals.mclk, &mut peripherals.nvmctrl, ); let pins = bsp::Pins::new(peripherals.port); - let mut red_led: bsp::RedLed = pins.d13.into(); + let mut red_led: bsp::RedLed = pin_alias!(pins.red_led).into(); + + // Set up USB clocking + let (dfll_usb, _) = clocks.dfll.into_mode(dfll::FromUsb, |_| {}); + // GCLK1 comes from DFLL, outputs to USB + let (gclk_1, _) = Gclk::from_source(tokens.gclks.gclk1, dfll_usb); + let gclk_1_48mhz = gclk_1.enable(); + let (pclk_usb, _) = Pclk::enable(tokens.pclks.usb, gclk_1_48mhz); + + let usb_bus = UsbBus::new( + pclk_usb, + clocks.ahbs.usb, + buses.apb.enable(tokens.apbs.usb), + pins.usb_dm, + pins.usb_dp, + peripherals.usb, + ) + .unwrap(); let bus_allocator = unsafe { - USB_ALLOCATOR = Some(bsp::usb_allocator( - pins.usb_dm, - pins.usb_dp, - peripherals.usb, - &mut clocks, - &mut peripherals.mclk, - )); + USB_ALLOCATOR = Some(UsbBusAllocator::new(usb_bus)); USB_ALLOCATOR.as_ref().unwrap() }; unsafe { USB_SERIAL = Some(SerialPort::new(bus_allocator)); USB_BUS = Some( - UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x16c0, 0x27dd)) + UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x1209, 0x0001)) .strings(&[StringDescriptors::new(LangID::EN) .manufacturer("Fake company") .product("Serial port") @@ -78,9 +94,9 @@ fn main() -> ! { } } -static mut USB_ALLOCATOR: Option> = None; -static mut USB_BUS: Option> = None; -static mut USB_SERIAL: Option> = None; +static mut USB_ALLOCATOR: Option>> = None; +static mut USB_BUS: Option>> = None; +static mut USB_SERIAL: Option>> = None; fn poll_usb() { unsafe { diff --git a/boards/feather_m4/src/lib.rs b/boards/feather_m4/src/lib.rs index 0aec0a57b4a4..50db5cf1ef96 100644 --- a/boards/feather_m4/src/lib.rs +++ b/boards/feather_m4/src/lib.rs @@ -18,11 +18,6 @@ use hal::sercom::{ }; use hal::time::Hertz; -#[cfg(feature = "usb")] -use hal::usb::usb_device::bus::UsbBusAllocator; -#[cfg(feature = "usb")] -pub use hal::usb::UsbBus; - hal::bsp_peripherals!( Sercom1 { SpiSercom } Sercom2 { I2cSercom } @@ -256,21 +251,3 @@ pub fn uart( .baud(baud, BaudMode::Fractional(Oversampling::Bits16)) .enable() } - -#[cfg(feature = "usb")] -/// Convenience function for setting up USB -pub fn usb_allocator( - dm: impl Into, - dp: impl Into, - usb: pac::Usb, - clocks: &mut GenericClockController, - mclk: &mut pac::Mclk, -) -> UsbBusAllocator { - use pac::gclk::{genctrl::Srcselect, pchctrl::Genselect}; - - 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)) -} diff --git a/boards/metro_m4/Cargo.toml b/boards/metro_m4/Cargo.toml index 79df242185dc..14bd377822dd 100644 --- a/boards/metro_m4/Cargo.toml +++ b/boards/metro_m4/Cargo.toml @@ -23,10 +23,6 @@ default-features = false path = "../../hal" version = "0.22.2" -[dependencies.usb-device] -optional = true -version = "0.3.1" - [dependencies.cortex-m] features = ["critical-section-single-core"] version = "0.7" @@ -48,6 +44,7 @@ rtic-monotonics = {version = "2.0.1", features = ["cortex-m-systick"]} rtt-target = {version = "0.3.0", features = ["cortex-m"]} smart-leds = "0.3" usbd-serial = "0.2" +usb-device = "0.3.1" [dev-dependencies.ws2812-timer-delay] version = "0.3" @@ -61,7 +58,7 @@ dma = ["atsamd-hal/dma"] max-channels = ["dma", "atsamd-hal/max-channels"] rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"] rtic = ["atsamd-hal/rtic"] -usb = ["atsamd-hal/usb", "usb-device"] +usb = ["atsamd-hal/usb"] use_semihosting = [] [[example]] diff --git a/boards/metro_m4/examples/usb_logging.rs b/boards/metro_m4/examples/usb_logging.rs index 7cc2268bff08..4126e69b7c69 100644 --- a/boards/metro_m4/examples/usb_logging.rs +++ b/boards/metro_m4/examples/usb_logging.rs @@ -4,8 +4,10 @@ use metro_m4 as bsp; use bsp::ehal; +use bsp::entry; use bsp::hal; use bsp::pac; +use bsp::pin_alias; use cortex_m::asm::delay as cycle_delay; use cortex_m::peripheral::NVIC; @@ -14,8 +16,11 @@ use usb_device::bus::UsbBusAllocator; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; -use bsp::entry; -use hal::clock::GenericClockController; +use hal::clock::v2::{ + clock_system_at_reset, dfll, + gclk::{Gclk, Gclk1Id}, + pclk::Pclk, +}; use hal::usb::UsbBus; use pac::{interrupt, CorePeripherals, Peripherals}; @@ -28,32 +33,43 @@ use panic_semihosting as _; fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_external_32kosc( + let (mut buses, clocks, tokens) = clock_system_at_reset( + peripherals.oscctrl, + peripherals.osc32kctrl, peripherals.gclk, - &mut peripherals.mclk, - &mut peripherals.osc32kctrl, - &mut peripherals.oscctrl, + peripherals.mclk, &mut peripherals.nvmctrl, ); let pins = bsp::Pins::new(peripherals.port); - let mut red_led: bsp::RedLed = pins.d13.into(); + let mut red_led: bsp::RedLed = pin_alias!(pins.red_led).into(); + + // Set up USB clocking + let (dfll_usb, _) = clocks.dfll.into_mode(dfll::FromUsb, |_| {}); + // GCLK1 comes from DFLL, outputs to USB + let (gclk_1, _) = Gclk::from_source(tokens.gclks.gclk1, dfll_usb); + let gclk_1_48mhz = gclk_1.enable(); + let (pclk_usb, _) = Pclk::enable(tokens.pclks.usb, gclk_1_48mhz); + + let usb_bus = UsbBus::new( + pclk_usb, + clocks.ahbs.usb, + buses.apb.enable(tokens.apbs.usb), + pins.usb_dm, + pins.usb_dp, + peripherals.usb, + ) + .unwrap(); let bus_allocator = unsafe { - USB_ALLOCATOR = Some(bsp::usb_allocator( - peripherals.usb, - &mut clocks, - &mut peripherals.mclk, - pins.usb_dm, - pins.usb_dp, - )); + USB_ALLOCATOR = Some(UsbBusAllocator::new(usb_bus)); USB_ALLOCATOR.as_ref().unwrap() }; unsafe { USB_SERIAL = Some(SerialPort::new(bus_allocator)); USB_BUS = Some( - UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x2222, 0x3333)) + UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x1209, 0x0001)) .strings(&[StringDescriptors::new(LangID::EN) .manufacturer("Fake company") .product("Serial port") @@ -69,8 +85,6 @@ fn main() -> ! { NVIC::unmask(interrupt::USB_TRCPT0); core.NVIC.set_priority(interrupt::USB_TRCPT1, 1); NVIC::unmask(interrupt::USB_TRCPT1); - core.NVIC.set_priority(interrupt::USB_SOF_HSOF, 1); - NVIC::unmask(interrupt::USB_SOF_HSOF); core.NVIC.set_priority(interrupt::USB_OTHER, 1); NVIC::unmask(interrupt::USB_OTHER); } @@ -91,9 +105,9 @@ fn main() -> ! { } } -static mut USB_ALLOCATOR: Option> = None; -static mut USB_BUS: Option> = None; -static mut USB_SERIAL: Option> = None; +static mut USB_ALLOCATOR: Option>> = None; +static mut USB_BUS: Option>> = None; +static mut USB_SERIAL: Option>> = None; fn poll_usb() { unsafe { @@ -119,11 +133,6 @@ fn USB_TRCPT1() { poll_usb(); } -#[interrupt] -fn USB_SOF_HSOF() { - poll_usb(); -} - #[interrupt] fn USB_OTHER() { poll_usb(); diff --git a/boards/metro_m4/src/lib.rs b/boards/metro_m4/src/lib.rs index 7e972ef621ab..b24d60f3919e 100644 --- a/boards/metro_m4/src/lib.rs +++ b/boards/metro_m4/src/lib.rs @@ -24,9 +24,6 @@ use hal::{ use pac::Mclk; -#[cfg(feature = "usb")] -use hal::usb::{usb_device::bus::UsbBusAllocator, UsbBus}; - hal::bsp_peripherals!( Sercom2 { SpiSercom } Sercom3 { UartSercom } @@ -349,21 +346,3 @@ pub fn uart( .baud(baud, BaudMode::Fractional(Oversampling::Bits16)) .enable() } - -#[cfg(feature = "usb")] -/// Convenience function for setting up USB -pub fn usb_allocator( - usb: pac::Usb, - clocks: &mut GenericClockController, - mclk: &mut pac::Mclk, - dm: impl Into, - dp: impl Into, -) -> UsbBusAllocator { - use pac::gclk::{genctrl::Srcselect, pchctrl::Genselect}; - - 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)) -} diff --git a/boards/pygamer/Cargo.toml b/boards/pygamer/Cargo.toml index 4044a6d164ac..e1937206ba02 100644 --- a/boards/pygamer/Cargo.toml +++ b/boards/pygamer/Cargo.toml @@ -29,10 +29,6 @@ default-features = false path = "../../hal" version = "0.22.2" -[dependencies.usb-device] -optional = true -version = "0.3.2" - [dependencies.ws2812-spi] features = ["mosi_idle_high"] optional = true @@ -48,6 +44,7 @@ rtic = {version = "2.1.2", features = ["thumbv7-backend"]} smart-leds = "0.4" tinybmp = "0.6" usbd-serial = "0.2" +usb-device = "0.3.2" [features] # ask the HAL to enable atsamd51j support @@ -57,7 +54,7 @@ max-channels = ["dma", "atsamd-hal/max-channels"] neopixel-spi = ["dep:ws2812-spi"] panic_led = [] rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"] -usb = ["atsamd-hal/usb", "usb-device"] +usb = ["atsamd-hal/usb"] # Enable async support from atsamd-hal async = ["atsamd-hal/async"] # Enable rtic support from atsamd-hal diff --git a/boards/pygamer/examples/usb_poll.rs b/boards/pygamer/examples/usb_poll.rs index 4e252c8639b7..08d2e11b8d91 100644 --- a/boards/pygamer/examples/usb_poll.rs +++ b/boards/pygamer/examples/usb_poll.rs @@ -9,9 +9,11 @@ use bsp::{entry, hal, pac, Pins, RedLed}; use panic_halt as _; use pygamer as bsp; -use hal::clock::GenericClockController; +use hal::clock::v2::{clock_system_at_reset, dfll, gclk::Gclk, pclk::Pclk}; use hal::prelude::*; +use hal::usb::UsbBus; use pac::{CorePeripherals, Peripherals}; +use usb_device::bus::UsbBusAllocator; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; @@ -19,24 +21,39 @@ use usbd_serial::{SerialPort, USB_CLASS_CDC}; fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); let mut _core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_internal_32kosc( + let (mut buses, clocks, tokens) = clock_system_at_reset( + peripherals.oscctrl, + peripherals.osc32kctrl, peripherals.gclk, - &mut peripherals.mclk, - &mut peripherals.osc32kctrl, - &mut peripherals.oscctrl, + peripherals.mclk, &mut peripherals.nvmctrl, ); let pins = Pins::new(peripherals.port).split(); - let usb_bus = pins - .usb - .init(peripherals.usb, &mut clocks, &mut peripherals.mclk); + // Set up USB clocking + let (dfll_usb, _) = clocks.dfll.into_mode(dfll::FromUsb, |_| {}); + // GCLK1 comes from DFLL, outputs to USB + let (gclk_1, _) = Gclk::from_source(tokens.gclks.gclk1, dfll_usb); + let gclk_1_48mhz = gclk_1.enable(); + let (pclk_usb, _) = Pclk::enable(tokens.pclks.usb, gclk_1_48mhz); - let mut serial = SerialPort::new(&usb_bus); + let usb_bus = UsbBus::new( + pclk_usb, + clocks.ahbs.usb, + buses.apb.enable(tokens.apbs.usb), + pins.usb.dm, + pins.usb.dp, + peripherals.usb, + ) + .unwrap(); + + let bus_allocator = UsbBusAllocator::new(usb_bus); + + let mut serial = SerialPort::new(&bus_allocator); let mut led: RedLed = pins.led_pin.into(); - let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + let mut usb_dev = UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x1209, 0x0001)) .strings(&[StringDescriptors::new(LangID::EN) .manufacturer("Fake company") .product("Serial port") diff --git a/boards/pygamer/src/pins.rs b/boards/pygamer/src/pins.rs index 2f1f5de4c63c..b2e3b57a9a85 100644 --- a/boards/pygamer/src/pins.rs +++ b/boards/pygamer/src/pins.rs @@ -16,13 +16,6 @@ use hal::typelevel::NoneT; use st7735_lcd::{Orientation, ST7735}; -#[cfg(feature = "usb")] -use hal::usb::usb_device::bus::UsbBusAllocator; -#[cfg(feature = "usb")] -pub use hal::usb::UsbBus; -#[cfg(feature = "usb")] -use pac::gclk::{genctrl::Srcselect, pchctrl::Genselect}; - hal::bsp_peripherals!( Sercom2 { I2cSercom } Sercom5 { UartSercom } @@ -798,24 +791,6 @@ pub struct USB { pub dp: UsbDpReset, } -impl USB { - #[cfg(feature = "usb")] - /// Convenience for setting up the onboard usb port to operate - /// as a USB device. - pub fn init( - self, - usb: pac::Usb, - clocks: &mut GenericClockController, - mclk: &mut pac::Mclk, - ) -> UsbBusAllocator { - 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): (UsbDm, UsbDp) = (self.dm.into(), self.dp.into()); - UsbBusAllocator::new(UsbBus::new(usb_clock, mclk, dm, dp, usb)) - } -} - /// UART pins pub struct UART { pub tx: UartTxReset, diff --git a/hal/src/peripherals/clock/d5x/v2/gclk.rs b/hal/src/peripherals/clock/d5x/v2/gclk.rs index 18a28eddf99e..3e65c49d0578 100644 --- a/hal/src/peripherals/clock/d5x/v2/gclk.rs +++ b/hal/src/peripherals/clock/d5x/v2/gclk.rs @@ -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) diff --git a/hal/src/peripherals/usb/d5x/bus.rs b/hal/src/peripherals/usb/d5x/bus.rs index 1441ff780dc2..568b1e6df820 100644 --- a/hal/src/peripherals/usb/d5x/bus.rs +++ b/hal/src/peripherals/usb/d5x/bus.rs @@ -7,17 +7,23 @@ 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 fugit::HertzU32; use usb_device::bus::PollResult; use usb_device::endpoint::{EndpointAddress, EndpointType}; use usb_device::{Result as UsbResult, UsbDirection, UsbError}; @@ -191,16 +197,20 @@ impl BufferAllocator { } } -struct Inner { +struct Inner { desc: RefCell, _dm_pad: Pin, _dp_pad: Pin, endpoints: RefCell, buffers: RefCell, + pclk: Pclk, + ahb_clk: AhbClk, + apb_clk: ApbClk, + _usb: Usb, } -pub struct UsbBus { - inner: Mutex>, +pub struct UsbBus { + inner: Mutex>>, } struct Bank<'a, T> { @@ -469,7 +479,7 @@ impl Bank<'_, T> { } } -impl Inner { +impl Inner { #[inline] fn epcfg(&self, endpoint: usize) -> &pac::usb::device::device_endpoint::Epcfg { self.usb().device_endpoint(endpoint).epcfg() @@ -524,17 +534,59 @@ impl Inner { } } -impl UsbBus { +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum UsbBusErr { + /// USB clock freq is not valid for a stable connection + InvalidClockFreq, +} + +/// The individual resources returned when consuming a `UsbBus`. +pub type UsbBusParts = ( + Pclk, + AhbClk, + ApbClk, + Pin, + Pin, + Usb, +); + +impl UsbBus { + /// Create a new USB Bus, checking the clock frequency of the USB clock for + /// a stable USB link to most hosts. The `clock` freq must be 48Mhz, + /// otherwise [`UsbBusErr::InvalidClockFreq`] will be returned pub fn new( - _clock: &clock::UsbClock, - mclk: &mut Mclk, + pclk: Pclk, + ahb_clk: AhbClk, + apb_clk: ApbClk, dm_pad: impl AnyPin, dp_pad: impl AnyPin, _usb: Usb, - ) -> Self { - mclk.ahbmask().modify(|_, w| w.usb_().set_bit()); - mclk.apbbmask().modify(|_, w| w.usb_().set_bit()); + ) -> Result { + if pclk.freq() != HertzU32::MHz(48) { + Err(UsbBusErr::InvalidClockFreq) + } else { + Ok(unsafe { Self::new_unchecked(pclk, ahb_clk, apb_clk, dm_pad, dp_pad, _usb) }) + } + } + /// Creates a new USB Bus, but does NOT perform the USB clock frequency + /// check. + /// + /// SAFETY: For a SAMx to PC connection, the USB clock must be 48Mhz for + /// stability. This function allows you to bypass this check however if you + /// intend to connect multiple SAM chips together with faster running USB + /// clocks for a boost in transfer rate. + /// + /// Consult the datasheet for GCLK_USB absolute maximums + pub unsafe fn new_unchecked( + pclk: Pclk, + ahb_clk: AhbClk, + apb_clk: ApbClk, + dm_pad: impl AnyPin, + dp_pad: impl AnyPin, + _usb: Usb, + ) -> Self { let desc = RefCell::new(Descriptors::new()); let inner = Inner { @@ -543,15 +595,32 @@ impl UsbBus { desc, buffers: RefCell::new(BufferAllocator::new()), endpoints: RefCell::new(AllEndpoints::new()), + pclk, + ahb_clk, + apb_clk, + _usb, }; Self { inner: Mutex::new(RefCell::new(inner)), } } + + pub fn into_inner(self) -> UsbBusParts { + // 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, + inner._usb, + ) + } } -impl Inner { +impl Inner { fn usb(&self) -> &Device { unsafe { (*Usb::ptr()).device() } } @@ -576,7 +645,7 @@ enum FlushConfigMode { ProtocolReset, } -impl Inner { +impl Inner { fn enable(&mut self) { let usb = self.usb(); usb.ctrla().modify(|_, w| w.swrst().set_bit()); @@ -884,7 +953,7 @@ impl Inner { } } -impl UsbBus { +impl UsbBus { /// 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)) @@ -901,7 +970,7 @@ impl UsbBus { } } -impl usb_device::bus::UsbBus for UsbBus { +impl usb_device::bus::UsbBus for UsbBus { fn enable(&mut self) { disable_interrupts(|cs| self.inner.borrow(cs).borrow_mut().enable()) } diff --git a/hal/src/peripherals/usb/d5x/mod.rs b/hal/src/peripherals/usb/d5x/mod.rs index 10d22657214e..db402cc59ca5 100644 --- a/hal/src/peripherals/usb/d5x/mod.rs +++ b/hal/src/peripherals/usb/d5x/mod.rs @@ -1,8 +1,8 @@ //! USB Device support use crate::gpio::{ - pin::{Pin, PA23, PA24, PA25}, AlternateH, + pin::{PA23, PA24, PA25, Pin}, }; pub use usb_device;