1
1
//! Instrumentation Trace Macrocell
2
2
//!
3
- //! **NOTE** This module is only available on ARMv7-M and newer
3
+ //! **NOTE** This module is only available on ARMv7-M and newer.
4
4
5
- use core:: { fmt, mem, ptr, slice} ;
6
-
7
- use aligned:: { Aligned , A4 } ;
5
+ use core:: { fmt, ptr, slice} ;
8
6
9
7
use crate :: peripheral:: itm:: Stim ;
10
8
11
9
// NOTE assumes that `bytes` is 32-bit aligned
12
- #[ allow( clippy:: missing_inline_in_public_items) ]
13
10
unsafe fn write_words ( stim : & mut Stim , bytes : & [ u32 ] ) {
14
11
let mut p = bytes. as_ptr ( ) ;
15
12
for _ in 0 ..bytes. len ( ) {
@@ -19,6 +16,45 @@ unsafe fn write_words(stim: &mut Stim, bytes: &[u32]) {
19
16
}
20
17
}
21
18
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
+
22
58
struct Port < ' p > ( & ' p mut Stim ) ;
23
59
24
60
impl < ' p > fmt:: Write for Port < ' p > {
@@ -29,10 +65,15 @@ impl<'p> fmt::Write for Port<'p> {
29
65
}
30
66
}
31
67
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.
34
76
#[ allow( clippy:: missing_inline_in_public_items) ]
35
- #[ allow( clippy:: transmute_ptr_to_ptr) ]
36
77
pub fn write_all ( port : & mut Stim , buffer : & [ u8 ] ) {
37
78
unsafe {
38
79
let mut len = buffer. len ( ) ;
@@ -57,6 +98,9 @@ pub fn write_all(port: &mut Stim, buffer: &[u8]) {
57
98
if len > 1 {
58
99
// at least 2 bytes
59
100
while !port. is_fifo_ready ( ) { }
101
+
102
+ // We checked the alignment above, so this is safe
103
+ #[ allow( clippy:: cast_ptr_alignment) ]
60
104
port. write_u16 ( ptr:: read ( ptr as * const u16 ) ) ;
61
105
62
106
// 0x04
@@ -73,59 +117,31 @@ pub fn write_all(port: &mut Stim, buffer: &[u8]) {
73
117
}
74
118
}
75
119
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) ) ;
77
122
}
78
123
}
79
124
80
- /// Writes a 4-byte aligned `buffer` to the ITM ` port`
125
+ /// Writes a 4-byte aligned `buffer` to an ITM port.
81
126
///
82
127
/// # Examples
83
128
///
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]);
86
133
///
87
- /// buffer.copy_from_slice(b"Hello, world!\n");
134
+ /// buffer.0. copy_from_slice(b"Hello, world!\n");
88
135
///
89
- /// itm::write_aligned(&itm.stim[0] , &buffer);
136
+ /// itm::write_aligned(port , &buffer);
90
137
///
91
138
/// // Or equivalently
92
- /// itm::write_aligned(&itm.stim[0] , &Aligned(*b"Hello, world!\n"));
139
+ /// itm::write_aligned(port , &Aligned(*b"Hello, world!\n"));
93
140
/// ```
94
- #[ allow( clippy:: cast_ptr_alignment) ]
95
141
#[ 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 ] > ) {
98
143
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 )
129
145
}
130
146
}
131
147
0 commit comments