@@ -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,81 @@ 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
+ pub fn configure ( & mut self , settings : ITMSettings ) -> Result < ( ) , ITMConfigurationError > {
202
+ use ITMConfigurationError as Error ;
203
+
188
204
unsafe {
189
205
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
206
r. set_gtsfreq ( match settings. global_timestamps {
200
207
GlobalTimestampOptions :: Disabled => 0b00 ,
201
208
GlobalTimestampOptions :: Every128Cycles => 0b01 ,
202
209
GlobalTimestampOptions :: Every8192Cycles => 0b10 ,
203
210
GlobalTimestampOptions :: EveryPacket => 0b11 ,
204
211
} ) ;
212
+
213
+ r
214
+ } ) ;
215
+ }
216
+ // GTSFREQ is potentially RAZ/WI
217
+ if settings. global_timestamps != GlobalTimestampOptions :: Disabled
218
+ && self . tcr . read ( ) . gtsfreq ( ) == 0
219
+ {
220
+ return Err ( Error :: GTS ) ;
221
+ }
222
+
223
+ unsafe {
224
+ self . tcr . modify ( |mut r| {
205
225
r. set_swoena ( match settings. timestamp_clk_src {
206
226
TimestampClkSrc :: SystemClock => false ,
207
227
TimestampClkSrc :: AsyncTPIU => true ,
208
228
} ) ;
229
+
230
+ r
231
+ } ) ;
232
+ }
233
+ // SWOENA is potentially either RAZ or RAO
234
+ if !{
235
+ match settings. timestamp_clk_src {
236
+ TimestampClkSrc :: SystemClock => self . tcr . read ( ) . swoena ( ) == false ,
237
+ TimestampClkSrc :: AsyncTPIU => self . tcr . read ( ) . swoena ( ) == true ,
238
+ }
239
+ } {
240
+ return Err ( Error :: TimestampClkSrc ) ;
241
+ }
242
+
243
+ unsafe {
244
+ self . tcr . modify ( |mut r| {
245
+ r. set_tsprescale ( match settings. local_timestamps {
246
+ LocalTimestampOptions :: Disabled | LocalTimestampOptions :: Enabled => 0b00 ,
247
+ LocalTimestampOptions :: EnabledDiv4 => 0b10 ,
248
+ LocalTimestampOptions :: EnabledDiv16 => 0b10 ,
249
+ LocalTimestampOptions :: EnabledDiv64 => 0b11 ,
250
+ } ) ;
251
+
252
+ r
253
+ } )
254
+ }
255
+ // TSPrescale is potentially RAZ/WI
256
+ if settings. local_timestamps != LocalTimestampOptions :: Disabled
257
+ && settings. local_timestamps != LocalTimestampOptions :: Enabled
258
+ && self . tcr . read ( ) . tsprescale ( ) == 0
259
+ {
260
+ return Err ( Error :: TSPrescale ) ;
261
+ }
262
+
263
+ unsafe {
264
+ self . tcr . modify ( |mut r| {
265
+ r. set_itmena ( settings. enable ) ;
266
+ r. set_tsena ( settings. local_timestamps != LocalTimestampOptions :: Disabled ) ;
267
+ r. set_txena ( settings. forward_dwt ) ; // forward hardware event packets from the DWT to the ITM
209
268
r. set_tracebusid ( settings. bus_id . unwrap_or ( 0 ) ) ;
210
269
211
270
r
212
271
} ) ;
213
272
}
273
+
274
+ Ok ( ( ) )
214
275
}
215
276
}
0 commit comments