Skip to content

Remove aligned, improve ITM code #190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ edition = "2018"
links = "cortex-m" # prevent multiple versions of this crate to be linked together

[dependencies]
aligned = "0.3.1"
bare-metal = { version = "0.2.0", features = ["const-fn"] }
volatile-register = "0.2.0"

Expand Down
112 changes: 64 additions & 48 deletions src/itm.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
//! Instrumentation Trace Macrocell
//!
//! **NOTE** This module is only available on ARMv7-M and newer
//! **NOTE** This module is only available on ARMv7-M and newer.

use core::{fmt, mem, ptr, slice};

use aligned::{Aligned, A4};
use core::{fmt, ptr, slice};

use crate::peripheral::itm::Stim;

// NOTE assumes that `bytes` is 32-bit aligned
#[allow(clippy::missing_inline_in_public_items)]
unsafe fn write_words(stim: &mut Stim, bytes: &[u32]) {
let mut p = bytes.as_ptr();
for _ in 0..bytes.len() {
Expand All @@ -19,6 +16,45 @@ unsafe fn write_words(stim: &mut Stim, bytes: &[u32]) {
}
}

/// Writes an aligned byte slice to the ITM.
///
/// `buffer` must be 4-byte aligned.
unsafe fn write_aligned_impl(port: &mut Stim, buffer: &[u8]) {
let len = buffer.len();

if len == 0 {
return;
}

let split = len & !0b11;
#[allow(clippy::cast_ptr_alignment)]
write_words(
port,
slice::from_raw_parts(buffer.as_ptr() as *const u32, split >> 2),
);

// 3 bytes or less left
let mut left = len & 0b11;
let mut ptr = buffer.as_ptr().add(split);

// at least 2 bytes left
if left > 1 {
while !port.is_fifo_ready() {}

#[allow(clippy::cast_ptr_alignment)]
port.write_u16(ptr::read(ptr as *const u16));

ptr = ptr.offset(2);
left -= 2;
}

// final byte
if left == 1 {
while !port.is_fifo_ready() {}
port.write_u8(*ptr);
}
}

struct Port<'p>(&'p mut Stim);

impl<'p> fmt::Write for Port<'p> {
Expand All @@ -29,10 +65,15 @@ impl<'p> fmt::Write for Port<'p> {
}
}

/// Writes a `buffer` to the ITM `port`
#[allow(clippy::cast_ptr_alignment)]
/// A wrapper type that aligns its contents on a 4-Byte boundary.
///
/// ITM transfers are most efficient when the data is 4-Byte-aligned. This type provides an easy
/// way to accomplish and enforce such an alignment.
#[repr(align(4))]
pub struct Aligned<T: ?Sized>(pub T);

/// Writes `buffer` to an ITM port.
#[allow(clippy::missing_inline_in_public_items)]
#[allow(clippy::transmute_ptr_to_ptr)]
pub fn write_all(port: &mut Stim, buffer: &[u8]) {
unsafe {
let mut len = buffer.len();
Expand All @@ -57,6 +98,9 @@ pub fn write_all(port: &mut Stim, buffer: &[u8]) {
if len > 1 {
// at least 2 bytes
while !port.is_fifo_ready() {}

// We checked the alignment above, so this is safe
#[allow(clippy::cast_ptr_alignment)]
port.write_u16(ptr::read(ptr as *const u16));

// 0x04
Expand All @@ -73,59 +117,31 @@ pub fn write_all(port: &mut Stim, buffer: &[u8]) {
}
}

write_aligned(port, mem::transmute(slice::from_raw_parts(ptr, len)));
// The remaining data is 4-byte aligned, but might not be a multiple of 4 bytes
write_aligned_impl(port, slice::from_raw_parts(ptr, len));
}
}

/// Writes a 4-byte aligned `buffer` to the ITM `port`
/// Writes a 4-byte aligned `buffer` to an ITM port.
///
/// # Examples
///
/// ``` ignore
/// let mut buffer: Aligned<A4, _> = Aligned([0; 14]);
/// ```no_run
/// # use cortex_m::{itm::{self, Aligned}, peripheral::ITM};
/// # let port = unsafe { &mut (*ITM::ptr()).stim[0] };
/// let mut buffer = Aligned([0; 14]);
///
/// buffer.copy_from_slice(b"Hello, world!\n");
/// buffer.0.copy_from_slice(b"Hello, world!\n");
///
/// itm::write_aligned(&itm.stim[0], &buffer);
/// itm::write_aligned(port, &buffer);
///
/// // Or equivalently
/// itm::write_aligned(&itm.stim[0], &Aligned(*b"Hello, world!\n"));
/// itm::write_aligned(port, &Aligned(*b"Hello, world!\n"));
/// ```
#[allow(clippy::cast_ptr_alignment)]
#[allow(clippy::missing_inline_in_public_items)]
#[allow(clippy::transmute_ptr_to_ptr)]
pub fn write_aligned(port: &mut Stim, buffer: &Aligned<A4, [u8]>) {
pub fn write_aligned(port: &mut Stim, buffer: &Aligned<[u8]>) {
unsafe {
let len = buffer.len();

if len == 0 {
return;
}

let split = len & !0b11;
write_words(
port,
slice::from_raw_parts(buffer.as_ptr() as *const u32, split >> 2),
);

// 3 bytes or less left
let mut left = len & 0b11;
let mut ptr = buffer.as_ptr().add(split);

// at least 2 bytes left
if left > 1 {
while !port.is_fifo_ready() {}
port.write_u16(ptr::read(ptr as *const u16));

ptr = ptr.offset(2);
left -= 2;
}

// final byte
if left == 1 {
while !port.is_fifo_ready() {}
port.write_u8(*ptr);
}
write_aligned_impl(port, &buffer.0)
}
}

Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
// to be applied to the struct).
#![deny(clippy::missing_inline_in_public_items)]

extern crate aligned;
extern crate bare_metal;
extern crate volatile_register;

Expand Down