Skip to content

Commit 8a2ab27

Browse files
committed
itm: configure: check feature support during configuration
Related to rust-embedded#382.
1 parent 508292c commit 8a2ab27

File tree

1 file changed

+82
-12
lines changed

1 file changed

+82
-12
lines changed

src/peripheral/itm.rs

+82-12
Original file line numberDiff line numberDiff line change
@@ -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+
177199
impl 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

Comments
 (0)