Skip to content

Commit a3b4d17

Browse files
committed
stlink: Implement SWCLK self-measurement as a platform command
1 parent 102e705 commit a3b4d17

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

src/platforms/stlink/platform.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

src/platforms/stlink/platform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
extern bool debug_bmp;
4141
#endif
4242

43+
#define PLATFORM_HAS_CUSTOM_COMMANDS
44+
4345
#define PLATFORM_IDENT "(ST-Link/v2) "
4446

4547
/* Hardware definitions... */

0 commit comments

Comments
 (0)