@@ -209,3 +209,73 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value)
209209 (void )bus ;
210210 return value ;
211211}
212+
213+ #ifdef PLATFORM_HAS_CUSTOM_COMMANDS
214+
215+ #include "swd.h"
216+ #include "gdb_packet.h"
217+ #include "target_internal.h"
218+ #include <libopencm3/cm3/dwt.h>
219+
220+ static bool cmd_swdptap_calibration (target_s * target , int argc , const char * * argv );
221+
222+ const command_s platform_cmd_list [] = {
223+ {"calibrate_swd" , cmd_swdptap_calibration , "Calibrate SW-DP TAP timings" },
224+ {NULL , NULL , NULL },
225+ };
226+
227+ static void swdptap_linereset_measured (bool no_delay )
228+ {
229+ const uint32_t ts_pre = dwt_read_cycle_counter ();
230+ /* for robustness, we use 60 HIGH cycles and 4 idle cycles */
231+ swd_proc .seq_out (0xffffffffU , 32U );
232+ swd_proc .seq_out (0x0fffffffU , 32U );
233+ swd_proc .seq_out (0xffffffffU , 32U );
234+ swd_proc .seq_out (0x0fffffffU , 32U );
235+ swd_proc .seq_out (0xffffffffU , 32U );
236+ swd_proc .seq_out (0x0fffffffU , 32U );
237+ swd_proc .seq_out (0xffffffffU , 32U );
238+ swd_proc .seq_out (0x0fffffffU , 32U );
239+ const uint32_t ts_post = dwt_read_cycle_counter ();
240+ const uint32_t cycles_spent = ts_post - ts_pre ;
241+ /* Subtract the overhead of function calls */
242+ const uint32_t fncall_corr = no_delay ? (544U ) : (488U );
243+ /* Split the 64*4 into 16*16 for 216-240MHz clocks to not overflow a uint32_t */
244+ const uint32_t freq_measured = rcc_ahb_frequency * 16U / (cycles_spent - fncall_corr ) * 16U ;
245+ gdb_outf ("Estimated %7lu Hz (%5lu cycles - %ld corr)\n" , freq_measured , cycles_spent , fncall_corr );
246+ }
247+
248+ static bool cmd_swdptap_calibration (target_s * target , int argc , const char * * argv )
249+ {
250+ (void )argc ;
251+ (void )argv ;
252+ if (target && target -> attached )
253+ target_detach (target );
254+ platform_target_clk_output_enable (true);
255+ if (!swd_proc .seq_out )
256+ swdptap_init ();
257+ dwt_enable_cycle_counter ();
258+
259+ uint32_t freq = 0 ;
260+ gdb_outf ("Platform core clock %lu\n" , rcc_ahb_frequency );
261+
262+ /* Emit a _no_delay waveform */
263+ target_clk_divider = UINT32_MAX ;
264+ freq = platform_max_frequency_get ();
265+ gdb_outf ("Changing frequency to %7lu (no_delay)\t" , freq );
266+ swdptap_linereset_measured (true);
267+
268+ /* Loop through a few _delay values */
269+ for (uint32_t i = 0 ; i < 8 ; i ++ ) {
270+ target_clk_divider = i ;
271+ freq = platform_max_frequency_get ();
272+ gdb_outf ("Changing frequency to %7lu (divider=%lu)\t" , freq , target_clk_divider );
273+ swdptap_linereset_measured (false);
274+ }
275+
276+ /* Reset frequency to medium */
277+ platform_max_frequency_set (3000000U );
278+ return true;
279+ }
280+
281+ #endif
0 commit comments