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
97use crate :: peripheral:: itm:: Stim ;
108
119// NOTE assumes that `bytes` is 32-bit aligned
12- #[ allow( clippy:: missing_inline_in_public_items) ]
1310unsafe 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+
2258struct Port < ' p > ( & ' p mut Stim ) ;
2359
2460impl < ' 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) ]
3677pub 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
0 commit comments