Frequency: Implementing for jlink.

SWD frequency is fixed for jlink according to the docs from 2010.
This commit is contained in:
Uwe Bonnes 2020-11-28 12:46:19 +01:00
parent fdc654cfb3
commit 6dbb5ff7ee
3 changed files with 99 additions and 12 deletions

View File

@ -40,14 +40,19 @@
#define USB_VID_SEGGER_0105 0x0105 #define USB_VID_SEGGER_0105 0x0105
#define USB_VID_SEGGER_1020 0x1020 #define USB_VID_SEGGER_1020 0x1020
static uint32_t emu_caps;
static uint32_t emu_speed_kHz;
static uint16_t emu_min_divisor;
static uint16_t emu_current_divisor;
static void jlink_print_caps(bmp_info_t *info) static void jlink_print_caps(bmp_info_t *info)
{ {
uint8_t cmd[1] = {CMD_GET_CAPS}; uint8_t cmd[1] = {CMD_GET_CAPS};
uint8_t res[4]; uint8_t res[4];
send_recv(info->usb_link, cmd, 1, res, sizeof(res)); send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint32_t caps = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24); emu_caps = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24);
DEBUG_INFO("Caps %" PRIx32 "\n", caps); DEBUG_INFO("Caps %" PRIx32 "\n", emu_caps);
if (caps & JLINK_CAP_GET_HW_VERSION) { if (emu_caps & JLINK_CAP_GET_HW_VERSION) {
uint8_t cmd[1] = {CMD_GET_HW_VERSION}; uint8_t cmd[1] = {CMD_GET_HW_VERSION};
send_recv(info->usb_link, cmd, 1, NULL, 0); send_recv(info->usb_link, cmd, 1, NULL, 0);
send_recv(info->usb_link, NULL, 0, res, sizeof(res)); send_recv(info->usb_link, NULL, 0, res, sizeof(res));
@ -57,13 +62,15 @@ static void jlink_print_caps(bmp_info_t *info)
} }
static void jlink_print_speed(bmp_info_t *info) static void jlink_print_speed(bmp_info_t *info)
{ {
uint8_t cmd[1] = {CMD_GET_SPEED}; uint8_t cmd[1] = {CMD_GET_SPEEDS};
uint8_t res[6]; uint8_t res[6];
send_recv(info->usb_link, cmd, 1, res, sizeof(res)); send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint32_t speed = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24); emu_speed_kHz = (res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24)) /
double freq_mhz = speed / 1000000.0; 1000;
uint16_t divisor = res[4] | (res[5] << 8); emu_min_divisor = res[4] | (res[5] << 8);
DEBUG_INFO("Emulator speed %3.1f MHz, Mindiv %d\n", freq_mhz, divisor); DEBUG_INFO("Emulator speed %d kHz, Mindiv %d%s\n", emu_speed_kHz,
emu_min_divisor,
(emu_caps & JLINK_CAP_GET_SPEEDS) ? "" : ", fixed");
} }
static void jlink_print_version(bmp_info_t *info) static void jlink_print_version(bmp_info_t *info)
@ -98,8 +105,8 @@ static void jlink_print_interfaces(bmp_info_t *info)
static void jlink_info(bmp_info_t *info) static void jlink_info(bmp_info_t *info)
{ {
jlink_print_version(info); jlink_print_version(info);
jlink_print_speed(info);
jlink_print_caps(info); jlink_print_caps(info);
jlink_print_speed(info);
jlink_print_interfaces(info); jlink_print_interfaces(info);
} }
@ -214,7 +221,7 @@ int jlink_init(bmp_info_t *info)
const char *jlink_target_voltage(bmp_info_t *info) const char *jlink_target_voltage(bmp_info_t *info)
{ {
uint8_t cmd[1] = {CMD_GET_HW_STATUS}; uint8_t cmd[1] = {CMD_GET_HW_STATUS};
uint8_t res[8]; uint8_t res[8];
send_recv(info->usb_link, cmd, 1, res, sizeof(res)); send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint16_t mVolt = res[0] | (res[1] << 8); uint16_t mVolt = res[0] | (res[1] << 8);
static char ret[7]; static char ret[7];
@ -238,3 +245,27 @@ bool jlink_srst_get_val(bmp_info_t *info) {
send_recv(info->usb_link, cmd, 1, res, sizeof(res)); send_recv(info->usb_link, cmd, 1, res, sizeof(res));
return !(res[6]); return !(res[6]);
} }
void jlink_max_frequency_set(bmp_info_t *info, uint32_t freq)
{
if (!(emu_caps & JLINK_CAP_GET_SPEEDS))
return;
if (!info->is_jtag)
return;
uint16_t freq_kHz = freq /1000;
uint16_t divisor = (emu_speed_kHz + freq_kHz - 1) / freq_kHz;
if (divisor < emu_min_divisor)
divisor = emu_min_divisor;
emu_current_divisor = divisor;
uint16_t speed_kHz = emu_speed_kHz / divisor;
uint8_t cmd[3] = {CMD_SET_SPEED, speed_kHz & 0xff, speed_kHz >> 8};
DEBUG_WARN("Set Speed %d\n", speed_kHz);
send_recv(info->usb_link, cmd, 3, NULL, 0);
}
uint32_t jlink_max_frequency_get(bmp_info_t *info)
{
if ((emu_caps & JLINK_CAP_GET_SPEEDS) && (info->is_jtag))
return (emu_speed_kHz * 1000L)/ emu_current_divisor;
return FREQ_FIXED;
}

View File

@ -24,8 +24,9 @@
/** @cond PRIVATE */ /** @cond PRIVATE */
#define CMD_GET_VERSION 0x01 #define CMD_GET_VERSION 0x01
#define CMD_SET_SPEED 0x05
#define CMD_GET_HW_STATUS 0x07 #define CMD_GET_HW_STATUS 0x07
#define CMD_GET_SPEED 0xc0 #define CMD_GET_SPEEDS 0xc0
#define CMD_GET_SELECT_IF 0xc7 #define CMD_GET_SELECT_IF 0xc7
#define CMD_HW_JTAG3 0xcf #define CMD_HW_JTAG3 0xcf
#define CMD_HW_RESET0 0xdc #define CMD_HW_RESET0 0xdc
@ -37,7 +38,8 @@
#define JLINK_IF_GET_ACTIVE 0xfe #define JLINK_IF_GET_ACTIVE 0xfe
#define JLINK_IF_GET_AVAILABLE 0xff #define JLINK_IF_GET_AVAILABLE 0xff
#define JLINK_CAP_GET_HW_VERSION 2 #define JLINK_CAP_GET_SPEEDS (1 << 9)
#define JLINK_CAP_GET_HW_VERSION (1 << 1)
#define JLINK_IF_JTAG 1 #define JLINK_IF_JTAG 1
#define JLINK_IF_SWD 2 #define JLINK_IF_SWD 2
@ -53,13 +55,54 @@ int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc) {return 0;};
const char *jlink_target_voltage(bmp_info_t *info) {return "ERROR";}; const char *jlink_target_voltage(bmp_info_t *info) {return "ERROR";};
void jlink_srst_set_val(bmp_info_t *info, bool assert) {}; void jlink_srst_set_val(bmp_info_t *info, bool assert) {};
bool jlink_srst_get_val(bmp_info_t *info) {return true;}; bool jlink_srst_get_val(bmp_info_t *info) {return true;};
void jlink_max_frequency_set(bmp_info_t *info, uint32_t freq) {};
uint32_t jlink_max_frequency_get(bmp_info_t *info) {return 0;};
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#else #else
/** Device capabilities. (from openocd*/
enum jaylink_device_capability {
/** Device supports retrieval of the hardware version. */
JAYLINK_DEV_CAP_GET_HW_VERSION = 1,
/** Device supports adaptive clocking. */
JAYLINK_DEV_CAP_ADAPTIVE_CLOCKING = 3,
/** Device supports reading configuration data. */
JAYLINK_DEV_CAP_READ_CONFIG = 4,
/** Device supports writing configuration data. */
JAYLINK_DEV_CAP_WRITE_CONFIG = 5,
/** Device supports retrieval of target interface speeds. */
JAYLINK_DEV_CAP_GET_SPEEDS = 9,
/** Device supports retrieval of free memory size. */
JAYLINK_DEV_CAP_GET_FREE_MEMORY = 11,
/** Device supports retrieval of hardware information. */
JAYLINK_DEV_CAP_GET_HW_INFO = 12,
/** Device supports the setting of the target power supply. */
JAYLINK_DEV_CAP_SET_TARGET_POWER = 13,
/** Device supports target interface selection. */
JAYLINK_DEV_CAP_SELECT_TIF = 17,
/** Device supports retrieval of counter values. */
JAYLINK_DEV_CAP_GET_COUNTERS = 19,
/** Device supports capturing of SWO trace data. */
JAYLINK_DEV_CAP_SWO = 23,
/** Device supports file I/O operations. */
JAYLINK_DEV_CAP_FILE_IO = 26,
/** Device supports registration of connections. */
JAYLINK_DEV_CAP_REGISTER = 27,
/** Device supports retrieval of extended capabilities. */
JAYLINK_DEV_CAP_GET_EXT_CAPS = 31,
/** Device supports EMUCOM. */
JAYLINK_DEV_CAP_EMUCOM = 33,
/** Device supports ethernet connectivity. */
JAYLINK_DEV_CAP_ETHERNET = 38
};
int jlink_init(bmp_info_t *info); int jlink_init(bmp_info_t *info);
int jlink_swdp_scan(bmp_info_t *info); int jlink_swdp_scan(bmp_info_t *info);
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc); int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc);
const char *jlink_target_voltage(bmp_info_t *info); const char *jlink_target_voltage(bmp_info_t *info);
void jlink_srst_set_val(bmp_info_t *info, bool assert); void jlink_srst_set_val(bmp_info_t *info, bool assert);
bool jlink_srst_get_val(bmp_info_t *info); bool jlink_srst_get_val(bmp_info_t *info);
void jlink_max_frequency_set(bmp_info_t *info, uint32_t freq);
uint32_t jlink_max_frequency_get(bmp_info_t *info);
#endif #endif
#endif #endif

View File

@ -339,10 +339,21 @@ void platform_max_frequency_set(uint32_t freq)
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
stlink_max_frequency_set(&info, freq); stlink_max_frequency_set(&info, freq);
break; break;
case BMP_TYPE_JLINK:
jlink_max_frequency_set(&info, freq);
break;
default: default:
DEBUG_WARN("Setting max SWJ frequency not yet implemented\n"); DEBUG_WARN("Setting max SWJ frequency not yet implemented\n");
break; break;
} }
uint32_t max_freq = platform_max_frequency_get();
if (max_freq == FREQ_FIXED)
DEBUG_INFO("Device has fixed frequency for %s\n",
(info.is_jtag) ? "JTAG" : "SWD" );
else
DEBUG_INFO("Speed set to %7.4f MHz for %s\n",
platform_max_frequency_get() / 1000000.0,
(info.is_jtag) ? "JTAG" : "SWD" );
} }
uint32_t platform_max_frequency_get(void) uint32_t platform_max_frequency_get(void)
@ -357,6 +368,8 @@ uint32_t platform_max_frequency_get(void)
return libftdi_max_frequency_get(); return libftdi_max_frequency_get();
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
return stlink_max_frequency_get(&info); return stlink_max_frequency_get(&info);
case BMP_TYPE_JLINK:
return jlink_max_frequency_get(&info);
default: default:
DEBUG_WARN("Reading max SWJ frequency not yet implemented\n"); DEBUG_WARN("Reading max SWJ frequency not yet implemented\n");
break; break;