Skip to content
Snippets Groups Projects
Commit 6a5a789b authored by homunkulus's avatar homunkulus
Browse files

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).
parents bdc7ca96 ee21e7d6
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ use aligned::Aligned; ...@@ -7,7 +7,7 @@ use aligned::Aligned;
use peripheral::itm::Stim; use peripheral::itm::Stim;
// NOTE assumes that `bytes` is 32-bit aligned // NOTE assumes that `bytes` is 32-bit aligned
unsafe fn write_words(stim: &Stim, bytes: &[u32]) { unsafe fn write_words(stim: &mut Stim, bytes: &[u32]) {
let mut p = bytes.as_ptr(); let mut p = bytes.as_ptr();
for _ in 0..bytes.len() { for _ in 0..bytes.len() {
while !stim.is_fifo_ready() {} while !stim.is_fifo_ready() {}
...@@ -16,7 +16,7 @@ unsafe fn write_words(stim: &Stim, bytes: &[u32]) { ...@@ -16,7 +16,7 @@ unsafe fn write_words(stim: &Stim, bytes: &[u32]) {
} }
} }
struct Port<'p>(&'p Stim); struct Port<'p>(&'p mut Stim);
impl<'p> fmt::Write for Port<'p> { impl<'p> fmt::Write for Port<'p> {
fn write_str(&mut self, s: &str) -> fmt::Result { fn write_str(&mut self, s: &str) -> fmt::Result {
...@@ -26,7 +26,7 @@ impl<'p> fmt::Write for Port<'p> { ...@@ -26,7 +26,7 @@ impl<'p> fmt::Write for Port<'p> {
} }
/// Writes a `buffer` to the ITM `port` /// Writes a `buffer` to the ITM `port`
pub fn write_all(port: &Stim, buffer: &[u8]) { pub fn write_all(port: &mut Stim, buffer: &[u8]) {
unsafe { unsafe {
let mut len = buffer.len(); let mut len = buffer.len();
let mut ptr = buffer.as_ptr(); let mut ptr = buffer.as_ptr();
...@@ -84,7 +84,7 @@ pub fn write_all(port: &Stim, buffer: &[u8]) { ...@@ -84,7 +84,7 @@ pub fn write_all(port: &Stim, buffer: &[u8]) {
/// // Or equivalently /// // Or equivalently
/// itm::write_aligned(&itm.stim[0], &Aligned(*b"Hello, world!\n")); /// itm::write_aligned(&itm.stim[0], &Aligned(*b"Hello, world!\n"));
/// ``` /// ```
pub fn write_aligned(port: &Stim, buffer: &Aligned<u32, [u8]>) { pub fn write_aligned(port: &mut Stim, buffer: &Aligned<u32, [u8]>) {
unsafe { unsafe {
let len = buffer.len(); let len = buffer.len();
...@@ -120,13 +120,13 @@ pub fn write_aligned(port: &Stim, buffer: &Aligned<u32, [u8]>) { ...@@ -120,13 +120,13 @@ pub fn write_aligned(port: &Stim, buffer: &Aligned<u32, [u8]>) {
} }
/// Writes `fmt::Arguments` to the ITM `port` /// Writes `fmt::Arguments` to the ITM `port`
pub fn write_fmt(port: &Stim, args: fmt::Arguments) { pub fn write_fmt(port: &mut Stim, args: fmt::Arguments) {
use core::fmt::Write; use core::fmt::Write;
Port(port).write_fmt(args).ok(); Port(port).write_fmt(args).ok();
} }
/// Writes a string to the ITM `port` /// Writes a string to the ITM `port`
pub fn write_str(port: &Stim, string: &str) { pub fn write_str(port: &mut Stim, string: &str) {
write_all(port, string.as_bytes()) write_all(port, string.as_bytes())
} }
...@@ -33,17 +33,17 @@ pub struct Stim { ...@@ -33,17 +33,17 @@ pub struct Stim {
impl Stim { impl Stim {
/// Writes an `u8` payload into the stimulus port /// Writes an `u8` payload into the stimulus port
pub fn write_u8(&self, value: u8) { pub fn write_u8(&mut self, value: u8) {
unsafe { ptr::write_volatile(self.register.get() as *mut u8, value) } unsafe { ptr::write_volatile(self.register.get() as *mut u8, value) }
} }
/// Writes an `u16` payload into the stimulus port /// Writes an `u16` payload into the stimulus port
pub fn write_u16(&self, value: u16) { pub fn write_u16(&mut self, value: u16) {
unsafe { ptr::write_volatile(self.register.get() as *mut u16, value) } unsafe { ptr::write_volatile(self.register.get() as *mut u16, value) }
} }
/// Writes an `u32` payload into the stimulus port /// Writes an `u32` payload into the stimulus port
pub fn write_u32(&self, value: u32) { pub fn write_u32(&mut self, value: u32) {
unsafe { ptr::write_volatile(self.register.get(), value) } unsafe { ptr::write_volatile(self.register.get(), value) }
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#![allow(private_no_mangle_statics)] #![allow(private_no_mangle_statics)]
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ops::Deref; use core::ops::{Deref, DerefMut};
use interrupt; use interrupt;
...@@ -262,8 +262,8 @@ pub struct ITM { ...@@ -262,8 +262,8 @@ pub struct ITM {
impl ITM { impl ITM {
/// Returns a pointer to the register block /// Returns a pointer to the register block
pub fn ptr() -> *const itm::RegisterBlock { pub fn ptr() -> *mut itm::RegisterBlock {
0xE000_0000 as *const _ 0xE000_0000 as *mut _
} }
} }
...@@ -275,6 +275,12 @@ impl Deref for ITM { ...@@ -275,6 +275,12 @@ impl Deref for ITM {
} }
} }
impl DerefMut for ITM {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *Self::ptr() }
}
}
/// Memory Protection Unit /// Memory Protection Unit
pub struct MPU { pub struct MPU {
_marker: PhantomData<*const ()>, _marker: PhantomData<*const ()>,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment