aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2022-08-27 19:35:56 -0400
committerBrian Cully <bjc@kublai.com>2022-08-27 19:35:56 -0400
commit0f80c612d59c855a99073e583db339fe6a42b883 (patch)
tree7594496b532f6aaa75b7793efd561503f5f948a1
parent7846e30a25dfbbb2794035894d4b9e5c0f1ef41d (diff)
downloadluchie-0f80c612d59c855a99073e583db339fe6a42b883.tar.gz
luchie-0f80c612d59c855a99073e583db339fe6a42b883.zip
this is also broken, but at least it ain't mine
-rw-r--r--Cargo.lock13
-rw-r--r--Cargo.toml4
-rw-r--r--src/blink.rs62
-rwxr-xr-xsrc/main.rs126
-rwxr-xr-x[-rw-r--r--]src/usb.rs919
5 files changed, 175 insertions, 949 deletions
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",
]
@@ -281,6 +282,18 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
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<pac::TIMER6>,
frequency: Hertz,
led: LED,
- state: State,
}
+static mut TIMER_FIRED: bool = false;
+
impl Task {
pub fn new(mut timer: Timer<pac::TIMER6>, 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
index c6920e1..1ec36af 100644..100755
--- 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<bool, UsbError> {
- 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<bool, UsbError> {
- 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<usize, UsbError> {
- 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<Self::Item> {
- 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<Input<Floating>>,
+ pub pin_dp: PA12<Input<Floating>>,
+ 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<u8, UsbError> {
- 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<EndpointAddress>,
- ep_type: EndpointType,
- max_packet_size: u16,
- _interval: u8
- ) -> Result<EndpointAddress, UsbError> {
- 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<usize, UsbError> {
- 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<usize, UsbError> {
- 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
}
}