Skip to content
Snippets Groups Projects
Commit 0086ca5e authored by Per Lindgren's avatar Per Lindgren
Browse files

prepare for merge

parent 3e0ffe04
No related branches found
No related tags found
No related merge requests found
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
"tasks": [ "tasks": [
{ {
"type": "shell", "type": "shell",
"label": "cargo +stable run --example example --features debug-fmt", "label": "cargo build",
"command": "cargo +stable run --example example --features debug-fmt", "command": "cargo build",
"problemMatcher": [ "problemMatcher": [
"$rustc" "$rustc"
], ],
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
}, },
{ {
"type": "shell", "type": "shell",
"label": "cargo +nightly run --example example2 --features 'debug-fmt nightly'", "label": "cargo build --all-features",
"command": "cargo +nightly run --example example2 --features 'debug-fmt nightly'", "command": "cargo build --all-features",
"problemMatcher": [ "problemMatcher": [
"$rustc" "$rustc"
], ],
...@@ -26,6 +26,6 @@ ...@@ -26,6 +26,6 @@
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true
} }
} },
] ]
} }
\ No newline at end of file
...@@ -15,15 +15,8 @@ version = "0.3.0" ...@@ -15,15 +15,8 @@ version = "0.3.0"
[dependencies] [dependencies]
vcell = "0.1.0" vcell = "0.1.0"
array-debug = { git = "https://gitlab.henriktjader.com/pln/array-debug", optional = true } klee = { path = "..", optional = true }
[features] [features]
debug-fmt = [] klee-analysis = ["klee"]
nightly = ["array-debug"]
[[example]]
name = "example"
[[example]]
name = "example2"
required-features = ["nightly"]
...@@ -5,90 +5,11 @@ ...@@ -5,90 +5,11 @@
> Volatile access to memory mapped hardware registers > Volatile access to memory mapped hardware registers
Adds debug to volatile register when compiled with `--features debug-fmt`.
## Caveats
Notice, the current implementation of `array-debug` (see `examples/example2.rs`) requires a nightly toolchain (`#![feature(unsize)]`). This is however an "opt-in", and needed to support `#[derive(Debug)]` for cases with (register) arrays larger than 32 elements.
``` rust
//! Example to show the use of `Debug` formatting for small register arrays
//!
//! > cargo +stable run --example example --features debug-fmt
//!
extern crate volatile_register;
use std::mem;
use volatile_register::{RW};
#[repr(C)]
#[derive(Debug)]
pub struct Nvic {
/// Interrupt Set-Enable
pub iser: [RW<u32>; 8],
reserved0: [u32; 24],
/// Interrupt Clear-Enable
pub icer: [RW<u32>; 8],
reserved1: [u32; 24],
// .. more registers ..
}
fn main() {
let r : Nvic = unsafe {mem::uninitialized() };
println!("{:?}", r);
}
```
This will render an output of the form:
``` txt
Nvic { iser: [0xB618860, 0x7FFE, 0x20, 0x0, 0x0, 0x7F70, 0x30, 0x0], reserved0: [7, 0, 3, 0, 274354200, 22074, 31, 0, 80, 0, 4294967024, 4294967295, 0, 0, 3, 48, 0, 0, 0, 0, 91, 110, 0, 0], icer: [0x77, 0x7C, 0xFFFFFEF0,0xFFFFFFFF, 0xC3041AA0, 0x7F70, 0x20, 0x0], reserved1: [132352, 0, 3271845168, 32624, 274356992, 22074, 1, 0, 3272547558, 32624, 3269993280, 32624, 274357008, 22074, 3272638464, 32624, 252047400, 22074, 3269993088, 32624, 3270237052, 32624, 274356816, 22074] }
```
Registers will be formatted under `UpperHex`, notice in the example that arrays are of size less than 32, hence `Debug` of array (`[T; N]`) is implemented by default. Notice that the `reserved` fields falls back to the default integer formatting (as not wrapped by the `volatile-register` abstraction).
For register arrays with more then 32 elements, `array-debug` provides a newtype over array, replicating the array behavior while providing `Debug`.
``` rust
//! Example to show the use of ¡Debug` formatting for big register arrays
//!
//! > cargo +nightly run --example example2 --features 'debug-fmt nightly'
//!
extern crate array_debug;
extern crate volatile_register;
use array_debug::ArrayDebug;
use std::mem;
use volatile_register::RW;
#[repr(C)]
#[derive(Debug)]
pub struct Nvic {
/// Interrupt Set-Enable
pub iser: ArrayDebug<[RW<u32>; 38], RW<u32>>,
reserved0: [u32; 24],
/// Interrupt Clear-Enable
pub icer: [RW<u32>; 8],
reserved1: [u32; 24],
// .. more registers ..
}
fn main() {
let r: Nvic = unsafe { mem::uninitialized() };
println!("{:?}", r);
}
```
Rendering output of the form:
``` text
Nvic { iser: [0x3, 0x30, 0x0, 0x0, 0x0, 0x0, 0x5B, 0x6E, 0x0, 0x0, 0x77, 0x7C, 0x4C6DAEC0, 0x7F95, 0x1F, 0x0, 0x20, 0x0, 0x1, 0x0, 0xFFFFFEF0, 0xFFFFFFFF, 0x0, 0x0, 0x4C65C340, 0x7F95, 0x4C6E2967, 0x7F95, 0x20, 0x0, 0xD7FADB10, 0x7FFF, 0x20, 0x0, 0x0, 0x7F95, 0x30, 0x0], reserved0: [7, 0, 3, 0, 4060155928, 22095, 31, 0, 80, 0, 4294967024, 4294967295, 0, 0, 3, 48, 0, 0, 0, 0, 91, 110, 0, 0], icer: [0x77, 0x7C, 0xFFFFFEF0, 0xFFFFFFFF, 0x4C81BAA0, 0x7F95, 0x20, 0x0], reserved1: [132352, 0, 1283589424, 32661, 4060158720, 22095, 1, 0, 1284291814, 32661, 1281737536, 32661, 4060158736, 22095, 1284382720, 32661, 4038778920, 22095, 1281737344, 32661, 1281981308, 32661, 4060158544, 22095] }
```
## [Documentation](https://docs.rs/crate/volatile-register) ## [Documentation](https://docs.rs/crate/volatile-register)
## Version 0.3.0
KLEE support making register reads symbolic, enabled by the `klee-analysis` feature.
## License ## License
Licensed under either of Licensed under either of
......
...@@ -26,12 +26,15 @@ ...@@ -26,12 +26,15 @@
//! ``` //! ```
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(warnings)]
#![no_std] #![no_std]
extern crate vcell; extern crate vcell;
#[cfg(feature = "debug-fmt")] #[cfg(feature = "klee-analysis")]
use core::fmt::{self, Debug, UpperHex}; #[macro_use]
extern crate klee;
use vcell::VolatileCell; use vcell::VolatileCell;
/// Read-Only register /// Read-Only register
...@@ -39,19 +42,11 @@ pub struct RO<T> ...@@ -39,19 +42,11 @@ pub struct RO<T>
where where
T: Copy, T: Copy,
{ {
#[allow(unused)]
register: VolatileCell<T>, register: VolatileCell<T>,
} }
#[cfg(feature = "debug-fmt")] #[cfg(not(feature = "klee-analysis"))]
impl<T> fmt::Debug for RO<T>
where
T: Copy + Debug + UpperHex,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#X}", self.read())
}
}
impl<T> RO<T> impl<T> RO<T>
where where
T: Copy, T: Copy,
...@@ -63,13 +58,17 @@ where ...@@ -63,13 +58,17 @@ where
} }
} }
#[cfg(feature = "debug-fmt")] #[cfg(feature = "klee-analysis")]
impl<T> fmt::Debug for RW<T> impl<T> RO<T>
where where
T: Copy + Debug + UpperHex, T: Copy,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// Reads the symbolic value of the register
write!(f, "{:#X}", self.read()) #[inline(always)]
pub fn read(&self) -> T {
let mut register: T = unsafe { core::mem::uninitialized() };
ksymbol!(&mut register, "register");
register
} }
} }
...@@ -81,6 +80,7 @@ where ...@@ -81,6 +80,7 @@ where
register: VolatileCell<T>, register: VolatileCell<T>,
} }
#[cfg(not(feature = "klee-analysis"))]
impl<T> RW<T> impl<T> RW<T>
where where
T: Copy, T: Copy,
...@@ -111,24 +111,49 @@ where ...@@ -111,24 +111,49 @@ where
} }
} }
/// Write-Only register #[cfg(feature = "klee-analysis")]
pub struct WO<T> impl<T> RW<T>
where where
T: Copy, T: Copy,
{ {
register: VolatileCell<T>, /// Performs a read-modify-write operation
///
/// NOTE: `unsafe` to keep API consistent,
/// in `klee-analysis` the reading side effect is preserved
#[inline(always)]
pub unsafe fn modify<F>(&self, f: F)
where
F: FnOnce(T) -> T,
{
f(self.register.get());
}
/// Reads the symbolic value of the register
#[inline(always)]
pub fn read(&self) -> T {
let mut register: T = unsafe { core::mem::uninitialized() };
ksymbol!(&mut register, "register");
register
} }
#[cfg(feature = "debug-fmt")] /// Writes a `value` into the register
impl<T> fmt::Debug for WO<T> ///
/// NOTE: `unsafe` to keep API consistent,
/// in `klee-analysis` writing has no side effect
#[inline(always)]
pub unsafe fn write(&self, _value: T) {}
}
/// Write-Only register
pub struct WO<T>
where where
T: Copy + Debug, T: Copy,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[allow(unused)]
write!(f, "- write only -") // TODO: perhaps self.register.get() register: VolatileCell<T>,
}
} }
#[cfg(not(feature = "klee-analysis"))]
impl<T> WO<T> impl<T> WO<T>
where where
T: Copy, T: Copy,
...@@ -141,3 +166,16 @@ where ...@@ -141,3 +166,16 @@ where
self.register.set(value) self.register.set(value)
} }
} }
#[cfg(feature = "klee-analysis")]
impl<T> WO<T>
where
T: Copy,
{
/// Writes `value` into the register
///
/// NOTE: `unsafe` to keep API consistent,
/// in `klee-analysis` writing has no side effect
#[inline(always)]
pub unsafe fn write(&self, _value: T) {}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment