Skip to content

Commit 7c3173f

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

File tree

1 file changed

+73
-12
lines changed

1 file changed

+73
-12
lines changed

src/peripheral/itm.rs

+73-12
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,20 @@ 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+
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+
177191
impl ITM {
178192
/// Removes the software lock on the ITM. Must be called before any other [ITM] functions.
179193
#[inline]
@@ -182,34 +196,81 @@ impl ITM {
182196
unsafe { self.lar.write(0xC5AC_CE55) }
183197
}
184198

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+
188204
unsafe {
189205
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-
});
199206
r.set_gtsfreq(match settings.global_timestamps {
200207
GlobalTimestampOptions::Disabled => 0b00,
201208
GlobalTimestampOptions::Every128Cycles => 0b01,
202209
GlobalTimestampOptions::Every8192Cycles => 0b10,
203210
GlobalTimestampOptions::EveryPacket => 0b11,
204211
});
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| {
205225
r.set_swoena(match settings.timestamp_clk_src {
206226
TimestampClkSrc::SystemClock => false,
207227
TimestampClkSrc::AsyncTPIU => true,
208228
});
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
209268
r.set_tracebusid(settings.bus_id.unwrap_or(0));
210269

211270
r
212271
});
213272
}
273+
274+
Ok(())
214275
}
215276
}

0 commit comments

Comments
 (0)