Skip to content

Commit b1881e4

Browse files
committed
Use riscv_pac::CoreInterruptNumber in xip registers
1 parent ca86c48 commit b1881e4

File tree

6 files changed

+89
-5
lines changed

6 files changed

+89
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Cargo.lock
22
target/
33

4+
.idea/
45
.vscode/
56
.DS_Store

riscv/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
- New convenience `try_new` and `new` associated functions for `Mtvec` and `Stvec`.
1313
- New methods and functions for enabling core interrupts in the `mie` and `sie` registers
14-
using the `riscv_pac::CoreInterrupt` trait.
14+
using the `riscv_pac::CoreInterruptNumber` trait.
1515
- New `riscv::interrupt::{is_interrupt_enabled, disable_interrupt, enable_interrupt}` functions.
16+
- New methods and functions for dealing with pending interrupts in `mip` and `sip` registers
17+
using the `riscv_pac::CoreInterruptNumber` trait.
18+
- New `riscv::interrupt::is_interrupt_pending` function.
1619

1720
### Changed
1821

riscv/src/interrupt/machine.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
interrupt::Trap,
3-
register::{mcause, mepc, mie, mstatus},
3+
register::{mcause, mepc, mie, mip, mstatus},
44
};
55
use riscv_pac::{
66
result::{Error, Result},
@@ -123,6 +123,12 @@ pub unsafe fn enable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
123123
mie::enable(interrupt);
124124
}
125125

126+
/// Checks if a specific core interrupt source is pending in the current hart (machine mode).
127+
#[inline]
128+
pub fn is_interrupt_pending<I: CoreInterruptNumber>(interrupt: I) -> bool {
129+
mip::read().is_pending(interrupt)
130+
}
131+
126132
/// Disables interrupts globally in the current hart (machine mode).
127133
#[inline]
128134
pub fn disable() {

riscv/src/interrupt/supervisor.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
interrupt::Trap,
3-
register::{scause, sepc, sie, sstatus},
3+
register::{scause, sepc, sie, sip, sstatus},
44
};
55
use riscv_pac::{
66
result::{Error, Result},
@@ -116,6 +116,12 @@ pub unsafe fn enable_interrupt<I: CoreInterruptNumber>(interrupt: I) {
116116
sie::enable(interrupt);
117117
}
118118

119+
/// Checks if a specific core interrupt source is pending in the current hart (supervisor mode).
120+
#[inline]
121+
pub fn is_interrupt_pending<I: CoreInterruptNumber>(interrupt: I) -> bool {
122+
sip::read().is_pending(interrupt)
123+
}
124+
119125
/// Disables interrupts globally in the current hart (supervisor mode).
120126
#[inline]
121127
pub fn disable() {

riscv/src/register/mip.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
//! mip register
22
3+
use crate::bits::{bf_extract, bf_insert};
4+
use riscv_pac::CoreInterruptNumber;
5+
36
read_write_csr! {
47
/// `mip` register
58
Mip: 0x344,
6-
mask: 0xaaa,
9+
mask: usize::MAX,
710
}
811

912
read_write_csr_field! {
@@ -42,6 +45,26 @@ read_only_csr_field! {
4245
mext: 11,
4346
}
4447

48+
impl Mip {
49+
/// Returns true when a given interrupt is pending.
50+
#[inline]
51+
pub fn is_pending<I: CoreInterruptNumber>(&self, interrupt: I) -> bool {
52+
bf_extract(self.bits, interrupt.number(), 1) != 0
53+
}
54+
55+
/// Clear the pending state of a specific core interrupt source.
56+
///
57+
/// # Safety
58+
///
59+
/// Not all interrupt sources allow clearing of pending interrupts via the `mip` register.
60+
/// Instead, it may be necessary to perform an alternative action to clear the interrupt.
61+
/// Check the specification of your target chip for details.
62+
#[inline]
63+
pub unsafe fn clear_pending<I: CoreInterruptNumber>(&mut self, interrupt: I) {
64+
self.bits = bf_insert(self.bits, interrupt.number(), 1, 0);
65+
}
66+
}
67+
4568
set!(0x344);
4669
clear!(0x344);
4770

@@ -55,6 +78,17 @@ set_clear_csr!(
5578
/// Supervisor External Interrupt Pending
5679
, set_sext, clear_sext, 1 << 9);
5780

81+
/// Clear the pending state of a specific core interrupt source.
82+
///
83+
/// # Safety
84+
///
85+
/// Not all interrupt sources allow clearing of pending interrupts via the `mip` register.
86+
/// Instead, it may be necessary to perform an alternative action to clear the interrupt.
87+
/// Check the specification of your target chip for details.
88+
pub unsafe fn clear_pending<I: CoreInterruptNumber>(interrupt: I) {
89+
_clear(1 << interrupt.number());
90+
}
91+
5892
#[cfg(test)]
5993
mod tests {
6094
use super::*;

riscv/src/register/sip.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
//! sip register
22
3+
use crate::bits::{bf_extract, bf_insert};
4+
use riscv_pac::CoreInterruptNumber;
5+
36
read_write_csr! {
47
/// sip register
58
Sip: 0x144,
6-
mask: 0x222,
9+
mask: usize::MAX,
710
}
811

912
read_write_csr_field! {
@@ -24,13 +27,44 @@ read_only_csr_field! {
2427
sext: 9,
2528
}
2629

30+
impl Sip {
31+
/// Returns true when a given interrupt is pending.
32+
#[inline]
33+
pub fn is_pending<I: CoreInterruptNumber>(&self, interrupt: I) -> bool {
34+
bf_extract(self.bits, interrupt.number(), 1) != 0
35+
}
36+
37+
/// Clear the pending state of a specific core interrupt source.
38+
///
39+
/// # Safety
40+
///
41+
/// Not all interrupt sources allow clearing of pending interrupts via the `sip` register.
42+
/// Instead, it may be necessary to perform an alternative action to clear the interrupt.
43+
/// Check the specification of your target chip for details.
44+
#[inline]
45+
pub unsafe fn clear_pending<I: CoreInterruptNumber>(&mut self, interrupt: I) {
46+
self.bits = bf_insert(self.bits, interrupt.number(), 1, 0);
47+
}
48+
}
49+
2750
set!(0x144);
2851
clear!(0x144);
2952

3053
set_clear_csr!(
3154
/// Supervisor Software Interrupt Pending
3255
, set_ssoft, clear_ssoft, 1 << 1);
3356

57+
/// Clear the pending state of a specific core interrupt source.
58+
///
59+
/// # Safety
60+
///
61+
/// Not all interrupt sources allow clearing of pending interrupts via the `sip` register.
62+
/// Instead, it may be necessary to perform an alternative action to clear the interrupt.
63+
/// Check the specification of your specific core for details.
64+
pub unsafe fn clear_pending<I: CoreInterruptNumber>(interrupt: I) {
65+
_clear(1 << interrupt.number());
66+
}
67+
3468
#[cfg(test)]
3569
mod tests {
3670
use super::*;

0 commit comments

Comments
 (0)