diff --git a/boards/arduino_mkr1000/Cargo.toml b/boards/arduino_mkr1000/Cargo.toml index eabc3333b33c..471d29abdff8 100644 --- a/boards/arduino_mkr1000/Cargo.toml +++ b/boards/arduino_mkr1000/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "arduino_mkr1000" -version = "0.5.1" -authors = ["Eric Rushing "] +version = "0.6.0" +authors = [ + "Eric Rushing ", + "Joël Bourgault ", +] description = "Board Support crate for the Arduino MKR 1000 WiFi" keywords = ["no-std", "arm", "cortex-m", "embedded-hal"] categories = ["embedded", "hardware-support", "no-std"] @@ -15,7 +18,7 @@ version = "0.7" optional = true [dependencies.atsamd-hal] -version = "0.14" +version = "0.16" default-features = false [dependencies.usb-device] @@ -23,17 +26,41 @@ version = "0.2" optional = true [dev-dependencies] +cortex-m = "0.7" +usbd-serial = "0.1" panic-halt = "0.2" panic-semihosting = "0.5" +cortex-m-rtic = "1.0" [features] # ask the HAL to enable atsamd21g support -default = ["rt", "atsamd-hal/samd21g"] +default = ["rt", "atsamd-hal/samd21g", "usb"] rt = ["cortex-m-rt", "atsamd-hal/samd21g-rt"] usb = ["atsamd-hal/usb", "usb-device"] unproven = ["atsamd-hal/unproven"] use_semihosting = [] +rtic = ["atsamd-hal/rtic"] # for cargo flash [package.metadata] chip = "ATSAMD21G18A" + +[dependencies] +embedded-hal = "0.2.7" + +[[example]] +name = "blinky_basic" + +[[example]] +name = "blinky_rtic" +required-features = ["rtic", "unproven"] +# This example also requires `cortex-m-rtic`. +# Don't import `rtic`; see `blinky_rtic` comments in code for explanation. + +[[example]] +name = "usb_logging" +required-features = ["usb"] + +[[example]] +name = "pwm" +required-features = ["unproven"] diff --git a/boards/arduino_mkr1000/examples/blinky_basic.rs b/boards/arduino_mkr1000/examples/blinky_basic.rs index 66c8789a2313..fe2700c5e7f3 100644 --- a/boards/arduino_mkr1000/examples/blinky_basic.rs +++ b/boards/arduino_mkr1000/examples/blinky_basic.rs @@ -1,15 +1,15 @@ #![no_std] #![no_main] -use arduino_mkr1000 as bsp; -use bsp::hal; - #[cfg(not(feature = "use_semihosting"))] use panic_halt as _; #[cfg(feature = "use_semihosting")] use panic_semihosting as _; -use bsp::entry; +use arduino_mkr1000 as bsp; +use bsp::hal; + +use bsp::{entry, pin_alias}; use hal::clock::GenericClockController; use hal::delay::Delay; use hal::pac::{CorePeripherals, Peripherals}; @@ -25,9 +25,10 @@ fn main() -> ! { &mut peripherals.SYSCTRL, &mut peripherals.NVMCTRL, ); - let mut pins = bsp::Pins::new(peripherals.PORT); - let mut led = pins.d6.into_open_drain_output(&mut pins.port); + let pins = bsp::pins::Pins::new(peripherals.PORT); + let mut led = pin_alias!(pins.led).into_push_pull_output(); let mut delay = Delay::new(core.SYST, &mut clocks); + loop { delay.delay_ms(200u8); led.set_high().unwrap(); diff --git a/boards/arduino_mkr1000/examples/blinky_rtic.rs b/boards/arduino_mkr1000/examples/blinky_rtic.rs new file mode 100644 index 000000000000..1fae6f8e3710 --- /dev/null +++ b/boards/arduino_mkr1000/examples/blinky_rtic.rs @@ -0,0 +1,92 @@ +//! Uses RTIC with the RTC as time source to blink an LED. +//! +//! The idle task is sleeping the CPU, so in practice this gives similar power +//! figure as the "sleeping_timer_rtc" example. +//! +//! Note on imports: this example requires `cortex-m-rtic`, whih brings the +//! `rtic` package, but also brings/selects the appropriate RTIC backend. +//! +//! If `rtic` package is imported instead of `cortex-m-rtic`, following message +//! is displayed at compilation, containing `No backend feature selected.`: +//! +//! ```sh +//! $ cargo build +//! (...) +//! error: failed to run custom build command for `rtic v2.2.0` +//! Caused by: +//! process didn't exit successfully: `/home/.../dev/électronique/my-great-prj/target/debug/build/rtic-4840d1be515a89f0/build-script-build` (exit status: 101) +//! --- stderr +//! thread 'main' panicked at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rtic-2.2.0/build.rs:18:34: +//! No backend feature selected. +//! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +//! ``` + +#![no_std] +#![no_main] + +use arduino_mkr1000 as bsp; + +#[cfg(not(feature = "use_semihosting"))] +use panic_halt as _; +#[cfg(feature = "use_semihosting")] +use panic_semihosting as _; +use rtic::app; + +#[app(device = bsp::pac, peripherals = true, dispatchers = [EVSYS])] +mod app { + use super::*; + use bsp::hal; + use hal::clock::{ClockGenId, ClockSource, GenericClockController}; + use hal::pac::Peripherals; + use hal::prelude::*; + use hal::rtc::{Count32Mode, Duration, Rtc}; + + #[local] + struct Local {} + + #[shared] + struct Shared { + // The LED could be a local resource, since it is only used in one task + // But we want to showcase shared resources and locking + led: bsp::pins::Led, + } + + #[monotonic(binds = RTC, default = true)] + type RtcMonotonic = Rtc; + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let mut peripherals: Peripherals = cx.device; + let pins = bsp::pins::Pins::new(peripherals.PORT); + let mut core: rtic::export::Peripherals = cx.core; + let mut clocks = GenericClockController::with_external_32kosc( + peripherals.GCLK, + &mut peripherals.PM, + &mut peripherals.SYSCTRL, + &mut peripherals.NVMCTRL, + ); + let _gclk = clocks.gclk0(); + let rtc_clock_src = clocks + .configure_gclk_divider_and_source(ClockGenId::GCLK2, 1, ClockSource::XOSC32K, false) + .unwrap(); + clocks.configure_standby(ClockGenId::GCLK2, true); + let rtc_clock = clocks.rtc(&rtc_clock_src).unwrap(); + let rtc = Rtc::count32_mode(peripherals.RTC, rtc_clock.freq(), &mut peripherals.PM); + let led = bsp::pin_alias!(pins.led).into(); + + // We can use the RTC in standby for maximum power savings + core.SCB.set_sleepdeep(); + + // Start the blink task + blink::spawn().unwrap(); + + (Shared { led }, Local {}, init::Monotonics(rtc)) + } + + #[task(shared = [led])] + fn blink(mut cx: blink::Context) { + // If the LED were a local resource, the lock would not be necessary + let _ = cx.shared.led.lock(|led| led.toggle()); + blink::spawn_after(Duration::millis(750)).ok(); + } +} diff --git a/boards/arduino_mkr1000/examples/pwm.rs b/boards/arduino_mkr1000/examples/pwm.rs new file mode 100644 index 000000000000..507af15e8c0d --- /dev/null +++ b/boards/arduino_mkr1000/examples/pwm.rs @@ -0,0 +1,52 @@ +#![no_std] +#![no_main] + +use arduino_mkr1000 as bsp; +use bsp::hal; + +#[cfg(not(feature = "use_semihosting"))] +use panic_halt as _; +#[cfg(feature = "use_semihosting")] +use panic_semihosting as _; + +use bsp::entry; +use hal::clock::GenericClockController; +use hal::delay::Delay; +use hal::pac::{CorePeripherals, Peripherals}; +use hal::prelude::*; +use hal::pwm::{Channel, Pwm0}; + +#[entry] +fn main() -> ! { + let mut peripherals = Peripherals::take().unwrap(); + let core = CorePeripherals::take().unwrap(); + let mut clocks = GenericClockController::with_external_32kosc( + peripherals.GCLK, + &mut peripherals.PM, + &mut peripherals.SYSCTRL, + &mut peripherals.NVMCTRL, + ); + let mut delay = Delay::new(core.SYST, &mut clocks); + let pins = bsp::pins::Pins::new(peripherals.PORT); + let gclk0 = clocks.gclk0(); + + // configure target pin + let _pin: bsp::pins::D6PwmF = pins.led.into(); + + let mut pwm0 = Pwm0::new( + &clocks.tcc0_tcc1(&gclk0).unwrap(), + 1u32.kHz(), + peripherals.TCC0, + &mut peripherals.PM, + ); + let channel = Channel::_2; + pwm0.enable(channel); + + let max_duty = pwm0.get_max_duty(); + loop { + pwm0.set_duty(channel, max_duty); + delay.delay_ms(500u16); + pwm0.set_duty(channel, max_duty / 4); + delay.delay_ms(500u16); + } +} diff --git a/boards/arduino_mkr1000/examples/usb_logging.rs b/boards/arduino_mkr1000/examples/usb_logging.rs new file mode 100644 index 000000000000..8f4d5b2ff5d2 --- /dev/null +++ b/boards/arduino_mkr1000/examples/usb_logging.rs @@ -0,0 +1,105 @@ +#![no_std] +#![no_main] + +use arduino_mkr1000 as bsp; +use bsp::hal; + +#[cfg(not(feature = "use_semihosting"))] +use panic_halt as _; +#[cfg(feature = "use_semihosting")] +use panic_semihosting as _; + +use bsp::entry; +use hal::clock::GenericClockController; +use hal::delay::Delay; +use hal::pac::{interrupt, CorePeripherals, Peripherals}; +use hal::prelude::*; + +use hal::usb::UsbBus; +use usb_device::bus::UsbBusAllocator; +use usb_device::prelude::*; +use usbd_serial::{SerialPort, USB_CLASS_CDC}; + +use cortex_m::peripheral::NVIC; + +static mut USB_ALLOCATOR: Option> = None; +static mut USB_BUS: Option> = None; +static mut USB_SERIAL: Option> = None; + +#[entry] +fn main() -> ! { + let mut peripherals = Peripherals::take().unwrap(); + let mut core = CorePeripherals::take().unwrap(); + let mut clocks = GenericClockController::with_external_32kosc( + peripherals.GCLK, + &mut peripherals.PM, + &mut peripherals.SYSCTRL, + &mut peripherals.NVMCTRL, + ); + let pins = bsp::pins::Pins::new(peripherals.PORT); + let mut led = bsp::pin_alias!(pins.led).into_push_pull_output(); + let mut delay = Delay::new(core.SYST, &mut clocks); + + let usb_n = bsp::pin_alias!(pins.usb_n); + let usb_p = bsp::pin_alias!(pins.usb_p); + + let bus_allocator = unsafe { + USB_ALLOCATOR = Some(bsp::usb::usb_allocator( + peripherals.USB, + &mut clocks, + &mut peripherals.PM, + usb_n.into(), + usb_p.into(), + )); + USB_ALLOCATOR.as_ref().unwrap() + }; + + unsafe { + USB_SERIAL = Some(SerialPort::new(bus_allocator)); + USB_BUS = Some( + UsbDeviceBuilder::new(bus_allocator, UsbVidPid(0x2222, 0x3333)) + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST") + .device_class(USB_CLASS_CDC) + .build(), + ); + } + + unsafe { + core.NVIC.set_priority(interrupt::USB, 1); + NVIC::unmask(interrupt::USB); + } + + loop { + delay.delay_ms(200u8); + led.set_high().unwrap(); + delay.delay_ms(200u8); + led.set_low().unwrap(); + + // Turn off interrupts so we don't fight with the interrupt + cortex_m::interrupt::free(|_| unsafe { + if let Some(serial) = USB_SERIAL.as_mut() { + let _ = serial.write("log line\r\n".as_bytes()); + } + }); + } +} + +fn poll_usb() { + unsafe { + if let Some(usb_dev) = USB_BUS.as_mut() { + if let Some(serial) = USB_SERIAL.as_mut() { + usb_dev.poll(&mut [serial]); + // Make the other side happy + let mut buf = [0u8; 16]; + let _ = serial.read(&mut buf); + } + } + }; +} + +#[interrupt] +fn USB() { + poll_usb(); +} diff --git a/boards/arduino_mkr1000/src/lib.rs b/boards/arduino_mkr1000/src/lib.rs index e35ae163945c..20c457cfac68 100644 --- a/boards/arduino_mkr1000/src/lib.rs +++ b/boards/arduino_mkr1000/src/lib.rs @@ -1,126 +1,15 @@ #![no_std] pub use atsamd_hal as hal; -pub use hal::common::*; -pub use hal::pac; #[cfg(feature = "rt")] -use cortex_m_rt; +extern crate cortex_m_rt; #[cfg(feature = "rt")] pub use cortex_m_rt::entry; -use hal::prelude::*; -use hal::*; - -use hal::clock::GenericClockController; -use hal::time::Hertz; - -use hal::sercom::{PadPin, UART5}; - -use gpio::{Floating, Input, PfD, Port}; - -define_pins!( - /// Maps the pins to their arduino names and - /// the numbers printed on the board. - struct Pins, - pac: pac, - - /// RX - pin rx = b23, - - /// TX - pin tx = b22, - - /// Digital 0 - pin d0 = a22, - - /// Digital 1 - pin d1 = a23, - - /// Digital 2: ADC - pin d2 = a10, - - /// Digital 3: ADC - pin d3 = a11, - - /// Digital 4 - pin d4 = b10, - - /// Digital 5 - pin d5 = b11, - - /// Digital 6: LED_BUILTIN - pin d6 = a20, - - /// Digital 7 - pin d7 = a21, - - /// Digital 8/SC1 MOSI - pin mosi = a16, - - /// Digital 9/SC1 SCK - pin sck = a17, - - /// Digital 10/SC1 MISO - pin miso = a19, - - /// Digital 11/SC2 SDA - pin sda = a8, - - /// Digital 12/SC2 SCL - pin scl = a9, - - /// Analog 0/DAC0 - pin a0 = a2, - - /// Analog 1 - pin a1 = b2, - - /// Analog 2 - pin a2 = b3, - - /// Analog 3 - pin a3 = a4, - - /// Analog 4 - pin a4 = a5, - - /// Analog 5 - pin a5 = a6, - - /// Analog 6 - pin a6 = a7, - - pin usb_dn = a24, - pin usb_dp = a25, - pin usb_id = a18, - - pin aref = a3, -); - -/// Convenience for setting up the labelled RX, TX pins to -/// operate as a UART device running at the specified baud. -pub fn uart>( - clocks: &mut GenericClockController, - baud: F, - sercom5: pac::SERCOM5, - pm: &mut pac::PM, - d13: gpio::Pb23>, //rx - d14: gpio::Pb22>, //tx - port: &mut Port, -) -> UART5< - hal::sercom::Sercom5Pad3>, //rx - hal::sercom::Sercom5Pad2>, //tx - (), - (), -> { - let gclk0 = clocks.gclk0(); +pub use hal::pac; - UART5::new( - &clocks.sercom5_core(&gclk0).unwrap(), - baud.into(), - sercom5, - pm, - (d13.into_pad(port), d14.into_pad(port)), - ) -} +pub mod pins; +pub mod sercom; +#[cfg(feature = "usb")] +pub mod usb; diff --git a/boards/arduino_mkr1000/src/pins.rs b/boards/arduino_mkr1000/src/pins.rs new file mode 100644 index 000000000000..a9f8826a77d4 --- /dev/null +++ b/boards/arduino_mkr1000/src/pins.rs @@ -0,0 +1,257 @@ +//! Pin definitions for the Arduino Mkr1000 board +//! +//! Built-in pin definitions are defined here for each pin, +//! and additional pin capabilities, such as the timer/counter or waveform +//! output, and alternate sercom pad definitsions must be defined separately. + +use super::hal; + +hal::bsp_pins! { + PA02 { + /// PA02: Analog DAC output / ADC input 0, digital pin 15. + name: d15 + aliases: { + PushPullOutput: D15 + AlternateB: Dac0 + AlternateB: A0 + // FIXME: how to reach TCC3? + AlternateF: D15Pwm // tcc3 wo0 + } + } + PA03 { + /// PA03: ADC/DAC reference voltage. + name: aref + aliases: { + AlternateB: ARef + // FIXME: how to reach TCC3? + AlternateF: PA03Pwm // tcc3 wo1 + } + } + PA04 { + /// PA04: Analog input 3, digital pin 18. + name: d18 + aliases: { + PushPullOutput: D18 + AlternateB: A3 + AlternateE: D18Pwm // tcc0 wo0 + // FIXME: how to reach TCC3? + AlternateF: D18PwmF // tcc3 wo2 + } + } + PA05 { + /// PA05: Analog input 4, digital pin 19. + name: d19 + aliases: { + PushPullOutput: D19 + AlternateB: A4 + AlternateE: D19Pwm // tcc0 wo1 + // FIXME: how to reach TCC3? + AlternateF: D19PwmF // tcc3 wo3 + } + } + PA06 { + /// PA06: Analog input 5, digital pin 20. + name: d20 + aliases: { + PushPullOutput: D20 + AlternateB: A5 + AlternateE: D20Pwm // tcc1 wo0 + // FIXME: how to reach TCC3? + AlternateF: D20PwmF // tcc3 wo4 + } + } + PA07 { + /// PA07: Analog input 6, digital pin 21. + name: d21 + aliases: { + PushPullOutput: D21 + AlternateB: A6 + AlternateE: D21Pwm // tcc1 wo1 + // FIXME: how to reach TCC3? + AlternateF: D21PwmF // tcc3 wo5 + } + } + PA08 { + /// PA08: Sercom 2 SDA, digital pin 11. + name: d11 + aliases: { + PushPullOutput: D11 + AlternateD: I2cSda + AlternateE: D11Pwm // tcc0 wo0 + AlternateF: D11PwmF // tcc1 wo2 + } + } + PA09 { + /// PA09: Sercom 2 SCL, digital pin 12. + name: d12 + aliases: { + PushPullOutput: D12 + AlternateD: I2cScl + // FIXME: none of these PWM work + AlternateE: D12Pwm // tcc0 wo0 + AlternateF: D12PwmF // tcc1 wo3 + } + } + PA10 { + /// PA10: Digital pin 2. + name: d2 + aliases: { + PushPullOutput: D2 + AlternateE: D2Pwm // tcc1 wo0 + AlternateF: D2PwmF // tcc0 wo2 + } + } + PA11 { + /// PA11: Digital pin 3. + name: d3 + aliases: { + PushPullOutput: D3 + AlternateE: D3Pwm // tcc1 wo1 + AlternateF: D3PwmF // tcc0 wo3 + } + } + PA16 { + /// PA16: Sercom 1 SPI COPI, digital pin 8. + name: d8 + aliases: { + PushPullOutput: D8 + AlternateC: SpiCopi + AlternateE: D8Pwm // tcc2 wo0 + AlternateF: D8PwmF // tcc0 wo6 -> ch2 + } + } + PA17 { + /// PA17: Sercom 1 SPI SCK, digital pin 9 + name: d9 + aliases: { + PushPullOutput: D9 + AlternateC: SpiSck + AlternateE: D9Pwm // tcc2 wo1 + AlternateF: D9PwmF // tcc0 wo7 -> ch3 + } + } + PA18 { + /// PA18: USB Input Detection + aliases: { + FloatingDisabled: UsbId + } + } + PA19 { + /// PA19: Main SPI CIPO, digital pin 10 + name: d10 + aliases: { + PushPullOutput: D10 + AlternateC: SpiCipo + AlternateE: D10Pwm // tc3 wo0 + AlternateF: D10PwmF // tcc0 wo3 + } + } + PA20 { + /// PA20: Digital pin 6, also board led + name: led + aliases: { + PushPullOutput: Led + AlternateE: D6Pwm // tc7 wo0 + AlternateF: D6PwmF // tcc0 wo6 -> ch2 + } + } + PA21 { + /// PA21: Digital pin 7 + name: d7 + aliases: { + PushPullOutput: D7 + AlternateE: D7Pwm // tc7 wo1 + AlternateF: D7PwmF // tcc0 wo7 -> ch3 + } + } + PA22 { + /// PA22: Digital pin 0 + name: d0 + aliases: { + PushPullOutput: D0 + AlternateE: D0Pwm // tc4 wo0 + AlternateF: D0PwmF // tcc0 wo4 -> ch0 + } + } + PA23 { + /// PA23: Digital pin 1 + name: d1 + aliases: { + PushPullOutput: D1 + AlternateE: D1Pwm // tc4 wo1 + AlternateF: D1PwmF // tcc0 wo5 -> ch1 + } + } + PA24 { + /// PA24: USB Negative + aliases: { + AlternateG: UsbN + } + } + PA25 { + /// PA25: USB Positive + aliases: { + AlternateG: UsbP + } + } + PB02 { + /// PB02: Analog input 1, digital pin 16 + name: d16 + aliases: { + AlternateB: A1 + PushPullOutput: D16 + AlternateE: D16Pwm // tc6 wo0 + // FIXME: how to reach TCC3? + AlternateF: D16PwmF // tcc3 wo0 + } + } + PB03 { + /// PB03: Analog input 2, digital pin 17 + name: d17 + aliases: { + AlternateB: A2 + PushPullOutput: D17 + AlternateE: D17Pwm // tc6 wo1 + // FIXME: how to reach TCC3? + AlternateF: D17PwmF // tcc3 wo3 + } + } + PB09 { + /// PB09: Battery voltage sensor + /// + /// This pin is not visible on MKR1000 board pinout. + aliases: { + AlternateB: VBatt + } + } + PB10 { + /// PB10: Digital pin 4 + name: d4 + aliases: { + PushPullOutput: D4 + AlternateE: D4Pwm // tc5 wo0 + AlternateF: D4PwmF // tcc0 wo4 -> ch0 + } + } + PB11 { + /// PB11: Digital pin 5 + name: d5 + aliases: { + PushPullOutput: D5 + AlternateE: D5Pwm // tc5 wo1 + AlternateF: D5PwmF // tcc0 wo5 -> ch1 + } + } + PB22 { + /// PB22: UART Tx + aliases: { + AlternateD: UartTx + } + } + PB23 { + /// PB22: UART Rx + aliases: { + AlternateD: UartRx + } + } +} diff --git a/boards/arduino_mkr1000/src/sercom.rs b/boards/arduino_mkr1000/src/sercom.rs new file mode 100644 index 000000000000..8096d2656fa4 --- /dev/null +++ b/boards/arduino_mkr1000/src/sercom.rs @@ -0,0 +1,102 @@ +use crate::hal; +use hal::pac; + +use embedded_hal; + +use hal::clock::GenericClockController; +use hal::sercom::{i2c, spi, uart}; +use hal::time::Hertz; +use uart::{BaudMode, Oversampling}; + +use crate::pins::*; + +hal::bsp_peripherals!( + SERCOM1 { SpiSercom } + SERCOM2 { I2cSercom } + SERCOM5 { UartSercom } +); + +/// SPI pads for the labelled SPI peripheral +pub type SpiPads = spi::Pads; + +/// SPI master for the labelled SPI peripheral +pub type Spi = spi::Spi, spi::Duplex>; + +/// Set up the SPI peripheral +#[allow(clippy::too_many_arguments)] +pub fn setup_spi( + clocks: &mut GenericClockController, + baud: Hertz, + spi_sercom: SpiSercom, + pm: &pac::PM, + cipo: impl Into, + copi: impl Into, + sck: impl Into, + mode: embedded_hal::spi::Mode, +) -> Spi { + let gclk0 = clocks.gclk0(); + let clock = clocks.sercom1_core(&gclk0).unwrap(); + let freq = clock.freq(); + let (cipo, copi, sck) = (cipo.into(), copi.into(), sck.into()); + let pads = spi::Pads::default().data_in(cipo).data_out(copi).sclk(sck); + spi::Config::new(pm, spi_sercom, pads, freq) + .baud(baud) + .spi_mode(mode) + .enable() +} + +/// I2C pads for the labelled I2C peripheral +/// +/// You can use these pads with other, user-defined [`i2c::Config`] +/// configurations. +pub type I2cPads = i2c::Pads; + +/// I2C master for the labelled I2C peripheral +/// +/// This type implements [`Read`](ehal::blocking::i2c::Read), +/// [`Write`](ehal::blocking::i2c::Write) and +/// [`WriteRead`](ehal::blocking::i2c::WriteRead). +pub type I2c = i2c::I2c>; + +/// Convenience for setting up the labelled SDA, SCL pins to +/// operate as an I2C master running at the specified frequency. +pub fn setup_i2c( + clocks: &mut GenericClockController, + baud: impl Into, + sercom: I2cSercom, + pm: &mut pac::PM, + sda: impl Into, + sck: impl Into, +) -> I2c { + let gclk0 = clocks.gclk0(); + let clock = &clocks.sercom0_core(&gclk0).unwrap(); + let freq = clock.freq(); + let baud = baud.into(); + let pads = i2c::Pads::new(sda.into(), sck.into()); + i2c::Config::new(pm, sercom, pads, freq).baud(baud).enable() +} + +/// UART pads for the labelled RX & TX pins +pub type UartPads = uart::Pads; + +/// UART device for the labelled RX & TX pins +pub type Uart = uart::Uart, uart::Duplex>; + +/// Convenience for setting up the labelled RX, TX pins to +/// operate as a UART device running at the specified baud. +pub fn uart( + clocks: &mut GenericClockController, + baud: impl Into, + sercom: UartSercom, + pm: &mut pac::PM, + uart_rx: impl Into, + uart_tx: impl Into, +) -> Uart { + let gclk0 = clocks.gclk0(); + let clock = &clocks.sercom5_core(&gclk0).unwrap(); + let baud = baud.into(); + let pads = uart::Pads::default().rx(uart_rx.into()).tx(uart_tx.into()); + uart::Config::new(pm, sercom, pads, clock.freq()) + .baud(baud, BaudMode::Fractional(Oversampling::Bits16)) + .enable() +} diff --git a/boards/arduino_mkr1000/src/usb.rs b/boards/arduino_mkr1000/src/usb.rs new file mode 100644 index 000000000000..1a5c9d944a49 --- /dev/null +++ b/boards/arduino_mkr1000/src/usb.rs @@ -0,0 +1,19 @@ +use crate::hal; +use crate::pins::{UsbN, UsbP}; +use hal::pac; + +use hal::clock::GenericClockController; +use hal::usb::{usb_device::bus::UsbBusAllocator, UsbBus}; + +pub fn usb_allocator( + usb: pac::USB, + clocks: &mut GenericClockController, + pm: &mut pac::PM, + dm: UsbN, + dp: UsbP, +) -> UsbBusAllocator { + let gclk0 = clocks.gclk0(); + let usb_clock = &clocks.usb(&gclk0).unwrap(); + + UsbBusAllocator::new(UsbBus::new(usb_clock, pm, dm, dp, usb)) +}