Skip to content

Commit 6a5a789

Browse files
committed
Auto merge of #73 - japaric:itm, r=japaric
make `Stim::write_*` methods take `&mut self` instead of `&self` this prevents people from overlapping non-atomic write operations on the same stimulus port when working with generators (cooperative tasks). For example, with this change the following code won't compile ``` rust let stim = &mut ITM.stim[0]; let a = || { loop { // .. for byte in b"Hello, world!".iter() { while !stim.is_fifo_ready() { yield } stim.write_u8(*byte); } // .. } }; let b = || { loop { // .. for byte in b"The quick brown fox jumps over the lazy dog".iter() { while !stim.is_fifo_ready() { yield } stim.write_u8(*byte); } // .. } }; ``` A possible fix for the above code is to use different stimulus ports in each task (generator).
2 parents bdc7ca9 + ee21e7d commit 6a5a789

File tree

3 files changed

+18
-12
lines changed

3 files changed

+18
-12
lines changed

src/itm.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use aligned::Aligned;
77
use peripheral::itm::Stim;
88

99
// NOTE assumes that `bytes` is 32-bit aligned
10-
unsafe fn write_words(stim: &Stim, bytes: &[u32]) {
10+
unsafe fn write_words(stim: &mut Stim, bytes: &[u32]) {
1111
let mut p = bytes.as_ptr();
1212
for _ in 0..bytes.len() {
1313
while !stim.is_fifo_ready() {}
@@ -16,7 +16,7 @@ unsafe fn write_words(stim: &Stim, bytes: &[u32]) {
1616
}
1717
}
1818

19-
struct Port<'p>(&'p Stim);
19+
struct Port<'p>(&'p mut Stim);
2020

2121
impl<'p> fmt::Write for Port<'p> {
2222
fn write_str(&mut self, s: &str) -> fmt::Result {
@@ -26,7 +26,7 @@ impl<'p> fmt::Write for Port<'p> {
2626
}
2727

2828
/// Writes a `buffer` to the ITM `port`
29-
pub fn write_all(port: &Stim, buffer: &[u8]) {
29+
pub fn write_all(port: &mut Stim, buffer: &[u8]) {
3030
unsafe {
3131
let mut len = buffer.len();
3232
let mut ptr = buffer.as_ptr();
@@ -84,7 +84,7 @@ pub fn write_all(port: &Stim, buffer: &[u8]) {
8484
/// // Or equivalently
8585
/// itm::write_aligned(&itm.stim[0], &Aligned(*b"Hello, world!\n"));
8686
/// ```
87-
pub fn write_aligned(port: &Stim, buffer: &Aligned<u32, [u8]>) {
87+
pub fn write_aligned(port: &mut Stim, buffer: &Aligned<u32, [u8]>) {
8888
unsafe {
8989
let len = buffer.len();
9090

@@ -120,13 +120,13 @@ pub fn write_aligned(port: &Stim, buffer: &Aligned<u32, [u8]>) {
120120
}
121121

122122
/// Writes `fmt::Arguments` to the ITM `port`
123-
pub fn write_fmt(port: &Stim, args: fmt::Arguments) {
123+
pub fn write_fmt(port: &mut Stim, args: fmt::Arguments) {
124124
use core::fmt::Write;
125125

126126
Port(port).write_fmt(args).ok();
127127
}
128128

129129
/// Writes a string to the ITM `port`
130-
pub fn write_str(port: &Stim, string: &str) {
130+
pub fn write_str(port: &mut Stim, string: &str) {
131131
write_all(port, string.as_bytes())
132132
}

src/peripheral/itm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ pub struct Stim {
3333

3434
impl Stim {
3535
/// Writes an `u8` payload into the stimulus port
36-
pub fn write_u8(&self, value: u8) {
36+
pub fn write_u8(&mut self, value: u8) {
3737
unsafe { ptr::write_volatile(self.register.get() as *mut u8, value) }
3838
}
3939

4040
/// Writes an `u16` payload into the stimulus port
41-
pub fn write_u16(&self, value: u16) {
41+
pub fn write_u16(&mut self, value: u16) {
4242
unsafe { ptr::write_volatile(self.register.get() as *mut u16, value) }
4343
}
4444

4545
/// Writes an `u32` payload into the stimulus port
46-
pub fn write_u32(&self, value: u32) {
46+
pub fn write_u32(&mut self, value: u32) {
4747
unsafe { ptr::write_volatile(self.register.get(), value) }
4848
}
4949

src/peripheral/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#![allow(private_no_mangle_statics)]
1010

1111
use core::marker::PhantomData;
12-
use core::ops::Deref;
12+
use core::ops::{Deref, DerefMut};
1313

1414
use interrupt;
1515

@@ -262,8 +262,8 @@ pub struct ITM {
262262

263263
impl ITM {
264264
/// Returns a pointer to the register block
265-
pub fn ptr() -> *const itm::RegisterBlock {
266-
0xE000_0000 as *const _
265+
pub fn ptr() -> *mut itm::RegisterBlock {
266+
0xE000_0000 as *mut _
267267
}
268268
}
269269

@@ -275,6 +275,12 @@ impl Deref for ITM {
275275
}
276276
}
277277

278+
impl DerefMut for ITM {
279+
fn deref_mut(&mut self) -> &mut Self::Target {
280+
unsafe { &mut *Self::ptr() }
281+
}
282+
}
283+
278284
/// Memory Protection Unit
279285
pub struct MPU {
280286
_marker: PhantomData<*const ()>,

0 commit comments

Comments
 (0)