From 99a9806b9b2b042d168f32ae10dd4b89a3295021 Mon Sep 17 00:00:00 2001 From: Andy Isaacson Date: Sun, 11 Jul 2021 20:11:31 -0700 Subject: [PATCH] import 0.12 (?) usb_echo wholesale --- rs-lorachat/Cargo.toml | 8 +- rs-lorachat/src/lib.rs | 226 ++++++++++++++++++++++++++++++++++++++++ rs-lorachat/src/main.rs | 105 ++++++++++++++----- 3 files changed, 307 insertions(+), 32 deletions(-) create mode 100644 rs-lorachat/src/lib.rs diff --git a/rs-lorachat/Cargo.toml b/rs-lorachat/Cargo.toml index cff8d1a..b76ed91 100644 --- a/rs-lorachat/Cargo.toml +++ b/rs-lorachat/Cargo.toml @@ -16,6 +16,7 @@ optional = true [dependencies.atsamd-hal] version = "0.12" +default-features = false [dependencies.panic-halt] version = "0.2" @@ -25,10 +26,6 @@ optional = true version = "0.2" optional = true -[dependencies.rtic-monotonic] -version = "=0.1.0-alpha.1" -optional = true - [dependencies.usbd-serial] version = "0.1" optional = true @@ -37,9 +34,6 @@ optional = true cortex-m-semihosting = "0.3" heapless = "0.5" -[dev-dependencies.cortex-m-rtic] -version = "0.6.0-alpha.4" - [features] default = ["rt", "atsamd-hal/samd21g", "panic_halt"] rt = ["cortex-m-rt", "atsamd-hal/samd21g-rt"] diff --git a/rs-lorachat/src/lib.rs b/rs-lorachat/src/lib.rs new file mode 100644 index 0000000..ad9b80c --- /dev/null +++ b/rs-lorachat/src/lib.rs @@ -0,0 +1,226 @@ +#![no_std] + +extern crate atsamd_hal as hal; + +#[cfg(feature = "rt")] +extern crate cortex_m_rt; +#[cfg(feature = "rt")] +pub use cortex_m_rt::entry; + +use hal::prelude::*; +use hal::*; + +pub use hal::common::*; +pub use hal::samd21::*; +pub use hal::target_device as pac; + +use gpio::{Floating, Input, PfC, Port}; +use hal::clock::GenericClockController; +use hal::sercom::{I2CMaster3, PadPin, SPIMaster4, UART0}; +use hal::time::Hertz; + +#[cfg(feature = "usb")] +use hal::usb::usb_device::bus::UsbBusAllocator; +#[cfg(feature = "usb")] +pub use hal::usb::UsbBus; + +define_pins!( + /// Maps the pins to their arduino names and + /// the numbers printed on the board. + struct Pins, + target_device: target_device, + + /// AREF pin - has 1uF capacitor to ground + pin aref = a3, + + /// Analog pin 0. Can act as a true analog output + /// as it has a DAC (which is not currently supported + /// by this hal) as well as input. + pin a0 = a2, + + /// Analog Pin 1 + pin a1 = b8, + /// Analog Pin 2 + pin a2 = b9, + /// Analog Pin 3 + pin a3 = a4, + /// Analog Pin 4 + pin a4 = a5, + /// Analog Pin 5 + pin a5 = b2, + + /// Pin 0, rx + pin d0 = a11, + /// Pin 1, tx + pin d1 = a10, + /// Pin 5, PWM capable + pin d5 = a15, + /// Pin 6, PWM capable + pin d6 = a20, + /// Pin 9, PWM capable. Also analog input (A7) + pin d9 = a7, + /// Pin 10, PWM capable + pin d10 = a18, + /// Pin 11, PWM capable + pin d11 = a16, + /// Pin 12, PWM capable + pin d12 = a19, + /// Pin 13, which is also attached to + /// the red LED. PWM capable. + pin d13 = a17, + + /// The I2C data line + pin sda = a22, + /// The I2C clock line + pin scl = a23, + + /// The SPI SCK + pin sck = b11, + /// The SPI MOSI + pin mosi = b10, + /// The SPI MISO + pin miso = a12, + + /// The USB D- pad + pin usb_dm = a24, + /// The USB D+ pad + pin usb_dp = a25, + + /// SPI chip select for the RFM module + #[cfg(feature = "rfm")] + pin rfm_cs = a6, + + /// Reset for the RFM module + #[cfg(feature = "rfm")] + pin rfm_reset = a8, + + /// Interrupt from the RFM module + #[cfg(feature = "rfm")] + pin rfm_irq = a9, + + /// Neopixel data + #[cfg(feature = "express")] + pin neopixel = a6, + + /// SPI clock for the external flash + #[cfg(feature = "express")] + pin flash_sck = a9, + + /// SPI MOSI for the external flash + #[cfg(feature = "express")] + pin flash_mosi = a8, + + /// SPI MISO for the external flash + #[cfg(feature = "express")] + pin flash_miso = a14, + + /// SPI chip select for the external flash + #[cfg(feature = "express")] + pin flash_cs = a13, +); + +/// Convenience for setting up the labelled SPI peripheral. +/// This powers up SERCOM4 and configures it for use as an +/// SPI Master in SPI Mode 0. +pub fn spi_master>( + clocks: &mut GenericClockController, + bus_speed: F, + sercom4: pac::SERCOM4, + pm: &mut pac::PM, + sck: gpio::Pb11>, + mosi: gpio::Pb10>, + miso: gpio::Pa12>, + port: &mut Port, +) -> SPIMaster4< + hal::sercom::Sercom4Pad0>, + hal::sercom::Sercom4Pad2>, + hal::sercom::Sercom4Pad3>, +> { + let gclk0 = clocks.gclk0(); + SPIMaster4::new( + &clocks.sercom4_core(&gclk0).unwrap(), + bus_speed.into(), + hal::hal::spi::Mode { + phase: hal::hal::spi::Phase::CaptureOnFirstTransition, + polarity: hal::hal::spi::Polarity::IdleLow, + }, + sercom4, + pm, + (miso.into_pad(port), mosi.into_pad(port), sck.into_pad(port)), + ) +} + +/// Convenience for setting up the labelled SDA, SCL pins to +/// operate as an I2C master running at the specified frequency. +pub fn i2c_master>( + clocks: &mut GenericClockController, + bus_speed: F, + sercom3: pac::SERCOM3, + pm: &mut pac::PM, + sda: gpio::Pa22>, + scl: gpio::Pa23>, + port: &mut Port, +) -> I2CMaster3< + hal::sercom::Sercom3Pad0>, + hal::sercom::Sercom3Pad1>, +> { + let gclk0 = clocks.gclk0(); + I2CMaster3::new( + &clocks.sercom3_core(&gclk0).unwrap(), + bus_speed.into(), + sercom3, + pm, + sda.into_pad(port), + scl.into_pad(port), + ) +} + +/// 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, + sercom0: pac::SERCOM0, + pm: &mut pac::PM, + d0: gpio::Pa11>, + d1: gpio::Pa10>, + port: &mut Port, +) -> UART0< + hal::sercom::Sercom0Pad3>, + hal::sercom::Sercom0Pad2>, + (), + (), +> { + let gclk0 = clocks.gclk0(); + + UART0::new( + &clocks.sercom0_core(&gclk0).unwrap(), + baud.into(), + sercom0, + pm, + (d0.into_pad(port), d1.into_pad(port)), + ) +} + +#[cfg(feature = "usb")] +pub fn usb_allocator( + usb: pac::USB, + clocks: &mut GenericClockController, + pm: &mut pac::PM, + dm: gpio::Pa24>, + dp: gpio::Pa25>, + port: &mut Port, +) -> UsbBusAllocator { + use gpio::IntoFunction; + + let gclk0 = clocks.gclk0(); + let usb_clock = &clocks.usb(&gclk0).unwrap(); + + UsbBusAllocator::new(UsbBus::new( + usb_clock, + pm, + dm.into_function(port), + dp.into_function(port), + usb, + )) +} diff --git a/rs-lorachat/src/main.rs b/rs-lorachat/src/main.rs index 92e4f45..89ad868 100644 --- a/rs-lorachat/src/main.rs +++ b/rs-lorachat/src/main.rs @@ -1,46 +1,101 @@ #![no_std] #![no_main] -use panic_halt as _; +extern crate cortex_m; +extern crate feather_m0 as hal; +extern crate panic_halt; +extern crate usb_device; +extern crate usbd_serial; -use bsp::hal; -use feather_m0 as bsp; - -use bsp::entry; -use hal::clock::{GenericClockController}; -use hal::delay::Delay; -use hal::pac::{CorePeripherals, Peripherals}; +use hal::clock::GenericClockController; +use hal::entry; +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::asm::delay as cycle_delay; +use cortex_m::peripheral::NVIC; + #[entry] fn main() -> ! { let mut peripherals = Peripherals::take().unwrap(); - let core = CorePeripherals::take().unwrap(); - let mut clocks = GenericClockController::with_external_32kosc( + let mut core = CorePeripherals::take().unwrap(); + let mut clocks = GenericClockController::with_internal_32kosc( peripherals.GCLK, &mut peripherals.PM, &mut peripherals.SYSCTRL, &mut peripherals.NVMCTRL, ); - let pins = bsp::Pins::new(peripherals.PORT); - let mut delay = Delay::new(core.SYST, &mut clocks); - let mut red_led = pins.d13.into_push_pull_output(); + let mut pins = hal::Pins::new(peripherals.PORT); + let mut red_led = pins.d13.into_open_drain_output(&mut pins.port); + let bus_allocator = unsafe { + USB_ALLOCATOR = Some(hal::usb_allocator( + peripherals.USB, + &mut clocks, + &mut peripherals.PM, + pins.usb_dm, + pins.usb_dp, + &mut pins.port, + )); + USB_ALLOCATOR.as_ref().unwrap() + }; - red_led.set_high().unwrap(); - delay.delay_ms(500_u32); - red_led.set_low().unwrap(); - delay.delay_ms(500_u32); - red_led.set_high().unwrap(); - - red_led.set_low().unwrap(); - delay.delay_ms(500_u32); + unsafe { + USB_SERIAL = Some(SerialPort::new(&bus_allocator)); + USB_BUS = Some( + UsbDeviceBuilder::new(&bus_allocator, UsbVidPid(0x16c0, 0x27dd)) + .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); + } + // Flash the LED in a spin loop to demonstrate that USB is + // entirely interrupt driven. loop { - delay.delay_ms(1_000_u32); - red_led.set_high().unwrap(); - delay.delay_ms(1_000_u32); - red_led.set_low().unwrap(); + cycle_delay(15 * 1024 * 1024); + red_led.toggle(); } } + +static mut USB_ALLOCATOR: Option> = None; +static mut USB_BUS: Option> = None; +static mut USB_SERIAL: Option> = None; + +fn poll_usb() { + unsafe { + USB_BUS.as_mut().map(|usb_dev| { + USB_SERIAL.as_mut().map(|serial| { + usb_dev.poll(&mut [serial]); + let mut buf = [0u8; 64]; + + if let Ok(count) = serial.read(&mut buf) { + for (i, c) in buf.iter().enumerate() { + if i >= count { + break; + } + serial.write(&[c.clone()]); + } + }; + }); + }); + }; +} + +#[interrupt] +fn USB() { + poll_usb(); +} -- 2.42.0