From 0f80c612d59c855a99073e583db339fe6a42b883 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sat, 27 Aug 2022 19:35:56 -0400 Subject: this is also broken, but at least it ain't mine --- Cargo.lock | 13 + Cargo.toml | 4 + src/blink.rs | 62 ++-- src/main.rs | 126 +++++--- src/usb.rs | 919 ++--------------------------------------------------------- 5 files changed, 175 insertions(+), 949 deletions(-) mode change 100644 => 100755 src/usb.rs diff --git a/Cargo.lock b/Cargo.lock index ff4e28f..53b2efa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,6 +103,7 @@ dependencies = [ "nb 1.0.0", "riscv 0.8.0", "riscv-rt", + "synopsys-usb-otg", "usb-device", "usbd-serial", ] @@ -280,6 +281,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synopsys-usb-otg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5999b93d4d7e294fc26de39181dbe1428d61dd3b4046642ee0b3927ea2037c9b" +dependencies = [ + "embedded-hal", + "riscv 0.6.0", + "usb-device", + "vcell", +] + [[package]] name = "unicode-ident" version = "1.0.3" diff --git a/Cargo.toml b/Cargo.toml index ab7756a..ce3f550 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,10 @@ embedded-hal = "0.2.7" usb-device = "0.2.9" usbd-serial = "0.1.1" +[dependencies.synopsys-usb-otg] +version = "0.3.0" +features = ["riscv", "fs"] + [[bin]] name = "luchie" test = false diff --git a/src/blink.rs b/src/blink.rs index bb53845..ba3d6ca 100644 --- a/src/blink.rs +++ b/src/blink.rs @@ -1,59 +1,67 @@ -use gd32vf103xx_hal::prelude::_embedded_hal_timer_CountDown; - use core::convert::Infallible; use gd32vf103xx_hal::{ eclic::{self, EclicExt}, pac::{self, Interrupt}, + prelude::*, time::Hertz, timer::{Event, Timer}, }; use nb; +use riscv::interrupt; use crate::led::LED; -enum State { - WaitForTimer, - ToggleLED, -} - pub struct Task { timer: Timer, frequency: Hertz, led: LED, - state: State, } +static mut TIMER_FIRED: bool = false; + impl Task { pub fn new(mut timer: Timer, frequency: Hertz, led: LED) -> Self { pac::ECLIC::setup(Interrupt::TIMER6, eclic::TriggerType::RisingEdge, eclic::Level::L0, eclic::Priority::P3); unsafe { pac::ECLIC::unmask(Interrupt::TIMER6); } - if !pac::ECLIC::is_enabled(Interrupt::TIMER6) { - panic!("timer6 interrupt not enabled"); - } + assert!(pac::ECLIC::is_enabled(Interrupt::TIMER6)); timer.listen(Event::Update); - Self { timer, frequency, led, state: State::ToggleLED } + Self { timer, frequency, led } } pub fn poll(&mut self) -> nb::Result<(), Infallible> { - match self.state { - State::WaitForTimer => { - if let Ok(_) = self.timer.wait() { - self.state = State::ToggleLED; - // self.timer.unlisten(Event::Update); - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - }, - State::ToggleLED => { + interrupt::free(|_cs| { + if unsafe { TIMER_FIRED } { + unsafe { TIMER_FIRED = false }; self.led.toggle(); self.timer.start(self.frequency); - self.state = State::WaitForTimer; - // self.timer.listen(Event::Update); - Err(nb::Error::WouldBlock) } - } + }); + Err(nb::Error::WouldBlock) } } + +/* + * because i'm using ‘wfi’ to sleep as much as possible, i need to + * actually schedule the timer to fire an interrupt. that, in turn, + * requires a handler. + * + * why? because, for efficiency reasons, ‘_irq_handler’ uses the + * bumblebee core ‘jalmnxti’ csr, and the default entry in the irq + * vector is ‘0’. so the core jumps to 0, which is the ‘_start’ entry + * point. but it does this *from the interrupt*, which masks the + * interrupt (because it's currently being serviced), so any + * subsequent firings are never triggered, nor any interrupts at lower + * priority. + * + * so it looks like the core resets every other time it's + * started. adding a real isr avoids these problems. + */ +#[export_name="TIMER6"] +fn timer6() { + // logln!("I timer6 I"); + let regs = unsafe { &*pac::TIMER6::ptr() }; + regs.intf.write(|w| w.upif().clear_bit()); + unsafe { TIMER_FIRED = true }; +} diff --git a/src/main.rs b/src/main.rs index 19f2b7a..dce005a 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +/* #![no_std] #![no_main] @@ -9,7 +10,6 @@ mod usb; use gd32vf103xx_hal::{ afio::AfioExt, eclic::{self, EclicExt}, - exti::Exti, gpio::GpioExt, pac::{self, Peripherals}, rcu::RcuExt, @@ -22,10 +22,12 @@ use riscv::{ interrupt, }; use riscv_rt::entry; +use usb_device::prelude::*; use led::LED; +use usb::{USB, UsbBus}; -// global_asm!(include_str!("boot.S")); +static mut EP_MEMORY: [u32; 1024] = [0; 1024]; #[entry] fn main(_hartid: usize) -> ! { @@ -35,7 +37,11 @@ fn main(_hartid: usize) -> ! { pac::ECLIC::set_threshold_level(eclic::Level::L0); pac::ECLIC::set_level_priority_bits(eclic::LevelPriorityBits::L3P1); - let mut rcu = p.RCU.configure().sysclk(MegaHertz(48)).freeze(); + let mut rcu = p.RCU + .configure() + .ext_hf_clock(MegaHertz(8)) + .sysclk(MegaHertz(96)) + .freeze(); let mut afio = p.AFIO.constrain(&mut rcu); let gpioa = p.GPIOA.split(&mut rcu); @@ -56,18 +62,24 @@ fn main(_hartid: usize) -> ! { let led = LED::new(gpioa.pa7); let mut blink = blink::Task::new(timer, Hertz(5), led); - logln!("+++ busabus"); - let mut exti = Exti::new(p.EXTI); - let bus = usb::Bus::new(p.USBFS_GLOBAL, p.USBFS_DEVICE, p.USBFS_PWRCLK, &mut rcu, &mut exti); - bus.init(); - // let bus_alloc = UsbBusAllocator::new(bus); - // logln!("+++ devadev"); - // let mut usb_dev = UsbDeviceBuilder::new(&bus_alloc, UsbVidPid(0xdead, 0xbeef)) - // .manufacturer("luchie") - // .product("pad") - // .serial_number("test") - // .build(); - // logln!("+++ superserious"); + let usb = USB { + usb_global: p.USBFS_GLOBAL, + usb_device: p.USBFS_DEVICE, + usb_pwrclk: p.USBFS_PWRCLK, + pin_dm: gpioa.pa11, + pin_dp: gpioa.pa12, + hclk: rcu.clocks.hclk() + }; + + let usb_bus = UsbBus::new(usb, unsafe { &mut EP_MEMORY }); + + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .manufacturer("Fake company") + .product("Enumeration test") + .serial_number("TEST") + .device_class(0) + .build(); + //let mut serial = SerialPort::new(&bus_alloc); unsafe { interrupt::enable() }; @@ -75,25 +87,20 @@ fn main(_hartid: usize) -> ! { loop { let mut can_sleep = true; - log!("yo"); if let Ok(_) = blink.poll() { can_sleep = false; } - log!(" mtv"); - // was: usb_dev.poll(&mut [&mut serial]) - // if usb_dev.poll(&mut []) { - // can_sleep = false; - // } - log!(" raps"); - - if can_sleep { + if usb_dev.poll(&mut []) { + logln!("usb"); + can_sleep = false; + } + + if can_sleep && false { log!("!"); unsafe { wfi() }; } - logln!(""); } } - #[export_name="ExceptionHandler"] fn exception_handler(_frame: &riscv_rt::TrapFrame) -> ! { spin(); @@ -108,19 +115,74 @@ fn default_handler() -> ! { fn machine_timer() { spin(); } +*/ + +#![no_std] +#![no_main] + +mod usb; + +use riscv::asm::wfi; +use riscv_rt::entry; +use gd32vf103xx_hal::prelude::*; +use gd32vf103xx_hal::pac; + +use usb::{USB, UsbBus}; +use usb_device::prelude::*; +use usbd_serial::SerialPort; + +static mut EP_MEMORY: [u32; 1024] = [0; 1024]; + +#[entry] +fn main() -> ! { + let dp = pac::Peripherals::take().unwrap(); + + // Configure clocks + let mut rcu = dp.RCU.configure() + .ext_hf_clock(8.mhz()) + .sysclk(96.mhz()) + .freeze(); + + assert!(rcu.clocks.usbclk_valid()); + + let gpioa = dp.GPIOA.split(&mut rcu); + let usb = USB { + usb_global: dp.USBFS_GLOBAL, + usb_device: dp.USBFS_DEVICE, + usb_pwrclk: dp.USBFS_PWRCLK, + pin_dm: gpioa.pa11, + pin_dp: gpioa.pa12, + hclk: rcu.clocks.hclk() + }; + + let usb_bus = UsbBus::new(usb, unsafe { &mut EP_MEMORY }); + + let mut serial = SerialPort::new(&usb_bus); + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .manufacturer("Fake company") + .product("Enumeration test") + .serial_number("TEST") + .device_class(0) + .build(); + + loop { + if usb_dev.poll(&mut [&mut serial]) { + } + } +} #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { - interrupt::free(|_cs| { - log!("!!! panic "); +// interrupt::free(|_cs| { +// log!("!!! panic "); if let Some(loc) = info.location() { - log!("in {}:{} ", loc.file(), loc.line()); +// log!("in {}:{} ", loc.file(), loc.line()); } if let Some(msg) = info.payload().downcast_ref::<&str>() { - log!("⇒ {} ", msg); +// log!("⇒ {} ", msg); } - logln!("!!!"); - }); +// logln!("!!!"); +// }); spin(); } diff --git a/src/usb.rs b/src/usb.rs old mode 100644 new mode 100755 index c6920e1..1ec36af --- a/src/usb.rs +++ b/src/usb.rs @@ -1,903 +1,42 @@ -//use embedded_hal::digital::v2::OutputPin; -use gd32vf103xx_hal::prelude::_embedded_hal_blocking_delay_DelayMs; -use gd32vf103xx_hal::{ - eclic::{EclicExt, Level, Priority, TriggerType}, - exti::{Exti, ExtiLine, InternalLine, TriggerEdge}, - pac::{ECLIC, Interrupt, RCU, USBFS_DEVICE, USBFS_GLOBAL, USBFS_PWRCLK}, - rcu::Rcu, - time::MegaHertz, -}; -use riscv::{ - asm::delay, - interrupt, -}; -use usb_device::{ - class_prelude::*, - bus::PollResult, - UsbDirection, -}; +use gd32vf103xx_hal::pac; +use gd32vf103xx_hal::gpio::{Input, Floating, gpioa::{PA11, PA12}}; +use gd32vf103xx_hal::time::Hertz; +pub use synopsys_usb_otg::UsbBus; +use synopsys_usb_otg::UsbPeripheral; -use crate::{log, logln}; - -struct EPAllocation(u8); -impl EPAllocation { - const MAX_ENDPOINT: usize = 4; - - fn new() -> Self { - EPAllocation(0) - } - - fn is_alloc(&self, index: usize) -> Result { - if index < Self::MAX_ENDPOINT { - let test = 1 << index; - logln!("is_alloc: {} & {} = {}", self.0, test, self.0 & test == test); - Ok(self.0 & test == test) - } else { - logln!("is_alloc underflow"); - Err(UsbError::EndpointOverflow) - } - } - - fn is_free(&self, index: usize) -> Result { - self.is_alloc(index).map(|v| !v) - } - - fn alloc(&mut self, index: usize) -> Result<(), UsbError> { - if index < Self::MAX_ENDPOINT { - let test = 1 << index; - self.0 |= test; - logln!("alloc: {} & {}", self.0, test); - Ok(()) - } else { - logln!("alloc underflow"); - Err(UsbError::EndpointOverflow) - } - } - - fn next_ep(&self) -> Result { - for i in 0..Self::MAX_ENDPOINT { - if self.is_free(i)? { - logln!("next: {}", i); - return Ok(i) - } - } - logln!("next underflow"); - Err(UsbError::EndpointOverflow) - } - - fn iter(&self) -> EPAllocationIter { - EPAllocationIter { i: 0, alloc: self } - } -} - -struct EPAllocationIter<'a> { - i: u8, - alloc: &'a EPAllocation, -} - -impl Iterator for EPAllocationIter<'_> { - type Item = u8; - - fn next(&mut self) -> Option { - while let Ok(is_alloc) = self.alloc.is_alloc(self.i.into()) { - self.i += 1; - if is_alloc { - return Some(self.i - 1); - } - } - None - } -} - -pub struct Bus { - usbg: USBFS_GLOBAL, - usbd: USBFS_DEVICE, - usbpwr: USBFS_PWRCLK, - - ep_in_alloc: EPAllocation, - ep_out_alloc: EPAllocation, -} - -fn rcu_config(rcu: &mut Rcu) { - let system_clock = rcu.clocks.sysclk(); - let psc: u8 = if system_clock == MegaHertz(48).into() { - logln!("48mhz"); - 0b01 - } else if system_clock == MegaHertz(72).into() { - logln!("72mhz"); - 0b00 - } else if system_clock == MegaHertz(96).into() { - logln!("96mhz"); - 0b11 - } else { - logln!("clk: {}", system_clock.0); - 0b01 - }; - // rcu_usb_clock_config(psc) - let rcup = unsafe { &*RCU::ptr() }; - rcup.cfg0.modify(|_, w| unsafe { w.usbfspsc().bits(psc) }); - - // Enable USB peripheral - rcup.ahben.modify(|_, w| w.usbfsen().set_bit()); - // Reset USB peripheral - // rcup.ahbrst.modify(|_, w| w.usbfsrst().set_bit()); - // rcup.ahbrst.modify(|_, w| w.usbfsrst().clear_bit()); - -} - -fn intr_config(exti: &mut Exti) { - ECLIC::setup(Interrupt::USBFS, TriggerType::RisingEdge, Level::L1, Priority::P0); - - let rcup = unsafe { &*RCU::ptr() }; - - // Enable PMU clock - rcup.apb1en.modify(|_, w| w.pmuen().set_bit()); - - // Reset USB peripheral - rcup.apb1rst.modify(|_, w| w.pmurst().set_bit()); - rcup.apb1rst.modify(|_, w| w.pmurst().clear_bit()); - - let line = ExtiLine::from_internal_line(InternalLine::UsbWakeup); - Exti::clear(line); - exti.listen(line, TriggerEdge::Rising); - - ECLIC::setup(Interrupt::USBFS_WKUP, TriggerType::RisingEdge, Level::L1, Priority::P0); - - unsafe { - ECLIC::unmask(Interrupt::USBFS); - ECLIC::unmask(Interrupt::USBFS_WKUP); - } +#[allow(dead_code)] +pub struct USB { + pub usb_global: pac::USBFS_GLOBAL, + pub usb_device: pac::USBFS_DEVICE, + pub usb_pwrclk: pac::USBFS_PWRCLK, + pub pin_dm: PA11>, + pub pin_dp: PA12>, + pub hclk: Hertz, } -impl Bus { - pub fn new( - usbg: USBFS_GLOBAL, - usbd: USBFS_DEVICE, - usbpwr: USBFS_PWRCLK, - rcu: &mut Rcu, - exti: &mut Exti, - ) -> Self { - /* - eclic_global_interrupt_enable(); +unsafe impl Sync for USB {} - eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL2_PRIO2); +unsafe impl UsbPeripheral for USB { + const REGISTERS: *const () = pac::USBFS_GLOBAL::ptr() as *const (); - usb_rcu_config(); + const HIGH_SPEED: bool = false; + const FIFO_DEPTH_WORDS: usize = 320; + const ENDPOINT_COUNT: usize = 4; - usb_timer_init(); + fn enable() { + let rcu = unsafe { &*pac::RCU::ptr() }; - usb_intr_config(); - - usbd_init (&USB_OTG_dev, USB_CORE_ENUM_FS, &usbd_cdc_cb); - - */ - rcu_config(rcu); - - intr_config(exti); - - let ep_in_alloc = EPAllocation::new(); - let ep_out_alloc = EPAllocation::new(); - Self { usbg, usbd, usbpwr, ep_in_alloc, ep_out_alloc } - } + riscv::interrupt::free(|_| { + // Enable USB peripheral + rcu.ahben.modify(|_, w| w.usbfsen().set_bit()); - fn basic_init(&self) { - // transfer_mode = use_fifo - // core_speed = full - // core_enum = 1 (FS) (HS is 0) - // reg_base = USBFS_REG_BASE; - - /* set the host channel numbers */ - // usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; - - // /* set the device endpoint numbers */ - // usb_basic->num_ep = USBFS_MAX_EP_COUNT; - - // /* USBFS core use embedded physical layer */ - // usb_basic->phy_itf = USB_EMBEDDED_PHY; - // usb_basic->sof_enable = USB_SOF_OUTPUT; /* 1 in cdcacm */ - // usb_basic->low_power = USB_LOW_POWER; /* 1 in cdcacm */ - } - - fn mdelay(d: u32) { - let mut delay = riscv::delay::McycleDelay::new(108_000); - delay.delay_ms(d); - } - - fn udelay(d: u32) { - let mut delay = riscv::delay::McycleDelay::new(108); - delay.delay_ms(d); - } - - fn core_reset(&self) { - self.usbg.grstctl.modify(|_, w| w.csrst().set_bit()); - while self.usbg.grstctl.read().csrst().bit_is_set() {} - Self::udelay(3); - } - - fn core_init(&self) { - self.usbg.gahbcs.modify(|_, w| w.ginten().clear_bit()); - // this sets a reserved field to a magic value, and i hope - // it's not neccessary. - self.usbg.gusbcs.modify(|r, w| unsafe { w.bits(r.bits() | 1 << 6) }); - logln!("-> core_reset"); - self.core_reset(); - logln!("<- core_reset"); - self.usbg.gccfg.modify(|_, w| { - w - .pwron().set_bit() - .vbusacen().set_bit() - .vbusbcen().set_bit() - .sofoen().set_bit() - }); - - Self::mdelay(20); - } - - fn devdisconnect(&self) { - self.usbd.dctl.modify(|_, w| w.sd().set_bit()); - } - - fn disconnect(&self) { - self.devdisconnect(); - Self::mdelay(3); - } - - // 32 bit words - const RX_FIFO_SIZE: u16 = 128; - const TX_FIFO_SIZE: [u16; 4] = [64, 128, 0, 0]; - - fn devint_enable(&self) { - self.usbg.gotgintf.write(|w| unsafe { w.bits(0xffff_ffffu32) }); - self.usbg.gintf.write(|w| unsafe { w.bits(0xbfff_ffffu32) }); - self.usbg.ginten.modify(|_, w| { - w - .wkupie().set_bit() - .spie().set_bit() - .rxfneie().set_bit() - .rstie().set_bit() - .enumfie().set_bit() - .iepie().set_bit() - .oepie().set_bit() - .sofie().set_bit() - .mfie().set_bit() + // Reset USB peripheral + rcu.ahbrst.modify(|_, w| w.usbfsrst().set_bit()); + rcu.ahbrst.modify(|_, w| w.usbfsrst().clear_bit()); }); - self.usbg.gahbcs.modify(|_, w| w.ginten().set_bit()); } - fn txfifo_flush(&self, fifo_num: u8) { - self.usbg.grstctl.modify(|_, w| { - unsafe { - w - .txfnum().bits(fifo_num) - .txff().set_bit() - } - }); - while self.usbg.grstctl.read().txff().bit_is_set() {} - - Self::mdelay(3); - } - - fn rxfifo_flush(&self) { - self.usbg.grstctl.modify(|_, w| w.txff().set_bit()); - while self.usbg.grstctl.read().txff().bit_is_set() {} - - Self::mdelay(3); - } - - fn devcore_init(&self) { - self.usbg.gusbcs.modify(|_, w| { - w - .fdm().clear_bit() - .fhm().clear_bit() - }); - self.usbg.gusbcs.modify(|_, w| w.fdm().set_bit()); - self.usbpwr.pwrclkctl.modify(|_, w| unsafe { w.bits(0) }); - self.usbd.dcfg.modify(|_, w| { - unsafe { - w - .eopft().bits(0) - .ds().bits(0b11) - } - }); - self.usbg.grflen.modify(|_, w| unsafe { w.rxfd().bits(Self::RX_FIFO_SIZE)}); - self.usbg.hnptflen().modify(|_, w| { - unsafe { - w - .hnptxfd().bits(Self::TX_FIFO_SIZE[0]) - .hnptxrsar().bits(Self::RX_FIFO_SIZE) - } - }); - let mut ram_addr = Self::RX_FIFO_SIZE; - - ram_addr += Self::TX_FIFO_SIZE[0]; - self.usbg.diep1tflen.modify(|_, w| { - unsafe { - w - .ieptxfd().bits(Self::TX_FIFO_SIZE[1]) - .ieptxrsar().bits(ram_addr) - } - }); - ram_addr += Self::TX_FIFO_SIZE[1]; - self.usbg.diep1tflen.modify(|_, w| { - unsafe { - w - .ieptxfd().bits(Self::TX_FIFO_SIZE[2]) - .ieptxrsar().bits(ram_addr) - } - }); - ram_addr += Self::TX_FIFO_SIZE[2]; - self.usbg.diep1tflen.modify(|_, w| { - unsafe { - w - .ieptxfd().bits(Self::TX_FIFO_SIZE[3]) - .ieptxrsar().bits(ram_addr) - } - }); - - self.txfifo_flush(0x10); - self.rxfifo_flush(); - - self.usbd.diepinten.modify(|_, w| unsafe { w.bits(0) }); - self.usbd.doepinten.modify(|_, w| unsafe { w.bits(0) }); - self.usbd.daepinten.modify(|_, w| unsafe { w.bits(0) }); - // read-only in the pac and datasheet - //self.usbd.daepint.modify(|_, w| unsafe { w.bits(0xffff_ffffu32) }); - - if self.usbd.diep0ctl.read().epen().bit_is_set() { - self.usbd.diep0ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.diep0ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.diep0len.write(|w| unsafe { w.bits(0) }); - self.usbd.diep0intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.doep0ctl.read().epen().bit_is_set() { - self.usbd.doep0ctl.modify(|_, w| w.snak().set_bit()); - } else { - self.usbd.doep0ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.doep0len.write(|w| unsafe { w.bits(0) }); - self.usbd.doep0intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.diep1ctl.read().epen().bit_is_set() { - self.usbd.diep1ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.diep1ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.diep1len.write(|w| unsafe { w.bits(0) }); - self.usbd.diep1intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.doep1ctl.read().epen().bit_is_set() { - self.usbd.doep1ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.doep1ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.doep1len.write(|w| unsafe { w.bits(0) }); - self.usbd.doep1intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.diep2ctl.read().epen().bit_is_set() { - self.usbd.diep2ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.diep2ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.diep2len.write(|w| unsafe { w.bits(0) }); - self.usbd.diep2intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.doep2ctl.read().epen().bit_is_set() { - self.usbd.doep2ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.doep2ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.doep2len.write(|w| unsafe { w.bits(0) }); - self.usbd.doep2intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.diep3ctl.read().epen().bit_is_set() { - self.usbd.diep3ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.diep3ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.diep3len.write(|w| unsafe { w.bits(0) }); - self.usbd.diep3intf.write(|w| unsafe { w.bits(0xff) }); - - if self.usbd.doep3ctl.read().epen().bit_is_set() { - self.usbd.doep3ctl.modify(|_, w| w.epd().set_bit().snak().set_bit()); - } else { - self.usbd.doep3ctl.write(|w| unsafe { w.bits(0) }); - } - self.usbd.doep3len.write(|w| unsafe { w.bits(0) }); - self.usbd.doep3intf.write(|w| unsafe { w.bits(0xff) }); - - - self.devint_enable(); - } - - fn devconnect(&self) { - self.usbd.dctl.modify(|_, w| w.sd().clear_bit()); - } - - fn connect(&self) { - self.devconnect(); - Self::mdelay(3); - } - - pub fn init(&self) { - logln!("!!! basic_init"); - self.basic_init(); - logln!("!!! core_init"); - self.core_init(); - logln!("!!! disconnect"); - self.disconnect(); - logln!("!!! devcore_init"); - self.devcore_init(); - logln!("!!! connect"); - self.connect(); - - // cur_status = default; - } -} - -unsafe impl Sync for Bus {} - -fn mpl_from_int(i: usize) -> Result { - match i { - 64 => Ok(0b00), - 32 => Ok(0b01), - 16 => Ok(0b10), - 8 => Ok(0b11), - _ => Err(UsbError::Unsupported), - } -} - -trait ToBits { - type Width; - fn to_bits(&self) -> Self::Width; -} - -impl ToBits for EndpointType { - type Width = u8; - - fn to_bits(&self) -> Self::Width { - match self { - EndpointType::Control => 0b00, - EndpointType::Isochronous => 0b01, - EndpointType::Bulk => 0b10, - EndpointType::Interrupt => 0b11, - } - } -} - -impl UsbBus for Bus { - // TODO: just allocate. enable() is called after this and can - // enable the endpoints. gets called with ep0 - fn alloc_ep( - &mut self, - dir: UsbDirection, - ep_addr: Option, - ep_type: EndpointType, - max_packet_size: u16, - _interval: u8 - ) -> Result { - logln!("--- alloc_ep {:?} {:?} {:?} {}", dir, ep_addr, ep_type, max_packet_size); - let fd = self.usbg.hptflen.read().hptxfd().bits(); - let sar = self.usbg.hptflen.read().hptxfsar().bits(); - logln!("fd: 0x{:08x} sar: 0x{:08x}", fd, sar); - let ep_alloc = if dir == UsbDirection::Out { - &mut self.ep_out_alloc - } else { - &mut self.ep_in_alloc - }; - interrupt::free(|_cs| { - let mpl = mpl_from_int(max_packet_size as usize)?; - let next = { - let a = ep_alloc.next_ep()?; - EndpointAddress::from_parts(a, dir) - }; - let addr = match ep_addr { - None => next, - Some(a) => { - if ep_alloc.is_free(a.index())? { - a - } else { - return Err(UsbError::InvalidEndpoint); - } - }, - }; - let eptype = ep_type.to_bits(); - // i yield! i can think of no good way to cover all cases - // without macros. - unsafe { - logln!("checking dir/idx"); - match (dir, addr.index()) { - (_, 0) => { - let nfd = self.usbg.diep0tflen().read().iep0txfd().bits(); - let nsar = self.usbg.diep0tflen().read().iep0txrsar().bits(); - logln!("{}ifd: 0x{:08x} sar: 0x{:08x}", 0, nfd, nsar); - self.usbd.diep0ctl.modify(|_, w| { - w - .bits(mpl.into()) - .epen().clear_bit() - }); - - self.usbd.doep0ctl.modify(|_, w| { - w - .bits(mpl.into()) - .epen().clear_bit() - }); - } - - (UsbDirection::In, 1) => { - let nfd = self.usbg.diep1tflen.read().ieptxfd().bits(); - let nsar = self.usbg.diep1tflen.read().ieptxrsar().bits(); - logln!("{}ifd: 0x{:08x} sar: 0x{:08x}", 1, nfd, nsar); - self.usbd.diep1ctl.modify(|_, w| { - w - .eptype().bits(eptype) - .mpl().bits(mpl.into()) - .epen().clear_bit() - }); - } - (UsbDirection::Out, 1) => { - self.usbd.doep1ctl.modify(|_, w| { - w - .eptype().bits(eptype) - .mpl().bits(mpl.into()) - .epen().clear_bit() - }); - } - (UsbDirection::In, 2) => { - let nfd = self.usbg.diep2tflen.read().ieptxfd().bits(); - let nsar = self.usbg.diep2tflen.read().ieptxrsar().bits(); - logln!("{}ifd: 0x{:08x} sar: 0x{:08x}", 2, nfd, nsar); - self.usbd.diep2ctl.modify(|_, w| { - w - .eptype().bits(eptype) - .mpl().bits(mpl.into()) - .epen().clear_bit() - }); - } - (UsbDirection::Out, 2) => { - self.usbd.doep2ctl.modify(|_, w| { - w - .eptype().bits(eptype) - .mpl().bits(mpl.into()) - .epen().clear_bit() - }); - } - (UsbDirection::In, 3) => { - let nfd = self.usbg.diep3tflen.read().ieptxfd().bits(); - let nsar = self.usbg.diep3tflen.read().ieptxrsar().bits(); - logln!("{}ifd: 0x{:08x} sar: 0x{:08x}", 3, nfd, nsar); - self.usbd.diep3ctl.modify(|_, w| { - w - .eptype().bits(eptype) - .mpl().bits(mpl.into()) - .epen().clear_bit() - }); - } - (UsbDirection::Out, 3) => { - self.usbd.doep3ctl.modify(|_, w| { - w - .eptype().bits(eptype) - .mpl().bits(mpl.into()) - .epen().clear_bit() - }); - } - (dir, ep) => { - logln!("--- couldn't alloc ep for {:?} {}", dir, ep); - return Err(UsbError::EndpointOverflow) - }, - } - } - - ep_alloc.alloc(addr.index())?; - logln!("--- allocated ep for {:?} {}", dir, addr.index()); - Ok(addr) - }) - } - - // reset() is called after this. start enumeration there - fn enable(&mut self) { - logln!("--- enable"); - interrupt::free(|_cs| { - // power off the bus - self.usbg.gccfg.modify(|_, w| w.pwron().clear_bit()); - - self.usbg.gahbcs.modify(|_, w| w.ginten().clear_bit()); - - // See: [[file:~/src/GD32VF103_Firmware_Library/Firmware/GD32VF103_usbfs_driver/Include/drv_usb_regs.h::define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */]] and [[file:~/src/GD32VF103_Firmware_Library/Firmware/GD32VF103_usbfs_driver/Source/drv_usb_core.c::usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY;]] - // GUSBCS_EMBPHY ?? bit 6 - self.usbg.gusbcs.modify(|r, w| unsafe { w.bits(r.bits() | 1 << 6) }); - - // usb_core_reset - self.usbg.grstctl.modify(|_, w| w.csrst().set_bit()); - while self.usbg.grstctl.read().csrst().bit_is_set() {} - unsafe { delay(108_000 * 3) }; - - self.usbg.gccfg.modify(|_, w| { - w - .pwron().set_bit() - .vbusacen().set_bit() - .vbusbcen().set_bit() - .sofoen().set_bit() - }); - - // delay 20ms - unsafe { delay(108_000 * 20) }; - - // RST should trigger when the host notices the device, - // which will proceed to ‘reset()’ - }); - logln!("--- enable: done"); - } - - // everything is allocated, the device is enabled. now reset - // everything to begin enumeration - fn reset(&self) { - logln!("--- reset"); - // program d[oi]ep[0123]ctl - // d[oi]epinten - // d[oi]eplen - // set epen in ctl reg - - interrupt::free(|_cs| { - for ep in self.ep_out_alloc.iter() { - match ep { - 0 => self.usbd.doep0ctl.modify(|_, w| w.epen().set_bit()), - 1 => self.usbd.doep1ctl.modify(|_, w| w.epen().set_bit()), - 2 => self.usbd.doep2ctl.modify(|_, w| w.epen().set_bit()), - 3 => self.usbd.doep3ctl.modify(|_, w| w.epen().set_bit()), - _ => (), - } - } - - for ep in self.ep_in_alloc.iter() { - match ep { - 0 => self.usbd.diep0ctl.modify(|_, w| w.epen().set_bit()), - 1 => self.usbd.diep1ctl.modify(|_, w| w.epen().set_bit()), - 2 => self.usbd.diep2ctl.modify(|_, w| w.epen().set_bit()), - 3 => self.usbd.diep3ctl.modify(|_, w| w.epen().set_bit()), - _ => (), - } - } - - // wait for enum interrupt in gintf register - }); - } - - fn set_device_address(&self, address: u8) { - logln!("--- set_device_address"); - interrupt::free(|_cs| { - self.usbd.dcfg.modify(|_, w| unsafe { w.dar().bits(address & 7) }); - }); - } - - fn write(&self, _ep_addr: EndpointAddress, buf: &[u8]) -> Result { - logln!("--- write"); - assert!(buf.as_ptr() as u8 & 0b11 == 0); - interrupt::free(|_cs| { - // new - set ep fifo - self.usbg.diep1tflen.modify(|_, w| { - unsafe { - w - // depth (in 32 bit words) - .ieptxfd().bits((buf.len() >> 2).try_into().unwrap()) - // ram start address (in 32 bit words) - .ieptxrsar().bits((buf.as_ptr() as usize >> 2).try_into().unwrap()) - } - }); - }); - Err(UsbError::WouldBlock) - } - - fn read(&self, ep_addr: EndpointAddress, _buf: &mut [u8]) -> Result { - logln!("--- read"); - interrupt::free(|_cs| { - match ep_addr.index() { - 0 => { - let v = &self.usbd.doep0len; - logln!(" 0tlen: {}", v.read().tlen().bits()); - logln!(" 0pcnt: {}", v.read().pcnt().bits()); - logln!(" 0stpcnt: {}", v.read().stpcnt().bits()); - }, - 1 => { - let v = &self.usbd.doep1len; - logln!(" 1tlen: {}", v.read().tlen().bits()); - logln!(" 1pcnt: {}", v.read().pcnt().bits()); - logln!(" 1stpcnt_rxdpid: {}", v.read().stpcnt_rxdpid().bits()); - }, - 2 => { - let v = &self.usbd.doep1len; - logln!(" 2tlen: {}", v.read().tlen().bits()); - logln!(" 2pcnt: {}", v.read().pcnt().bits()); - logln!(" 2stpcnt_rxdpid: {}", v.read().stpcnt_rxdpid().bits()); - }, - 3 => { - let v = &self.usbd.doep1len; - logln!(" 3tlen: {}", v.read().tlen().bits()); - logln!(" 3pcnt: {}", v.read().pcnt().bits()); - logln!(" 3stpcnt_rxdpid: {}", v.read().stpcnt_rxdpid().bits()); - }, - ep => logln!(" bad ep {}", ep), - }; - - // rx fifo through grstatr/grstatp - let ep = usize::from(self.usbg.grstatr_device().read().epnum().bits()); - let packet_waiting = self.usbg.grstatr_device().read().rpckst().bits() != 1; - logln!(" grstatr: {}", self.usbg.grstatr_device().read().bits()); - logln!(" bcountn: {}", self.usbg.grstatr_device().read().bcount().bits()); - logln!(" dpid: {}", self.usbg.grstatr_device().read().dpid().bits()); - logln!(" rpckst: {}", self.usbg.grstatr_device().read().rpckst().bits()); - logln!(" ep: {}, waiting: {}", ep, packet_waiting); - if packet_waiting && ep == ep_addr.index() { - logln!(" pkt match"); - Ok(0) - } else { - logln!(" wouldblock"); - Err(UsbError::WouldBlock) - } - }) - } - - fn set_stalled(&self, ep_addr: EndpointAddress, _stalled: bool) { - logln!("--- set_stalled"); - let ep = ep_addr.index(); - interrupt::free(|_cs| { - if ep_addr.direction() == UsbDirection::Out { - if self.ep_out_alloc.is_alloc(ep).is_ok() { - match ep { - 0 => self.usbd.doep0ctl.modify(|_, w| w.stall().set_bit()), - 1 => self.usbd.doep1ctl.modify(|_, w| w.stall().set_bit()), - 2 => self.usbd.doep2ctl.modify(|_, w| w.stall().set_bit()), - 3 => self.usbd.doep3ctl.modify(|_, w| w.stall().set_bit()), - _ => (), - } - } - } else if let Ok(_) = self.ep_in_alloc.is_alloc(ep) { - match ep { - 0 => self.usbd.diep0ctl.modify(|_, w| w.epd().set_bit().stall().set_bit()), - 1 => self.usbd.diep1ctl.modify(|_, w| w.epd().set_bit().stall().set_bit()), - 2 => self.usbd.diep2ctl.modify(|_, w| w.epd().set_bit().stall().set_bit()), - 3 => self.usbd.diep3ctl.modify(|_, w| w.epd().set_bit().stall().set_bit()), - _ => (), - } - } - }) - } - - fn is_stalled(&self, ep_addr: EndpointAddress) -> bool { - logln!("--- is_stalled"); - let ep = ep_addr.index(); - interrupt::free(|_cs| { - if ep_addr.direction() == UsbDirection::Out { - if self.ep_out_alloc.is_alloc(ep).is_ok() { - match ep { - 0 => self.usbd.doep0ctl.read().stall().bit_is_set(), - 1 => self.usbd.doep1ctl.read().stall().bit_is_set(), - 2 => self.usbd.doep2ctl.read().stall().bit_is_set(), - 3 => self.usbd.doep3ctl.read().stall().bit_is_set(), - _ => false, - } - } else { - false - } - } else if let Ok(_) = self.ep_in_alloc.is_alloc(ep) { - match ep { - 0 => self.usbd.diep0ctl.read().stall().bit_is_set(), - 1 => self.usbd.diep1ctl.read().stall().bit_is_set(), - 2 => self.usbd.diep2ctl.read().stall().bit_is_set(), - 3 => self.usbd.diep3ctl.read().stall().bit_is_set(), - _ => false, - } - } else { - false - } - }) - } - - fn suspend(&self) { - logln!("--- suspend"); - /* - __IO uint32_t devstat = udev->regs.dr->DSTAT; - - if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { - /* switch-off the USB clocks */ - *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; - - /* enter DEEP_SLEEP mode with LDO in low power mode */ - pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); - } - */ - } - - fn resume(&self) { - logln!("--- resume"); - /* - if (USB_OTG_dev.bp.low_power) { - SystemInit(); - - rcu_usb_clock_config(usbfs_prescaler); - - rcu_periph_clock_enable(RCU_USBFS); - - usb_clock_active(&USB_OTG_dev); - } - - exti_interrupt_flag_clear(EXTI_18); - - */ - } - - fn poll(&self) -> PollResult { - logln!("--- poll"); - let res = interrupt::free(|_cs| { - let intf = self.usbg.gintf.read(); - if intf.rst().bit_is_set() { - PollResult::Reset - } else if intf.sp().bit_is_set() { - PollResult::Suspend - } else if intf.wkupif().bit_is_set() { - PollResult::Resume - } else { - let statd = self.usbg.grstatr_device().read(); - let mut ep_setup = 0; - let mut ep_out = 0; - let mut ep_in_complete = 0; - - // TODO: i don't know of any other way to see if there's a - // pending setup packet - if statd.rpckst().bits() != 1 { - let ep = statd.epnum().bits(); - let is_setup = statd.rpckst().bits() & 0b10 == 0b10; - if is_setup { - ep_setup |= 1 << ep; - } else { - ep_out |= 1 << ep; - } - } - - if self.usbd.doep0intf.read().tf().bit_is_set() { - ep_out |= 1 << 0; - } - if self.usbd.doep1intf.read().tf().bit_is_set() { - ep_out |= 1 << 1; - } - if self.usbd.doep2intf.read().tf().bit_is_set() { - ep_out |= 1 << 2; - } - if self.usbd.doep3intf.read().tf().bit_is_set() { - ep_out |= 1 << 3; - } - - if self.usbd.diep0intf.read().tf().bit_is_set() { - ep_in_complete |= 1 << 0; - } - if self.usbd.diep1intf.read().tf().bit_is_set() { - ep_in_complete |= 1 << 1; - } - if self.usbd.diep2intf.read().tf().bit_is_set() { - ep_in_complete |= 1 << 2; - } - if self.usbd.diep3intf.read().tf().bit_is_set() { - ep_in_complete |= 1 << 3; - } - - if ep_setup != 0 || ep_out != 0 || ep_in_complete != 0 { - PollResult::Data { ep_out, ep_in_complete, ep_setup } - } else { - PollResult::None - } - } - }); - - log!("+++ poll: "); - match res { - PollResult::Reset => logln!("reset"), - PollResult::Suspend=> logln!("suspend"), - PollResult::Resume => logln!("resume"), - PollResult::Data{ep_out, ep_in_complete, ep_setup} => logln!("data(out: {}, in: {}, setup: {})", ep_out, ep_in_complete, ep_setup), - PollResult::None => logln!("none"), - } - - res + fn ahb_frequency_hz(&self) -> u32 { + self.hclk.0 } } -- cgit v1.2.3