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