@@ -174,6 +174,28 @@ pub struct ITMSettings {
174174 pub timestamp_clk_src : TimestampClkSrc ,
175175}
176176
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+
177199impl ITM {
178200 /// Removes the software lock on the ITM. Must be called before any other [ITM] functions.
179201 #[ inline]
@@ -182,34 +204,82 @@ impl ITM {
182204 unsafe { self . lar . write ( 0xC5AC_CE55 ) }
183205 }
184206
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+
188213 unsafe {
189214 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- } ) ;
199215 r. set_gtsfreq ( match settings. global_timestamps {
200216 GlobalTimestampOptions :: Disabled => 0b00 ,
201217 GlobalTimestampOptions :: Every128Cycles => 0b01 ,
202218 GlobalTimestampOptions :: Every8192Cycles => 0b10 ,
203219 GlobalTimestampOptions :: EveryPacket => 0b11 ,
204220 } ) ;
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| {
205234 r. set_swoena ( match settings. timestamp_clk_src {
206235 TimestampClkSrc :: SystemClock => false ,
207236 TimestampClkSrc :: AsyncTPIU => true ,
208237 } ) ;
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
209277 r. set_tracebusid ( settings. bus_id . unwrap_or ( 0 ) ) ;
210278
211279 r
212280 } ) ;
213281 }
282+
283+ Ok ( ( ) )
214284 }
215285}
0 commit comments