Skip to content

Commit 38af0ed

Browse files
Merge pull request #342 from KushalMeghani1644/add_dcsr_support
Add dcsr support
2 parents 18cc082 + 02c1edf commit 38af0ed

File tree

3 files changed

+198
-1
lines changed

3 files changed

+198
-1
lines changed

riscv/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

12+
- Added DCSR (Debug Control and Status Register) CSR support for the RISC-V
1213
- Add `miselect` CSR
1314
- Improved assembly macro handling in asm.rs
1415

@@ -116,7 +117,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
116117
the CSR
117118
- Export `riscv::register::macros` module macros for external use
118119
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
119-
- Add `Mcounteren` in-memory update functions
120+
- Add `Mcounteren` in-memory update functions
120121
- Add `Mstatus` vector extension support
121122
- Add fallible counterparts to all functions that `panic`
122123
- Add `riscv-pac` as a dependency
@@ -285,3 +286,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
285286
[v0.6.0]: https://github.com/rust-embedded/riscv/compare/v0.5.6...v0.6.0
286287
[v0.5.6]: https://github.com/rust-embedded/riscv/compare/v0.5.5...v0.5.6
287288
[v0.5.5]: https://github.com/rust-embedded/riscv/compare/v0.5.4...v0.5.5
289+
[v0.5.5]: https://github.com/rust-embedded/riscv/compare/v0.5.4...v0.5.5u

riscv/src/register.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,4 @@ mod tests;
126126
// TODO: Debug/Trace Registers (shared with Debug Mode)
127127

128128
// TODO: Debug Mode Registers
129+
pub mod dcsr;

riscv/src/register/dcsr.rs

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
//! dcsr register — Debug Control and Status Register (0x7b0)
2+
//!
3+
//! Provides control and status for debug mode, including cause of entry, step control, and privilege level.
4+
5+
read_write_csr! {
6+
/// Debug Control and Status Register
7+
Dcsr: 0x7b0,
8+
mask: 0xf000_bfdf,
9+
}
10+
11+
csr_field_enum! {
12+
/// Operating privilege level.
13+
Prv {
14+
default: Machine,
15+
/// User/Application.
16+
User = 0b00,
17+
/// Supervisor.
18+
Supervisor = 0b01,
19+
/// Machine.
20+
Machine = 0b11,
21+
}
22+
}
23+
24+
csr_field_enum! {
25+
/// Cause for entering debug mode.
26+
Cause {
27+
default: None,
28+
/// No cause.
29+
None = 0,
30+
/// EBREAK instruction.
31+
Ebreak = 1,
32+
/// Trigger module.
33+
Trigger = 2,
34+
/// External halt request.
35+
HaltRequest = 3,
36+
/// Single-step completed.
37+
Step = 4,
38+
/// Reset-halt request.
39+
ResetHaltRequest = 5,
40+
}
41+
}
42+
43+
read_write_csr_field! {
44+
Dcsr,
45+
/// Previous privilege level when entering debug mode (bits 0..1).
46+
prv,
47+
Prv: [0:1],
48+
}
49+
50+
read_write_csr_field! {
51+
Dcsr,
52+
/// Single step mode (bit 2)
53+
step: 2,
54+
}
55+
56+
read_only_csr_field! {
57+
Dcsr,
58+
/// Non-maskable interrupt pending (bit 3)
59+
nmip: 3,
60+
}
61+
62+
read_write_csr_field! {
63+
Dcsr,
64+
/// Use mstatus.mprv in debug mode (bit 4)
65+
mprven: 4,
66+
}
67+
68+
read_only_csr_field! {
69+
Dcsr,
70+
/// Cause for entering debug mode (bits 6..8)
71+
cause,
72+
Cause: [6:8],
73+
}
74+
75+
read_write_csr_field! {
76+
Dcsr,
77+
/// Stop timer increment in debug mode (bit 9)
78+
stoptime: 9,
79+
}
80+
81+
read_write_csr_field! {
82+
Dcsr,
83+
/// Stop counter increment in debug mode (bit 10)
84+
stopcount: 10,
85+
}
86+
87+
read_write_csr_field! {
88+
Dcsr,
89+
/// Interrupt enable during single-step (bit 11)
90+
stepie: 11,
91+
}
92+
93+
read_write_csr_field! {
94+
Dcsr,
95+
/// EBREAK behavior in User mode (bit 12)
96+
ebreaku: 12,
97+
}
98+
99+
read_write_csr_field! {
100+
Dcsr,
101+
/// EBREAK behavior in Supervisor mode (bit 13)
102+
ebreaks: 13,
103+
}
104+
105+
read_write_csr_field! {
106+
Dcsr,
107+
/// EBREAK behavior in Machine mode (bit 15)
108+
ebreakm: 15,
109+
}
110+
111+
read_only_csr_field! {
112+
Dcsr,
113+
/// Debug version (bits 28..31)
114+
xdebugver: [28:31],
115+
}
116+
117+
#[cfg(test)]
118+
mod tests {
119+
use super::*;
120+
use crate::result::Error;
121+
122+
#[test]
123+
fn test_dcsr_bitfields() {
124+
let mut dcsr = Dcsr::from_bits(0);
125+
126+
dcsr.set_step(true);
127+
assert!(dcsr.step());
128+
dcsr.set_mprven(true);
129+
assert!(dcsr.mprven());
130+
dcsr.set_stoptime(true);
131+
assert!(dcsr.stoptime());
132+
dcsr.set_stopcount(true);
133+
assert!(dcsr.stopcount());
134+
dcsr.set_stepie(true);
135+
assert!(dcsr.stepie());
136+
dcsr.set_ebreaku(true);
137+
assert!(dcsr.ebreaku());
138+
dcsr.set_ebreaks(true);
139+
assert!(dcsr.ebreaks());
140+
dcsr.set_ebreakm(true);
141+
assert!(dcsr.ebreakm());
142+
143+
dcsr.set_step(false);
144+
assert!(!dcsr.step());
145+
dcsr.set_mprven(false);
146+
assert!(!dcsr.mprven());
147+
dcsr.set_stoptime(false);
148+
assert!(!dcsr.stoptime());
149+
dcsr.set_stopcount(false);
150+
assert!(!dcsr.stopcount());
151+
dcsr.set_stepie(false);
152+
assert!(!dcsr.stepie());
153+
dcsr.set_ebreaku(false);
154+
assert!(!dcsr.ebreaku());
155+
dcsr.set_ebreaks(false);
156+
assert!(!dcsr.ebreaks());
157+
dcsr.set_ebreakm(false);
158+
assert!(!dcsr.ebreakm());
159+
}
160+
161+
#[test]
162+
fn test_dcsr_enums() {
163+
let mut dcsr = Dcsr::from_bits(0);
164+
165+
[
166+
Cause::None,
167+
Cause::Ebreak,
168+
Cause::Trigger,
169+
Cause::HaltRequest,
170+
Cause::Step,
171+
Cause::ResetHaltRequest,
172+
]
173+
.into_iter()
174+
.enumerate()
175+
.for_each(|(val, variant)| {
176+
dcsr = Dcsr::from_bits((val as usize) << 6);
177+
assert_eq!(dcsr.cause(), variant);
178+
assert_eq!(dcsr.try_cause(), Ok(variant));
179+
});
180+
181+
// invalid variant value 6
182+
dcsr = Dcsr::from_bits(6 << 6);
183+
assert_eq!(dcsr.try_cause(), Err(Error::InvalidVariant(6)));
184+
}
185+
186+
#[test]
187+
fn test_dcsr_convenience_methods() {
188+
let mut dcsr = Dcsr::from_bits(0);
189+
190+
dcsr.set_prv(Prv::Machine);
191+
assert_eq!(dcsr.try_prv().unwrap(), Prv::Machine);
192+
assert_eq!(dcsr.prv(), Prv::Machine);
193+
}
194+
}

0 commit comments

Comments
 (0)