From d1bfdb0c683e7cc6aa9f783aca1c40ffda5a4b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Wed, 4 Sep 2024 15:43:21 +0200 Subject: [PATCH] update to new HAL --- .cargo/config | 8 ---- .cargo/config.toml | 9 +++++ .vscode/settings.json | 6 ++- Cargo.toml | 12 ++---- assemble.sh | 11 ------ bin/flash.a | Bin 2222 -> 0 bytes build.rs | 8 ++-- examples/gpio4.rs | 78 ++++++++++++++++++++++++++++++++++++ examples/mtimer.rs | 61 +++++++++++++++++++++++++++++ examples/virq.rs | 89 ------------------------------------------ flash.S | 45 --------------------- src/clock.rs | 6 +-- src/flash.rs | 57 +++++++++++++++++++++++++-- src/stdout.rs | 14 +++---- 14 files changed, 224 insertions(+), 180 deletions(-) delete mode 100644 .cargo/config create mode 100644 .cargo/config.toml delete mode 100755 assemble.sh delete mode 100644 bin/flash.a create mode 100644 examples/gpio4.rs create mode 100644 examples/mtimer.rs delete mode 100644 examples/virq.rs delete mode 100644 flash.S diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index aa75f41..0000000 --- a/.cargo/config +++ /dev/null @@ -1,8 +0,0 @@ -[target.riscv32imac-unknown-none-elf] -runner = "/home/steew/things/dev/bin/riscv-sifive/bin/riscv64-unknown-elf-gdb -q -x gdb_init" -rustflags = [ - "-C", "link-arg=-Thifive1-link.x", -] - -[build] -target = "riscv32imac-unknown-none-elf" diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..6f096c8 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,9 @@ +[target.'cfg(all(target_arch = "riscv32", target_os = "none"))'] +runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -kernel" +# runner = "riscv64-unknown-elf-gdb -q -x gdb_init" +rustflags = [ + "-C", "link-arg=-Thifive1-link.x", +] + +[build] +target = "riscv32imac-unknown-none-elf" diff --git a/.vscode/settings.json b/.vscode/settings.json index 4302e07..49346de 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,5 @@ { - "cortex-debug.variableUseNaturalFormat": true -} \ No newline at end of file + "cortex-debug.variableUseNaturalFormat": true, + "rust-analyzer.cargo.features": ["board-redv"], + "rust-analyzer.check.allTargets": false, +} diff --git a/Cargo.toml b/Cargo.toml index 8781071..90e11dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,13 +7,13 @@ categories = ["embedded", "hardware-support", "no-std"] description = "Board support crate for HiFive1 and LoFive boards" keywords = ["riscv", "register", "peripheral"] license = "ISC" -edition = "2018" +edition = "2021" [dependencies] e310x-hal = {git = "https://github.com/greenlsi/e310x-hal"} embedded-hal = "0.2.5" -riscv = "0.6.0" -riscv-rt = "0.11.0" +riscv = { git = "https://github.com/rust-embedded/riscv", branch = "riscv-pac-only", features = ["critical-section-single-hart"]} # TODO use crates.io +riscv-rt = { git = "https://github.com/rust-embedded/riscv", branch = "riscv-pac-only" } # TODO use crates.io nb = "1.0.0" panic-halt = "0.2.0" @@ -23,11 +23,7 @@ board-hifive1-revb = ["e310x-hal/g002"] board-redv = ["e310x-hal/g002"] board-lofive = [] board-lofive-r1 = ["e310x-hal/g002"] -v-extern = ["e310x-hal/v-extern"] - -[[example]] -name = "virq" -required-features = ["v-extern"] +v-trap = ["e310x-hal/v-trap"] [package.metadata.docs.rs] features = ['board-hifive1-revb'] diff --git a/assemble.sh b/assemble.sh deleted file mode 100755 index 3a04536..0000000 --- a/assemble.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -euxo pipefail - -# remove existing blobs because otherwise this will append object files to the old blobs -rm -f bin/*.a - -riscv64-unknown-elf-gcc -ggdb3 -fdebug-prefix-map=$(pwd)=/hifive1 -c -mabi=ilp32 -march=rv32imac flash.S -o bin/flash.o -riscv64-unknown-elf-ar crs bin/flash.a bin/flash.o - -rm bin/flash.o diff --git a/bin/flash.a b/bin/flash.a deleted file mode 100644 index 4c734e21c25daa429a7aced6fcbdaeb1545f37ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2222 zcma)6&rcIU6n@ifD@7=U5+x#L6-A6@DGS2I5J;>hhUft`Mh~!s0!_+~Y?lU&iNup8 z9zE#IgE2jL@Fs~~JaF{D-=GJNCSFWT)bGuY?Y2PlCG+O{-n{wV%(!+*wA$x#^?q;AU6`@G2Xze*&>k9?qPvU<7iQ!4-Db2dS3wH^45 z+D`x51bxeYxsmv-d^VYkf8R~yYrBuPUPH;E6YxU(O1Hzy@>qhOjxYMEK(qgGv9Hy(+Z`o5bw(E?zoYsc+2PQ~76zws|&2-k8 z8ieypmH8?OKFfq(9dS$UdTw@woyTq-&dfQew;H}Se;KuElW!psHH&b#(ZD`DI&2X> zSTvyX>u1rdhZ}+XmT->Zoe>^F0E_rh)Xkz~Q@u1IL}Ot}T%P4Xgm(d7i0}{sSadi_ z!P}d7x`}6~M@M*%8SIyw>6{Jc#)jdCwRfrU6>~1u!4AfsH={T0Fy=+V&Z7z55R5ya zm&5l(=%uiP&91bPQyGfi^RC8$7D_5qdWfV?90xqqhWX<^a+p2;W^}X6yk12J_e* z5SxKEeeG!jJX$vc!uOWz^0ha0p8~U94vlRSq)$QVd5qgj-OC`{3j}RL(6b)fbF^sP z!AMwCdI%(U`J7)-buF1x|xns<~BCv(Vzk{P_tjF(^pE&eFTL9Vbd+`3F Nd6N*>4rkTt{sl;fv@QSu diff --git a/build.rs b/build.rs index ec4ac5f..9408687 100644 --- a/build.rs +++ b/build.rs @@ -46,8 +46,8 @@ fn main() { println!("cargo:rerun-if-changed=hifive1-link.x"); // Copy library with flash setup code - let name = env::var("CARGO_PKG_NAME").unwrap(); - fs::copy("bin/flash.a", out_dir.join(format!("lib{}.a", name))).unwrap(); - println!("cargo:rustc-link-lib=static={}", name); - println!("cargo:rerun-if-changed=bin/flash.a"); + // let name = env::var("CARGO_PKG_NAME").unwrap(); + // fs::copy("bin/flash.a", out_dir.join(format!("lib{}.a", name))).unwrap(); + // println!("cargo:rustc-link-lib=static={}", name); + println!("cargo:rerun-if-changed=src/flash.S"); } diff --git a/examples/gpio4.rs b/examples/gpio4.rs new file mode 100644 index 0000000..343fc12 --- /dev/null +++ b/examples/gpio4.rs @@ -0,0 +1,78 @@ +//! Demonstration on how to configure the GPIO4 interrupt on HiFive boards. +//! You must connect a button to pin 12 (GPIO4) and ground to test this example. + +#![no_main] +#![no_std] + +extern crate panic_halt; + +use hifive1::hal::e310x::PLIC; +use hifive1::{hal::prelude::*, hal::DeviceResources, pin, sprintln}; + +use riscv::register::mstatus; +use riscv_rt::entry; + +/* Handler for the GPIO0 interrupt */ +#[riscv_rt::external_interrupt(ExternalInterrupt::GPIO4)] +fn gpio4_handler() { + sprintln!("We reached the GPIO4 interrupt!"); + /* Clear the GPIO pending interrupt */ + let gpio_block = unsafe { hifive1::hal::e310x::Gpio0::steal() }; + gpio_block.fall_ip().write(|w| w.pin4().set_bit()); +} + +/* Code adapted from https://github.com/riscv-rust/riscv-rust-quickstart/blob/interrupt-test/examples/interrupt.rs*/ +#[entry] +fn main() -> ! { + /* Get the ownership of the device resources singleton */ + let resources = DeviceResources::take().unwrap(); + let peripherals = resources.peripherals; + + /* Configure system clock */ + let sysclock = hifive1::configure_clocks(peripherals.PRCI, peripherals.AONCLK, 64.mhz().into()); + /* Get the board pins */ + let gpio = resources.pins; + + /* Configure stdout for debugging */ + hifive1::stdout::configure( + peripherals.UART0, + pin!(gpio, uart0_tx), + pin!(gpio, uart0_rx), + 115_200.bps(), + sysclock, + ); + + sprintln!("Configuring GPIO..."); + /* Set GPIO4 (pin 12) as input */ + // let gpio4 = pin!(gpio, dig12); + gpio.pin4.into_pull_up_input(); + //let input = gpio4.into_pull_up_input(); + + sprintln!("Configuring priorities..."); + /* Set interrupt source priority */ + let priorities = PLIC::priorities(); + unsafe { priorities.set_priority(ExternalInterrupt::GPIO4, Priority::P7) }; + + let gpio_block = unsafe { hifive1::hal::e310x::Gpio0::steal() }; + unsafe { + /* Clear pending interrupts from previous states */ + gpio_block.fall_ie().write(|w| w.bits(0x00000000)); + gpio_block.rise_ie().write(|w| w.bits(0x00000000)); + gpio_block.fall_ip().write(|w| w.bits(0xffffffff)); + gpio_block.rise_ip().write(|w| w.bits(0xffffffff)); + } + gpio_block.fall_ie().write(|w| w.pin4().set_bit()); + gpio_block.rise_ie().write(|w| w.pin4().clear_bit()); + + /* Activate global interrupts (mie bit) */ + let ctx = PLIC::ctx0(); + unsafe { + ctx.threshold().set_threshold(Priority::P1); + ctx.enables().enable(ExternalInterrupt::GPIO4); + mstatus::set_mie(); + PLIC::enable(); + } + loop { + riscv::asm::wfi(); + } +} diff --git a/examples/mtimer.rs b/examples/mtimer.rs new file mode 100644 index 0000000..75e504a --- /dev/null +++ b/examples/mtimer.rs @@ -0,0 +1,61 @@ +//! This example demonstrates how to configure the CLINT to generate +//! periodic interrupts using the machine timer. + +#![no_main] +#![no_std] + +extern crate panic_halt; + +use hifive1::{ + configure_clocks, + hal::{e310x::CLINT, prelude::*, DeviceResources}, + pin, sprintln, +}; + +const PERIOD_MS: u64 = 1000; +const FREQUENCY_HZ: u64 = 32768; +const CLINT_TICKS_PER_MS: u64 = PERIOD_MS * FREQUENCY_HZ / 1000; + +/// Handler for the machine timer interrupt (handled by the CLINT) +#[riscv_rt::core_interrupt(CoreInterrupt::MachineTimer)] +fn mtimer_handler() { + sprintln!("MTIMER interrupt!"); + CLINT::mtimecmp0().modify(|f| *f += CLINT_TICKS_PER_MS); +} + +#[riscv_rt::entry] +fn main() -> ! { + /* Get the ownership of the device resources singleton */ + let resources = DeviceResources::take().unwrap(); + let peripherals = resources.peripherals; + + /* Configure system clock */ + let sysclock = configure_clocks(peripherals.PRCI, peripherals.AONCLK, 64.mhz().into()); + + /* Configure stdout for printing via UART */ + let gpio = resources.pins; + hifive1::stdout::configure( + peripherals.UART0, + pin!(gpio, uart0_tx), + pin!(gpio, uart0_rx), + 115_200.bps(), + sysclock, + ); + + sprintln!("Configuring CLINT..."); + CLINT::mtimer_disable(); + let mtimer = CLINT::mtimer(); + let (mtimecmp, mtime) = (mtimer.mtimecmp0, mtimer.mtime); + mtime.write(0); + mtimecmp.write(CLINT_TICKS_PER_MS); + + sprintln!("Enabling interrupts..."); + unsafe { + riscv::interrupt::enable(); + CLINT::mtimer_enable(); + } + loop { + sprintln!("Sleeping..."); + riscv::asm::wfi(); + } +} diff --git a/examples/virq.rs b/examples/virq.rs deleted file mode 100644 index c834cf9..0000000 --- a/examples/virq.rs +++ /dev/null @@ -1,89 +0,0 @@ -#![no_main] -#![no_std] - -/* - Demonstration on how to use the feature "virq" from e310x-hal. -This feature enables a kind of vectorized interrupt matching for -all 52 the external interrupts that e310x has. It simply offers a convenient -way to handle each interrupt separately with a function called as the interrupt source. -For example, if an interrupt for GPIO0 is received, and a no mangled function called GPIO0() -exists, that function will automatically handle the exception, and it will be automatically -marked as complete by the PLIC. -This can be applied for all the 52 interrupts declared in e310x/interrupts.rs. -*/ - -extern crate panic_halt; - -use hifive1::{hal::prelude::*, hal::DeviceResources, pin, sprintln}; - -use riscv::register::mstatus; -use riscv_rt::entry; - -/* we have chosen the GPIO4 (a.k.a dig12) for this example */ -const GPIO_N: usize = 4; - -/* Handler for the GPIO0 interrupt */ -#[no_mangle] -#[allow(non_snake_case)] -fn GPIO4() { - sprintln!("We reached the GPIO4 interrupt!"); - /* Clear the GPIO pending interrupt */ - unsafe { - let gpio_block = &*hifive1::hal::e310x::GPIO0::ptr(); - gpio_block.fall_ip.write(|w| w.bits(1 << GPIO_N)); - } -} - -/* Code adapted from https://github.com/riscv-rust/riscv-rust-quickstart/blob/interrupt-test/examples/interrupt.rs*/ -#[entry] -fn main() -> ! { - /* Get the ownership of the device resources singleton */ - let resources = DeviceResources::take().unwrap(); - let peripherals = resources.peripherals; - - /* Configure system clock */ - let sysclock = hifive1::configure_clocks(peripherals.PRCI, peripherals.AONCLK, 64.mhz().into()); - /* Get the board pins */ - let gpio = resources.pins; - - /* Configure stdout for debugging */ - hifive1::stdout::configure( - peripherals.UART0, - pin!(gpio, uart0_tx), - pin!(gpio, uart0_rx), - 115_200.bps(), - sysclock, - ); - - /* Set GPIO4 (pin 12) as input */ - // let gpio4 = pin!(gpio, dig12); - let input = gpio.pin4.into_pull_up_input(); - //let input = gpio4.into_pull_up_input(); - - /* Wrapper for easy access */ - let mut plic = resources.core_peripherals.plic; - - /* Unsafe block */ - unsafe { - /* Get raw PLIC pointer */ - //let rplic = &*hifive1::hal::e310x::PLIC::ptr(); - hifive1::hal::e310x::PLIC::set_priority( - &mut plic, - hifive1::hal::e310x::Interrupt::GPIO4, - e310x_hal::e310x::Priority::P7, - ); - let gpio_block = &*hifive1::hal::e310x::GPIO0::ptr(); - /* Enable GPIO fall interrupts */ - gpio_block.fall_ie.write(|w| w.bits(1 << GPIO_N)); - gpio_block.rise_ie.write(|w| w.bits(0x0)); - /* Clear pending interrupts from previous states */ - gpio_block.fall_ip.write(|w| w.bits(0xffffffff)); - gpio_block.rise_ip.write(|w| w.bits(0x0fffffff)); - - /* Activate global interrupts (mie bit) */ - mstatus::set_mie(); - plic.set_threshold(e310x_hal::e310x::Priority::P1); - plic.enable_interrupt(hifive1::hal::e310x::Interrupt::GPIO4); - } - loop {} -} diff --git a/flash.S b/flash.S deleted file mode 100644 index 53dd795..0000000 --- a/flash.S +++ /dev/null @@ -1,45 +0,0 @@ -.cfi_sections .debug_frame - -.section .data._setup_is25lp -.global _setup_is25lp -.cfi_startproc -_setup_is25lp: - li a1, 0x10014000 // QSPI0 base address - - // Disable mapped region - sw zero,96(a1) // fctrl.en = 0 - - // Construct ffmt value for 4 dummy cycles - li a2, 0x00BB1447 - - beqz a0, 2f - - // We need to set 8 dummy cycles instead of 4. - // Issue a "Set Read Parameters" command. - - li a0,2 - sw a0,24(a1) // csmode = HOLD - li a0,0xC0 - sw a0,72(a1) // txdata = 0xC0 - li a0,0xF0 - sw a0,72(a1) // txdata = 0xF0 - sw zero,24(a1) // csmode = AUTO - - // Discard two response bytes -1: lw a0,76(a1) - bltz a0,1b -1: lw a0,76(a1) - bltz a0,1b - - addi a2,a2,0x40 // ffmt: 4 -> 8 dummy cycles -2: - sw a2,100(a1) // Write ffmt - - // Enable mapped region - li a0, 1 - sw a0,96(a1) // fctrl.en = 1 - ret - - -.cfi_endproc -.size _setup_is25lp, . - _setup_is25lp diff --git a/src/clock.rs b/src/clock.rs index 05bd348..d91867a 100644 --- a/src/clock.rs +++ b/src/clock.rs @@ -2,7 +2,7 @@ use e310x_hal::{ clock::{AonExt, Clocks, PrciExt}, - e310x::{AONCLK, PRCI}, + e310x::{Aonclk, Prci}, time::Hertz, }; @@ -15,7 +15,7 @@ use e310x_hal::{ /// /// For HiFive1 and HiFive1 Rev B boards external oscillators are enabled for /// both high-frequency and low-frequency clocks. -pub fn configure(prci: PRCI, aonclk: AONCLK, target_coreclk: Hertz) -> Clocks { +pub fn configure(prci: Prci, aonclk: Aonclk, target_coreclk: Hertz) -> Clocks { let coreclk = prci.constrain(); let coreclk = coreclk .use_external(Hertz(16_000_000)) @@ -32,7 +32,7 @@ pub fn configure(prci: PRCI, aonclk: AONCLK, target_coreclk: Hertz) -> Clocks { /// /// For the LoFive and LoFive R1 boards, external oscillator is enabled for /// high-frequency clock. For low-frequency clock internal oscillator is used. -pub fn configure(prci: PRCI, aonclk: AONCLK, target_coreclk: Hertz) -> Clocks { +pub fn configure(prci: Prci, aonclk: Aonclk, target_coreclk: Hertz) -> Clocks { let coreclk = prci.constrain(); let coreclk = coreclk .use_external(Hertz(16_000_000)) diff --git a/src/flash.rs b/src/flash.rs index e138c99..68fbb6e 100644 --- a/src/flash.rs +++ b/src/flash.rs @@ -1,11 +1,62 @@ //! On-board SPI Flash use e310x_hal::clock::Clocks; -use e310x_hal::e310x::QSPI0; +use e310x_hal::e310x::Qspi0; + +#[cfg(target_arch = "riscv32")] +core::arch::global_asm!( + r#" +.cfi_sections .debug_frame + +.section .data._setup_is25lp +.global _setup_is25lp +.cfi_startproc +_setup_is25lp: + li a1, 0x10014000 // QSPI0 base address + + // Disable mapped region + sw zero,96(a1) // fctrl.en = 0 + + // Construct ffmt value for 4 dummy cycles + li a2, 0x00BB1447 + + beqz a0, 2f + + // We need to set 8 dummy cycles instead of 4. + // Issue a "Set Read Parameters" command. + + li a0,2 + sw a0,24(a1) // csmode = HOLD + li a0,0xC0 + sw a0,72(a1) // txdata = 0xC0 + li a0,0xF0 + sw a0,72(a1) // txdata = 0xF0 + sw zero,24(a1) // csmode = AUTO + + // Discard two response bytes +1: lw a0,76(a1) + bltz a0,1b +1: lw a0,76(a1) + bltz a0,1b + + addi a2,a2,0x40 // ffmt: 4 -> 8 dummy cycles +2: + sw a2,100(a1) // Write ffmt + + // Enable mapped region + li a0, 1 + sw a0,96(a1) // fctrl.en = 1 + ret + + +.cfi_endproc +.size _setup_is25lp, . - _setup_is25lp +"# +); /// Configure SPI Flash interface to maximum supported speed #[inline(always)] -pub fn configure_spi_flash(qspi: &QSPI0, clocks: &Clocks) { +pub fn configure_spi_flash(qspi: &Qspi0, clocks: &Clocks) { unsafe { extern "C" { fn _setup_is25lp(dummy8: bool); @@ -17,5 +68,5 @@ pub fn configure_spi_flash(qspi: &QSPI0, clocks: &Clocks) { _setup_is25lp(true) } } - qspi.sckdiv.modify(|_, w| unsafe { w.div().bits(0) }); + qspi.sckdiv().modify(|_, w| unsafe { w.div().bits(0) }); } diff --git a/src/stdout.rs b/src/stdout.rs index 68779d4..59be531 100644 --- a/src/stdout.rs +++ b/src/stdout.rs @@ -3,7 +3,7 @@ use core::fmt; use e310x_hal::{ clock::Clocks, - e310x::UART0, + e310x::Uart0, gpio::gpio0::{Pin16, Pin17}, prelude::*, serial::{Rx, Serial, Tx}, @@ -14,7 +14,7 @@ use riscv::interrupt; static mut STDOUT: Option = None; -struct SerialWrapper(Tx); +struct SerialWrapper(Tx); impl core::fmt::Write for SerialWrapper { fn write_str(&mut self, s: &str) -> fmt::Result { @@ -39,18 +39,18 @@ impl core::fmt::Write for SerialWrapper { /// Configures stdout pub fn configure( - uart: UART0, + uart: Uart0, tx: Pin17, rx: Pin16, baud_rate: Bps, clocks: Clocks, -) -> Rx { +) -> Rx { let tx = tx.into_iof0(); let rx = rx.into_iof0(); let serial = Serial::new(uart, (tx, rx), baud_rate, clocks); let (tx, rx) = serial.split(); - interrupt::free(|_| unsafe { + interrupt::free(|| unsafe { STDOUT.replace(SerialWrapper(tx)); }); rx @@ -58,7 +58,7 @@ pub fn configure( /// Writes string to stdout pub fn write_str(s: &str) { - interrupt::free(|_| unsafe { + interrupt::free(|| unsafe { if let Some(stdout) = STDOUT.as_mut() { let _ = stdout.write_str(s); } @@ -67,7 +67,7 @@ pub fn write_str(s: &str) { /// Writes formatted string to stdout pub fn write_fmt(args: fmt::Arguments) { - interrupt::free(|_| unsafe { + interrupt::free(|| unsafe { if let Some(stdout) = STDOUT.as_mut() { let _ = stdout.write_fmt(args); }