Skip to content

Commit 5612138

Browse files
Merge pull request #222 from rmsyn/riscv/result
riscv: add fallible functions
2 parents 9d3fb05 + 2b35502 commit 5612138

File tree

17 files changed

+795
-138
lines changed

17 files changed

+795
-138
lines changed

riscv-pac/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add `result` module for `Error` and `Result` types
13+
1014
## [v0.1.1] - 2024-02-15
1115

1216
- Fix crates.io badge links

riscv-pac/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#![no_std]
22

3+
pub mod result;
4+
5+
use result::Result;
6+
37
/// Trait for enums of target-specific external interrupt numbers.
48
///
59
/// This trait should be implemented by a peripheral access crate (PAC)
@@ -23,7 +27,7 @@ pub unsafe trait InterruptNumber: Copy {
2327

2428
/// Tries to convert a number to a valid interrupt source.
2529
/// If the conversion fails, it returns an error with the number back.
26-
fn from_number(value: u16) -> Result<Self, u16>;
30+
fn from_number(value: u16) -> Result<Self>;
2731
}
2832

2933
/// Trait for enums of priority levels.
@@ -49,7 +53,7 @@ pub unsafe trait PriorityNumber: Copy {
4953

5054
/// Tries to convert a number to a valid priority level.
5155
/// If the conversion fails, it returns an error with the number back.
52-
fn from_number(value: u8) -> Result<Self, u8>;
56+
fn from_number(value: u8) -> Result<Self>;
5357
}
5458

5559
/// Trait for enums of HART identifiers.
@@ -75,5 +79,5 @@ pub unsafe trait HartIdNumber: Copy {
7579

7680
/// Tries to convert a number to a valid HART ID.
7781
/// If the conversion fails, it returns an error with the number back.
78-
fn from_number(value: u16) -> Result<Self, u16>;
82+
fn from_number(value: u16) -> Result<Self>;
7983
}

riscv-pac/src/result.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use core::fmt;
2+
3+
/// Convenience alias for the [Result](core::result::Result) type for the library.
4+
pub type Result<T> = core::result::Result<T, Error>;
5+
6+
/// Represents error variants for the library.
7+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8+
pub enum Error {
9+
/// Attempted out-of-bounds access.
10+
IndexOutOfBounds {
11+
index: usize,
12+
min: usize,
13+
max: usize,
14+
},
15+
/// Invalid field value.
16+
InvalidFieldValue {
17+
field: &'static str,
18+
value: usize,
19+
bitmask: usize,
20+
},
21+
/// Invalid value of a register field that does not match any known variants.
22+
InvalidFieldVariant { field: &'static str, value: usize },
23+
/// Invalid value.
24+
InvalidValue { value: usize, bitmask: usize },
25+
/// Invalid value that does not match any known variants.
26+
InvalidVariant(usize),
27+
/// Unimplemented function or type.
28+
Unimplemented,
29+
}
30+
31+
impl fmt::Display for Error {
32+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33+
match self {
34+
Self::IndexOutOfBounds { index, min, max } => write!(
35+
f,
36+
"out-of-bounds access, index: {index}, min: {min}, max: {max}"
37+
),
38+
Self::InvalidFieldValue {
39+
field,
40+
value,
41+
bitmask,
42+
} => write!(
43+
f,
44+
"invalid {field} field value: {value:#x}, valid bitmask: {bitmask:#x}",
45+
),
46+
Self::InvalidFieldVariant { field, value } => {
47+
write!(f, "invalid {field} field variant: {value:#x}")
48+
}
49+
Self::InvalidValue { value, bitmask } => {
50+
write!(f, "invalid value: {value:#x}, valid bitmask: {bitmask:#x}",)
51+
}
52+
Self::InvalidVariant(value) => {
53+
write!(f, "invalid variant: {value:#x}")
54+
}
55+
Self::Unimplemented => write!(f, "unimplemented"),
56+
}
57+
}
58+
}

riscv-peripheral/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- use `riscv-pac` result types for trait implementations
13+
1014
### Fixed
1115

1216
- `clippy` fixes

riscv-peripheral/examples/e310x.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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};
56
use riscv_pac::{HartIdNumber, InterruptNumber, PriorityNumber};
67

78
#[repr(u16)]
@@ -19,9 +20,9 @@ unsafe impl HartIdNumber for HartId {
1920
}
2021

2122
#[inline]
22-
fn from_number(number: u16) -> Result<Self, u16> {
23+
fn from_number(number: u16) -> Result<Self> {
2324
if number > Self::MAX_HART_ID_NUMBER {
24-
Err(number)
25+
Err(Error::InvalidVariant(number as usize))
2526
} else {
2627
// SAFETY: valid context number
2728
Ok(unsafe { core::mem::transmute(number) })
@@ -95,9 +96,9 @@ unsafe impl InterruptNumber for Interrupt {
9596
}
9697

9798
#[inline]
98-
fn from_number(number: u16) -> Result<Self, u16> {
99+
fn from_number(number: u16) -> Result<Self> {
99100
if number == 0 || number > Self::MAX_INTERRUPT_NUMBER {
100-
Err(number)
101+
Err(Error::InvalidVariant(number as usize))
101102
} else {
102103
// SAFETY: valid interrupt number
103104
Ok(unsafe { core::mem::transmute(number) })
@@ -127,9 +128,9 @@ unsafe impl PriorityNumber for Priority {
127128
}
128129

129130
#[inline]
130-
fn from_number(number: u8) -> Result<Self, u8> {
131+
fn from_number(number: u8) -> Result<Self> {
131132
if number > Self::MAX_PRIORITY_NUMBER {
132-
Err(number)
133+
Err(Error::InvalidVariant(number as usize))
133134
} else {
134135
// SAFETY: valid priority number
135136
Ok(unsafe { core::mem::transmute(number) })

riscv-peripheral/src/aclint.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl<C: Clint> CLINT<C> {
6363
#[cfg(test)]
6464
pub(crate) mod test {
6565
use super::HartIdNumber;
66+
use riscv_pac::result::{Error, Result};
6667

6768
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6869
#[repr(u16)]
@@ -81,9 +82,9 @@ pub(crate) mod test {
8182
}
8283

8384
#[inline]
84-
fn from_number(number: u16) -> Result<Self, u16> {
85+
fn from_number(number: u16) -> Result<Self> {
8586
if number > Self::MAX_HART_ID_NUMBER {
86-
Err(number)
87+
Err(Error::InvalidVariant(number as usize))
8788
} else {
8889
// SAFETY: valid context number
8990
Ok(unsafe { core::mem::transmute(number) })
@@ -101,7 +102,7 @@ pub(crate) mod test {
101102
assert_eq!(HartId::from_number(1), Ok(HartId::H1));
102103
assert_eq!(HartId::from_number(2), Ok(HartId::H2));
103104

104-
assert_eq!(HartId::from_number(3), Err(3));
105+
assert_eq!(HartId::from_number(3), Err(Error::InvalidVariant(3)));
105106
}
106107

107108
#[allow(dead_code)]

riscv-peripheral/src/macros.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
///
3131
/// ```
3232
/// use riscv_peripheral::clint_codegen;
33+
/// use riscv_pac::result::{Error, Result};
3334
///
3435
/// /// HART IDs for the target CLINT peripheral
3536
/// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -40,9 +41,9 @@
4041
/// unsafe impl riscv_peripheral::aclint::HartIdNumber for HartId {
4142
/// const MAX_HART_ID_NUMBER: u16 = 2;
4243
/// fn number(self) -> u16 { self as _ }
43-
/// fn from_number(number: u16) -> Result<Self, u16> {
44+
/// fn from_number(number: u16) -> Result<Self> {
4445
/// if number > Self::MAX_HART_ID_NUMBER {
45-
/// Err(number)
46+
/// Err(Error::InvalidVariant(number as usize))
4647
/// } else {
4748
/// // SAFETY: valid context number
4849
/// Ok(unsafe { core::mem::transmute(number) })

riscv-peripheral/src/plic.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ pub mod pendings;
88
pub mod priorities;
99
pub mod threshold;
1010

11-
pub use riscv_pac::{HartIdNumber, InterruptNumber, PriorityNumber}; // re-export useful riscv-pac traits
11+
// re-export useful riscv-pac traits
12+
pub use riscv_pac::{HartIdNumber, InterruptNumber, PriorityNumber};
1213

1314
/// Trait for a PLIC peripheral.
1415
///
@@ -145,6 +146,7 @@ impl<P: Plic> CTX<P> {
145146
#[cfg(test)]
146147
pub(crate) mod test {
147148
use super::{HartIdNumber, InterruptNumber, PriorityNumber};
149+
use riscv_pac::result::{Error, Result};
148150

149151
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
150152
#[repr(u16)]
@@ -181,9 +183,9 @@ pub(crate) mod test {
181183
}
182184

183185
#[inline]
184-
fn from_number(number: u16) -> Result<Self, u16> {
186+
fn from_number(number: u16) -> Result<Self> {
185187
if number > Self::MAX_INTERRUPT_NUMBER || number == 0 {
186-
Err(number)
188+
Err(Error::InvalidVariant(number as usize))
187189
} else {
188190
// SAFETY: valid interrupt number
189191
Ok(unsafe { core::mem::transmute(number) })
@@ -200,9 +202,9 @@ pub(crate) mod test {
200202
}
201203

202204
#[inline]
203-
fn from_number(number: u8) -> Result<Self, u8> {
205+
fn from_number(number: u8) -> Result<Self> {
204206
if number > Self::MAX_PRIORITY_NUMBER {
205-
Err(number)
207+
Err(Error::InvalidVariant(number as usize))
206208
} else {
207209
// SAFETY: valid priority number
208210
Ok(unsafe { core::mem::transmute(number) })
@@ -219,9 +221,9 @@ pub(crate) mod test {
219221
}
220222

221223
#[inline]
222-
fn from_number(number: u16) -> Result<Self, u16> {
224+
fn from_number(number: u16) -> Result<Self> {
223225
if number > Self::MAX_HART_ID_NUMBER {
224-
Err(number)
226+
Err(Error::InvalidVariant(number as usize))
225227
} else {
226228
// SAFETY: valid context number
227229
Ok(unsafe { core::mem::transmute(number) })
@@ -241,8 +243,8 @@ pub(crate) mod test {
241243
assert_eq!(Interrupt::from_number(3), Ok(Interrupt::I3));
242244
assert_eq!(Interrupt::from_number(4), Ok(Interrupt::I4));
243245

244-
assert_eq!(Interrupt::from_number(0), Err(0));
245-
assert_eq!(Interrupt::from_number(5), Err(5));
246+
assert_eq!(Interrupt::from_number(0), Err(Error::InvalidVariant(0)),);
247+
assert_eq!(Interrupt::from_number(5), Err(Error::InvalidVariant(5)),);
246248
}
247249

248250
#[test]
@@ -257,7 +259,7 @@ pub(crate) mod test {
257259
assert_eq!(Priority::from_number(2), Ok(Priority::P2));
258260
assert_eq!(Priority::from_number(3), Ok(Priority::P3));
259261

260-
assert_eq!(Priority::from_number(4), Err(4));
262+
assert_eq!(Priority::from_number(4), Err(Error::InvalidVariant(4)),);
261263
}
262264

263265
#[test]
@@ -270,7 +272,7 @@ pub(crate) mod test {
270272
assert_eq!(Context::from_number(1), Ok(Context::C1));
271273
assert_eq!(Context::from_number(2), Ok(Context::C2));
272274

273-
assert_eq!(Context::from_number(3), Err(3));
275+
assert_eq!(Context::from_number(3), Err(Error::InvalidVariant(3)),);
274276
}
275277

276278
#[allow(dead_code)]

riscv/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1919
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
2020
- Add `Mcounteren` in-memory update functions
2121
- Add `Mstatus` vector extension support
22+
- Add fallible counterparts to all functions that `panic`
2223

2324
### Fixed
2425

riscv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ critical-section-single-hart = ["critical-section/restore-state-bool"]
2626
[dependencies]
2727
critical-section = "1.1.2"
2828
embedded-hal = "1.0.0"
29+
riscv-pac = { path = "../riscv-pac", version = "0.1.1", default-features = false }

0 commit comments

Comments
 (0)