#define STLINK_TRACE_SIZE 4096
#define STLINK_TRACE_MAX_HZ 2000000
-#define STLINK_TRACE_MIN_VERSION 13
/** */
enum stlink_mode {
* Map the relevant features, quirks and workaround for specific firmware
* version of stlink
*/
+#define STLINK_F_HAS_TRACE (1UL << 0)
+#define STLINK_F_HAS_SWD_SET_FREQ (1UL << 1)
+#define STLINK_F_HAS_JTAG_SET_FREQ (1UL << 2)
+#define STLINK_F_HAS_MEM_16BIT (1UL << 3)
/* aliases */
+#define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE
struct speed_map {
int speed;
assert(handle != NULL);
- assert(h->version.stlink >= 2);
+ assert(h->version.flags & STLINK_F_HAS_TRACE);
if (jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf,
size, STLINK_READ_TIMEOUT) != size) {
/* all ST-LINK/V2 and ST-Link/V2.1 use api-v2 */
h->version.jtag_api_max = STLINK_JTAG_API_V2;
+ /* API for trace from J13 */
+ /* API for target voltage from J13 */
+ if (h->version.jtag >= 13)
+ flags |= STLINK_F_HAS_TRACE;
+
+ /* API to set SWD frequency from J22 */
+ if (h->version.jtag >= 22)
+ flags |= STLINK_F_HAS_SWD_SET_FREQ;
+
+ /* API to set JTAG frequency from J24 */
+ if (h->version.jtag >= 24)
+ flags |= STLINK_F_HAS_JTAG_SET_FREQ;
+
+ /* API to read/write memory at 16 bit from J26 */
+ if (h->version.jtag >= 26)
+ flags |= STLINK_F_HAS_MEM_16BIT;
+
break;
default:
break;
struct stlink_usb_handle_s *h = handle;
uint32_t adc_results[2];
- /* only supported by stlink/v2 and for firmware >= 13 */
- if (h->version.stlink == 1 || h->version.jtag < 13)
+ /* no error message, simply quit with error */
+ if (!(h->version.flags & STLINK_F_HAS_TARGET_VOLT))
return ERROR_COMMAND_NOTFOUND;
stlink_usb_init_buffer(handle, h->rx_ep, 8);
assert(handle != NULL);
- /* only supported by stlink/v2 and for firmware >= 22 */
- if (h->version.stlink == 1 || h->version.jtag < 22)
+ if (!(h->version.flags & STLINK_F_HAS_SWD_SET_FREQ))
return ERROR_COMMAND_NOTFOUND;
stlink_usb_init_buffer(handle, h->rx_ep, 2);
assert(handle != NULL);
- /* only supported by stlink/v2 and for firmware >= 24 */
- if (h->version.stlink == 1 || h->version.jtag < 24)
+ if (!(h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ))
return ERROR_COMMAND_NOTFOUND;
stlink_usb_init_buffer(handle, h->rx_ep, 2);
assert(handle != NULL);
- if (h->trace.enabled && h->version.jtag >= STLINK_TRACE_MIN_VERSION) {
+ if (h->trace.enabled && (h->version.flags & STLINK_F_HAS_TRACE)) {
int res;
stlink_usb_init_buffer(handle, h->rx_ep, 10);
assert(handle != NULL);
- assert(h->version.jtag >= STLINK_TRACE_MIN_VERSION);
+ assert(h->version.flags & STLINK_F_HAS_TRACE);
LOG_DEBUG("Tracing: disable");
assert(handle != NULL);
- if (h->version.jtag >= STLINK_TRACE_MIN_VERSION) {
+ if (h->version.flags & STLINK_F_HAS_TRACE) {
stlink_usb_init_buffer(handle, h->rx_ep, 10);
h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
assert(handle != NULL);
- /* only supported by stlink/v2 and for firmware >= 26 */
- if (h->jtag_api == STLINK_JTAG_API_V1 ||
- (h->jtag_api == STLINK_JTAG_API_V2 && h->version.jtag < 26))
+ if (!(h->version.flags & STLINK_F_HAS_MEM_16BIT))
return ERROR_COMMAND_NOTFOUND;
/* data must be a multiple of 2 and half-word aligned */
assert(handle != NULL);
- /* only supported by stlink/v2 and for firmware >= 26 */
- if (h->jtag_api == STLINK_JTAG_API_V1 ||
- (h->jtag_api == STLINK_JTAG_API_V2 && h->version.jtag < 26))
+ if (!(h->version.flags & STLINK_F_HAS_MEM_16BIT))
return ERROR_COMMAND_NOTFOUND;
/* data must be a multiple of 2 and half-word aligned */
count *= size;
/* switch to 8 bit if stlink does not support 16 bit memory read */
- if (size == 2 && (h->jtag_api == STLINK_JTAG_API_V1 ||
- (h->jtag_api == STLINK_JTAG_API_V2 && h->version.jtag < 26)))
+ if (size == 2 && !(h->version.flags & STLINK_F_HAS_MEM_16BIT))
size = 1;
while (count) {
count *= size;
/* switch to 8 bit if stlink does not support 16 bit memory read */
- if (size == 2 && (h->jtag_api == STLINK_JTAG_API_V1 ||
- (h->jtag_api == STLINK_JTAG_API_V2 && h->version.jtag < 26)))
+ if (size == 2 && !(h->version.flags & STLINK_F_HAS_MEM_16BIT))
size = 1;
while (count) {
int speed_index;
struct stlink_usb_handle_s *h = handle;
- /* only supported by stlink/v2 and for firmware >= 22 */
- if (h->version.stlink == 1 || h->version.jtag < 22)
+ /* old firmware cannot change it */
+ if (!(h->version.flags & STLINK_F_HAS_SWD_SET_FREQ))
return khz;
speed_index = stlink_match_speed_map(stlink_khz_to_speed_map_swd,
int speed_index;
struct stlink_usb_handle_s *h = handle;
- /* only supported by stlink/v2 and for firmware >= 24 */
- if (h->version.stlink == 1 || h->version.jtag < 24)
+ /* old firmware cannot change it */
+ if (!(h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ))
return khz;
speed_index = stlink_match_speed_map(stlink_khz_to_speed_map_jtag,
case STLINK_V1_PID:
h->version.stlink = 1;
h->tx_ep = STLINK_TX_EP;
- h->trace_ep = STLINK_TRACE_EP;
break;
case STLINK_V2_1_PID:
case STLINK_V2_1_NO_MSD_PID:
}
if (h->transport == HL_TRANSPORT_JTAG) {
- /* jtag clock speed only supported by stlink/v2 and for firmware >= 24 */
- if (h->version.stlink >= 2 && h->version.jtag >= 24) {
+ if (h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ) {
stlink_dump_speed_map(stlink_khz_to_speed_map_jtag, ARRAY_SIZE(stlink_khz_to_speed_map_jtag));
stlink_speed(h, param->initial_interface_speed, false);
}
} else if (h->transport == HL_TRANSPORT_SWD) {
- /* clock speed only supported by stlink/v2 and for firmware >= 22 */
- if (h->version.stlink >= 2 && h->version.jtag >= 22) {
+ if (h->version.flags & STLINK_F_HAS_SWD_SET_FREQ) {
stlink_dump_speed_map(stlink_khz_to_speed_map_swd, ARRAY_SIZE(stlink_khz_to_speed_map_swd));
stlink_speed(h, param->initial_interface_speed, false);
}
{
struct stlink_usb_handle_s *h = handle;
- if (enabled && (h->jtag_api < 2 ||
+ if (enabled && (!(h->version.flags & STLINK_F_HAS_TRACE) ||
pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) {
LOG_ERROR("The attached ST-LINK version doesn't support this trace mode");
return ERROR_FAIL;