Skip to content

Commit 465c64d

Browse files
Merge #190
190: Remove `aligned`, improve ITM code r=adamgreig a=jonas-schievink This does a handful of things: * Removes the dependency on `aligned` (and thus `as-slice` and the 2 versions of `generic-array`), instead providing our own simplified `Aligned` wrapper * Moves the innards of `write_aligned` to its own function, and calls that from `write_all` instead of transmuting `&[u8]` to `&Aligned<A4, [u8]>` (which is likely UB) * Fixes the doc example, which didn't compile anymore * Sinks the `#[allow]` attributes into the functions so they only cover the statements they need to Closes #184 Co-authored-by: Jonas Schievink <[email protected]>
2 parents b889e49 + 1498b1c commit 465c64d

File tree

3 files changed

+64
-50
lines changed

3 files changed

+64
-50
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ edition = "2018"
1616
links = "cortex-m" # prevent multiple versions of this crate to be linked together
1717

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

src/itm.rs

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
//! Instrumentation Trace Macrocell
22
//!
3-
//! **NOTE** This module is only available on ARMv7-M and newer
3+
//! **NOTE** This module is only available on ARMv7-M and newer.
44
5-
use core::{fmt, mem, ptr, slice};
6-
7-
use aligned::{Aligned, A4};
5+
use core::{fmt, ptr, slice};
86

97
use crate::peripheral::itm::Stim;
108

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

19+
/// Writes an aligned byte slice to the ITM.
20+
///
21+
/// `buffer` must be 4-byte aligned.
22+
unsafe fn write_aligned_impl(port: &mut Stim, buffer: &[u8]) {
23+
let len = buffer.len();
24+
25+
if len == 0 {
26+
return;
27+
}
28+
29+
let split = len & !0b11;
30+
#[allow(clippy::cast_ptr_alignment)]
31+
write_words(
32+
port,
33+
slice::from_raw_parts(buffer.as_ptr() as *const u32, split >> 2),
34+
);
35+
36+
// 3 bytes or less left
37+
let mut left = len & 0b11;
38+
let mut ptr = buffer.as_ptr().add(split);
39+
40+
// at least 2 bytes left
41+
if left > 1 {
42+
while !port.is_fifo_ready() {}
43+
44+
#[allow(clippy::cast_ptr_alignment)]
45+
port.write_u16(ptr::read(ptr as *const u16));
46+
47+
ptr = ptr.offset(2);
48+
left -= 2;
49+
}
50+
51+
// final byte
52+
if left == 1 {
53+
while !port.is_fifo_ready() {}
54+
port.write_u8(*ptr);
55+
}
56+
}
57+
2258
struct Port<'p>(&'p mut Stim);
2359

2460
impl<'p> fmt::Write for Port<'p> {
@@ -29,10 +65,15 @@ impl<'p> fmt::Write for Port<'p> {
2965
}
3066
}
3167

32-
/// Writes a `buffer` to the ITM `port`
33-
#[allow(clippy::cast_ptr_alignment)]
68+
/// A wrapper type that aligns its contents on a 4-Byte boundary.
69+
///
70+
/// ITM transfers are most efficient when the data is 4-Byte-aligned. This type provides an easy
71+
/// way to accomplish and enforce such an alignment.
72+
#[repr(align(4))]
73+
pub struct Aligned<T: ?Sized>(pub T);
74+
75+
/// Writes `buffer` to an ITM port.
3476
#[allow(clippy::missing_inline_in_public_items)]
35-
#[allow(clippy::transmute_ptr_to_ptr)]
3677
pub fn write_all(port: &mut Stim, buffer: &[u8]) {
3778
unsafe {
3879
let mut len = buffer.len();
@@ -57,6 +98,9 @@ pub fn write_all(port: &mut Stim, buffer: &[u8]) {
5798
if len > 1 {
5899
// at least 2 bytes
59100
while !port.is_fifo_ready() {}
101+
102+
// We checked the alignment above, so this is safe
103+
#[allow(clippy::cast_ptr_alignment)]
60104
port.write_u16(ptr::read(ptr as *const u16));
61105

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

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

80-
/// Writes a 4-byte aligned `buffer` to the ITM `port`
125+
/// Writes a 4-byte aligned `buffer` to an ITM port.
81126
///
82127
/// # Examples
83128
///
84-
/// ``` ignore
85-
/// let mut buffer: Aligned<A4, _> = Aligned([0; 14]);
129+
/// ```no_run
130+
/// # use cortex_m::{itm::{self, Aligned}, peripheral::ITM};
131+
/// # let port = unsafe { &mut (*ITM::ptr()).stim[0] };
132+
/// let mut buffer = Aligned([0; 14]);
86133
///
87-
/// buffer.copy_from_slice(b"Hello, world!\n");
134+
/// buffer.0.copy_from_slice(b"Hello, world!\n");
88135
///
89-
/// itm::write_aligned(&itm.stim[0], &buffer);
136+
/// itm::write_aligned(port, &buffer);
90137
///
91138
/// // Or equivalently
92-
/// itm::write_aligned(&itm.stim[0], &Aligned(*b"Hello, world!\n"));
139+
/// itm::write_aligned(port, &Aligned(*b"Hello, world!\n"));
93140
/// ```
94-
#[allow(clippy::cast_ptr_alignment)]
95141
#[allow(clippy::missing_inline_in_public_items)]
96-
#[allow(clippy::transmute_ptr_to_ptr)]
97-
pub fn write_aligned(port: &mut Stim, buffer: &Aligned<A4, [u8]>) {
142+
pub fn write_aligned(port: &mut Stim, buffer: &Aligned<[u8]>) {
98143
unsafe {
99-
let len = buffer.len();
100-
101-
if len == 0 {
102-
return;
103-
}
104-
105-
let split = len & !0b11;
106-
write_words(
107-
port,
108-
slice::from_raw_parts(buffer.as_ptr() as *const u32, split >> 2),
109-
);
110-
111-
// 3 bytes or less left
112-
let mut left = len & 0b11;
113-
let mut ptr = buffer.as_ptr().add(split);
114-
115-
// at least 2 bytes left
116-
if left > 1 {
117-
while !port.is_fifo_ready() {}
118-
port.write_u16(ptr::read(ptr as *const u16));
119-
120-
ptr = ptr.offset(2);
121-
left -= 2;
122-
}
123-
124-
// final byte
125-
if left == 1 {
126-
while !port.is_fifo_ready() {}
127-
port.write_u8(*ptr);
128-
}
144+
write_aligned_impl(port, &buffer.0)
129145
}
130146
}
131147

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
// to be applied to the struct).
5151
#![deny(clippy::missing_inline_in_public_items)]
5252

53-
extern crate aligned;
5453
extern crate bare_metal;
5554
extern crate volatile_register;
5655

0 commit comments

Comments
 (0)