From 0c4eb964b015961e3c90e45ef498f6c7f89eddba Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Tue, 25 Oct 2022 12:20:32 -0400 Subject: convert to gd32f303 (stm32f103) bluepill variant --- .cargo/config.toml | 13 +-- .gitignore | 1 + Cargo.lock | 313 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 21 ++-- README.org | 6 + gdbinit | 8 +- memory.x | 15 +-- src-riscv/.#main.rs | 1 + src-riscv/blink.rs | 70 ++++++++++++ src-riscv/boot.S | 11 ++ src-riscv/led.rs | 42 +++++++ src-riscv/log.rs | 36 ++++++ src-riscv/main.rs | 215 ++++++++++++++++++++++++++++++++++++ src-riscv/usb.rs | 42 +++++++ src/blink.rs | 67 ----------- src/boot.S | 11 -- src/led.rs | 24 ++-- src/log.rs | 20 ++-- src/main.rs | 285 ++++++++++++++++++++++------------------------- src/usb.rs | 42 ------- 20 files changed, 769 insertions(+), 474 deletions(-) create mode 120000 src-riscv/.#main.rs create mode 100644 src-riscv/blink.rs create mode 100644 src-riscv/boot.S create mode 100644 src-riscv/led.rs create mode 100644 src-riscv/log.rs create mode 100755 src-riscv/main.rs create mode 100755 src-riscv/usb.rs delete mode 100644 src/blink.rs delete mode 100644 src/boot.S delete mode 100755 src/usb.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index d0fb511..033305c 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,15 +1,8 @@ -[alias] -t = "test --target x86_64-unknown-linux-gnu" -xtask = "run --package xtask --" - [build] -target = "riscv32imac-unknown-none-elf" +target = "thumbv7em-none-eabihf" -[target.riscv32imac-unknown-none-elf] -runner = "riscv32-elf-gdb -x gdbinit" -#rustflags = ["-C", "link-arg=-Tdevice.lds", "-C", "link-arg=-nostdlib"] +[target.thumbv7em-none-eabihf] +runner = "arm-none-eabi-gdb -x gdbinit" rustflags = [ - "-C", "link-arg=-Tmemory.x", "-C", "link-arg=-Tlink.x", ] -#linker = "riscv32-elf-ld" diff --git a/.gitignore b/.gitignore index ea8c4bf..3f92f04 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/.gdb_history diff --git a/Cargo.lock b/Cargo.lock index 53b2efa..b17d189 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,22 +2,13 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - [[package]] name = "bare-metal" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" dependencies = [ - "rustc_version 0.2.3", + "rustc_version", ] [[package]] @@ -27,202 +18,178 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" [[package]] -name = "bit_field" -version = "0.10.1" +name = "bitfield" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" [[package]] -name = "cast" -version = "0.2.7" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bxcan" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b13b4b2ea9ab2ba924063ebb86ad895cb79f4a79bf90f27949eb20c335b30f9" dependencies = [ - "rustc_version 0.4.0", + "bitflags", + "nb 1.0.0", + "vcell", ] [[package]] -name = "embedded-dma" -version = "0.1.2" +name = "cortex-m" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c8c02e4347a0267ca60813c952017f4c5948c232474c6010a381a337f1bda4" +checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" dependencies = [ - "stable_deref_trait", + "bare-metal 0.2.5", + "bitfield", + "embedded-hal", + "volatile-register", ] [[package]] -name = "embedded-hal" -version = "0.2.7" +name = "cortex-m-rt" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7" dependencies = [ - "nb 0.1.3", - "void", + "cortex-m-rt-macros", ] [[package]] -name = "gd32vf103-pac" -version = "0.4.0" +name = "cortex-m-rt-macros" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffd430737a49edbd1c0241b58cabe79a7ac7ebe208f67dc838c1c981eb60e83" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" dependencies = [ - "bare-metal 0.2.5", - "riscv 0.6.0", - "vcell", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "gd32vf103xx-hal" +name = "cortex-m-semihosting" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bdffb2f55a16c7916b5df9c02b1dab0dc1c8545237491821a7fd98c61378e4a" +checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0" dependencies = [ - "cast", - "embedded-dma", - "embedded-hal", - "gd32vf103-pac", - "nb 0.1.3", - "riscv 0.6.0", - "vcell", - "void", + "cortex-m", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "embedded-dma" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" +dependencies = [ + "stable_deref_trait", +] [[package]] -name = "luchie" -version = "0.1.0" +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" dependencies = [ - "embedded-hal", - "gd32vf103-pac", - "gd32vf103xx-hal", - "nb 1.0.0", - "riscv 0.8.0", - "riscv-rt", - "synopsys-usb-otg", - "usb-device", - "usbd-serial", + "nb 0.1.3", + "void", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "fugit" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "7ab17bb279def6720d058cb6c052249938e7f99260ab534879281a95367a87e5" +dependencies = [ + "gcd", +] [[package]] -name = "nb" +name = "fugit-timer" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +checksum = "d9607bfc4c388f9d629704f56ede4a007546cad417b3bcd6fc7c87dc7edce04a" dependencies = [ + "fugit", "nb 1.0.0", ] [[package]] -name = "nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" - -[[package]] -name = "proc-macro2" -version = "1.0.43" +name = "gcd" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "f37978dab2ca789938a83b2f8bc1ef32db6633af9051a6cd409eff72cbaaa79a" dependencies = [ - "unicode-ident", + "paste", ] [[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +name = "luchie" +version = "0.1.0" dependencies = [ - "proc-macro2", + "cortex-m", + "cortex-m-rt", + "embedded-hal", + "nb 1.0.0", + "panic-semihosting", + "stm32f1xx-hal", + "usb-device", + "usbd-serial", + "usbd-webusb", ] [[package]] -name = "r0" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" - -[[package]] -name = "regex" -version = "1.6.0" +name = "nb" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "nb 1.0.0", ] [[package]] -name = "regex-syntax" -version = "0.6.27" +name = "nb" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" [[package]] -name = "riscv" +name = "panic-semihosting" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f0b705d428e9d0f78e2bb73093887ee58a83c9688de3faedbb4c0631c4618e" +checksum = "ee8a3e1233d9073d76a870223512ce4eeea43c067a94a445c13bd6d792d7b1ab" dependencies = [ - "bare-metal 0.2.5", - "bit_field", - "riscv-target", + "cortex-m", + "cortex-m-semihosting", ] [[package]] -name = "riscv" -version = "0.8.0" +name = "paste" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2856a701069e2d262b264750d382407d272d5527f7a51d3777d1805b4e2d3c" -dependencies = [ - "bare-metal 1.0.0", - "bit_field", - "embedded-hal", -] +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] -name = "riscv-rt" -version = "0.9.0" +name = "proc-macro2" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527ddfacbbfeed89256163c2655b0392c4aa76dd95c0189dc05044bf2c47c3f8" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ - "r0", - "riscv 0.8.0", - "riscv-rt-macros", - "riscv-target", + "unicode-ident", ] [[package]] -name = "riscv-rt-macros" -version = "0.2.0" +name = "quote" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38509d7b17c2f604ceab3e5ff8ac97bb8cd2f544688c512be75c715edaf4daf" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "riscv-target" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" -dependencies = [ - "lazy_static", - "regex", ] [[package]] @@ -231,16 +198,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.13", + "semver", ] [[package]] @@ -252,12 +210,6 @@ dependencies = [ "semver-parser", ] -[[package]] -name = "semver" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" - [[package]] name = "semver-parser" version = "0.7.0" @@ -271,33 +223,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "syn" -version = "1.0.99" +name = "stm32-usbd" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "c6c94998f166d66b210a164648a0b7866428d8f1e0740bf8a4c5edd89d4750c1" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "cortex-m", + "usb-device", + "vcell", ] [[package]] -name = "synopsys-usb-otg" -version = "0.3.0" +name = "stm32f1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5999b93d4d7e294fc26de39181dbe1428d61dd3b4046642ee0b3927ea2037c9b" +checksum = "78d0d11d776bc6f165c68c67468826b33b3eabd04c3c319df5e8476dd580002d" dependencies = [ - "embedded-hal", - "riscv 0.6.0", - "usb-device", + "bare-metal 1.0.0", + "cortex-m", + "cortex-m-rt", "vcell", ] +[[package]] +name = "stm32f1xx-hal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1232c561785bdbc59a5ab2b28c5c9429cb9ee9b04687133e59d1a34a39426943" +dependencies = [ + "bitflags", + "bxcan", + "cortex-m", + "cortex-m-rt", + "embedded-dma", + "embedded-hal", + "fugit", + "fugit-timer", + "nb 1.0.0", + "stm32-usbd", + "stm32f1", + "void", +] + +[[package]] +name = "syn" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "usb-device" @@ -316,6 +299,15 @@ dependencies = [ "usb-device", ] +[[package]] +name = "usbd-webusb" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed33ecaa7a26365f13059e753bfa23f0a4a557565499f46d255c51e737464bd8" +dependencies = [ + "usb-device", +] + [[package]] name = "vcell" version = "0.1.3" @@ -327,3 +319,12 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] diff --git a/Cargo.toml b/Cargo.toml index ce3f550..e9238a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,20 +17,23 @@ lto = true codegen-units = 1 [dependencies] -gd32vf103-pac = "0.4.0" -gd32vf103xx-hal = "0.5.0" -riscv = "0.8.0" -riscv-rt = "0.9.0" +cortex-m = "0.7.6" +cortex-m-rt = "0.7.1" nb = "1.0.0" -embedded-hal = "0.2.7" +panic-semihosting = "0.6.0" usb-device = "0.2.9" usbd-serial = "0.1.1" +usbd-webusb = "1.0.2" +embedded-hal = "0.2.7" -[dependencies.synopsys-usb-otg] -version = "0.3.0" -features = ["riscv", "fs"] +[dependencies.stm32f1xx-hal] +version = "0.9" +features = ["stm32f103", "stm32-usbd", "rt"] [[bin]] name = "luchie" test = false -bench = false \ No newline at end of file +bench = false + +[patch.crates-io] +#usb-device = { path = "../usb-device" } diff --git a/README.org b/README.org index b9da1b8..537960b 100644 --- a/README.org +++ b/README.org @@ -1,3 +1,9 @@ +* start rust container +#+begin_src shell + doas podman run --rm -v /home/bjc/src:/home/bjc/src -it --name luchie -h luchie luchie +#+end_src + + looks like the start board is a gd32vf103cbt from the tiny print silk-screened on the chip. [[https://www.tme.com/us/en-us/details/gd32vf103c-start/development-kits-others/gigadevice/][TME]] says it's a gd32vf103d6t6 — but [[https://www.gigadevice.com/products/microcontrollers/gd32-development-tools/gd32-mcu-starter-kits/][gigadevice]] says gd32vf103cbt6 which means it has 128k flash and 32k sram and 37(!) gpio pins diff --git a/gdbinit b/gdbinit index 695822f..fe53799 100644 --- a/gdbinit +++ b/gdbinit @@ -2,10 +2,12 @@ define hook-quit set confirm off end -# print demangled symbols by default +set history save on +set confirm off set print asm-demangle on -# OpenOCD set remote hardware-breakpoint-limit 4 set remote hardware-watchpoint-limit 2 -target extended-remote psyduck:3333 +target extended-remote psyduck:3334 + +monitor arm semihosting enable diff --git a/memory.x b/memory.x index 6d8ae75..56c58de 100644 --- a/memory.x +++ b/memory.x @@ -1,13 +1,10 @@ +/* Linker script for the STM32F303VCT6 */ MEMORY { - /* 0x0000_0000 is an alias for 0x08000_0000 */ - FLASH(rwx) : ORIGIN = 0x00000000, LENGTH = 128K - RAM(rw) : ORIGIN = 0x20000000, LENGTH = 32K + CCRAM : ORIGIN = 0x10000000, LENGTH = 8K + FLASH : ORIGIN = 0x08000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 40K } -REGION_ALIAS("REGION_TEXT", FLASH); -REGION_ALIAS("REGION_RODATA", FLASH); -REGION_ALIAS("REGION_DATA", RAM); -REGION_ALIAS("REGION_BSS", RAM); -REGION_ALIAS("REGION_HEAP", RAM); -REGION_ALIAS("REGION_STACK", RAM); +/* _stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM); */ +_stack_start = ORIGIN(RAM) + LENGTH(RAM); diff --git a/src-riscv/.#main.rs b/src-riscv/.#main.rs new file mode 120000 index 0000000..988fc15 --- /dev/null +++ b/src-riscv/.#main.rs @@ -0,0 +1 @@ +bjc@ditto.691749627316654132 \ No newline at end of file diff --git a/src-riscv/blink.rs b/src-riscv/blink.rs new file mode 100644 index 0000000..967cde6 --- /dev/null +++ b/src-riscv/blink.rs @@ -0,0 +1,70 @@ +use core::convert::Infallible; + +// use gd32vf103xx_hal as hal; +use stm32f30x_hal as hal; + +use hal::{ + //eclic::{self, EclicExt}, + pac::{self, Interrupt}, + prelude::*, + time::Hertz, + timer::{Event, Timer}, +}; +use nb; +use riscv::interrupt; + +use crate::led::LED; + +pub struct Task { + timer: Timer, + frequency: Hertz, + led: LED, +} + +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); } + // assert!(pac::ECLIC::is_enabled(Interrupt::TIMER6)); + timer.listen(Event::Update); + + Self { timer, frequency, led } + } + + pub fn poll(&mut self) -> nb::Result<(), Infallible> { + interrupt::free(|_cs| { + if unsafe { TIMER_FIRED } { + unsafe { TIMER_FIRED = false }; + self.led.toggle(); + self.timer.start(self.frequency); + } + }); + 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-riscv/boot.S b/src-riscv/boot.S new file mode 100644 index 0000000..d31e5fe --- /dev/null +++ b/src-riscv/boot.S @@ -0,0 +1,11 @@ + .global _start + .section .text.init +_start: + .option push + .option norelax + la gp, __global_pointer$ + .option pop + la sp, _stack_top + + csrr a0, mhartid + tail main diff --git a/src-riscv/led.rs b/src-riscv/led.rs new file mode 100644 index 0000000..536121b --- /dev/null +++ b/src-riscv/led.rs @@ -0,0 +1,42 @@ +use gd32vf103xx_hal::{ + gpio::{Floating, Input, Output, PushPull, Pxx, State, gpioa::PA7}, +}; +use embedded_hal::digital::v2::OutputPin; + +pub struct LED { + pin: Pxx>, + state: State, +} + +impl LED { + pub fn new(pin: PA7>) -> Self { + let mut p = pin.into_push_pull_output().downgrade(); + p.set_low().ok(); + Self { pin: p, state: State::Low } + } + + pub fn is_on(&self) -> bool { + match self.state { + State::High => true, + State::Low => false, + } + } + + pub fn on(&mut self) { + self.state = State::High; + self.pin.set_high().ok(); + } + + pub fn off(&mut self) { + self.state = State::Low; + self.pin.set_low().ok(); + } + + pub fn toggle(&mut self) { + if self.is_on() { + self.off(); + } else { + self.on(); + } + } +} diff --git a/src-riscv/log.rs b/src-riscv/log.rs new file mode 100644 index 0000000..ddb6792 --- /dev/null +++ b/src-riscv/log.rs @@ -0,0 +1,36 @@ +use core::fmt::{write, Arguments}; + +use gd32vf103xx_hal::{ + serial::Tx, + pac::USART1, +}; +use riscv::interrupt::{self, Mutex}; + +#[macro_export] +macro_rules! log { + ($($args:tt)+) => { + $crate::log::log_args(core::format_args!($($args)+)) + } +} + +#[macro_export] +macro_rules! logln { + () => ({ kprint!("\r\n") }); + ($fmt: literal $(, $($arg: tt)+)?) => { + log!(concat!($fmt, "\n") $(, $($arg)+)?) + } +} + +static mut TX: Mutex>> = Mutex::new(None); + +pub fn init(tx: Tx) { + interrupt::free(|_cs| { + unsafe { TX.get_mut().insert(tx) }; + }); +} + +pub fn log_args(args: Arguments) { + interrupt::free(|_cs| { + unsafe { TX.get_mut().as_mut().map(|tx| write(tx, args)) }; + }); +} diff --git a/src-riscv/main.rs b/src-riscv/main.rs new file mode 100755 index 0000000..68fa8da --- /dev/null +++ b/src-riscv/main.rs @@ -0,0 +1,215 @@ +#![no_std] +#![no_main] + +mod blink; +mod led; +mod log; +mod usb; + +// use gd32vf103xx_hal as hal; +use stm32f30x_hal as hal; + +use hal::{ + afio::AfioExt, + eclic::{self, EclicExt}, + gpio::GpioExt, + pac::{self, Peripherals}, + rcu::RcuExt, + serial::Serial, + time::{Hertz, MegaHertz}, + timer::Timer, +}; +use riscv::{ + asm::wfi, + interrupt, +}; +use riscv_rt::entry; +use usb_device::prelude::*; + +use led::LED; +use usb::{USB, UsbBus}; + +static mut EP_MEMORY: [u32; 1024] = [0; 1024]; + +#[entry] +fn main(_hartid: usize) -> ! { + let p = Peripherals::take().expect("couldn't take peripherals"); + + pac::ECLIC::reset(); + pac::ECLIC::set_threshold_level(eclic::Level::L0); + pac::ECLIC::set_level_priority_bits(eclic::LevelPriorityBits::L3P1); + + 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); + + // TODO: figure out how to use the usb serial on the start board. + // + // this version has to be wired up physically. + let serial = Serial::new( + p.USART1, + (gpioa.pa2, gpioa.pa3), + Default::default(), + &mut afio, + &mut rcu, + ); + let (tx, _rx) = serial.split(); + log::init(tx); + logln!("luchie starting"); + + let timer = Timer::::timer6(p.TIMER6, Hertz(5), &mut rcu); + let led = LED::new(gpioa.pa7); + let mut blink = blink::Task::new(timer, Hertz(5), led); + + 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() + }; + logln!("hclk: {:?}", rcu.clocks.hclk().0); + + 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() }; + + loop { + let mut can_sleep = true; + + if let Ok(_) = blink.poll() { + can_sleep = false; + } + if usb_dev.poll(&mut []) { + logln!("usb"); + can_sleep = false; + } + + if can_sleep && false { + log!("!"); + unsafe { wfi() }; + } + } +} +#[export_name="ExceptionHandler"] +fn exception_handler(_frame: &riscv_rt::TrapFrame) -> ! { + spin(); +} + +#[export_name="DefaultHandler"] +fn default_handler() -> ! { + spin(); +} + +#[export_name="MachineTimer"] +fn machine_timer() { + spin(); +} + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + interrupt::free(|_cs| { + log!("!!! panic "); + if let Some(loc) = info.location() { + log!("in {}:{} ", loc.file(), loc.line()); + } + if let Some(msg) = info.payload().downcast_ref::<&str>() { + log!("⇒ {} ", msg); + } + logln!("!!!"); + }); + spin(); +} + +fn spin() -> ! { + loop { unsafe { wfi() } }; +} + +/* +#![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 "); + if let Some(loc) = info.location() { +// log!("in {}:{} ", loc.file(), loc.line()); + } + if let Some(msg) = info.payload().downcast_ref::<&str>() { +// log!("⇒ {} ", msg); + } +// logln!("!!!"); +// }); + spin(); +} + +fn spin() -> ! { + loop { unsafe { wfi() } }; +} +*/ diff --git a/src-riscv/usb.rs b/src-riscv/usb.rs new file mode 100755 index 0000000..1ec36af --- /dev/null +++ b/src-riscv/usb.rs @@ -0,0 +1,42 @@ +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; + +#[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, +} + +unsafe impl Sync for USB {} + +unsafe impl UsbPeripheral for USB { + const REGISTERS: *const () = pac::USBFS_GLOBAL::ptr() as *const (); + + const HIGH_SPEED: bool = false; + const FIFO_DEPTH_WORDS: usize = 320; + const ENDPOINT_COUNT: usize = 4; + + fn enable() { + let rcu = unsafe { &*pac::RCU::ptr() }; + + riscv::interrupt::free(|_| { + // Enable USB peripheral + rcu.ahben.modify(|_, w| w.usbfsen().set_bit()); + + // Reset USB peripheral + rcu.ahbrst.modify(|_, w| w.usbfsrst().set_bit()); + rcu.ahbrst.modify(|_, w| w.usbfsrst().clear_bit()); + }); + } + + fn ahb_frequency_hz(&self) -> u32 { + self.hclk.0 + } +} diff --git a/src/blink.rs b/src/blink.rs deleted file mode 100644 index ba3d6ca..0000000 --- a/src/blink.rs +++ /dev/null @@ -1,67 +0,0 @@ -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; - -pub struct Task { - timer: Timer, - frequency: Hertz, - led: LED, -} - -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); } - assert!(pac::ECLIC::is_enabled(Interrupt::TIMER6)); - timer.listen(Event::Update); - - Self { timer, frequency, led } - } - - pub fn poll(&mut self) -> nb::Result<(), Infallible> { - interrupt::free(|_cs| { - if unsafe { TIMER_FIRED } { - unsafe { TIMER_FIRED = false }; - self.led.toggle(); - self.timer.start(self.frequency); - } - }); - 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/boot.S b/src/boot.S deleted file mode 100644 index d31e5fe..0000000 --- a/src/boot.S +++ /dev/null @@ -1,11 +0,0 @@ - .global _start - .section .text.init -_start: - .option push - .option norelax - la gp, __global_pointer$ - .option pop - la sp, _stack_top - - csrr a0, mhartid - tail main diff --git a/src/led.rs b/src/led.rs index 536121b..788ec81 100644 --- a/src/led.rs +++ b/src/led.rs @@ -1,17 +1,23 @@ -use gd32vf103xx_hal::{ - gpio::{Floating, Input, Output, PushPull, Pxx, State, gpioa::PA7}, +use stm32f1xx_hal::{ + gpio::{Cr, CRL, Floating, Input, Output, PushPull, gpiob::PB2}, }; -use embedded_hal::digital::v2::OutputPin; + +enum State { + Low, + High, +} + +type LEDPin = PB2; pub struct LED { - pin: Pxx>, + pin: LEDPin>, state: State, } impl LED { - pub fn new(pin: PA7>) -> Self { - let mut p = pin.into_push_pull_output().downgrade(); - p.set_low().ok(); + pub fn new(pin: LEDPin>, cr: &mut Cr) -> Self { + let mut p = pin.into_push_pull_output(cr); + p.set_low(); Self { pin: p, state: State::Low } } @@ -24,12 +30,12 @@ impl LED { pub fn on(&mut self) { self.state = State::High; - self.pin.set_high().ok(); + self.pin.set_high(); } pub fn off(&mut self) { self.state = State::Low; - self.pin.set_low().ok(); + self.pin.set_low(); } pub fn toggle(&mut self) { diff --git a/src/log.rs b/src/log.rs index ddb6792..7eb15e4 100644 --- a/src/log.rs +++ b/src/log.rs @@ -1,10 +1,14 @@ -use core::fmt::{write, Arguments}; +use core::{ + cell::RefCell, + fmt::{write, Arguments}, +}; -use gd32vf103xx_hal::{ +use stm32f1xx_hal::{ serial::Tx, pac::USART1, }; -use riscv::interrupt::{self, Mutex}; + +use cortex_m::interrupt::{self, Mutex}; #[macro_export] macro_rules! log { @@ -21,16 +25,16 @@ macro_rules! logln { } } -static mut TX: Mutex>> = Mutex::new(None); +static TX: Mutex>>> = Mutex::new(RefCell::new(None)); pub fn init(tx: Tx) { - interrupt::free(|_cs| { - unsafe { TX.get_mut().insert(tx) }; + interrupt::free(|cs| { + TX.borrow(cs).replace(Some(tx)); }); } pub fn log_args(args: Arguments) { - interrupt::free(|_cs| { - unsafe { TX.get_mut().as_mut().map(|tx| write(tx, args)) }; + interrupt::free(|cs| { + TX.borrow(cs).borrow_mut().as_mut().map(|tx| write(tx, args)); }); } diff --git a/src/main.rs b/src/main.rs index dce005a..d0dfe1a 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,191 +1,176 @@ -/* #![no_std] #![no_main] -mod blink; +//extern crate panic_semihosting; + mod led; mod log; -mod usb; - -use gd32vf103xx_hal::{ - afio::AfioExt, - eclic::{self, EclicExt}, - gpio::GpioExt, - pac::{self, Peripherals}, - rcu::RcuExt, - serial::Serial, - time::{Hertz, MegaHertz}, - timer::Timer, -}; -use riscv::{ - asm::wfi, - interrupt, -}; -use riscv_rt::entry; -use usb_device::prelude::*; use led::LED; -use usb::{USB, UsbBus}; -static mut EP_MEMORY: [u32; 1024] = [0; 1024]; +use cortex_m::{ + asm::{bkpt, wfi}, + interrupt, +}; +use cortex_m_rt::entry; +use embedded_hal::spi::{Mode, Phase, Polarity}; +use stm32f1xx_hal::{ + pac, + prelude::*, + serial::{Config, Serial, StopBits, WordLength}, + spi::Spi, + usb::{self, UsbBus}, +}; +use usb_device::prelude::*; +use usbd_serial::{SerialPort, USB_CLASS_CDC}; #[entry] -fn main(_hartid: usize) -> ! { - let p = Peripherals::take().expect("couldn't take peripherals"); - - pac::ECLIC::reset(); - pac::ECLIC::set_threshold_level(eclic::Level::L0); - pac::ECLIC::set_level_priority_bits(eclic::LevelPriorityBits::L3P1); - - 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); - - // TODO: figure out how to use the usb serial on the start board. - // - // this version has to be wired up physically. - let serial = Serial::new( - p.USART1, - (gpioa.pa2, gpioa.pa3), - Default::default(), - &mut afio, - &mut rcu, +fn main() -> ! { + let dp = pac::Peripherals::take().unwrap(); + + let mut flash = dp.FLASH.constrain(); + let rcc = dp.RCC.constrain(); + + let clocks = rcc + .cfgr + .use_hse(8.MHz()) + .sysclk(72.MHz()) // TODO: gd32 can get up to 120MHz + // .pclk1(24.MHz()) // TODO: causes issues with gd32 usb (dropped packets) and garbled usart1 output + .freeze(&mut flash.acr); + + assert!(clocks.usbclk_valid()); + + let mut gpiob = dp.GPIOB.split(); + let mut led = LED::new(gpiob.pb2, &mut gpiob.crl); + + let mut afio = dp.AFIO.constrain(); + let mut gpioa = dp.GPIOA.split(); + + let tx_pin = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh); + let rx_pin = gpioa.pa10; + let serial = Serial::usart1( + dp.USART1, + (tx_pin, rx_pin), + &mut afio.mapr, + Config::default() + .baudrate(115200.bps()) + .wordlength(WordLength::Bits8) + .parity_none() + .stopbits(StopBits::STOP1), + clocks, ); - let (tx, _rx) = serial.split(); + let (tx, _) = serial.split(); + log::init(tx); - let timer = Timer::::timer6(p.TIMER6, Hertz(5), &mut rcu); - let led = LED::new(gpioa.pa7); - let mut blink = blink::Task::new(timer, Hertz(5), led); + logln!("luchie started!"); + + // cirque spi connections to spi1: + // + // pb0 - dr + // pa4 - ss1 + // pa5 - clk1 + // pa6 - miso1 + // pa7 - mosi1 + + let dr_pin = gpiob.pb0; + let sck_pin = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl); + let miso_pin = gpioa.pa6; + let mosi_pin = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl); + let cs_pin = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); + let spi_mode = Mode { + phase: Phase::CaptureOnSecondTransition, + polarity: Polarity::IdleHigh, + }; + let spi = Spi::spi1( + dp.SPI1, + (sck_pin, miso_pin, mosi_pin), + &mut afio.mapr, + spi_mode, + 1.MHz(), + clocks, + ); - let usb = USB { - usb_global: p.USBFS_GLOBAL, - usb_device: p.USBFS_DEVICE, - usb_pwrclk: p.USBFS_PWRCLK, + // BluePill board has a pull-up resistor on the D+ line. + // Pull the D+ pin down to send a RESET condition to the USB bus. + // This forced reset is needed only for development, without it host + // will not reset your device when you upload new firmware. + let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); + usb_dp.set_low(); + // let mut delay = dp.TIM2.delay_us(&clocks); + // delay.delay_ms(10u8); + cortex_m::asm::delay(clocks.sysclk().raw() / 100); + + let usb = usb::Peripheral { + usb: dp.USB, pin_dm: gpioa.pa11, - pin_dp: gpioa.pa12, - hclk: rcu.clocks.hclk() + pin_dp: usb_dp.into_floating_input(&mut gpioa.crh), }; + let usb_bus = UsbBus::new(usb); - 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)) + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0xdead, 0xbeef)) .manufacturer("Fake company") - .product("Enumeration test") + .product("Serial port") .serial_number("TEST") - .device_class(0) + .device_class(USB_CLASS_CDC) .build(); - //let mut serial = SerialPort::new(&bus_alloc); - - unsafe { interrupt::enable() }; - loop { - let mut can_sleep = true; - - if let Ok(_) = blink.poll() { - can_sleep = false; - } - if usb_dev.poll(&mut []) { - logln!("usb"); - can_sleep = false; + logln!("."); + if !usb_dev.poll(&mut [&mut serial]) { + continue; } - if can_sleep && false { - log!("!"); - unsafe { wfi() }; + let mut buf = [0u8; 64]; + + match serial.read(&mut buf) { + Ok(count) if count > 0 => { + led.on(); + + // Echo back in upper case + for c in buf[0..count].iter_mut() { + if 0x61 <= *c && *c <= 0x7a { + *c &= !0x20; + } + } + + let mut write_offset = 0; + while write_offset < count { + match serial.write(&buf[write_offset..count]) { + Ok(len) if len > 0 => { + write_offset += len; + } + _ => {} + } + } + } + _ => {} } - } -} -#[export_name="ExceptionHandler"] -fn exception_handler(_frame: &riscv_rt::TrapFrame) -> ! { - spin(); -} - -#[export_name="DefaultHandler"] -fn default_handler() -> ! { - spin(); -} -#[export_name="MachineTimer"] -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]) { - } + led.off(); } } #[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(); } fn spin() -> ! { - loop { unsafe { wfi() } }; + bkpt(); + loop { + wfi(); + } } diff --git a/src/usb.rs b/src/usb.rs deleted file mode 100755 index 1ec36af..0000000 --- a/src/usb.rs +++ /dev/null @@ -1,42 +0,0 @@ -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; - -#[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, -} - -unsafe impl Sync for USB {} - -unsafe impl UsbPeripheral for USB { - const REGISTERS: *const () = pac::USBFS_GLOBAL::ptr() as *const (); - - const HIGH_SPEED: bool = false; - const FIFO_DEPTH_WORDS: usize = 320; - const ENDPOINT_COUNT: usize = 4; - - fn enable() { - let rcu = unsafe { &*pac::RCU::ptr() }; - - riscv::interrupt::free(|_| { - // Enable USB peripheral - rcu.ahben.modify(|_, w| w.usbfsen().set_bit()); - - // Reset USB peripheral - rcu.ahbrst.modify(|_, w| w.usbfsrst().set_bit()); - rcu.ahbrst.modify(|_, w| w.usbfsrst().clear_bit()); - }); - } - - fn ahb_frequency_hz(&self) -> u32 { - self.hclk.0 - } -} -- cgit v1.2.3