This is an automated email from Gerrit. Adrian M Negreanu (adrian.negre...@nxp.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/5820
-- gerrit commit b186a8febaa55e1d78ee7467c5cd0830bdd29733 Author: Adrian Negreanu <adrian.negre...@nxp.com> Date: Wed Aug 19 20:10:59 2020 +0300 RFC: add CMSIS-DAP SWO commands Change-Id: Ieba79b16efd445143f964b614673d041aae74f92 Signed-off-by: Adrian Negreanu <adrian.negre...@nxp.com> diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index 6d55392..9cc0c0e 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -37,6 +37,8 @@ #include <jtag/interface.h> #include <jtag/commands.h> #include <jtag/tcl.h> +#include <target/cortex_m.h> +#include <math.h> #include <hidapi.h> @@ -86,9 +88,12 @@ static bool swd_mode; #define INFO_ID_CAPS 0xf0 /* byte */ #define INFO_ID_PKT_CNT 0xfe /* byte */ #define INFO_ID_PKT_SZ 0xff /* short */ +#define INFO_ID_SWO_BUF_SZ 0xfd /* word */ #define INFO_CAPS_SWD 0x01 #define INFO_CAPS_JTAG 0x02 +#define INFO_CAPS_SWO_UART 0x04 +#define INFO_CAPS_SWO_MANCHESTER 0x08 /* CMD_LED */ #define LED_ID_CONNECT 0x00 @@ -152,16 +157,47 @@ static bool swd_mode; #define DAP_OK 0 #define DAP_ERROR 0xFF +/* CMSIS-DAP SWO Commands */ +#define CMD_DAP_SWO_TRANSPORT 0x17 +#define CMD_DAP_SWO_MODE 0x18 +#define CMD_DAP_SWO_BAUDRATE 0x19 +#define CMD_DAP_SWO_CONTROL 0x1A +#define CMD_DAP_SWO_STATUS 0x1B +#define CMD_DAP_SWO_DATA 0x1C +#define CMD_DAP_SWO_EX_STATUS 0x1E + +/* SWO transport mode for reading trace data */ +#define DAP_SWO_TRANSPORT_NONE 0 +#define DAP_SWO_TRANSPORT_DATA 1 +#define DAP_SWO_TRANSPORT_WINUSB 2 + +/* SWO trace capture mode */ +#define DAP_SWO_MODE_OFF 0 +#define DAP_SWO_MODE_UART 1 +#define DAP_SWO_MODE_MANCHESTER 2 + +/* SWO trace data capture */ +#define DAP_SWO_CONTROL_STOP 0 +#define DAP_SWO_CONTROL_START 1 + +/* SWO trace status */ +#define DAP_SWO_STATUS_CAPTURE_ACTIVE (1U<<0) +#define DAP_SWO_STATUS_CAPTURE_PAUSED (1U<<1) +#define DAP_SWO_STATUS_STREAM_ERROR (1U<<6) +#define DAP_SWO_STATUS_BUFFER_OVERRUN (1U<<7) + /* CMSIS-DAP Vendor Commands * None as yet... */ static const char * const info_caps_str[] = { "SWD Supported", - "JTAG Supported" + "JTAG Supported", + "SWO-UART Supported", + "SWO-MANCHESTER Supported" }; /* max clock speed (kHz) */ -#define DAP_MAX_CLOCK 5000 +#define DAP_MAX_CLOCK_kHz 50000 struct cmsis_dap { hid_device *dev_handle; @@ -170,6 +206,8 @@ struct cmsis_dap { uint8_t *packet_buffer; uint8_t caps; uint8_t mode; + uint8_t enabled; + uint32_t swo_buf_sz; }; struct pending_transfer_result { @@ -625,6 +663,183 @@ static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us) } #endif +static int cmsis_dap_cmd_DAP_SWO_Transport( + struct cmsis_dap *dap, + uint8_t transport) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_TRANSPORT; + buffer[2] = transport; + retval = cmsis_dap_usb_xfer(dap, 3); + + if (retval != ERROR_OK || buffer[1] != DAP_OK) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Transport(%d) failed.", transport); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +static int cmsis_dap_cmd_DAP_SWO_Mode(struct cmsis_dap *dap, uint8_t mode) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_MODE; + buffer[2] = mode; + retval = cmsis_dap_usb_xfer(dap, 3); + + if (retval != ERROR_OK || buffer[1] != DAP_OK) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Mode(%d) failed.", mode); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +static int cmsis_dap_cmd_DAP_SWO_Baudrate( + struct cmsis_dap *dap, + uint32_t in_baudrate, + uint32_t *dev_baudrate) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + uint32_t rvbr; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_BAUDRATE; + buffer[2] = in_baudrate & 0xff; + buffer[3] = (in_baudrate >> 8) & 0xff; + buffer[4] = (in_baudrate >> 16) & 0xff; + buffer[5] = (in_baudrate >> 24) & 0xff; + retval = cmsis_dap_usb_xfer(dap, 6); + + rvbr = le_to_h_u32(&buffer[1]); + + if (retval != ERROR_OK || rvbr == 0) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Baudrate(%u) -> %u failed.", in_baudrate, rvbr); + if (dev_baudrate) *dev_baudrate = 0; + return ERROR_JTAG_DEVICE_ERROR; + } + + if (dev_baudrate) + *dev_baudrate = rvbr; + + return ERROR_OK; +} + +static int cmsis_dap_cmd_DAP_SWO_Control( + struct cmsis_dap *dap, + uint8_t control) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_CONTROL; + buffer[2] = control; + retval = cmsis_dap_usb_xfer(dap, 3); + + if (retval != ERROR_OK || buffer[1] != DAP_OK) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Control(%d) failed.", control); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +static int cmsis_dap_cmd_DAP_SWO_Status( + struct cmsis_dap *dap, + uint8_t *trace_status, + size_t *trace_count) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_STATUS; + retval = cmsis_dap_usb_xfer(dap, 2); + + if (retval != ERROR_OK) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Status failed."); + return ERROR_JTAG_DEVICE_ERROR; + } + + if (trace_status) + *trace_status = buffer[1]; + if (trace_count) + *trace_count = le_to_h_u32(&buffer[2]); + + return ERROR_OK; +} + +static int cmsis_dap_cmd_DAP_SWO_Ex_Status( + struct cmsis_dap *dap, + uint8_t *trace_status, + uint32_t *trace_count, + uint32_t *trace_index, + uint32_t *td_timestamp) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_EX_STATUS; + retval = cmsis_dap_usb_xfer(dap, 2); + + if (retval != ERROR_OK) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Extended_Status failed."); + return ERROR_JTAG_DEVICE_ERROR; + } + + if (trace_status) + *trace_status = buffer[1]; + if (trace_count) + *trace_count = le_to_h_u32(&buffer[2]); + if (trace_index) + *trace_index = le_to_h_u32(&buffer[6]); + if (td_timestamp) + *td_timestamp = le_to_h_u32(&buffer[10]); + + return ERROR_OK; +} + +static int cmsis_dap_cmd_DAP_SWO_Data( + struct cmsis_dap *dap, + size_t max_trace_count, + uint8_t *trace_status, + size_t *trace_count, + uint8_t *data) +{ + int retval; + uint8_t *buffer = dap->packet_buffer; + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWO_DATA; + buffer[2] = max_trace_count & 0xff; + buffer[3] = (max_trace_count >> 8) & 0xff; + retval = cmsis_dap_usb_xfer(dap, 4); + + if (retval != ERROR_OK) { + LOG_ERROR("CMSIS-DAP: command CMD_SWO_Data failed."); + return ERROR_JTAG_DEVICE_ERROR; + } + + *trace_status = buffer[1]; + *trace_count = le_to_h_u16(&buffer[2]); + + if (*trace_count > 0) { + memcpy(data, &(buffer[4]), *trace_count); + LOG_INFO("read %d out of %d", *trace_count, max_trace_count); + } + + return ERROR_OK; +} + static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) { uint8_t *buffer = dap->packet_buffer; @@ -870,11 +1085,34 @@ static int cmsis_dap_get_caps_info(void) LOG_INFO("CMSIS-DAP: %s", info_caps_str[0]); if (caps & INFO_CAPS_JTAG) LOG_INFO("CMSIS-DAP: %s", info_caps_str[1]); + if (caps & INFO_CAPS_SWO_UART) + LOG_INFO("CMSIS-DAP: %s", info_caps_str[2]); + if (caps & INFO_CAPS_SWO_MANCHESTER) + LOG_INFO("CMSIS-DAP: %s", info_caps_str[3]); } return ERROR_OK; } +static int cmsis_dap_get_swo_buf_sz(struct cmsis_dap *dap, uint32_t *swo_buf_sz) +{ + uint8_t *data; + + /* INFO_ID_SWO_BUF_SZ - word */ + int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_SWO_BUF_SZ, &data); + if (retval != ERROR_OK) + return retval; + + if (data[0] != 4) + return ERROR_FAIL; + + *swo_buf_sz = le_to_h_u32(&data[1]); + + LOG_INFO("CMSIS-DAP: SWO Trace Buffer Size = %u bytes", *swo_buf_sz); + + return ERROR_OK; +} + static int cmsis_dap_get_status(void) { uint8_t d; @@ -1626,7 +1864,7 @@ static int cmsis_dap_execute_queue(void) static int cmsis_dap_speed(int speed) { - if (speed > DAP_MAX_CLOCK) + if (speed > DAP_MAX_CLOCK_kHz) LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed); if (speed == 0) { @@ -1649,6 +1887,154 @@ static int cmsis_dap_khz(int khz, int *jtag_speed) return ERROR_OK; } +/* Maximum SWO frequency deviation. */ +/* Probe's UART speed must be within 3% of the TPIU's SWO baud rate. */ +#define SWO_MAX_FREQ_DEV 0.03 + +static bool calculate_swo_prescaler( + unsigned int traceclkin_freq, + uint32_t swo_freq, + uint16_t *swo_prescaler) +{ + unsigned int presc; + double deviation; + + presc = traceclkin_freq/swo_freq; + if (presc > TPIU_ACPR_MAX_SWOSCALER) + return false; + deviation = fabs(1.0 - ((double)presc*swo_freq / traceclkin_freq)); + if (deviation > SWO_MAX_FREQ_DEV) + return false; + *swo_prescaler = presc; + + return true; +} + +#define MIN_BAUDRATE 300 +#define MAX_BAUDRATE 921600 +static int cmsis_dap_config_trace( + bool enabled, + enum tpiu_pin_protocol pin_protocol, + uint32_t port_size, + unsigned int *swo_freq, + unsigned int traceclkin_freq, + uint16_t *swo_prescaler) +{ + int retval; + + if (!(cmsis_dap_handle->caps & INFO_CAPS_SWO_UART)) { + LOG_ERROR("Trace capturing is not supported by the device."); + return ERROR_FAIL; + } + + uint8_t swo_mode; + switch (pin_protocol) { + case TPIU_PIN_PROTOCOL_ASYNC_UART: + swo_mode = DAP_SWO_MODE_UART; + break; + case TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER: + swo_mode = DAP_SWO_MODE_MANCHESTER; + break; + default: + LOG_ERROR("Selected pin protocol is not supported."); + return ERROR_FAIL; + } + + if (*swo_freq == 0 ) { + LOG_INFO("SWO frequency autodetection not implemented."); + return ERROR_FAIL; + } + + retval = cmsis_dap_cmd_DAP_SWO_Baudrate(cmsis_dap_handle, *swo_freq, swo_freq); + if (retval != ERROR_OK || *swo_freq == 0) + return ERROR_FAIL; + + if (*swo_freq > MAX_BAUDRATE) { + LOG_INFO("Given SWO frequency too high, using %u Hz instead.", + MAX_BAUDRATE); + *swo_freq = MAX_BAUDRATE; + } else if (*swo_freq < MIN_BAUDRATE) { + LOG_INFO("Given SWO frequency too low, using %u Hz instead.", + MIN_BAUDRATE); + *swo_freq = MIN_BAUDRATE; + } + + if (!calculate_swo_prescaler(traceclkin_freq, *swo_freq, + swo_prescaler)) { + LOG_ERROR("SWO frequency is not suitable. Please choose a " + "different frequency or use auto-detection."); + return ERROR_FAIL; + } + + LOG_INFO("SWO frequency: %u Hz.", *swo_freq); + LOG_INFO("SWO prescaler: %u.", *swo_prescaler); + + retval = cmsis_dap_cmd_DAP_SWO_Control(cmsis_dap_handle, DAP_SWO_CONTROL_STOP); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_get_swo_buf_sz(cmsis_dap_handle, &cmsis_dap_handle->swo_buf_sz); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_cmd_DAP_SWO_Transport(cmsis_dap_handle, DAP_SWO_TRANSPORT_DATA); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_cmd_DAP_SWO_Mode(cmsis_dap_handle, swo_mode); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_cmd_DAP_SWO_Control(cmsis_dap_handle, DAP_SWO_CONTROL_START); + if (retval != ERROR_OK) + return retval; + + cmsis_dap_handle->enabled = 1; + + return ERROR_OK; +} + +static int cmsis_dap_poll_trace(uint8_t *buf, size_t *size) +{ + int retval; + uint8_t trace_status; + size_t trace_count; + + if (!cmsis_dap_handle->enabled) { + *size = 0; + return ERROR_OK; + } + + if (!(cmsis_dap_handle->caps & INFO_CAPS_SWO_UART)) { + LOG_ERROR("SWO-UART capturing is not supported by the device."); + return ERROR_FAIL; + } + + retval = cmsis_dap_cmd_DAP_SWO_Status(cmsis_dap_handle, &trace_status, &trace_count); + if (retval != ERROR_OK) + return retval; + if ((trace_status&DAP_SWO_STATUS_CAPTURE_ACTIVE) != DAP_SWO_STATUS_CAPTURE_ACTIVE) + return ERROR_FAIL; + + *size = trace_count < *size ? trace_count : *size - 1; + int off=0; + do { + int rb = 0; + retval = cmsis_dap_cmd_DAP_SWO_Data( + cmsis_dap_handle, + *size - off, + &trace_status, + &rb, + buf + off); + if (retval != ERROR_OK) + return retval; + if ((trace_status&DAP_SWO_STATUS_CAPTURE_ACTIVE) != DAP_SWO_STATUS_CAPTURE_ACTIVE) + return ERROR_FAIL; + off += rb; + } while ( off < *size); + return ERROR_OK; +} + COMMAND_HANDLER(cmsis_dap_handle_info_command) { if (cmsis_dap_get_version_info() == ERROR_OK) @@ -1801,6 +2187,8 @@ struct adapter_driver cmsis_dap_adapter_driver = { .speed = cmsis_dap_speed, .khz = cmsis_dap_khz, .speed_div = cmsis_dap_speed_div, + .config_trace = &cmsis_dap_config_trace, + .poll_trace = &cmsis_dap_poll_trace, .jtag_ops = &cmsis_dap_interface, .swd_ops = &cmsis_dap_swd_driver, diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink index 9aa7a59..f73ad5e 160000 --- a/src/jtag/drivers/libjaylink +++ b/src/jtag/drivers/libjaylink @@ -1 +1 @@ -Subproject commit 9aa7a5957c07bb6e862fc1a6d3153d109c7407e4 +Subproject commit f73ad5e667ae8b26a52b847c603fdadaabf302a6 diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 931471a..9185747 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -36,7 +36,14 @@ #define ITM_TPR 0xE0000E40 #define ITM_TCR 0xE0000E80 #define ITM_LAR 0xE0000FB0 +#define ITM_LSR 0xE0000FB4 #define ITM_LAR_KEY 0xC5ACCE55 +#define ITM_TCR_ITMENA_BIT 0 +#define ITM_TCR_BUSY_BIT 23 + +#define SWO_LAR 0xe0048FB0 +#define SWO_LSR 0xe0048FB4 + #define CPUID 0xE000ED00 -- _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel