Skip to content

Commit 1d28859

Browse files
committed
Add riscv-peripheral changes as well
1 parent fd82252 commit 1d28859

File tree

11 files changed

+83
-62
lines changed

11 files changed

+83
-62
lines changed

riscv-pac/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "riscv-pac"
33
version = "0.2.0"
44
edition = "2021"
5-
rust-version = "1.61"
5+
rust-version = "1.60"
66
repository = "https://github.com/rust-embedded/riscv"
77
authors = ["The RISC-V Team <[email protected]>"]
88
categories = ["embedded", "hardware-support", "no-std"]

riscv-peripheral/CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1313

1414
### Changed
1515

16-
- Bump `riscv-pac` version
16+
- `PLIC` now expects interrupt enums to implement the `riscv_pac::ExternalInterruptNumber` trait.
1717

1818
### Fixed
1919

riscv-peripheral/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "riscv-peripheral"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2021"
55
rust-version = "1.75"
66
repository = "https://github.com/rust-embedded/riscv"

riscv-peripheral/examples/e310x.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22
//! This is a simple example of how to use the `riscv-peripheral` crate to generate
33
//! peripheral definitions for a target.
44
5-
use riscv_pac::result::{Error, Result};
6-
use riscv_pac::{HartIdNumber, InterruptNumber, PriorityNumber};
5+
use riscv_pac::{
6+
result::{Error, Result},
7+
ExternalInterruptNumber, HartIdNumber, InterruptNumber, PriorityNumber,
8+
};
79

8-
#[repr(u16)]
910
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1011
pub enum HartId {
1112
H0 = 0,
1213
}
1314

1415
unsafe impl HartIdNumber for HartId {
15-
const MAX_HART_ID_NUMBER: u16 = 0;
16+
const MAX_HART_ID_NUMBER: u16 = Self::H0 as u16;
1617

1718
#[inline]
1819
fn number(self) -> u16 {
@@ -86,7 +87,7 @@ pub enum Interrupt {
8687
}
8788

8889
unsafe impl InterruptNumber for Interrupt {
89-
const MAX_INTERRUPT_NUMBER: usize = 52;
90+
const MAX_INTERRUPT_NUMBER: usize = Self::I2C0 as usize;
9091

9192
#[inline]
9293
fn number(self) -> usize {
@@ -104,8 +105,9 @@ unsafe impl InterruptNumber for Interrupt {
104105
}
105106
}
106107

108+
unsafe impl ExternalInterruptNumber for Interrupt {}
109+
107110
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
108-
#[repr(u8)]
109111
pub enum Priority {
110112
P0 = 0,
111113
P1 = 1,
@@ -118,7 +120,7 @@ pub enum Priority {
118120
}
119121

120122
unsafe impl PriorityNumber for Priority {
121-
const MAX_PRIORITY_NUMBER: u8 = 7;
123+
const MAX_PRIORITY_NUMBER: u8 = Self::P7 as u8;
122124

123125
#[inline]
124126
fn number(self) -> u8 {

riscv-peripheral/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![no_std]
1010

1111
pub use riscv; // re-export riscv crate to allow macros to use it
12+
pub use riscv_pac::result; // re-export the result module
1213

1314
pub mod common; // common definitions for all peripherals
1415
pub mod hal; // trait implementations for embedded-hal

riscv-peripheral/src/macros.rs

+35-16
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
/// Macro to create interfaces to CLINT peripherals in PACs.
44
/// The resulting struct will be named `CLINT`, and will provide safe access to the CLINT registers.
55
///
6-
/// This macro expects 4 different argument types:
6+
/// This macro expects 5 different argument types:
77
///
88
/// - Base address (**MANDATORY**): base address of the CLINT peripheral of the target.
99
/// - Frequency (**OPTIONAL**): clock frequency (in Hz) of the `MTIME` register. It enables the `delay` method of the `CLINT` struct.
10+
/// - Async flag (**OPTIONAL**): It enables the `async_delay` method of the `CLINT struct`.
11+
/// You must activate the `embedded-hal-async` feature to use this flag.
1012
/// - Per-HART mtimecmp registers (**OPTIONAL**): a list of `mtimecmp` registers for easing access to per-HART mtimecmp regs.
1113
/// - Per-HART msip registers (**OPTIONAL**): a list of `msip` registers for easing access to per-HART msip regs.
1214
///
@@ -17,41 +19,37 @@
1719
/// ## Base address only
1820
///
1921
/// ```
20-
/// use riscv_peripheral::clint_codegen;
21-
///
22-
/// clint_codegen!(base 0x0200_0000, freq 32_768,); // do not forget the ending comma!
22+
/// riscv_peripheral::clint_codegen!(base 0x0200_0000, freq 32_768,); // do not forget the ending comma!
2323
///
24-
/// let mswi = CLINT::mswi(); // MSWI peripheral
24+
/// let mswi = CLINT::mswi(); // MSWI peripheral
2525
/// let mtimer = CLINT::mtimer(); // MTIMER peripheral
26-
/// let delay = CLINT::delay(); // For the `embedded_hal::delay::DelayNs` trait
26+
/// let delay = CLINT::delay(); // For the `embedded_hal::delay::DelayNs` trait
2727
/// ```
2828
///
2929
/// ## Base address and per-HART mtimecmp registers
3030
///
3131
/// ```
32-
/// use riscv_peripheral::clint_codegen;
3332
/// use riscv_pac::result::{Error, Result};
3433
///
3534
/// /// HART IDs for the target CLINT peripheral
3635
/// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
37-
/// #[repr(u16)]
3836
/// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
3937
///
4038
/// // Implement `HartIdNumber` for `HartId`
4139
/// unsafe impl riscv_peripheral::aclint::HartIdNumber for HartId {
4240
/// const MAX_HART_ID_NUMBER: u16 = 2;
4341
/// fn number(self) -> u16 { self as _ }
4442
/// fn from_number(number: u16) -> Result<Self> {
45-
/// if number > Self::MAX_HART_ID_NUMBER {
46-
/// Err(Error::InvalidVariant(number as usize))
47-
/// } else {
48-
/// // SAFETY: valid context number
49-
/// Ok(unsafe { core::mem::transmute(number) })
43+
/// match number {
44+
/// 0 => Ok(HartId::H0),
45+
/// 1 => Ok(HartId::H1),
46+
/// 2 => Ok(HartId::H2),
47+
/// _ => Err(Error::InvalidVariant(number as _)),
5048
/// }
5149
/// }
5250
/// }
5351
///
54-
/// clint_codegen!(
52+
/// riscv_peripheral::clint_codegen!(
5553
/// base 0x0200_0000,
5654
/// mtimecmps [mtimecmp0 = (HartId::H0, "`H0`"), mtimecmp1 = (HartId::H1, "`H1`"), mtimecmp2 = (HartId::H2, "`H2`")],
5755
/// msips [msip0=(HartId::H0,"`H0`"), msip1=(HartId::H1,"`H1`"), msip2=(HartId::H2,"`H2`")], // do not forget the ending comma!
@@ -206,7 +204,7 @@ macro_rules! clint_codegen {
206204
///
207205
/// # Note
208206
///
209-
/// You must export the `riscv_peripheral::hal::delay::DelayNs` trait in order to use delay methods.
207+
/// You must export the [`embedded_hal::delay::DelayNs`] trait in order to use delay methods.
210208
#[inline]
211209
pub const fn delay() -> $crate::hal::aclint::Delay {
212210
$crate::hal::aclint::Delay::new(Self::mtime(), Self::freq())
@@ -220,7 +218,7 @@ macro_rules! clint_codegen {
220218
///
221219
/// # Note
222220
///
223-
/// You must export the `riscv_peripheral::hal_async::delay::DelayNs` trait in order to use delay methods.
221+
/// You must export the [`embedded_hal_async::delay::DelayNs`] trait in order to use delay methods.
224222
///
225223
/// This implementation relies on the machine-level timer interrupts to wake futures.
226224
/// Therefore, it needs to schedule the machine-level timer interrupts via the `MTIMECMP` register assigned to the current HART.
@@ -264,6 +262,27 @@ macro_rules! clint_codegen {
264262
}
265263

266264
/// Macro to create interfaces to PLIC peripherals in PACs.
265+
/// The resulting struct will be named `PLIC`, and will provide safe access to the PLIC registers.
266+
///
267+
/// This macro expects 2 different argument types:
268+
///
269+
/// - Base address (**MANDATORY**): base address of the PLIC peripheral of the target.
270+
/// - Per-HART contexts (**OPTIONAL**): a list of `ctx` contexts for easing access to per-HART PLIC contexts.
271+
///
272+
/// Check the examples below for more details about the usage and syntax of this macro.
273+
///
274+
/// # Example
275+
///
276+
/// ## Base address only
277+
///
278+
/// ```
279+
/// use riscv_peripheral::clint_codegen;
280+
///
281+
/// riscv_peripheral::plic_codegen!(base 0x0C00_0000,); // do not forget the ending comma!
282+
///
283+
/// let priorities = PLIC::priorities(); // Priorities registers
284+
/// let pendings = PLIC::pendings(); // Pendings registers
285+
/// ```
267286
#[macro_export]
268287
macro_rules! plic_codegen {
269288
() => {

riscv-peripheral/src/plic.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,11 @@ impl<P: Plic> CTX<P> {
145145

146146
#[cfg(test)]
147147
pub(crate) mod test {
148-
use super::{HartIdNumber, InterruptNumber, PriorityNumber};
149148
use riscv_pac::result::{Error, Result};
149+
use riscv_pac::{ExternalInterruptNumber, HartIdNumber, InterruptNumber, PriorityNumber};
150150

151151
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
152-
#[repr(u16)]
152+
#[repr(usize)]
153153
pub(crate) enum Interrupt {
154154
I1 = 1,
155155
I2 = 2,
@@ -194,6 +194,8 @@ pub(crate) mod test {
194194
}
195195
}
196196

197+
unsafe impl ExternalInterruptNumber for Interrupt {}
198+
197199
unsafe impl PriorityNumber for Priority {
198200
const MAX_PRIORITY_NUMBER: u8 = 3;
199201

riscv-peripheral/src/plic/claim.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
//! Interrupt claim/complete register
22
3-
use crate::{common::unsafe_peripheral, plic::InterruptNumber};
3+
use crate::common::unsafe_peripheral;
4+
use riscv_pac::ExternalInterruptNumber;
45

56
unsafe_peripheral!(CLAIM, u32, RW);
67

78
impl CLAIM {
89
/// Claims the number of a pending interrupt for for the PLIC context.
910
/// If no interrupt is pending for this context, it returns [`None`].
1011
#[inline]
11-
pub fn claim<I: InterruptNumber>(self) -> Option<I> {
12+
pub fn claim<I: ExternalInterruptNumber>(self) -> Option<I> {
1213
match self.register.read() {
1314
0 => None,
1415
i => Some(I::from_number(i as _).unwrap()),
@@ -22,7 +23,7 @@ impl CLAIM {
2223
/// If the source ID does not match an interrupt source that is
2324
/// currently enabled for the target, the completion is silently ignored.
2425
#[inline]
25-
pub fn complete<I: InterruptNumber>(self, source: I) {
26+
pub fn complete<I: ExternalInterruptNumber>(self, source: I) {
2627
self.register.write(source.number() as _)
2728
}
2829
}
@@ -31,6 +32,7 @@ impl CLAIM {
3132
mod test {
3233
use super::super::test::Interrupt;
3334
use super::*;
35+
use riscv_pac::InterruptNumber;
3436

3537
#[test]
3638
fn test_claim() {

riscv-peripheral/src/plic/enables.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
//! Interrupt enables register of a PLIC context.
22
3-
use crate::{
4-
common::{Reg, RW},
5-
plic::InterruptNumber,
6-
};
3+
use crate::common::{Reg, RW};
4+
use riscv_pac::ExternalInterruptNumber;
75

86
/// Enables register of a PLIC context.
97
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -31,8 +29,8 @@ impl ENABLES {
3129

3230
/// Checks if an interrupt source is enabled for the PLIC context.
3331
#[inline]
34-
pub fn is_enabled<I: InterruptNumber>(self, source: I) -> bool {
35-
let source = source.number() as usize;
32+
pub fn is_enabled<I: ExternalInterruptNumber>(self, source: I) -> bool {
33+
let source = source.number();
3634
let offset = (source / u32::BITS as usize) as _;
3735
// SAFETY: valid interrupt number
3836
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };
@@ -49,8 +47,8 @@ impl ENABLES {
4947
///
5048
/// * Enabling an interrupt source can break mask-based critical sections.
5149
#[inline]
52-
pub unsafe fn enable<I: InterruptNumber>(self, source: I) {
53-
let source = source.number() as usize;
50+
pub unsafe fn enable<I: ExternalInterruptNumber>(self, source: I) {
51+
let source = source.number();
5452
let offset = (source / u32::BITS as usize) as _;
5553
// SAFETY: valid interrupt number
5654
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };
@@ -70,12 +68,12 @@ impl ENABLES {
7068
/// * Register must be properly aligned **for atomic operations**.
7169
/// * The register must not be accessed through non-atomic operations until this function returns.
7270
#[inline]
73-
pub unsafe fn atomic_enable<I: InterruptNumber>(
71+
pub unsafe fn atomic_enable<I: ExternalInterruptNumber>(
7472
self,
7573
source: I,
7674
order: core::sync::atomic::Ordering,
7775
) {
78-
let source = source.number() as usize;
76+
let source = source.number();
7977
let offset = (source / u32::BITS as usize) as _;
8078
// SAFETY: valid interrupt number
8179
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };
@@ -88,8 +86,8 @@ impl ENABLES {
8886
///
8987
/// It performs non-atomic read-modify-write operations, which may lead to **wrong** behavior.
9088
#[inline]
91-
pub fn disable<I: InterruptNumber>(self, source: I) {
92-
let source = source.number() as usize;
89+
pub fn disable<I: ExternalInterruptNumber>(self, source: I) {
90+
let source = source.number();
9391
let offset = (source / u32::BITS as usize) as _;
9492
// SAFETY: valid interrupt number
9593
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };
@@ -108,12 +106,12 @@ impl ENABLES {
108106
/// * Register must be properly aligned **for atomic operations**.
109107
/// * The register must not be accessed through non-atomic operations until this function returns.
110108
#[inline]
111-
pub unsafe fn atomic_disable<I: InterruptNumber>(
109+
pub unsafe fn atomic_disable<I: ExternalInterruptNumber>(
112110
self,
113111
source: I,
114112
order: core::sync::atomic::Ordering,
115113
) {
116-
let source = source.number() as usize;
114+
let source = source.number();
117115
let offset = (source / u32::BITS as usize) as _;
118116
// SAFETY: valid interrupt number
119117
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };
@@ -126,7 +124,7 @@ impl ENABLES {
126124
///
127125
///* Enabling all interrupt sources can break mask-based critical sections.
128126
#[inline]
129-
pub unsafe fn enable_all<I: InterruptNumber>(self) {
127+
pub unsafe fn enable_all<I: ExternalInterruptNumber>(self) {
130128
for offset in 0..=(I::MAX_INTERRUPT_NUMBER as u32 / u32::BITS) as isize {
131129
// SAFETY: valid offset
132130
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };
@@ -136,7 +134,7 @@ impl ENABLES {
136134

137135
/// Disables all the external interrupt sources for the PLIC context.
138136
#[inline]
139-
pub fn disable_all<I: InterruptNumber>(self) {
137+
pub fn disable_all<I: ExternalInterruptNumber>(self) {
140138
for offset in 0..=(I::MAX_INTERRUPT_NUMBER as u32 / u32::BITS) as _ {
141139
// SAFETY: valid offset
142140
let reg: Reg<u32, RW> = unsafe { Reg::new(self.ptr.offset(offset)) };

riscv-peripheral/src/plic/pendings.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
//! Interrupt pending bits register.
22
3-
use crate::{
4-
common::{Reg, RO},
5-
plic::InterruptNumber,
6-
};
3+
use crate::common::{Reg, RO};
4+
use riscv_pac::ExternalInterruptNumber;
75

86
/// Interrupts pending bits register.
97
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -31,8 +29,8 @@ impl PENDINGS {
3129

3230
/// Checks if an interrupt triggered by a given source is pending.
3331
#[inline]
34-
pub fn is_pending<I: InterruptNumber>(self, source: I) -> bool {
35-
let source = source.number() as usize;
32+
pub fn is_pending<I: ExternalInterruptNumber>(self, source: I) -> bool {
33+
let source = source.number();
3634
let offset = (source / u32::BITS as usize) as _;
3735
// SAFETY: valid interrupt number
3836
let reg: Reg<u32, RO> = unsafe { Reg::new(self.ptr.offset(offset)) };

0 commit comments

Comments
 (0)