@@ -174,6 +174,20 @@ pub struct ITMSettings {
174
174
pub timestamp_clk_src : TimestampClkSrc ,
175
175
}
176
176
177
+ /// Possible errors on [ITM::configure].
178
+ #[ derive( Debug , Eq , PartialEq , Copy , Clone ) ]
179
+ pub enum ITMConfigurationError {
180
+ /// Global timestamp generation is not supported on this target.
181
+ /// Request [GlobalTimestampOptions::Disabled] instead.
182
+ GTS ,
183
+ /// The requested timestamp clock source is not supported on this target.
184
+ TimestampClkSrc ,
185
+ /// The target does not implement the local timestamp prescaler.
186
+ /// Request [LocalTimestampOptions::Disabled] or
187
+ /// [LocalTimestampOptions::Disabled] instead.
188
+ TSPrescale ,
189
+ }
190
+
177
191
impl ITM {
178
192
/// Removes the software lock on the ITM. Must be called before any other [ITM] functions.
179
193
#[ inline]
@@ -182,34 +196,82 @@ impl ITM {
182
196
unsafe { self . lar . write ( 0xC5AC_CE55 ) }
183
197
}
184
198
185
- /// Configures the ITM with the passed [ITMSettings].
186
- #[ inline]
187
- pub fn configure ( & mut self , settings : ITMSettings ) {
199
+ /// Configures the ITM with the passed [ITMSettings]. Returns `true`
200
+ /// if the configuration was successfully applied.
201
+ #[ allow( clippy:: missing_inline_in_public_items) ]
202
+ pub fn configure ( & mut self , settings : ITMSettings ) -> Result < ( ) , ITMConfigurationError > {
203
+ use ITMConfigurationError as Error ;
204
+
188
205
unsafe {
189
206
self . tcr . modify ( |mut r| {
190
- r. set_itmena ( settings. enable ) ;
191
- r. set_tsena ( settings. local_timestamps != LocalTimestampOptions :: Disabled ) ;
192
- r. set_txena ( settings. forward_dwt ) ;
193
- r. set_tsprescale ( match settings. local_timestamps {
194
- LocalTimestampOptions :: Disabled | LocalTimestampOptions :: Enabled => 0b00 ,
195
- LocalTimestampOptions :: EnabledDiv4 => 0b10 ,
196
- LocalTimestampOptions :: EnabledDiv16 => 0b10 ,
197
- LocalTimestampOptions :: EnabledDiv64 => 0b11 ,
198
- } ) ;
199
207
r. set_gtsfreq ( match settings. global_timestamps {
200
208
GlobalTimestampOptions :: Disabled => 0b00 ,
201
209
GlobalTimestampOptions :: Every128Cycles => 0b01 ,
202
210
GlobalTimestampOptions :: Every8192Cycles => 0b10 ,
203
211
GlobalTimestampOptions :: EveryPacket => 0b11 ,
204
212
} ) ;
213
+
214
+ r
215
+ } ) ;
216
+ }
217
+ // GTSFREQ is potentially RAZ/WI
218
+ if settings. global_timestamps != GlobalTimestampOptions :: Disabled
219
+ && self . tcr . read ( ) . gtsfreq ( ) == 0
220
+ {
221
+ return Err ( Error :: GTS ) ;
222
+ }
223
+
224
+ unsafe {
225
+ self . tcr . modify ( |mut r| {
205
226
r. set_swoena ( match settings. timestamp_clk_src {
206
227
TimestampClkSrc :: SystemClock => false ,
207
228
TimestampClkSrc :: AsyncTPIU => true ,
208
229
} ) ;
230
+
231
+ r
232
+ } ) ;
233
+ }
234
+ // SWOENA is potentially either RAZ or RAO
235
+ if !{
236
+ match settings. timestamp_clk_src {
237
+ TimestampClkSrc :: SystemClock => !self . tcr . read ( ) . swoena ( ) ,
238
+ TimestampClkSrc :: AsyncTPIU => self . tcr . read ( ) . swoena ( ) ,
239
+ }
240
+ } {
241
+ return Err ( Error :: TimestampClkSrc ) ;
242
+ }
243
+
244
+ unsafe {
245
+ self . tcr . modify ( |mut r| {
246
+ r. set_tsprescale ( match settings. local_timestamps {
247
+ LocalTimestampOptions :: Disabled | LocalTimestampOptions :: Enabled => 0b00 ,
248
+ LocalTimestampOptions :: EnabledDiv4 => 0b10 ,
249
+ LocalTimestampOptions :: EnabledDiv16 => 0b10 ,
250
+ LocalTimestampOptions :: EnabledDiv64 => 0b11 ,
251
+ } ) ;
252
+
253
+ r
254
+ } )
255
+ }
256
+ // TSPrescale is potentially RAZ/WI
257
+ if settings. local_timestamps != LocalTimestampOptions :: Disabled
258
+ && settings. local_timestamps != LocalTimestampOptions :: Enabled
259
+ && self . tcr . read ( ) . tsprescale ( ) == 0
260
+ {
261
+ return Err ( Error :: TSPrescale ) ;
262
+ }
263
+
264
+ unsafe {
265
+ self . tcr . modify ( |mut r| {
266
+ r. set_itmena ( settings. enable ) ;
267
+ r. set_tsena ( settings. local_timestamps != LocalTimestampOptions :: Disabled ) ;
268
+ r. set_txena ( settings. forward_dwt ) ; // forward hardware event packets from the DWT to the ITM
209
269
r. set_tracebusid ( settings. bus_id . unwrap_or ( 0 ) ) ;
210
270
211
271
r
212
272
} ) ;
213
273
}
274
+
275
+ Ok ( ( ) )
214
276
}
215
277
}
0 commit comments