From a66598062eba21f52f2a8f2b76aed11787c67b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Tue, 22 Oct 2024 17:01:09 +0200 Subject: [PATCH] Update e310x-hal to new e310x --- e310x-hal/CHANGELOG.md | 4 +- e310x-hal/Cargo.toml | 12 +- e310x-hal/src/clock.rs | 35 +++-- e310x-hal/src/core/clint.rs | 117 ----------------- e310x-hal/src/core/mod.rs | 17 +-- e310x-hal/src/core/plic.rs | 252 ------------------------------------ e310x-hal/src/delay.rs | 30 ++--- e310x-hal/src/device.rs | 2 +- e310x-hal/src/interrupt.rs | 203 ----------------------------- e310x-hal/src/lib.rs | 2 - e310x-hal/src/prelude.rs | 4 + hifive1/Cargo.toml | 4 +- 12 files changed, 48 insertions(+), 634 deletions(-) delete mode 100644 e310x-hal/src/core/clint.rs delete mode 100644 e310x-hal/src/core/plic.rs delete mode 100644 e310x-hal/src/interrupt.rs diff --git a/e310x-hal/CHANGELOG.md b/e310x-hal/CHANGELOG.md index dd61301..9e8b183 100644 --- a/e310x-hal/CHANGELOG.md +++ b/e310x-hal/CHANGELOG.md @@ -8,11 +8,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Changed + +- Remove `virq` feature. Now interrupts are handled by `e310x` - Apply clippy changes - Use `portable-atomic` with `zaamo` feature to use native `amo*` operations. - Official target is now `riscv32imc-unknown-none-elf`, as it does not fully support the A extension. - Update `e310x` dependency and adapt code -- Bump MSRV to 1.72.0 to ensure a correct behavior of portable-atomic +- Bump MSRV to 1.76.0 to ensure a correct behavior of portable-atomic ## [v0.10.0] - 2023-03-28 diff --git a/e310x-hal/Cargo.toml b/e310x-hal/Cargo.toml index 57eaf03..33c148b 100644 --- a/e310x-hal/Cargo.toml +++ b/e310x-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "e310x-hal" -version = "0.11.0" +version = "0.12.0" authors = ["David Craven "] repository = "https://github.com/riscv-rust/e310x" categories = ["embedded", "hardware-support", "no-std"] @@ -8,18 +8,18 @@ description = "HAL for the E310x family of microcontrollers." keywords = ["riscv", "e310", "hal"] license = "ISC" edition = "2021" -rust-version = "1.72" +rust-version = "1.76" [dependencies] embedded-hal = { version = "0.2.6", features = ["unproven"] } nb = "1.0.0" -riscv = { version = "0.10.1", features = ["critical-section-single-hart"] } -e310x = { path = "../e310x", version = "0.11.0", features = ["rt", "critical-section"] } +riscv = { version = "0.12.1", features = ["critical-section-single-hart"] } +e310x = { path = "../e310x", version = "0.12.0", features = ["rt", "critical-section"] } portable-atomic = { version = "1.9", default-features = false} [features] g002 = ["e310x/g002"] -virq = [] +v-trap = ["e310x/v-trap"] [package.metadata.docs.rs] -features = ["g002", "virq"] +features = ["g002"] diff --git a/e310x-hal/src/clock.rs b/e310x-hal/src/clock.rs index 79fae5e..23a9818 100644 --- a/e310x-hal/src/clock.rs +++ b/e310x-hal/src/clock.rs @@ -1,7 +1,6 @@ //! Clock configuration -use crate::core::clint::MTIME; use crate::time::Hertz; -use e310x::{Aonclk as AONCLK, Prci as PRCI}; +use e310x::{Aonclk as AONCLK, Prci as PRCI, CLINT}; use riscv::interrupt; use riscv::register::mcycle; @@ -175,10 +174,10 @@ impl CoreClk { /// The resulting frequency may differ by 0-2% from the requested fn configure_pll(&self, pllref_freq: Hertz, divout_freq: Hertz) -> Hertz { let pllref_freq = pllref_freq.0; - assert!((PLLREF_MIN..=PLLREF_MAX).contains(&pllref_freq)); + assert!(PLLREF_MIN <= pllref_freq && pllref_freq <= PLLREF_MAX); let divout_freq = divout_freq.0; - assert!((DIVOUT_MIN..=DIVOUT_MAX).contains(&divout_freq)); + assert!(DIVOUT_MIN <= divout_freq && divout_freq <= DIVOUT_MAX); // Calculate PLL Output Divider settings let divider_div; @@ -205,7 +204,7 @@ impl CoreClk { 2 * (divider_div + 1) }; let pllout_freq = divout_freq * d; - assert!((PLLOUT_MIN..=PLLOUT_MAX).contains(&pllout_freq)); + assert!(PLLOUT_MIN <= pllout_freq && pllout_freq <= PLLOUT_MAX); // Calculate PLL R ratio let r = match pllref_freq { @@ -218,7 +217,7 @@ impl CoreClk { // Calculate refr frequency let refr_freq = pllref_freq / r; - assert!((REFR_MIN..=REFR_MAX).contains(&refr_freq)); + assert!(REFR_MIN <= refr_freq && refr_freq <= REFR_MAX); // Calculate PLL Q ratio let q = match pllout_freq { @@ -230,7 +229,7 @@ impl CoreClk { // Calculate the desired vco frequency let target_vco_freq = pllout_freq * q; - assert!((VCO_MIN..=VCO_MAX).contains(&target_vco_freq)); + assert!(VCO_MIN <= target_vco_freq && target_vco_freq <= VCO_MAX); // Calculate PLL F ratio let f = target_vco_freq / refr_freq; @@ -249,15 +248,15 @@ impl CoreClk { } else { (f_lo, vco_lo) }; - assert!((VCO_MIN..=VCO_MAX).contains(&vco_freq)); + assert!(VCO_MIN <= vco_freq && vco_freq <= VCO_MAX); // Calculate actual pllout frequency let pllout_freq = vco_freq / q; - assert!((PLLOUT_MIN..=PLLOUT_MAX).contains(&pllout_freq)); + assert!(PLLOUT_MIN <= pllout_freq && pllout_freq <= PLLOUT_MAX); // Calculate actual divout frequency let divout_freq = pllout_freq / d; - assert!((DIVOUT_MIN..=DIVOUT_MAX).contains(&divout_freq)); + assert!(DIVOUT_MIN <= divout_freq && divout_freq <= DIVOUT_MAX); // Calculate bit-values let r: u8 = (r - 1) as u8; @@ -291,9 +290,9 @@ impl CoreClk { // Need to wait 100 us // RTC is running at 32kHz. // So wait 4 ticks of RTC. - let mtime = MTIME; - let time = mtime.mtime() + 4; - while mtime.mtime() < time {} + let mtime = CLINT::mtimer().mtime; + let time = mtime.read() + 4; + while mtime.read() < time {} // Now it is safe to check for PLL Lock while !prci.pllcfg().read().lock().bit_is_set() {} @@ -385,19 +384,19 @@ impl Clocks { /// Measure the coreclk frequency by counting the number of aonclk ticks. fn _measure_coreclk(&self, min_ticks: u64) -> Hertz { - let mtime = MTIME; + let mtime = CLINT::mtimer().mtime; interrupt::free(|| { // Don't start measuring until we see an mtime tick - while mtime.mtime() == mtime.mtime() {} + while mtime.read() == mtime.read() {} let start_cycle = mcycle::read64(); - let start_time = mtime.mtime(); + let start_time = mtime.read(); // Wait for min_ticks to pass - while start_time + min_ticks > mtime.mtime() {} + while start_time + min_ticks > mtime.read() {} let end_cycle = mcycle::read64(); - let end_time = mtime.mtime(); + let end_time = mtime.read(); let delta_cycle: u64 = end_cycle - start_cycle; let delta_time: u64 = end_time - start_time; diff --git a/e310x-hal/src/core/clint.rs b/e310x-hal/src/core/clint.rs deleted file mode 100644 index 82912e6..0000000 --- a/e310x-hal/src/core/clint.rs +++ /dev/null @@ -1,117 +0,0 @@ -//! Core-Local Interruptor - -use e310x::Clint as CLINT; - -macro_rules! read64 { - ($hi:expr, $lo:expr) => { - loop { - let hi = $hi; - let lo = $lo; - if hi == $hi { - return ((hi as u64) << 32) | lo as u64; - } - } - }; -} - -/// Opaque msip register -pub struct MSIP { - _0: (), -} - -impl MSIP { - /// Set msip register value - pub fn set_value(&mut self, value: bool) { - unsafe { - CLINT::steal() - .msip() - .write(|w| if value { w.bits(1) } else { w.bits(0) }) - } - } -} - -/// Opaque mtime register -pub struct MTIME; - -impl MTIME { - /// Read mtime register. - #[inline] - pub fn mtime_lo(&self) -> u32 { - unsafe { CLINT::steal() }.mtime().read().bits() - } - - /// Read mtimeh register. - #[inline] - pub fn mtime_hi(&self) -> u32 { - unsafe { CLINT::steal() }.mtimeh().read().bits() - } - - /// Read mtime and mtimeh registers. - pub fn mtime(&self) -> u64 { - read64!(self.mtime_hi(), self.mtime_lo()) - } -} - -/// Opaque mtimecmp register -pub struct MTIMECMP { - _0: (), -} - -impl MTIMECMP { - /// Read mtimecmp register. - #[inline] - pub fn mtimecmp_lo(&self) -> u32 { - unsafe { CLINT::steal() }.mtimecmp().read().bits() - } - - /// Read mtimecmph register. - #[inline] - pub fn mtimecmp_hi(&self) -> u32 { - unsafe { CLINT::steal() }.mtimecmph().read().bits() - } - - /// Read mtimecmp and mtimecmph registers. - pub fn mtimecmp(&self) -> u64 { - read64!(self.mtimecmp_hi(), self.mtimecmp_lo()) - } - - /// Write mtimecmp register - #[inline] - pub fn set_mtimecmp_lo(&mut self, value: u32) { - unsafe { CLINT::steal().mtimecmp().write(|w| w.bits(value)) }; - } - - /// Write mtimecmph register - #[inline] - pub fn set_mtimecmp_hi(&mut self, value: u32) { - unsafe { CLINT::steal().mtimecmph().write(|w| w.bits(value)) }; - } - - /// Write mtimecmp and mtimecmph registers. - pub fn set_mtimecmp(&mut self, value: u64) { - // Volume II: RISC-V Privileged Architectures V1.10 p.31, figure 3.15 - self.set_mtimecmp_lo(0xffff_ffff); // No smaller than old value - self.set_mtimecmp_hi((value >> 32) as u32); // New value - self.set_mtimecmp_lo(value as u32); // New value - } -} - -/// Core-Local Interruptor abstraction -pub struct Clint { - /// Opaque msip register - pub msip: MSIP, - /// Opaque mtimecmp register - pub mtimecmp: MTIMECMP, - /// Opaque mtime register - pub mtime: MTIME, -} - -impl From for Clint { - fn from(_: CLINT) -> Self { - Clint { - msip: MSIP { _0: () }, - mtimecmp: MTIMECMP { _0: () }, - mtime: MTIME, - } - } -} diff --git a/e310x-hal/src/core/mod.rs b/e310x-hal/src/core/mod.rs index 5b8d03e..75e20d9 100644 --- a/e310x-hal/src/core/mod.rs +++ b/e310x-hal/src/core/mod.rs @@ -1,26 +1,18 @@ //! E31 core peripherals -pub mod clint; pub mod counters; -pub mod plic; + +pub use e310x::{CLINT, PLIC}; /// Core peripherals pub struct CorePeripherals { - /// Core-Local Interruptor - pub clint: clint::Clint, - - /// Platform-Level Interrupt Controller - pub plic: plic::Plic, - /// Performance counters pub counters: counters::PerformanceCounters, } impl CorePeripherals { - pub(crate) fn new(clint: e310x::Clint, plic: e310x::Plic) -> Self { + pub(crate) fn new() -> Self { Self { - clint: clint.into(), - plic: plic.into(), counters: counters::PerformanceCounters::new(), } } @@ -31,7 +23,6 @@ impl CorePeripherals { /// /// Using this function may break the guarantees of the singleton pattern. pub unsafe fn steal() -> Self { - let p = e310x::Peripherals::steal(); - Self::new(p.clint, p.plic) + Self::new() } } diff --git a/e310x-hal/src/core/plic.rs b/e310x-hal/src/core/plic.rs deleted file mode 100644 index 9f3e0a9..0000000 --- a/e310x-hal/src/core/plic.rs +++ /dev/null @@ -1,252 +0,0 @@ -//! Platform-Level Interrupt Controller -use core::marker::PhantomData; -use e310x::Interrupt; -use e310x::Plic as PLIC; -use riscv::register::{mie, mip}; - -/// Priority of a plic::Interrupt. -#[derive(Clone, Copy)] -pub enum Priority { - /// Priority 0: Never interrupt - P0, - /// Priority 1: Lowest active priority - P1, - /// Priority 2 - P2, - /// Priority 3 - P3, - /// Priority 4 - P4, - /// Priority 5 - P5, - /// Priority 6 - P6, - /// Priority 7: Highest priority - P7, -} - -impl Priority { - /// Takes a read interrupt priority or plic threshold - /// register value and returns a plic::Priority enum. - fn from(prio: u32) -> Option { - match prio { - 0 => Some(Priority::P0), - 1 => Some(Priority::P1), - 2 => Some(Priority::P2), - 3 => Some(Priority::P3), - 4 => Some(Priority::P4), - 5 => Some(Priority::P5), - 6 => Some(Priority::P6), - 7 => Some(Priority::P7), - _ => None, - } - } -} - -impl From for u32 { - /// Returns the numeric priority for writing to a - /// interrupt priority or the plic threshold register. - fn from(val: Priority) -> Self { - match val { - Priority::P0 => 0, - Priority::P1 => 1, - Priority::P2 => 2, - Priority::P3 => 3, - Priority::P4 => 4, - Priority::P5 => 5, - Priority::P6 => 6, - Priority::P7 => 7, - } - } -} - -/// Watchdog interrupt (type state) -pub struct IrqWatchdog; -/// Realtime clock interrupt (type state) -pub struct IrqRtc; -/// Uart0 interrupt (type state) -pub struct IrqUart0; - -/// Parts of `PLIC` peripheral for fine grained permissions. -pub struct Plic { - /// Opaque mext register - pub mext: MEXT, - /// Opaque threshold register - pub threshold: THRESHOLD, - /// Opaque claim register - pub claim: CLAIM, - /// Opaque watchdog register - pub wdog: INTERRUPT, - /// Opaque rtc register - pub rtc: INTERRUPT, - /// Opaque uart0 register - pub uart0: INTERRUPT, -} - -impl From for Plic { - fn from(_: PLIC) -> Self { - Plic { - mext: MEXT { _0: () }, - threshold: THRESHOLD { _0: () }, - claim: CLAIM { _0: () }, - wdog: INTERRUPT { - offset: 0, - mask: 1 << (Interrupt::WATCHDOG as u8), - priority_offset: Interrupt::WATCHDOG as usize, - _marker: PhantomData, - }, - rtc: INTERRUPT { - offset: 0, - mask: 1 << (Interrupt::RTC as u8), - priority_offset: Interrupt::RTC as usize, - _marker: PhantomData, - }, - uart0: INTERRUPT { - offset: 0, - mask: 1 << (Interrupt::UART0 as u8), - priority_offset: Interrupt::UART0 as usize, - _marker: PhantomData, - }, - } - } -} - -/// Opaque MEXT register. -pub struct MEXT { - _0: (), -} - -impl MEXT { - /// Enable MachineExternal interrupt. - #[inline] - pub fn enable(&mut self) { - unsafe { mie::set_mext() }; - } - - /// Disable MachineExternal interrupt. - #[inline] - pub fn disable(&mut self) { - unsafe { mie::clear_mext() }; - } - - /// Returns true when MachineExternal interrupt is pending. - #[inline] - pub fn is_pending(&self) -> bool { - mip::read().mext() - } -} - -/// Opaque THRESHOLD register. -pub struct THRESHOLD { - _0: (), -} - -impl THRESHOLD { - /// Returns the current active priority threshold. - pub fn get(&self) -> Priority { - // NOTE: Atomic read with no side effects. - let threshold = unsafe { PLIC::steal() }.threshold().read(); - Priority::from(threshold.bits()).unwrap() - } - - /// Sets the current active priority threshold. This - /// deactivates all interrupts with a lower priority. - pub fn set(&mut self, priority: Priority) { - // NOTE: Atomic write with no side effects. - unsafe { PLIC::steal().threshold().write(|w| w.bits(priority.into())) }; - } -} - -/// Opaque CLAIM register. -pub struct CLAIM { - _0: (), -} - -impl CLAIM { - /// Claims the interrupt with the highest priority. - pub fn claim(&mut self) -> Option { - // NOTE: Atomic read with side effects. - let intr = unsafe { PLIC::steal() }.claim().read().bits(); - - // If no interrupt is pending return None - if intr == 0 { - None - } else { - Some(Interrupt::try_from(intr as u8).unwrap()) - } - } - - /// Notifies the PLIC that a claimed interrupt is complete. - pub fn complete(&mut self, intr: Interrupt) { - // NOTE: Atomic write with side effects. - unsafe { PLIC::steal().claim().write(|w| w.bits(intr as u32)) }; - } -} - -/// Fine grained interrupt handling. -pub struct INTERRUPT { - /// Offset in to enable and pending plic registers - offset: usize, - /// Bitmask for enable and pending plic registers - mask: u32, - /// Offset in to priority plic registers - priority_offset: usize, - _marker: PhantomData, -} - -impl INTERRUPT { - /// Enable IRQ interrupt. - #[inline] - pub fn enable(&mut self) { - // NOTE: should use atomic operations - unsafe { - PLIC::steal() - .enable(self.offset) - .modify(|r, w| w.bits(r.bits() | self.mask)) - }; - } - - /// Disable IRQ interrupt. - #[inline] - pub fn disable(&mut self) { - // NOTE: should use atomic operations - unsafe { - PLIC::steal() - .enable(self.offset) - .modify(|r, w| w.bits(r.bits() & !self.mask)) - }; - } - - /// Returns true when IRQ interrupt is pending. - pub fn is_pending(&self) -> bool { - // NOTE: Atomic write without side effects. - let pending = unsafe { PLIC::steal() }.pending(self.offset).read(); - pending.bits() & self.mask == self.mask - } - - /// Returns true when WDOG interrupt is enabled. - pub fn is_enabled(&self) -> bool { - // NOTE: Atomic write without side effects. - let enabled = unsafe { PLIC::steal() }.enable(self.offset).read(); - enabled.bits() & self.mask == self.mask - } - - /// Returns the priority of the IRQ interrupt. - pub fn priority(&self) -> Priority { - // NOTE: Atomic read without side effects. - let priority = unsafe { PLIC::steal() } - .priority(self.priority_offset) - .read(); - Priority::from(priority.bits()).unwrap() - } - - /// Sets the priority of the IRQ interrupt. - pub fn set_priority(&mut self, priority: Priority) { - // NOTE: Atomic write without side effects. - unsafe { - PLIC::steal() - .priority(self.priority_offset) - .write(|w| w.bits(priority as u32)) - }; - } -} diff --git a/e310x-hal/src/delay.rs b/e310x-hal/src/delay.rs index 5a89293..596b2e2 100644 --- a/e310x-hal/src/delay.rs +++ b/e310x-hal/src/delay.rs @@ -1,9 +1,9 @@ //! # Delays use crate::clock::Clocks; -use crate::core::clint::{MTIME, MTIMECMP}; +use e310x::CLINT; use embedded_hal::blocking::delay::{DelayMs, DelayUs}; -use riscv::register::{mie, mip}; +use riscv::register::mip; /// Machine timer (mtime) as a busyloop delay provider #[derive(Default)] @@ -22,9 +22,9 @@ impl DelayUs for Delay { fn delay_us(&mut self, us: u32) { let ticks = (us as u64) * TICKS_PER_SECOND / 1_000_000; - let mtime = MTIME; - let t = mtime.mtime() + ticks; - while mtime.mtime() < t {} + let mtime = CLINT::mtimer().mtime; + let t = mtime.read() + ticks; + while mtime.read() < t {} } } @@ -83,15 +83,13 @@ impl DelayMs for Delay { /// Machine timer (mtime) as a sleep delay provider using mtimecmp pub struct Sleep { clock_freq: u32, - mtimecmp: MTIMECMP, } impl Sleep { /// Constructs a delay provider using mtimecmp register to sleep - pub fn new(mtimecmp: MTIMECMP, clocks: Clocks) -> Self { + pub fn new(clocks: Clocks) -> Self { Sleep { clock_freq: clocks.lfclk().0, - mtimecmp, } } } @@ -99,23 +97,19 @@ impl Sleep { impl DelayMs for Sleep { fn delay_ms(&mut self, ms: u32) { let ticks = (ms as u64) * (self.clock_freq as u64) / 1000; - let t = MTIME.mtime() + ticks; + let t = CLINT::mtimer().mtime.read() + ticks; - self.mtimecmp.set_mtimecmp(t); + CLINT::mtimecmp0().write(t); // Enable timer interrupt - unsafe { - mie::set_mtimer(); - } + unsafe { CLINT::mtimer_enable() }; // Wait For Interrupt will put CPU to sleep until an interrupt hits // in our case when internal timer mtime value >= mtimecmp value // after which empty handler gets called and we go into the // next iteration of this loop loop { - unsafe { - riscv::asm::wfi(); - } + riscv::asm::wfi(); // check if we got the right interrupt cause, otherwise just loop back to wfi if mip::read().mtimer() { @@ -124,9 +118,7 @@ impl DelayMs for Sleep { } // Clear timer interrupt - unsafe { - mie::clear_mtimer(); - } + CLINT::mtimer_disable(); } } diff --git a/e310x-hal/src/device.rs b/e310x-hal/src/device.rs index da0a63f..8bb56df 100644 --- a/e310x-hal/src/device.rs +++ b/e310x-hal/src/device.rs @@ -159,7 +159,7 @@ impl From for DeviceResources { }; DeviceResources { - core_peripherals: CorePeripherals::new(p.clint, p.plic), + core_peripherals: CorePeripherals::new(), peripherals, pins: p.gpio0.into(), } diff --git a/e310x-hal/src/interrupt.rs b/e310x-hal/src/interrupt.rs deleted file mode 100644 index 8599835..0000000 --- a/e310x-hal/src/interrupt.rs +++ /dev/null @@ -1,203 +0,0 @@ -//! Vectored machine external interrupt handler. -//! -//! # Notes -//! -//! - You must activate the `virq` feature to use this module. -//! -//! - The vectored handler automatically claims the PLIC interrupt source as complete. -//! Thus, users do not have to worry about this step. -//! -//! # Features -//! -//! This module provides: -//! -//! - A vectored implementation for handling each machine external interrupt source independently. -//! -//! - A linker script that provides weak symbols for all the interrupt sources of an E310X microcontroller. -//! This file must be supplied using rustflag when compiling. -//! -//! # Implementation details -//! -//! You can define a custom handler for each interrupt source (see [`e310x::interrupt::Interrupt`]). -//! For instance, if you want to define a custom handler for interrupts triggered by -//! the [`e310x::interrupt::Interrupt::GPIO0`] source, you must define the `GPIO0` function: -//! -//! ```ignore -//! #[no_mangle] -//! #[allow(non_snake_case)] -//! fn GPIO0() { -//! // define the behavior of your custom handler -//! } -//! ``` -//! -//! Note that the function must be marked as `no_mangle`. -//! You can also use the [`e310x::interrupt!`] macro. -//! -//! If a source without custom handler triggers an interruption, it executes the -//! `OtherMachineExternal` handler. This handler function is shared among all the -//! undefined interrupt sources. You can define this handler as follows: -//! -//! ```ignore,no_run -//! #[no_mangle] -//! #[allow(non_snake_case)] -//! fn OtherMachineExternal() { -//! // define the behavior of this handler -//! } -//! ``` -//! -//! By default, `OtherMachineExternal` executes the [`DefaultMachineExternal`] handler. -//! This handler is just an infinite loop. - -use crate::core::CorePeripherals; -pub use e310x::interrupt::*; - -extern "C" { - fn WATCHDOG(); - fn RTC(); - fn UART0(); - fn UART1(); - fn QSPI0(); - fn QSPI1(); - fn QSPI2(); - fn GPIO0(); - fn GPIO1(); - fn GPIO2(); - fn GPIO3(); - fn GPIO4(); - fn GPIO5(); - fn GPIO6(); - fn GPIO7(); - fn GPIO8(); - fn GPIO9(); - fn GPIO10(); - fn GPIO11(); - fn GPIO12(); - fn GPIO13(); - fn GPIO14(); - fn GPIO15(); - fn GPIO16(); - fn GPIO17(); - fn GPIO18(); - fn GPIO19(); - fn GPIO20(); - fn GPIO21(); - fn GPIO22(); - fn GPIO23(); - fn GPIO24(); - fn GPIO25(); - fn GPIO26(); - fn GPIO27(); - fn GPIO28(); - fn GPIO29(); - fn GPIO30(); - fn GPIO31(); - fn PWM0CMP0(); - fn PWM0CMP1(); - fn PWM0CMP2(); - fn PWM0CMP3(); - fn PWM1CMP0(); - fn PWM1CMP1(); - fn PWM1CMP2(); - fn PWM1CMP3(); - fn PWM2CMP0(); - fn PWM2CMP1(); - fn PWM2CMP2(); - fn PWM2CMP3(); - #[cfg(feature = "g002")] - fn I2C0(); -} - -#[no_mangle] -#[allow(non_snake_case)] -/// Default machine external interrupt handler. It is an infinite loop. -pub fn DefaultMachineExternal() { - loop { - // Prevent this from turning into a UDF instruction - // see rust-lang/rust#28728 for details - continue; - } -} - -#[cfg(not(feature = "g002"))] -const N_INTERRUPTS: usize = 51; -#[cfg(feature = "g002")] -const N_INTERRUPTS: usize = 52; - -/// Array of machine external interrupt handlers. -static HANDLERS: [unsafe extern "C" fn(); N_INTERRUPTS] = [ - WATCHDOG, - RTC, - UART0, - UART1, - QSPI0, - QSPI1, - QSPI2, - GPIO0, - GPIO1, - GPIO2, - GPIO3, - GPIO4, - GPIO5, - GPIO6, - GPIO7, - GPIO8, - GPIO9, - GPIO10, - GPIO11, - GPIO12, - GPIO13, - GPIO14, - GPIO15, - GPIO16, - GPIO17, - GPIO18, - GPIO19, - GPIO20, - GPIO21, - GPIO22, - GPIO23, - GPIO24, - GPIO25, - GPIO26, - GPIO27, - GPIO28, - GPIO29, - GPIO30, - GPIO31, - PWM0CMP0, - PWM0CMP1, - PWM0CMP2, - PWM0CMP3, - PWM1CMP0, - PWM1CMP1, - PWM1CMP2, - PWM1CMP3, - PWM2CMP0, - PWM2CMP1, - PWM2CMP2, - PWM2CMP3, - #[cfg(feature = "g002")] - I2C0, -]; - -/// Handler for vectored machine external interrupts (see the [`riscv-rt`] crate). -#[no_mangle] -#[allow(non_snake_case)] -unsafe fn MachineExternal() { - // Steal the PLIC peripheral and claim the interrupt - let mut plic = CorePeripherals::steal().plic; - let interrupt = plic.claim.claim().unwrap(); - let interrupt_n = interrupt as usize; - // Match the appropriate machine external interrupt - if interrupt_n == 0 { - // Interrupt number 0 is defined as no interrupt - } else if interrupt_n <= HANDLERS.len() { - // Execute corresponding interrupt handler - HANDLERS[interrupt_n - 1](); - } else { - // Any other interrupt number is not allowed - DefaultMachineExternal(); - } - // Claim PLIC interrupt source as complete by this handler - plic.claim.complete(interrupt); -} diff --git a/e310x-hal/src/lib.rs b/e310x-hal/src/lib.rs index 40bf01a..b040046 100644 --- a/e310x-hal/src/lib.rs +++ b/e310x-hal/src/lib.rs @@ -61,7 +61,5 @@ pub mod wdog; #[cfg(feature = "g002")] pub mod i2c; -#[cfg(feature = "virq")] -pub mod interrupt; pub use device::DeviceResources; diff --git a/e310x-hal/src/prelude.rs b/e310x-hal/src/prelude.rs index c6ccd12..4b7b561 100644 --- a/e310x-hal/src/prelude.rs +++ b/e310x-hal/src/prelude.rs @@ -7,6 +7,10 @@ pub use crate::rtc::RtcExt as _e310x_hal_rtc_RtcExt; pub use crate::stdout::Write as _e310x_hal_stdout_Write; pub use crate::time::U32Ext as _e310x_hal_time_U32Ext; pub use crate::wdog::WdogExt as _e310x_hal_wdog_WdogExt; +pub use e310x::interrupt::{ + CoreInterrupt, Exception, ExceptionNumber, ExternalInterrupt, InterruptNumber, Priority, + PriorityNumber, +}; pub use embedded_hal::digital::v2::{ InputPin as _embedded_hal_digital_v2_InputPin, OutputPin as _embedded_hal_digital_v2_OutputPin, StatefulOutputPin as _embedded_hal_digital_v2_StatefulOutputPin, diff --git a/hifive1/Cargo.toml b/hifive1/Cargo.toml index ac01280..1f2d081 100644 --- a/hifive1/Cargo.toml +++ b/hifive1/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.72" critical-section = { version = "1.1.3" } e310x-hal = { path = "../e310x-hal", version = "0.11.0" } embedded-hal = "0.2.7" -riscv = "0.10.1" +riscv = "0.12.1" nb = "1.0.0" [features] @@ -23,7 +23,7 @@ board-hifive1-revb = ["e310x-hal/g002"] board-redv = ["e310x-hal/g002"] board-lofive = [] board-lofive-r1 = ["e310x-hal/g002"] -virq = ["e310x-hal/virq"] +v-trap = ["e310x-hal/v-trap"] [package.metadata.docs.rs] features = ['board-hifive1-revb']