diff --git a/recipes-devtools/openocd/openocd-stm32mp.inc b/recipes-devtools/openocd/openocd-stm32mp.inc index 91ca09d..3b7ae50 100644 --- a/recipes-devtools/openocd/openocd-stm32mp.inc +++ b/recipes-devtools/openocd/openocd-stm32mp.inc @@ -5,14 +5,14 @@ RDEPENDS_${PN} += "libusb1 hidapi-stm32mp" inherit pkgconfig autotools-brokensep gettext SRC_URI = " \ - git://repo.or.cz/git2cl.git;;destsuffix=git/tools/git2cl;name=git2cl \ - git://repo.or.cz/jimtcl.git;destsuffix=git/jimtcl;name=jimtcl \ + git://repo.or.cz/git2cl.git;destsuffix=git/tools/git2cl;name=git2cl \ + git://github.com/msteveb/jimtcl;protocol=https;destsuffix=git/jimtcl;name=jimtcl \ git://repo.or.cz/libjaylink.git;destsuffix=git/src/jtag/drivers/libjaylink;name=libjaylink \ " SRCREV_git2cl = "8373c9f74993e218a08819cbcdbab3f3564bbeba" SRCREV_jimtcl = "0aa0fb4e3a38d38a49de9eb585d93d63a370dcf6" -SRCREV_libjaylink = "f73ad5e667ae8b26a52b847c603fdadaabf302a6" +SRCREV_libjaylink = "9aa7a5957c07bb6e862fc1a6d3153d109c7407e4" S = "${WORKDIR}/git" @@ -29,6 +29,7 @@ EXTRA_OECONF = " \ --disable-werror \ --enable-stlink \ --enable-cmsis-dap \ + --without-capstone \ MAKEINFO=true \ HIDAPI_CFLAGS=-I${STAGING_INCDIR}/hidapi \ HIDAPI_LIBS=-L${STAGING_LIBDIR}\ -lhidapi-libusb \ diff --git a/recipes-devtools/openocd/openocd-stm32mp/0001-M4-visible-rebase-on-b5d2b1224fed-fixes.patch b/recipes-devtools/openocd/openocd-stm32mp/0001-M4-visible-rebase-on-b5d2b1224fed-fixes.patch deleted file mode 100644 index 44e7ca9..0000000 --- a/recipes-devtools/openocd/openocd-stm32mp/0001-M4-visible-rebase-on-b5d2b1224fed-fixes.patch +++ /dev/null @@ -1,1525 +0,0 @@ -From 34d7a6bde003b73ca8767581c232675009b8ef41 Mon Sep 17 00:00:00 2001 -From: Antonio Borneo -Date: Fri, 13 Mar 2020 16:03:49 +0100 -Subject: [PATCH] M4 visible, rebase on b5d2b1224fed, fixes - -Change-Id: I7be2f54b197b3cf09813b8dee5cabbf6c99c4f95 -Signed-off-by: Antonio Borneo ---- - src/helper/log.h | 1 + - src/jtag/aice/aice_usb.c | 4 +- - src/jtag/core.c | 8 +- - src/jtag/drivers/ft232r.c | 2 +- - src/jtag/drivers/ftdi.c | 24 +- - src/jtag/drivers/kitprog.c | 2 +- - src/jtag/drivers/libusb_helper.c | 39 +- - src/jtag/drivers/libusb_helper.h | 8 +- - src/jtag/drivers/opendous.c | 2 +- - src/jtag/drivers/openjtag.c | 2 +- - src/jtag/drivers/osbdm.c | 2 +- - src/jtag/drivers/stlink_usb.c | 523 +++++++++++++++++- - .../usb_blaster/ublast2_access_libusb.c | 8 +- - src/target/arm_adi_v5.c | 28 + - src/target/arm_adi_v5.h | 22 + - src/target/armv8.c | 10 +- - src/target/armv8_dpm.c | 7 + - src/target/cortex_a.c | 4 +- - tcl/board/stm32mp15x_dk2.cfg | 11 + - tcl/board/stm32mp15x_ev1.cfg | 11 + - tcl/board/stm32mp15x_ev1_jlink_jtag.cfg | 9 + - tcl/board/stm32mp15x_ev1_jlink_swd.cfg | 9 + - tcl/board/stm32mp15x_ev1_stlink_jtag.cfg | 9 + - tcl/board/stm32mp15x_ev1_stlink_swd.cfg | 9 + - tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg | 9 + - tcl/board/stm32mp15x_ev1_ulink2_swd.cfg | 9 + - tcl/target/stm32mp15x.cfg | 121 ++++ - 27 files changed, 833 insertions(+), 60 deletions(-) - -diff --git a/src/helper/log.h b/src/helper/log.h -index eac535deb..b81018d84 100644 ---- a/src/helper/log.h -+++ b/src/helper/log.h -@@ -154,6 +154,7 @@ extern int debug_level; - #define ERROR_WAIT (-5) - /* ERROR_TIMEOUT is already taken by winerror.h. */ - #define ERROR_TIMEOUT_REACHED (-6) -+#define ERROR_OP_NOT_SUPPORTED (-7) - - - #endif /* OPENOCD_HELPER_LOG_H */ -diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c -index a5cccfef4..442754209 100644 ---- a/src/jtag/aice/aice_usb.c -+++ b/src/jtag/aice/aice_usb.c -@@ -2111,7 +2111,7 @@ static int aice_usb_open(struct aice_port_param_s *param) - const uint16_t pids[] = { param->pid, 0 }; - struct libusb_device_handle *devh; - -- if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK) -+ if (jtag_libusb_open(vids, pids, NULL, &devh, NULL) != ERROR_OK) - return ERROR_FAIL; - - /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS -@@ -2135,7 +2135,7 @@ static int aice_usb_open(struct aice_port_param_s *param) - /* reopen jlink after usb_reset - * on win32 this may take a second or two to re-enumerate */ - int retval; -- while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) { -+ while ((retval = jtag_libusb_open(vids, pids, NULL, &devh, NULL)) != ERROR_OK) { - usleep(1000); - timeout--; - if (!timeout) -diff --git a/src/jtag/core.c b/src/jtag/core.c -index c5011e522..2d0c84205 100644 ---- a/src/jtag/core.c -+++ b/src/jtag/core.c -@@ -2020,8 +2020,14 @@ int adapter_resets(int trst, int srst) - - /* adapters without trst signal will eventually use tlr sequence */ - jtag_add_reset(trst, srst); -+ /* -+ * The jtag queue is still used for reset by some adapter. Flush it! -+ * FIXME: To be removed when all adapter drivers will be updated! -+ */ -+ jtag_execute_queue(); - return ERROR_OK; -- } else if (transport_is_swd() || transport_is_hla()) { -+ } else if (transport_is_swd() || transport_is_hla() || -+ transport_is_dapdirect_swd() || transport_is_dapdirect_jtag()) { - if (trst == TRST_ASSERT) { - LOG_ERROR("transport %s has no trst signal", - get_current_transport()->name); -diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c -index 4812362a3..c9ed304a8 100644 ---- a/src/jtag/drivers/ft232r.c -+++ b/src/jtag/drivers/ft232r.c -@@ -257,7 +257,7 @@ static int ft232r_init(void) - { - uint16_t avids[] = {ft232r_vid, 0}; - uint16_t apids[] = {ft232r_pid, 0}; -- if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter)) { -+ if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter, NULL)) { - LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n", - ft232r_vid, ft232r_pid, (ft232r_serial_desc == NULL) ? "[any]" : ft232r_serial_desc); - return ERROR_JTAG_INIT_FAILED; -diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c -index 121cb469f..3a685b8fc 100644 ---- a/src/jtag/drivers/ftdi.c -+++ b/src/jtag/drivers/ftdi.c -@@ -524,17 +524,19 @@ static int ftdi_reset(int trst, int srst) - - LOG_DEBUG_IO("reset trst: %i srst %i", trst, srst); - -- if (trst == 1) { -- if (sig_ntrst) -- ftdi_set_signal(sig_ntrst, '0'); -- else -- LOG_ERROR("Can't assert TRST: nTRST signal is not defined"); -- } else if (sig_ntrst && jtag_get_reset_config() & RESET_HAS_TRST && -- trst == 0) { -- if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN) -- ftdi_set_signal(sig_ntrst, 'z'); -- else -- ftdi_set_signal(sig_ntrst, '1'); -+ if (!swd_mode) { -+ if (trst == 1) { -+ if (sig_ntrst) -+ ftdi_set_signal(sig_ntrst, '0'); -+ else -+ LOG_ERROR("Can't assert TRST: nTRST signal is not defined"); -+ } else if (sig_ntrst && jtag_get_reset_config() & RESET_HAS_TRST && -+ trst == 0) { -+ if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN) -+ ftdi_set_signal(sig_ntrst, 'z'); -+ else -+ ftdi_set_signal(sig_ntrst, '1'); -+ } - } - - if (srst == 1) { -diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c -index 0c1e74c42..28ed7ac61 100644 ---- a/src/jtag/drivers/kitprog.c -+++ b/src/jtag/drivers/kitprog.c -@@ -280,7 +280,7 @@ static int kitprog_usb_open(void) - const uint16_t pids[] = { PID, 0 }; - - if (jtag_libusb_open(vids, pids, kitprog_serial, -- &kitprog_handle->usb_handle) != ERROR_OK) { -+ &kitprog_handle->usb_handle, NULL) != ERROR_OK) { - LOG_ERROR("Failed to open or find the device"); - return ERROR_FAIL; - } -diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c -index 5a8129cb9..fbbfb4114 100644 ---- a/src/jtag/drivers/libusb_helper.c -+++ b/src/jtag/drivers/libusb_helper.c -@@ -58,7 +58,7 @@ static int jtag_libusb_error(int err) - } - } - --static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc, -+static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc, - const uint16_t vids[], const uint16_t pids[]) - { - for (unsigned i = 0; vids[i]; i++) { -@@ -123,9 +123,40 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in - return matched; - } - -+static bool jtag_libusb_match_serial(libusb_device_handle *device, -+ struct libusb_device_descriptor *dev_desc, const char *serial, -+ adapter_get_alternate_serial_fn adapter_get_alternate_serial) -+{ -+ if (string_descriptor_equal(device, dev_desc->iSerialNumber, serial)) -+ return true; -+ -+ /* check the alternate serial helper */ -+ if (!adapter_get_alternate_serial) -+ return false; -+ -+ /* get the alternate serial */ -+ char *alternate_serial = adapter_get_alternate_serial(device, dev_desc); -+ -+ /* check possible failures */ -+ if (alternate_serial == NULL) -+ return false; -+ -+ /* then compare and free the alternate serial */ -+ bool match = false; -+ if (strcmp(serial, alternate_serial) == 0) -+ match = true; -+ else -+ LOG_DEBUG("Device alternate serial number '%s' doesn't match requested serial '%s'", -+ alternate_serial, serial); -+ -+ free(alternate_serial); -+ return match; -+} -+ - int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - const char *serial, -- struct libusb_device_handle **out) -+ struct libusb_device_handle **out, -+ adapter_get_alternate_serial_fn adapter_get_alternate_serial) - { - int cnt, idx, errCode; - int retval = ERROR_FAIL; -@@ -143,7 +174,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0) - continue; - -- if (!jtag_libusb_match(&dev_desc, vids, pids)) -+ if (!jtag_libusb_match_ids(&dev_desc, vids, pids)) - continue; - - if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx])) -@@ -159,7 +190,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - - /* Device must be open to use libusb_get_string_descriptor_ascii. */ - if (serial != NULL && -- !string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) { -+ !jtag_libusb_match_serial(libusb_handle, &dev_desc, serial, adapter_get_alternate_serial)) { - serial_mismatch = true; - libusb_close(libusb_handle); - continue; -diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h -index 46e4954e7..74bb23c52 100644 ---- a/src/jtag/drivers/libusb_helper.h -+++ b/src/jtag/drivers/libusb_helper.h -@@ -22,9 +22,15 @@ - - #include - -+/* this callback should return a non NULL value only when the serial could not -+ * be retrieved by the standard 'libusb_get_string_descriptor_ascii' */ -+typedef char * (*adapter_get_alternate_serial_fn)(libusb_device_handle *device, -+ struct libusb_device_descriptor *dev_desc); -+ - int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - const char *serial, -- struct libusb_device_handle **out); -+ struct libusb_device_handle **out, -+ adapter_get_alternate_serial_fn adapter_get_alternate_serial); - void jtag_libusb_close(struct libusb_device_handle *dev); - int jtag_libusb_control_transfer(struct libusb_device_handle *dev, - uint8_t requestType, uint8_t request, uint16_t wValue, -diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c -index 7298a2a10..6812ef649 100644 ---- a/src/jtag/drivers/opendous.c -+++ b/src/jtag/drivers/opendous.c -@@ -715,7 +715,7 @@ struct opendous_jtag *opendous_usb_open(void) - struct opendous_jtag *result; - - struct libusb_device_handle *devh; -- if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK) -+ if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh, NULL) != ERROR_OK) - return NULL; - - jtag_libusb_set_configuration(devh, 0); -diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c -index 6131df914..7eab5c130 100644 ---- a/src/jtag/drivers/openjtag.c -+++ b/src/jtag/drivers/openjtag.c -@@ -449,7 +449,7 @@ static int openjtag_init_cy7c65215(void) - int ret; - - usbh = NULL; -- ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh); -+ ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh, NULL); - if (ret != ERROR_OK) { - LOG_ERROR("unable to open cy7c65215 device"); - goto err; -diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c -index aea126d0d..dc236660e 100644 ---- a/src/jtag/drivers/osbdm.c -+++ b/src/jtag/drivers/osbdm.c -@@ -374,7 +374,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue *queue) - static int osbdm_open(struct osbdm *osbdm) - { - (void)memset(osbdm, 0, sizeof(*osbdm)); -- if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK) -+ if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh, NULL) != ERROR_OK) - return ERROR_FAIL; - - if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK) -diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c -index ca7a4df4e..6c0601d0e 100644 ---- a/src/jtag/drivers/stlink_usb.c -+++ b/src/jtag/drivers/stlink_usb.c -@@ -47,6 +47,8 @@ - #define USE_LIBUSB_ASYNCIO - #endif - -+#define STLINK_SERIAL_LEN 24 -+ - #define ENDPOINT_IN 0x80 - #define ENDPOINT_OUT 0x00 - -@@ -83,11 +85,22 @@ - #define STLINK_MAX_RW8 (64) - #define STLINKV3_MAX_RW8 (512) - -+/* -+ * FIXME: this definition + comment should be moved in a generic header file -+ * ARM IHI 0031E: TAR Automatic address increment is only guaranteed to -+ * operate on the 10 least significant bits of the address -+ */ -+#define TAR_AUTOINCR_BLOCK (1 << 10) -+ - /* "WAIT" responses will be retried (with exponential backoff) at - * most this many times before failing to caller. - */ - #define MAX_WAIT_RETRIES 8 - -+/* HLA is currently limited at AP#0 and no control on CSW */ -+#define STLINK_HLA_AP_NUM 0 -+#define STLINK_HLA_CSW 0 -+ - enum stlink_jtag_api_version { - STLINK_JTAG_API_V1 = 1, - STLINK_JTAG_API_V2, -@@ -275,6 +288,10 @@ struct stlink_usb_handle_s { - #define STLINK_DEBUG_APIV2_INIT_AP 0x4B - #define STLINK_DEBUG_APIV2_CLOSE_AP_DBG 0x4C - -+#define STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC 0x50 -+ -+#define STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC 0x54 -+ - #define STLINK_APIV3_SET_COM_FREQ 0x61 - #define STLINK_APIV3_GET_COM_FREQ 0x62 - -@@ -321,6 +338,9 @@ enum stlink_mode { - - /* aliases */ - #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE -+#define STLINK_F_HAS_MEM_WR_NO_INC STLINK_F_HAS_MEM_16BIT -+#define STLINK_F_HAS_MEM_RD_NO_INC STLINK_F_HAS_DPBANKSEL -+#define STLINK_F_HAS_CSW STLINK_F_HAS_DPBANKSEL - - struct speed_map { - int speed; -@@ -345,7 +365,6 @@ static const struct speed_map stlink_khz_to_speed_map_swd[] = { - - /* JTAG clock speed */ - static const struct speed_map stlink_khz_to_speed_map_jtag[] = { -- {18000, 2}, - {9000, 4}, - {4500, 8}, - {2250, 16}, -@@ -1023,6 +1042,7 @@ static int stlink_usb_version(void *handle) - flags |= STLINK_F_QUIRK_JTAG_DP_READ; - - /* API to read/write memory at 16 bit from J26 */ -+ /* API to write memory without address increment from J26 */ - if (h->version.jtag >= 26) - flags |= STLINK_F_HAS_MEM_16BIT; - -@@ -1031,6 +1051,8 @@ static int stlink_usb_version(void *handle) - flags |= STLINK_F_HAS_AP_INIT; - - /* Banked regs (DPv1 & DPv2) support from V2J32 */ -+ /* API to read memory without address increment from V2J32 */ -+ /* Memory R/W supports CSW from V2J32 */ - if (h->version.jtag >= 32) - flags |= STLINK_F_HAS_DPBANKSEL; - -@@ -1052,12 +1074,15 @@ static int stlink_usb_version(void *handle) - flags |= STLINK_F_HAS_DAP_REG; - - /* API to read/write memory at 16 bit */ -+ /* API to write memory without address increment */ - flags |= STLINK_F_HAS_MEM_16BIT; - - /* API required to init AP before any AP access */ - flags |= STLINK_F_HAS_AP_INIT; - - /* Banked regs (DPv1 & DPv2) support from V3J2 */ -+ /* API to read memory without address increment from V3J2 */ -+ /* Memory R/W supports CSW from V3J2 */ - if (h->version.jtag >= 2) - flags |= STLINK_F_HAS_DPBANKSEL; - -@@ -2086,8 +2111,8 @@ static int stlink_usb_get_rw_status(void *handle) - } - - /** */ --static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, -- uint8_t *buffer) -+static int stlink_usb_read_mem8(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, uint8_t *buffer) - { - int res; - uint16_t read_len = len; -@@ -2109,6 +2134,9 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, - h->cmdidx += 4; - h_u16_to_le(h->cmdbuf+h->cmdidx, len); - h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; - - /* we need to fix read length for single bytes */ - if (read_len == 1) -@@ -2125,8 +2153,8 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, - } - - /** */ --static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, -- const uint8_t *buffer) -+static int stlink_usb_write_mem8(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, const uint8_t *buffer) - { - int res; - struct stlink_usb_handle_s *h = handle; -@@ -2147,6 +2175,9 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, - h->cmdidx += 4; - h_u16_to_le(h->cmdbuf+h->cmdidx, len); - h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; - - res = stlink_usb_xfer_noerrcheck(handle, buffer, len); - -@@ -2157,8 +2188,8 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, - } - - /** */ --static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, -- uint8_t *buffer) -+static int stlink_usb_read_mem16(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, uint8_t *buffer) - { - int res; - struct stlink_usb_handle_s *h = handle; -@@ -2182,6 +2213,9 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, - h->cmdidx += 4; - h_u16_to_le(h->cmdbuf+h->cmdidx, len); - h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; - - res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); - -@@ -2194,8 +2228,8 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, - } - - /** */ --static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, -- const uint8_t *buffer) -+static int stlink_usb_write_mem16(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, const uint8_t *buffer) - { - int res; - struct stlink_usb_handle_s *h = handle; -@@ -2219,6 +2253,9 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, - h->cmdidx += 4; - h_u16_to_le(h->cmdbuf+h->cmdidx, len); - h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; - - res = stlink_usb_xfer_noerrcheck(handle, buffer, len); - -@@ -2229,8 +2266,8 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, - } - - /** */ --static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, -- uint8_t *buffer) -+static int stlink_usb_read_mem32(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, uint8_t *buffer) - { - int res; - struct stlink_usb_handle_s *h = handle; -@@ -2251,6 +2288,9 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, - h->cmdidx += 4; - h_u16_to_le(h->cmdbuf+h->cmdidx, len); - h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; - - res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); - -@@ -2263,8 +2303,8 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, - } - - /** */ --static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, -- const uint8_t *buffer) -+static int stlink_usb_write_mem32(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, const uint8_t *buffer) - { - int res; - struct stlink_usb_handle_s *h = handle; -@@ -2285,6 +2325,9 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, - h->cmdidx += 4; - h_u16_to_le(h->cmdbuf+h->cmdidx, len); - h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; - - res = stlink_usb_xfer_noerrcheck(handle, buffer, len); - -@@ -2294,6 +2337,80 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, - return stlink_usb_get_rw_status(handle); - } - -+static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, uint8_t *buffer) -+{ -+ int res; -+ struct stlink_usb_handle_s *h = handle; -+ -+ assert(handle != NULL); -+ -+ if (!(h->version.flags & STLINK_F_HAS_MEM_RD_NO_INC)) -+ return ERROR_COMMAND_NOTFOUND; -+ -+ /* data must be a multiple of 4 and word aligned */ -+ if (len % 4 || addr % 4) { -+ LOG_DEBUG("Invalid data alignment"); -+ return ERROR_TARGET_UNALIGNED_ACCESS; -+ } -+ -+ stlink_usb_init_buffer(handle, h->rx_ep, len); -+ -+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; -+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC; -+ h_u32_to_le(h->cmdbuf+h->cmdidx, addr); -+ h->cmdidx += 4; -+ h_u16_to_le(h->cmdbuf+h->cmdidx, len); -+ h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; -+ -+ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); -+ if (res != ERROR_OK) -+ return res; -+ -+ memcpy(buffer, h->databuf, len); -+ -+ return stlink_usb_get_rw_status(handle); -+} -+ -+static int stlink_usb_write_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint16_t len, const uint8_t *buffer) -+{ -+ int res; -+ struct stlink_usb_handle_s *h = handle; -+ -+ assert(handle != NULL); -+ -+ if (!(h->version.flags & STLINK_F_HAS_MEM_WR_NO_INC)) -+ return ERROR_COMMAND_NOTFOUND; -+ -+ /* data must be a multiple of 4 and word aligned */ -+ if (len % 4 || addr % 4) { -+ LOG_DEBUG("Invalid data alignment"); -+ return ERROR_TARGET_UNALIGNED_ACCESS; -+ } -+ -+ stlink_usb_init_buffer(handle, h->tx_ep, len); -+ -+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; -+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC; -+ h_u32_to_le(h->cmdbuf+h->cmdidx, addr); -+ h->cmdidx += 4; -+ h_u16_to_le(h->cmdbuf+h->cmdidx, len); -+ h->cmdidx += 2; -+ h->cmdbuf[h->cmdidx++] = ap_num; -+ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); -+ h->cmdidx += 3; -+ -+ res = stlink_usb_xfer_noerrcheck(handle, buffer, len); -+ if (res != ERROR_OK) -+ return res; -+ -+ return stlink_usb_get_rw_status(handle); -+} -+ - static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t address) - { - uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address)); -@@ -2302,8 +2419,8 @@ static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t addr - return max_tar_block; - } - --static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size, -- uint32_t count, uint8_t *buffer) -+static int stlink_usb_read_ap_mem(void *handle, uint8_t ap_num, uint32_t csw, -+ uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) - { - int retval = ERROR_OK; - uint32_t bytes_remaining; -@@ -2350,7 +2467,7 @@ static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size, - if (addr & (size - 1)) { - - uint32_t head_bytes = size - (addr & (size - 1)); -- retval = stlink_usb_read_mem8(handle, addr, head_bytes, buffer); -+ retval = stlink_usb_read_mem8(handle, ap_num, csw, addr, head_bytes, buffer); - if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { - usleep((1<> 57FF72 ... -+ * this format could be read correctly by 'libusb_get_string_descriptor_ascii' -+ * so this case is managed by libusb_helper::string_descriptor_equal -+ * - the buggy DFU is not doing any unicode conversion and returns a raw serial data in the descriptor -+ * 0x1a, 0x03, 0x57, 0x00, 0xFF, 0x00, 0x72, 0x00 ... -+ * >> 57 FF 72 ... -+ * based on the length (0x1a = 26) we could easily decide if we have to fixup the serial -+ * and then we have just to convert the raw data into printable characters using sprintf -+ */ -+char *stlink_usb_get_alternate_serial(libusb_device_handle *device, -+ struct libusb_device_descriptor *dev_desc) -+{ -+ int usb_retval; -+ unsigned char desc_serial[(STLINK_SERIAL_LEN + 1) * 2]; -+ -+ if (dev_desc->iSerialNumber == 0) -+ return NULL; -+ -+ /* get the LANGID from String Descriptor Zero */ -+ usb_retval = libusb_get_string_descriptor(device, 0, 0, desc_serial, -+ sizeof(desc_serial)); -+ -+ if (usb_retval < LIBUSB_SUCCESS) { -+ LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)", -+ libusb_error_name(usb_retval), usb_retval); -+ return NULL; -+ } else if (usb_retval < 4) { -+ /* the size should be least 4 bytes to contain a minimum of 1 supported LANGID */ -+ LOG_ERROR("could not get the LANGID"); -+ return NULL; -+ } -+ -+ uint32_t langid = desc_serial[2] | (desc_serial[3] << 8); -+ -+ /* get the serial */ -+ usb_retval = libusb_get_string_descriptor(device, dev_desc->iSerialNumber, -+ langid, desc_serial, sizeof(desc_serial)); -+ -+ unsigned char len = desc_serial[0]; -+ -+ if (usb_retval < LIBUSB_SUCCESS) { -+ LOG_ERROR("libusb_get_string_descriptor() failed: %s(%d)", -+ libusb_error_name(usb_retval), usb_retval); -+ return NULL; -+ } else if (desc_serial[1] != LIBUSB_DT_STRING || len > usb_retval) { -+ LOG_ERROR("invalid string in ST-LINK USB serial descriptor"); -+ return NULL; -+ } -+ -+ if (len == ((STLINK_SERIAL_LEN + 1) * 2)) { -+ /* good ST-Link adapter, this case is managed by -+ * libusb::libusb_get_string_descriptor_ascii */ -+ return NULL; -+ } else if (len != ((STLINK_SERIAL_LEN / 2 + 1) * 2)) { -+ LOG_ERROR("unexpected serial length (%d) in descriptor", len); -+ return NULL; -+ } -+ -+ /* else (len == 26) => buggy ST-Link */ -+ -+ char *alternate_serial = malloc((STLINK_SERIAL_LEN + 1) * sizeof(char)); -+ if (alternate_serial == NULL) -+ return NULL; -+ -+ for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2) -+ sprintf(alternate_serial + i, "%02X", desc_serial[i + 2]); -+ -+ alternate_serial[STLINK_SERIAL_LEN] = '\0'; -+ -+ return alternate_serial; -+} -+ - /** */ - static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) - { -@@ -2778,7 +2988,8 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) - in order to become operational. - */ - do { -- if (jtag_libusb_open(param->vid, param->pid, param->serial, &h->fd) != ERROR_OK) { -+ if (jtag_libusb_open(param->vid, param->pid, param->serial, -+ &h->fd, stlink_usb_get_alternate_serial) != ERROR_OK) { - LOG_ERROR("open failed"); - goto error_open; - } -@@ -2910,7 +3121,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) - h->max_mem_packet = (1 << 10); - - uint8_t buffer[4]; -- err = stlink_usb_read_mem32(h, CPUID, 4, buffer); -+ err = stlink_usb_read_mem32(h, STLINK_HLA_AP_NUM, STLINK_HLA_CSW, CPUID, 4, buffer); - if (err == ERROR_OK) { - uint32_t cpuid = le_to_h_u32(buffer); - int i = (cpuid >> 4) & 0xf; -@@ -3452,6 +3663,249 @@ static int stlink_dap_op_run(struct adiv5_dap *dap) - return saved_retval; - } - -+/* -+ * Explanation on CSW hack used for firmware V2J24~V2J31 and V3J1 -+ * -+ * The API of these firmware versions don't provide a way to specify directly -+ * the value of CSW used for mem_ap accesses. The CSW value used by the -+ * firmware is not under user control. The lack of specific API would force -+ * the use of inefficient memory access through low-level AP register API. -+ * -+ * The CSW value internally computed by the firmware is cached by the firmware -+ * itself to minimize the writes to register MEM_AP_REG_CSW, writing it only -+ * to updated a new CSW value. The update is only triggered by a change in the -+ * CSW fields "size" and "addrinc" (note: with these firmware versions we only -+ * use "addrinc = true"). -+ * -+ * With the command STLINK_DEBUG_APIV2_WRITE_DAP_REG we can write the register -+ * MEM_AP_REG_CSW; the firmware does not intercept this write and its internal -+ * cached CSW value get out-of-sync wrt the value in register MEM_AP_REG_CSW. -+ * The hack rely on this mismatch between firmware cache and MEM_AP_REG_CSW. -+ * Given the "size" of data we plan to use for memory access, we execute: -+ * 1) a dummy memory read of "size" to let the firmware compute a CSW value -+ * coherent with "size". This will update the internal CSW cache and -+ * (eventually) the register MEM_AP_REG_CSW; -+ * 2) a write of the desired "user" CSW value in MEM_AP_REG_CSW, including the -+ * field "addrinc" ("size" has not to be changed wrt point 1); -+ * 3) a set of memory read/write commands of the same "size". -+ * While executing 3), the firmware will not modify the content of register -+ * MEM_AP_REG_CSW because accordingly to its cached value there is no need to -+ * update it! -+ * The memory accesses in 3) would then be executed with the desired CSW value -+ * programmed in 2). -+ * -+ * To simplify the code and only use one "size", the case of unaligned access -+ * is converted to a 8 bit access. -+ * -+ * Because of the available API, in step 3) we will use the normal access (with -+ * address auto-increment) also for addrinc==false, and this triggers another -+ * problem. The auto-increment of register MEM_AP_REG_TAR is guaranteed only -+ * on the 10 least significant bits. The firmware will update MEM_AP_REG_TAR -+ * every time the 10 bit increment is crossed, to avoid any potential -+ * wrap-around. This disrupts the address in MEM_AP_REG_TAR, that should -+ * instead be constant during the whole memory access. To prevent this, we -+ * split the memory access in chunks whose length cannot cause the 10 bits -+ * wrap-around so the firmware will not touch MEM_AP_REG_TAR. -+ * -+ * For write case only, the firmware operates per USB blocks, so it re-programs -+ * MEM_AP_REG_TAR every 64 bytes (on stlink/v1) or 512 bytes (on stlik/v3) and -+ * this limits the maximum size of each write chunk when addrinc==false. -+ */ -+static int stlink_dap_hack_csw(struct adiv5_ap *ap, uint32_t size, bool addrinc) -+{ -+ uint32_t csw; -+ uint8_t dummy[4]; -+ -+ switch (size) { -+ case 1: -+ csw = CSW_8BIT; -+ break; -+ case 2: -+ csw = CSW_16BIT; -+ break; -+ case 4: -+ /* -+ * ST-Link sets autoinc only in 32 bits mode -+ * -+ * ARM IHI 0031D: Note: -+ * It is IMPLEMENTATION DEFINED whether a MEM-AP supports transfer sizes other than Word. If a -+ * MEM-AP only supports word transfers and Increment single is selected, the TAR always -+ * increments by four after a successful DRW transaction. -+ */ -+ csw = addrinc ? (CSW_32BIT | CSW_ADDRINC_SINGLE) : CSW_32BIT; -+ break; -+ default: -+ return ERROR_FAIL; -+ } -+ csw |= ap->csw_default; -+ -+ /* This mem read will change CSW. Ignore errors */ -+ stlink_usb_read_ap_mem(stlink_dap_handle, ap->ap_num, STLINK_HLA_CSW, 0x00000000, size, 1, dummy); -+ -+ return dap_queue_ap_write(ap, MEM_AP_REG_CSW, csw); -+} -+ -+static int stlink_dap_hack_csw_mem_read(struct adiv5_ap *ap, uint8_t *buffer, -+ uint32_t size, uint32_t count, uint32_t address, bool addrinc) -+{ -+ int retval; -+ uint32_t bytes_remaining, max_count; -+ -+ /* unaligned access could be split in mix 32/16/8 bits. Force 8-bis only */ -+ if ((size == 4 && address & 3) || -+ (size == 2 && address & 1) || -+ (size == 2 && !(stlink_dap_handle->version.flags & STLINK_F_HAS_MEM_16BIT))) { -+ count *= size; -+ size = 1; -+ } -+ -+ retval = stlink_dap_hack_csw(ap, size, addrinc); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ if (addrinc) -+ return stlink_usb_read_ap_mem(stlink_dap_handle, ap->ap_num, -+ STLINK_HLA_CSW, address, size, count, buffer); -+ -+ count *= size; -+ max_count = TAR_AUTOINCR_BLOCK - (address & (TAR_AUTOINCR_BLOCK - 1)); -+ while (count) { -+ bytes_remaining = (count < max_count) ? count : max_count; -+ -+ retval = stlink_usb_read_mem32(stlink_dap_handle, ap->ap_num, -+ STLINK_HLA_CSW, address, bytes_remaining, buffer); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ buffer += bytes_remaining; -+ count -= bytes_remaining; -+ } -+ return ERROR_OK; -+} -+ -+static int stlink_dap_op_ap_mem_read(struct adiv5_ap *ap, uint8_t *buffer, -+ uint32_t size, uint32_t count, uint32_t address, bool addrinc) -+{ -+ int retval; -+ uint32_t bytes_remaining; -+ -+ if (!addrinc && size != 4) -+ return ERROR_OP_NOT_SUPPORTED; -+ -+ retval = stlink_dap_op_run(ap->dap); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ retval = stlink_dap_open_ap(ap->ap_num); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ dap_invalidate_cache(ap->dap); -+ -+ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_CSW)) -+ return stlink_dap_hack_csw_mem_read(ap, buffer, size, count, address, addrinc); -+ -+ if (addrinc) -+ return stlink_usb_read_ap_mem(stlink_dap_handle, ap->ap_num, -+ ap->csw_default, address, size, count, buffer); -+ -+ count *= size; -+ while (count) { -+ bytes_remaining = (count < STLINK_DATA_SIZE) ? count : STLINK_DATA_SIZE; -+ -+ retval = stlink_usb_read_mem32_noaddrinc(stlink_dap_handle, ap->ap_num, -+ ap->csw_default, address, bytes_remaining, buffer); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ buffer += bytes_remaining; -+ count -= bytes_remaining; -+ } -+ return ERROR_OK; -+} -+ -+static int stlink_dap_hack_csw_mem_write(struct adiv5_ap *ap, const uint8_t *buffer, -+ uint32_t size, uint32_t count, uint32_t address, bool addrinc) -+{ -+ int retval; -+ uint32_t bytes_remaining, max_count; -+ -+ /* unaligned access could be split in mix 32/16/8 bits. Force 8-bis only */ -+ if ((size == 4 && address & 3) || -+ (size == 2 && address & 1) || -+ (size == 2 && !(stlink_dap_handle->version.flags & STLINK_F_HAS_MEM_16BIT))) { -+ count *= size; -+ size = 1; -+ } -+ -+ retval = stlink_dap_hack_csw(ap, size, addrinc); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ if (addrinc) -+ return stlink_usb_write_ap_mem(stlink_dap_handle, ap->ap_num, -+ STLINK_HLA_CSW, address, size, count, buffer); -+ -+ count *= size; -+ max_count = TAR_AUTOINCR_BLOCK - (address & (TAR_AUTOINCR_BLOCK - 1)); -+ if (max_count > stlink_usb_block(&stlink_dap_handle)) -+ max_count = stlink_usb_block(&stlink_dap_handle); -+ -+ while (count) { -+ bytes_remaining = (count < max_count) ? count : max_count; -+ -+ retval = stlink_usb_write_mem32(stlink_dap_handle, ap->ap_num, -+ STLINK_HLA_CSW, address, bytes_remaining, buffer); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ buffer += bytes_remaining; -+ count -= bytes_remaining; -+ } -+ return ERROR_OK; -+} -+ -+static int stlink_dap_op_ap_mem_write(struct adiv5_ap *ap, const uint8_t *buffer, -+ uint32_t size, uint32_t count, uint32_t address, bool addrinc) -+{ -+ int retval; -+ uint32_t bytes_remaining; -+ -+ if (!addrinc && size != 4) -+ return ERROR_OP_NOT_SUPPORTED; -+ -+ retval = stlink_dap_op_run(ap->dap); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ retval = stlink_dap_open_ap(ap->ap_num); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ dap_invalidate_cache(ap->dap); -+ -+ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_CSW)) -+ return stlink_dap_hack_csw_mem_write(ap, buffer, size, count, address, addrinc); -+ -+ if (addrinc) -+ return stlink_usb_write_ap_mem(stlink_dap_handle, ap->ap_num, -+ ap->csw_default, address, size, count, buffer); -+ -+ count *= size; -+ while (count) { -+ bytes_remaining = (count < STLINK_DATA_SIZE) ? count : STLINK_DATA_SIZE; -+ -+ retval = stlink_usb_write_mem32_noaddrinc(stlink_dap_handle, ap->ap_num, -+ ap->csw_default, address, bytes_remaining, buffer); -+ if (retval != ERROR_OK) -+ return retval; -+ -+ buffer += bytes_remaining; -+ count -= bytes_remaining; -+ } -+ return ERROR_OK; -+} -+ - /** */ - static void stlink_dap_op_quit(struct adiv5_dap *dap) - { -@@ -3623,7 +4077,12 @@ static int stlink_dap_speed(int speed) - /** */ - static int stlink_dap_khz(int khz, int *jtag_speed) - { -- *jtag_speed = khz; -+ if (khz == 0) { -+ LOG_ERROR("RCLK not supported"); -+ return ERROR_FAIL; -+ } -+ -+ *jtag_speed = stlink_speed(stlink_dap_handle, khz, true); - return ERROR_OK; - } - -@@ -3645,6 +4104,10 @@ static const struct dap_ops stlink_dap_ops = { - .run = stlink_dap_op_run, - .sync = NULL, /* optional */ - .quit = stlink_dap_op_quit, /* optional */ -+ .ap_ops = { -+ .ap_mem_read = stlink_dap_op_ap_mem_read, -+ .ap_mem_write = stlink_dap_op_ap_mem_write, -+ }, - }; - - static const char *const stlink_dap_transport[] = { "dapdirect_jtag", "dapdirect_swd", NULL }; -diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c -index 4f7ee6300..b406c0321 100644 ---- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c -+++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c -@@ -195,7 +195,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low) - bool renumeration = false; - int ret; - -- if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) { -+ if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) { - LOG_INFO("Altera USB-Blaster II (uninitialized) found"); - LOG_INFO("Loading firmware..."); - ret = load_usb_blaster_firmware(temp, low); -@@ -209,13 +209,15 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low) - const uint16_t pids_renum[] = { low->ublast_pid, 0 }; - - if (renumeration == false) { -- if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) { -+ if (jtag_libusb_open(vids_renum, pids_renum, NULL, -+ &low->libusb_dev, NULL) != ERROR_OK) { - LOG_ERROR("Altera USB-Blaster II not found"); - return ERROR_FAIL; - } - } else { - int retry = 10; -- while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) { -+ while (jtag_libusb_open(vids_renum, pids_renum, NULL, -+ &low->libusb_dev, NULL) != ERROR_OK && retry--) { - usleep(1000000); - LOG_INFO("Waiting for renumerate..."); - } -diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c -index 2d47da3ea..ee0d1f329 100644 ---- a/src/target/arm_adi_v5.c -+++ b/src/target/arm_adi_v5.c -@@ -596,24 +596,52 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint - int mem_ap_read_buf(struct adiv5_ap *ap, - uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) - { -+ int retval; -+ -+ if (ap->dap->ops->ap_ops.ap_mem_read) { -+ retval = ap->dap->ops->ap_ops.ap_mem_read(ap, buffer, size, count, address, true); -+ if (retval != ERROR_OP_NOT_SUPPORTED) -+ return retval; -+ } - return mem_ap_read(ap, buffer, size, count, address, true); - } - - int mem_ap_write_buf(struct adiv5_ap *ap, - const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) - { -+ int retval; -+ -+ if (ap->dap->ops->ap_ops.ap_mem_write) { -+ retval = ap->dap->ops->ap_ops.ap_mem_write(ap, buffer, size, count, address, true); -+ if (retval != ERROR_OP_NOT_SUPPORTED) -+ return retval; -+ } - return mem_ap_write(ap, buffer, size, count, address, true); - } - - int mem_ap_read_buf_noincr(struct adiv5_ap *ap, - uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) - { -+ int retval; -+ -+ if (ap->dap->ops->ap_ops.ap_mem_read) { -+ retval = ap->dap->ops->ap_ops.ap_mem_read(ap, buffer, size, count, address, false); -+ if (retval != ERROR_OP_NOT_SUPPORTED) -+ return retval; -+ } - return mem_ap_read(ap, buffer, size, count, address, false); - } - - int mem_ap_write_buf_noincr(struct adiv5_ap *ap, - const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) - { -+ int retval; -+ -+ if (ap->dap->ops->ap_ops.ap_mem_write) { -+ retval = ap->dap->ops->ap_ops.ap_mem_write(ap, buffer, size, count, address, false); -+ if (retval != ERROR_OP_NOT_SUPPORTED) -+ return retval; -+ } - return mem_ap_write(ap, buffer, size, count, address, false); - } - -diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h -index 17365bddb..984cebc0c 100644 ---- a/src/target/arm_adi_v5.h -+++ b/src/target/arm_adi_v5.h -@@ -296,6 +296,26 @@ struct adiv5_dap { - bool ignore_syspwrupack; - }; - -+/** -+ * Optional optimized implementation of AP access. -+ * Use of low-level primitives in struct dap_ops already allows implementing -+ * any type of AP access. Some adapter offer faster API at higher level for -+ * specific AP types or mode. -+ * Specific request not available or not implemented should return error -+ * ERROR_OP_NOT_SUPPORTED. -+ */ -+struct ap_ops { -+ /** Optional interface-specific optimized AP memory read */ -+ int (*ap_mem_read)(struct adiv5_ap *ap, uint8_t *buffer, -+ uint32_t size, uint32_t count, uint32_t address, -+ bool addrinc); -+ -+ /** Optional interface-specific optimized AP memory write */ -+ int (*ap_mem_write)(struct adiv5_ap *ap, const uint8_t *buffer, -+ uint32_t size, uint32_t count, uint32_t address, -+ bool addrinc); -+}; -+ - /** - * Transport-neutral representation of queued DAP transactions, supporting - * both JTAG and SWD transports. All submitted transactions are logically -@@ -336,6 +356,8 @@ struct dap_ops { - - /** Optional; called at OpenOCD exit */ - void (*quit)(struct adiv5_dap *dap); -+ -+ struct ap_ops ap_ops; - }; - - /* -diff --git a/src/target/armv8.c b/src/target/armv8.c -index 88b932073..089250704 100644 ---- a/src/target/armv8.c -+++ b/src/target/armv8.c -@@ -399,7 +399,10 @@ static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *re - &value); - break; - case ARMV8_ESR_EL3: /* FIXME: no equivalent in aarch32? */ -- retval = ERROR_FAIL; -+ /* avoid false errors in state polling which may lead to reexamine the -+ * target and re-execute examine-state and examine-end event handlers */ -+ LOG_WARNING("Unsupported read from ESR_EL3 in AArch32 state"); -+ retval = ERROR_OK; - break; - case ARMV8_SPSR_EL1: /* mapped to SPSR_svc */ - retval = dpm->instr_read_data_r0(dpm, -@@ -533,7 +536,10 @@ static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t va - value); - break; - case ARMV8_ESR_EL3: /* FIXME: no equivalent in aarch32? */ -- retval = ERROR_FAIL; -+ /* avoid false errors in state polling which may lead to reexamine the -+ * target and re-execute examine-state and examine-end event handlers */ -+ LOG_WARNING("Unsupported write to ESR_EL3 in AArch32 state"); -+ retval = ERROR_OK; - break; - case ARMV8_SPSR_EL1: /* mapped to SPSR_svc */ - retval = dpm->instr_write_data_r0(dpm, -diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c -index 081eed21b..5be52726c 100644 ---- a/src/target/armv8_dpm.c -+++ b/src/target/armv8_dpm.c -@@ -681,6 +681,10 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) - LOG_DEBUG("READ: %s, hvalue=%16.8llx", r->name, (unsigned long long) hvalue); - } - } -+ -+ if (retval != ERROR_OK) -+ LOG_ERROR("Failed to read %s register", r->name); -+ - return retval; - } - -@@ -720,6 +724,9 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) - } - } - -+ if (retval != ERROR_OK) -+ LOG_ERROR("Failed to write %s register", r->name); -+ - return retval; - } - -diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c -index 729a173eb..f71b15524 100644 ---- a/src/target/cortex_a.c -+++ b/src/target/cortex_a.c -@@ -1703,6 +1703,7 @@ static int cortex_a_assert_reset(struct target *target) - - static int cortex_a_deassert_reset(struct target *target) - { -+ struct armv7a_common *armv7a = target_to_armv7a(target); - int retval; - - LOG_DEBUG(" "); -@@ -1721,7 +1722,8 @@ static int cortex_a_deassert_reset(struct target *target) - LOG_WARNING("%s: ran after reset and before halt ...", - target_name(target)); - if (target_was_examined(target)) { -- retval = target_halt(target); -+ retval = mem_ap_write_atomic_u32(armv7a->debug_ap, -+ armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT); - if (retval != ERROR_OK) - return retval; - } else -diff --git a/tcl/board/stm32mp15x_dk2.cfg b/tcl/board/stm32mp15x_dk2.cfg -new file mode 100644 -index 000000000..0233c6d75 ---- /dev/null -+++ b/tcl/board/stm32mp15x_dk2.cfg -@@ -0,0 +1,11 @@ -+# board MB1272B -+# http://www.st.com/en/evaluation-tools/stm32mp157a-dk1.html -+# http://www.st.com/en/evaluation-tools/stm32mp157c-dk2.html -+ -+source [find interface/stlink-dap.cfg] -+ -+transport select dapdirect_swd -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config srst_only -diff --git a/tcl/board/stm32mp15x_ev1.cfg b/tcl/board/stm32mp15x_ev1.cfg -new file mode 100644 -index 000000000..a381e790b ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1.cfg -@@ -0,0 +1,11 @@ -+# board set MB1262C + MB1263B -+# https://www.st.com/en/evaluation-tools/stm32mp157a-ev1.html -+# https://www.st.com/en/evaluation-tools/stm32mp157c-ev1.html -+ -+source [find interface/stlink-dap.cfg] -+ -+transport select dapdirect_swd -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config srst_only -diff --git a/tcl/board/stm32mp15x_ev1_jlink_jtag.cfg b/tcl/board/stm32mp15x_ev1_jlink_jtag.cfg -new file mode 100644 -index 000000000..ce0c56cdb ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1_jlink_jtag.cfg -@@ -0,0 +1,9 @@ -+# This is a STM32MP15x board set MB1262C + MB1263B. -+ -+source [find interface/jlink.cfg] -+ -+transport select jtag -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config trst_and_srst separate -diff --git a/tcl/board/stm32mp15x_ev1_jlink_swd.cfg b/tcl/board/stm32mp15x_ev1_jlink_swd.cfg -new file mode 100644 -index 000000000..58286d3f8 ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1_jlink_swd.cfg -@@ -0,0 +1,9 @@ -+# This is a STM32MP15x board set MB1262C + MB1263B. -+ -+source [find interface/jlink.cfg] -+ -+transport select swd -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config srst_only -diff --git a/tcl/board/stm32mp15x_ev1_stlink_jtag.cfg b/tcl/board/stm32mp15x_ev1_stlink_jtag.cfg -new file mode 100644 -index 000000000..b0cba47c3 ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1_stlink_jtag.cfg -@@ -0,0 +1,9 @@ -+# This is a STM32MP15x board set MB1262C + MB1263B. -+ -+source [find interface/stlink-dap.cfg] -+ -+transport select dapdirect_jtag -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config srst_only -diff --git a/tcl/board/stm32mp15x_ev1_stlink_swd.cfg b/tcl/board/stm32mp15x_ev1_stlink_swd.cfg -new file mode 100644 -index 000000000..793b2c771 ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1_stlink_swd.cfg -@@ -0,0 +1,9 @@ -+# This is a STM32MP15x board set MB1262C + MB1263B. -+ -+source [find interface/stlink-dap.cfg] -+ -+transport select dapdirect_swd -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config srst_only -diff --git a/tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg b/tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg -new file mode 100644 -index 000000000..fcf62d4f3 ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg -@@ -0,0 +1,9 @@ -+# This is a STM32MP15x board set MB1262C + MB1263B. -+ -+source [find interface/cmsis-dap.cfg] -+ -+transport select jtag -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config trst_and_srst separate -diff --git a/tcl/board/stm32mp15x_ev1_ulink2_swd.cfg b/tcl/board/stm32mp15x_ev1_ulink2_swd.cfg -new file mode 100644 -index 000000000..2c0528bf1 ---- /dev/null -+++ b/tcl/board/stm32mp15x_ev1_ulink2_swd.cfg -@@ -0,0 +1,9 @@ -+# This is a STM32MP15x board set MB1262C + MB1263B. -+ -+source [find interface/cmsis-dap.cfg] -+ -+transport select swd -+ -+source [find target/stm32mp15x.cfg] -+ -+reset_config srst_only -diff --git a/tcl/target/stm32mp15x.cfg b/tcl/target/stm32mp15x.cfg -new file mode 100644 -index 000000000..7f0d19c4d ---- /dev/null -+++ b/tcl/target/stm32mp15x.cfg -@@ -0,0 +1,121 @@ -+# STMicroelectronics STM32MP15x (Single/Dual Cortex-A7 plus Cortex-M4) -+# http://www.st.com/stm32mp1 -+ -+# HLA does not support multi-cores nor custom CSW nor AP other than 0 -+if { [using_hla] } { -+ echo "ERROR: HLA transport cannot work with this target." -+ echo "ERROR: To use STLink switch to DAP mode, as in \"board/stm32mp15x_dk2.cfg\"." -+ shutdown -+} -+ -+source [find target/swj-dp.tcl] -+ -+if { [info exists CHIPNAME] } { -+ set _CHIPNAME $CHIPNAME -+} else { -+ set _CHIPNAME stm32mp15x -+} -+ -+if { [info exists CPUTAPID] } { -+ set _CPUTAPID $CPUTAPID -+} else { -+ if { [using_jtag] } { -+ set _CPUTAPID 0x6ba00477 -+ } else { -+ set _CPUTAPID 0x6ba02477 -+ } -+} -+ -+# Chip Level TAP Controller, only in jtag mode -+if { [info exists CLCTAPID] } { -+ set _CLCTAPID $CLCTAPID -+} else { -+ set _CLCTAPID 0x06500041 -+} -+ -+swj_newdap $_CHIPNAME tap -expected-id $_CPUTAPID -irlen 4 -+if { [using_jtag] } { -+ jtag newtap $_CHIPNAME.clc tap -expected-id $_CLCTAPID -irlen 5 -+} -+ -+dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap -ignore-syspwrupack -+ -+# FIXME: Cortex-M code requires target accessible during reset, but this is not possible in STM32MP1 -+# so defer-examine it until the reset framework get merged -+# NOTE: keep ap-num and dbgbase to speed-up examine after reset -+# NOTE: do not change the order of target create -+target create $_CHIPNAME.ap1 mem_ap -dap $_CHIPNAME.dap -ap-num 1 -+target create $_CHIPNAME.ap2 mem_ap -dap $_CHIPNAME.dap -ap-num 2 -+target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 0 -+target create $_CHIPNAME.cpu0 cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 0 -dbgbase 0xE00D0000 -+target create $_CHIPNAME.cpu1 cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 1 -dbgbase 0xE00D2000 -+target create $_CHIPNAME.cm4 cortex_m -dap $_CHIPNAME.dap -ap-num 2 -defer-examine -+ -+targets $_CHIPNAME.cpu0 -+ -+target smp $_CHIPNAME.cpu0 $_CHIPNAME.cpu1 -+$_CHIPNAME.cpu0 cortex_a maskisr on -+$_CHIPNAME.cpu1 cortex_a maskisr on -+$_CHIPNAME.cpu0 cortex_a dacrfixup on -+$_CHIPNAME.cpu1 cortex_a dacrfixup on -+ -+cti create $_CHIPNAME.cti.sys -dap $_CHIPNAME.dap -ap-num 1 -ctibase 0xE0094000 -+cti create $_CHIPNAME.cti.cpu0 -dap $_CHIPNAME.dap -ap-num 1 -ctibase 0xE00D8000 -+cti create $_CHIPNAME.cti.cpu1 -dap $_CHIPNAME.dap -ap-num 1 -ctibase 0xE00D9000 -+cti create $_CHIPNAME.cti.cm4 -dap $_CHIPNAME.dap -ap-num 2 -ctibase 0xE0043000 -+ -+# interface does not work while srst is asserted -+# this is target specific, valid for every board -+# Errata "2.3.5 Incorrect reset of glitch-free kernel clock switch" requires -+# srst to force VDDCORE power cycle or pull srst_core. Both cases reset the -+# debug unit, behavior equivalent to "srst_pulls_trst" -+reset_config srst_gates_jtag srst_pulls_trst -+ -+adapter speed 5000 -+adapter srst pulse_width 200 -+# bootrom has an internal timeout of 1 second for detecting the boot flash. -+# wait at least 1 second to guarantee we are out of bootrom -+adapter srst delay 1100 -+ -+add_help_text axi_secure "Set secure mode for following AXI accesses" -+proc axi_secure {} { -+ $::_CHIPNAME.dap apsel 0 -+ $::_CHIPNAME.dap apcsw 0x10006000 -+} -+ -+add_help_text axi_nsecure "Set non-secure mode for following AXI accesses" -+proc axi_nsecure {} { -+ $::_CHIPNAME.dap apsel 0 -+ $::_CHIPNAME.dap apcsw 0x30006000 -+} -+ -+axi_secure -+ -+proc dbgmcu_enable_debug {} { -+ # set debug enable bits in DBGMCU_CR to get ap2 and cm4 visible -+ catch {$::_CHIPNAME.ap1 mww 0xe0081004 0x00000007} -+} -+ -+proc toggle_cpu0_dbg_claim0 {} { -+ # toggle CPU0 DBG_CLAIM[0] -+ $::_CHIPNAME.ap1 mww 0xe00d0fa0 1 -+ $::_CHIPNAME.ap1 mww 0xe00d0fa4 1 -+} -+ -+proc detect_cpu1 {} { -+ $::_CHIPNAME.ap1 mem2array cpu1_prsr 32 0xE00D2314 1 -+ set dual_core [expr $cpu1_prsr(0) & 1] -+ if {! $dual_core} {$::_CHIPNAME.cpu1 configure -defer-examine} -+} -+ -+# FIXME: most of handler below will be removed once reset framework get merged -+$_CHIPNAME.ap1 configure -event reset-deassert-pre {adapter deassert srst deassert trst;dap init;catch {$::_CHIPNAME.dap apid 1}} -+$_CHIPNAME.ap2 configure -event reset-deassert-pre {dbgmcu_enable_debug} -+$_CHIPNAME.cpu0 configure -event reset-deassert-pre {$::_CHIPNAME.cpu0 arp_examine} -+$_CHIPNAME.cpu1 configure -event reset-deassert-pre {$::_CHIPNAME.cpu1 arp_examine allow-defer} -+$_CHIPNAME.cpu0 configure -event reset-deassert-post {toggle_cpu0_dbg_claim0} -+$_CHIPNAME.cm4 configure -event reset-deassert-post {$::_CHIPNAME.cm4 arp_examine;if {[$::_CHIPNAME.ap2 curstate] == "halted"} {$::_CHIPNAME.cm4 arp_halt}} -+$_CHIPNAME.ap1 configure -event examine-start {dap init} -+$_CHIPNAME.ap2 configure -event examine-start {dbgmcu_enable_debug} -+$_CHIPNAME.cpu0 configure -event examine-end {detect_cpu1} -+$_CHIPNAME.ap2 configure -event examine-end {$::_CHIPNAME.cm4 arp_examine} --- -2.25.2 - diff --git a/recipes-devtools/openocd/openocd-stm32mp/0001-rebase-on-v0.11.0-rc2.patch b/recipes-devtools/openocd/openocd-stm32mp/0001-rebase-on-v0.11.0-rc2.patch new file mode 100644 index 0000000..e54fea8 --- /dev/null +++ b/recipes-devtools/openocd/openocd-stm32mp/0001-rebase-on-v0.11.0-rc2.patch @@ -0,0 +1,989 @@ +From 4b8f01fdcbbb47fe912a01ff33308d59adaae7cd Mon Sep 17 00:00:00 2001 +From: Antonio Borneo +Date: Mon, 11 Jan 2021 14:36:24 +0100 +Subject: [PATCH] rebase on v0.11.0-rc2 +--- + src/helper/log.h | 1 + + src/jtag/drivers/stlink_usb.c | 567 +++++++++++++++++++---- + src/target/arm_adi_v5.c | 28 ++ + src/target/arm_adi_v5.h | 22 + + tcl/board/stm32mp15x_ev1_jlink_jtag.cfg | 9 + + tcl/board/stm32mp15x_ev1_jlink_swd.cfg | 9 + + tcl/board/stm32mp15x_ev1_stlink_jtag.cfg | 9 + + tcl/board/stm32mp15x_ev1_stlink_swd.cfg | 9 + + tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg | 9 + + tcl/board/stm32mp15x_ev1_ulink2_swd.cfg | 9 + + 10 files changed, 577 insertions(+), 95 deletions(-) + +diff --git a/src/helper/log.h b/src/helper/log.h +index f2ba0daa6..f91925919 100644 +--- a/src/helper/log.h ++++ b/src/helper/log.h +@@ -155,6 +155,7 @@ extern int debug_level; + /* ERROR_TIMEOUT is already taken by winerror.h. */ + #define ERROR_TIMEOUT_REACHED (-6) + #define ERROR_NOT_IMPLEMENTED (-7) ++#define ERROR_OP_NOT_SUPPORTED (-8) + + + #endif /* OPENOCD_HELPER_LOG_H */ +diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c +index 4545bcba0..b04611144 100644 +--- a/src/jtag/drivers/stlink_usb.c ++++ b/src/jtag/drivers/stlink_usb.c +@@ -85,11 +85,22 @@ + #define STLINK_MAX_RW8 (64) + #define STLINKV3_MAX_RW8 (512) + ++/* ++ * FIXME: this definition + comment should be moved in a generic header file ++ * ARM IHI 0031E: TAR Automatic address increment is only guaranteed to ++ * operate on the 10 least significant bits of the address ++ */ ++#define TAR_AUTOINCR_BLOCK (1 << 10) ++ + /* "WAIT" responses will be retried (with exponential backoff) at + * most this many times before failing to caller. + */ + #define MAX_WAIT_RETRIES 8 + ++/* HLA is currently limited at AP#0 and no control on CSW */ ++#define STLINK_HLA_AP_NUM 0 ++#define STLINK_HLA_CSW 0 ++ + enum stlink_jtag_api_version { + STLINK_JTAG_API_V1 = 1, + STLINK_JTAG_API_V2, +@@ -286,6 +297,10 @@ struct stlink_usb_handle_s { + #define STLINK_DEBUG_APIV2_INIT_AP 0x4B + #define STLINK_DEBUG_APIV2_CLOSE_AP_DBG 0x4C + ++#define STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC 0x50 ++ ++#define STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC 0x54 ++ + #define STLINK_APIV3_SET_COM_FREQ 0x61 + #define STLINK_APIV3_GET_COM_FREQ 0x62 + +@@ -325,6 +340,9 @@ struct stlink_usb_handle_s { + /* aliases */ + #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE + #define STLINK_F_HAS_FPU_REG STLINK_F_HAS_GETLASTRWSTATUS2 ++#define STLINK_F_HAS_MEM_WR_NO_INC STLINK_F_HAS_MEM_16BIT ++#define STLINK_F_HAS_MEM_RD_NO_INC STLINK_F_HAS_DPBANKSEL ++#define STLINK_F_HAS_CSW STLINK_F_HAS_DPBANKSEL + + #define STLINK_REGSEL_IS_FPU(x) ((x) > 0x1F) + +@@ -1029,6 +1047,7 @@ static int stlink_usb_version(void *handle) + flags |= STLINK_F_QUIRK_JTAG_DP_READ; + + /* API to read/write memory at 16 bit from J26 */ ++ /* API to write memory without address increment from J26 */ + if (h->version.jtag >= 26) + flags |= STLINK_F_HAS_MEM_16BIT; + +@@ -1041,6 +1060,8 @@ static int stlink_usb_version(void *handle) + flags |= STLINK_F_FIX_CLOSE_AP; + + /* Banked regs (DPv1 & DPv2) support from V2J32 */ ++ /* API to read memory without address increment from V2J32 */ ++ /* Memory R/W supports CSW from V2J32 */ + if (h->version.jtag >= 32) + flags |= STLINK_F_HAS_DPBANKSEL; + +@@ -1062,6 +1083,7 @@ static int stlink_usb_version(void *handle) + flags |= STLINK_F_HAS_DAP_REG; + + /* API to read/write memory at 16 bit */ ++ /* API to write memory without address increment */ + flags |= STLINK_F_HAS_MEM_16BIT; + + /* API required to init AP before any AP access */ +@@ -1071,6 +1093,8 @@ static int stlink_usb_version(void *handle) + flags |= STLINK_F_FIX_CLOSE_AP; + + /* Banked regs (DPv1 & DPv2) support from V3J2 */ ++ /* API to read memory without address increment from V3J2 */ ++ /* Memory R/W supports CSW from V3J2 */ + if (h->version.jtag >= 2) + flags |= STLINK_F_HAS_DPBANKSEL; + +@@ -2111,8 +2135,8 @@ static int stlink_usb_get_rw_status(void *handle) + } + + /** */ +-static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, +- uint8_t *buffer) ++static int stlink_usb_read_mem8(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, uint8_t *buffer) + { + int res; + uint16_t read_len = len; +@@ -2134,6 +2158,9 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf+h->cmdidx, len); + h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; + + /* we need to fix read length for single bytes */ + if (read_len == 1) +@@ -2150,8 +2177,8 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, + } + + /** */ +-static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, +- const uint8_t *buffer) ++static int stlink_usb_write_mem8(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, const uint8_t *buffer) + { + int res; + struct stlink_usb_handle_s *h = handle; +@@ -2172,6 +2199,9 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf+h->cmdidx, len); + h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; + + res = stlink_usb_xfer_noerrcheck(handle, buffer, len); + +@@ -2182,8 +2212,8 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, + } + + /** */ +-static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, +- uint8_t *buffer) ++static int stlink_usb_read_mem16(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, uint8_t *buffer) + { + int res; + struct stlink_usb_handle_s *h = handle; +@@ -2207,6 +2237,9 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf+h->cmdidx, len); + h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; + + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); + +@@ -2219,8 +2252,8 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, + } + + /** */ +-static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, +- const uint8_t *buffer) ++static int stlink_usb_write_mem16(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, const uint8_t *buffer) + { + int res; + struct stlink_usb_handle_s *h = handle; +@@ -2244,6 +2277,9 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf+h->cmdidx, len); + h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; + + res = stlink_usb_xfer_noerrcheck(handle, buffer, len); + +@@ -2254,8 +2290,8 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, + } + + /** */ +-static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, +- uint8_t *buffer) ++static int stlink_usb_read_mem32(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, uint8_t *buffer) + { + int res; + struct stlink_usb_handle_s *h = handle; +@@ -2276,6 +2312,9 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf+h->cmdidx, len); + h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; + + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); + +@@ -2288,8 +2327,8 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, + } + + /** */ +-static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, +- const uint8_t *buffer) ++static int stlink_usb_write_mem32(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, const uint8_t *buffer) + { + int res; + struct stlink_usb_handle_s *h = handle; +@@ -2310,6 +2349,9 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, + h->cmdidx += 4; + h_u16_to_le(h->cmdbuf+h->cmdidx, len); + h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; + + res = stlink_usb_xfer_noerrcheck(handle, buffer, len); + +@@ -2319,6 +2361,80 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, + return stlink_usb_get_rw_status(handle); + } + ++static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, uint8_t *buffer) ++{ ++ int res; ++ struct stlink_usb_handle_s *h = handle; ++ ++ assert(handle != NULL); ++ ++ if (!(h->version.flags & STLINK_F_HAS_MEM_RD_NO_INC)) ++ return ERROR_COMMAND_NOTFOUND; ++ ++ /* data must be a multiple of 4 and word aligned */ ++ if (len % 4 || addr % 4) { ++ LOG_DEBUG("Invalid data alignment"); ++ return ERROR_TARGET_UNALIGNED_ACCESS; ++ } ++ ++ stlink_usb_init_buffer(handle, h->rx_ep, len); ++ ++ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; ++ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_32BIT_NO_ADDR_INC; ++ h_u32_to_le(h->cmdbuf+h->cmdidx, addr); ++ h->cmdidx += 4; ++ h_u16_to_le(h->cmdbuf+h->cmdidx, len); ++ h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; ++ ++ res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); ++ if (res != ERROR_OK) ++ return res; ++ ++ memcpy(buffer, h->databuf, len); ++ ++ return stlink_usb_get_rw_status(handle); ++} ++ ++static int stlink_usb_write_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint16_t len, const uint8_t *buffer) ++{ ++ int res; ++ struct stlink_usb_handle_s *h = handle; ++ ++ assert(handle != NULL); ++ ++ if (!(h->version.flags & STLINK_F_HAS_MEM_WR_NO_INC)) ++ return ERROR_COMMAND_NOTFOUND; ++ ++ /* data must be a multiple of 4 and word aligned */ ++ if (len % 4 || addr % 4) { ++ LOG_DEBUG("Invalid data alignment"); ++ return ERROR_TARGET_UNALIGNED_ACCESS; ++ } ++ ++ stlink_usb_init_buffer(handle, h->tx_ep, len); ++ ++ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; ++ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT_NO_ADDR_INC; ++ h_u32_to_le(h->cmdbuf+h->cmdidx, addr); ++ h->cmdidx += 4; ++ h_u16_to_le(h->cmdbuf+h->cmdidx, len); ++ h->cmdidx += 2; ++ h->cmdbuf[h->cmdidx++] = ap_num; ++ h_u24_to_le(h->cmdbuf+h->cmdidx, csw >> 8); ++ h->cmdidx += 3; ++ ++ res = stlink_usb_xfer_noerrcheck(handle, buffer, len); ++ if (res != ERROR_OK) ++ return res; ++ ++ return stlink_usb_get_rw_status(handle); ++} ++ + static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t address) + { + uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address)); +@@ -2327,8 +2443,95 @@ static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t addr + return max_tar_block; + } + ++static int stlink_usb_read_ap_mem(void *handle, uint8_t ap_num, uint32_t csw, ++ uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) ++{ ++ int retval = ERROR_OK; ++ uint32_t bytes_remaining; ++ int retries = 0; ++ struct stlink_usb_handle_s *h = handle; ++ ++ /* calculate byte count */ ++ count *= size; ++ ++ /* switch to 8 bit if stlink does not support 16 bit memory read */ ++ if (size == 2 && !(h->version.flags & STLINK_F_HAS_MEM_16BIT)) ++ size = 1; ++ ++ while (count) { ++ ++ bytes_remaining = (size != 1) ? ++ stlink_max_block_size(h->max_mem_packet, addr) : stlink_usb_block(h); ++ ++ if (count < bytes_remaining) ++ bytes_remaining = count; ++ ++ /* ++ * all stlink support 8/32bit memory read/writes and only from ++ * stlink V2J26 there is support for 16 bit memory read/write. ++ * Honour 32 bit and, if possible, 16 bit too. Otherwise, handle ++ * as 8bit access. ++ */ ++ if (size != 1) { ++ ++ /* When in jtag mode the stlink uses the auto-increment functionality. ++ * However it expects us to pass the data correctly, this includes ++ * alignment and any page boundaries. We already do this as part of the ++ * adi_v5 implementation, but the stlink is a hla adapter and so this ++ * needs implementing manually. ++ * currently this only affects jtag mode, according to ST they do single ++ * access in SWD mode - but this may change and so we do it for both modes */ ++ ++ /* we first need to check for any unaligned bytes */ ++ if (addr & (size - 1)) { ++ ++ uint32_t head_bytes = size - (addr & (size - 1)); ++ retval = stlink_usb_read_mem8(handle, ap_num, csw, addr, head_bytes, buffer); ++ if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { ++ usleep((1<version.flags & STLINK_F_HAS_MEM_16BIT)) +- size = 1; +- +- while (count) { +- +- bytes_remaining = (size != 1) ? +- stlink_max_block_size(h->max_mem_packet, addr) : stlink_usb_block(h); +- +- if (count < bytes_remaining) +- bytes_remaining = count; +- +- /* +- * all stlink support 8/32bit memory read/writes and only from +- * stlink V2J26 there is support for 16 bit memory read/write. +- * Honour 32 bit and, if possible, 16 bit too. Otherwise, handle +- * as 8bit access. +- */ +- if (size != 1) { +- +- /* When in jtag mode the stlink uses the auto-increment functionality. +- * However it expects us to pass the data correctly, this includes +- * alignment and any page boundaries. We already do this as part of the +- * adi_v5 implementation, but the stlink is a hla adapter and so this +- * needs implementing manually. +- * currently this only affects jtag mode, according to ST they do single +- * access in SWD mode - but this may change and so we do it for both modes */ +- +- /* we first need to check for any unaligned bytes */ +- if (addr & (size - 1)) { +- +- uint32_t head_bytes = size - (addr & (size - 1)); +- retval = stlink_usb_write_mem8(handle, addr, head_bytes, buffer); +- if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { +- usleep((1<max_mem_packet = (1 << 10); + + uint8_t buffer[4]; +- stlink_usb_open_ap(h, 0); +- err = stlink_usb_read_mem32(h, CPUID, 4, buffer); ++ stlink_usb_open_ap(h, STLINK_HLA_AP_NUM); ++ err = stlink_usb_read_mem32(h, STLINK_HLA_AP_NUM, STLINK_HLA_CSW, CPUID, 4, buffer); + if (err == ERROR_OK) { + uint32_t cpuid = le_to_h_u32(buffer); + int i = (cpuid >> 4) & 0xf; +@@ -3539,6 +3669,249 @@ static int stlink_dap_op_run(struct adiv5_dap *dap) + return saved_retval; + } + ++/* ++ * Explanation on CSW hack used for firmware V2J24~V2J31 and V3J1 ++ * ++ * The API of these firmware versions don't provide a way to specify directly ++ * the value of CSW used for mem_ap accesses. The CSW value used by the ++ * firmware is not under user control. The lack of specific API would force ++ * the use of inefficient memory access through low-level AP register API. ++ * ++ * The CSW value internally computed by the firmware is cached by the firmware ++ * itself to minimize the writes to register MEM_AP_REG_CSW, writing it only ++ * to updated a new CSW value. The update is only triggered by a change in the ++ * CSW fields "size" and "addrinc" (note: with these firmware versions we only ++ * use "addrinc = true"). ++ * ++ * With the command STLINK_DEBUG_APIV2_WRITE_DAP_REG we can write the register ++ * MEM_AP_REG_CSW; the firmware does not intercept this write and its internal ++ * cached CSW value get out-of-sync wrt the value in register MEM_AP_REG_CSW. ++ * The hack rely on this mismatch between firmware cache and MEM_AP_REG_CSW. ++ * Given the "size" of data we plan to use for memory access, we execute: ++ * 1) a dummy memory read of "size" to let the firmware compute a CSW value ++ * coherent with "size". This will update the internal CSW cache and ++ * (eventually) the register MEM_AP_REG_CSW; ++ * 2) a write of the desired "user" CSW value in MEM_AP_REG_CSW, including the ++ * field "addrinc" ("size" has not to be changed wrt point 1); ++ * 3) a set of memory read/write commands of the same "size". ++ * While executing 3), the firmware will not modify the content of register ++ * MEM_AP_REG_CSW because accordingly to its cached value there is no need to ++ * update it! ++ * The memory accesses in 3) would then be executed with the desired CSW value ++ * programmed in 2). ++ * ++ * To simplify the code and only use one "size", the case of unaligned access ++ * is converted to a 8 bit access. ++ * ++ * Because of the available API, in step 3) we will use the normal access (with ++ * address auto-increment) also for addrinc==false, and this triggers another ++ * problem. The auto-increment of register MEM_AP_REG_TAR is guaranteed only ++ * on the 10 least significant bits. The firmware will update MEM_AP_REG_TAR ++ * every time the 10 bit increment is crossed, to avoid any potential ++ * wrap-around. This disrupts the address in MEM_AP_REG_TAR, that should ++ * instead be constant during the whole memory access. To prevent this, we ++ * split the memory access in chunks whose length cannot cause the 10 bits ++ * wrap-around so the firmware will not touch MEM_AP_REG_TAR. ++ * ++ * For write case only, the firmware operates per USB blocks, so it re-programs ++ * MEM_AP_REG_TAR every 64 bytes (on stlink/v1) or 512 bytes (on stlik/v3) and ++ * this limits the maximum size of each write chunk when addrinc==false. ++ */ ++static int stlink_dap_hack_csw(struct adiv5_ap *ap, uint32_t size, bool addrinc) ++{ ++ uint32_t csw; ++ uint8_t dummy[4]; ++ ++ switch (size) { ++ case 1: ++ csw = CSW_8BIT; ++ break; ++ case 2: ++ csw = CSW_16BIT; ++ break; ++ case 4: ++ /* ++ * ST-Link sets autoinc only in 32 bits mode ++ * ++ * ARM IHI 0031D: Note: ++ * It is IMPLEMENTATION DEFINED whether a MEM-AP supports transfer sizes other than Word. If a ++ * MEM-AP only supports word transfers and Increment single is selected, the TAR always ++ * increments by four after a successful DRW transaction. ++ */ ++ csw = addrinc ? (CSW_32BIT | CSW_ADDRINC_SINGLE) : CSW_32BIT; ++ break; ++ default: ++ return ERROR_FAIL; ++ } ++ csw |= ap->csw_default; ++ ++ /* This mem read will change CSW. Ignore errors */ ++ stlink_usb_read_ap_mem(stlink_dap_handle, ap->ap_num, STLINK_HLA_CSW, 0x00000000, size, 1, dummy); ++ ++ return dap_queue_ap_write(ap, MEM_AP_REG_CSW, csw); ++} ++ ++static int stlink_dap_hack_csw_mem_read(struct adiv5_ap *ap, uint8_t *buffer, ++ uint32_t size, uint32_t count, uint32_t address, bool addrinc) ++{ ++ int retval; ++ uint32_t bytes_remaining, max_count; ++ ++ /* unaligned access could be split in mix 32/16/8 bits. Force 8-bis only */ ++ if ((size == 4 && address & 3) || ++ (size == 2 && address & 1) || ++ (size == 2 && !(stlink_dap_handle->version.flags & STLINK_F_HAS_MEM_16BIT))) { ++ count *= size; ++ size = 1; ++ } ++ ++ retval = stlink_dap_hack_csw(ap, size, addrinc); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ if (addrinc) ++ return stlink_usb_read_ap_mem(stlink_dap_handle, ap->ap_num, ++ STLINK_HLA_CSW, address, size, count, buffer); ++ ++ count *= size; ++ max_count = TAR_AUTOINCR_BLOCK - (address & (TAR_AUTOINCR_BLOCK - 1)); ++ while (count) { ++ bytes_remaining = (count < max_count) ? count : max_count; ++ ++ retval = stlink_usb_read_mem32(stlink_dap_handle, ap->ap_num, ++ STLINK_HLA_CSW, address, bytes_remaining, buffer); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ buffer += bytes_remaining; ++ count -= bytes_remaining; ++ } ++ return ERROR_OK; ++} ++ ++static int stlink_dap_op_ap_mem_read(struct adiv5_ap *ap, uint8_t *buffer, ++ uint32_t size, uint32_t count, uint32_t address, bool addrinc) ++{ ++ int retval; ++ uint32_t bytes_remaining; ++ ++ if (!addrinc && size != 4) ++ return ERROR_OP_NOT_SUPPORTED; ++ ++ retval = stlink_dap_op_run(ap->dap); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ retval = stlink_dap_open_ap(ap->ap_num); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ dap_invalidate_cache(ap->dap); ++ ++ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_CSW)) ++ return stlink_dap_hack_csw_mem_read(ap, buffer, size, count, address, addrinc); ++ ++ if (addrinc) ++ return stlink_usb_read_ap_mem(stlink_dap_handle, ap->ap_num, ++ ap->csw_default, address, size, count, buffer); ++ ++ count *= size; ++ while (count) { ++ bytes_remaining = (count < STLINK_DATA_SIZE) ? count : STLINK_DATA_SIZE; ++ ++ retval = stlink_usb_read_mem32_noaddrinc(stlink_dap_handle, ap->ap_num, ++ ap->csw_default, address, bytes_remaining, buffer); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ buffer += bytes_remaining; ++ count -= bytes_remaining; ++ } ++ return ERROR_OK; ++} ++ ++static int stlink_dap_hack_csw_mem_write(struct adiv5_ap *ap, const uint8_t *buffer, ++ uint32_t size, uint32_t count, uint32_t address, bool addrinc) ++{ ++ int retval; ++ uint32_t bytes_remaining, max_count; ++ ++ /* unaligned access could be split in mix 32/16/8 bits. Force 8-bis only */ ++ if ((size == 4 && address & 3) || ++ (size == 2 && address & 1) || ++ (size == 2 && !(stlink_dap_handle->version.flags & STLINK_F_HAS_MEM_16BIT))) { ++ count *= size; ++ size = 1; ++ } ++ ++ retval = stlink_dap_hack_csw(ap, size, addrinc); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ if (addrinc) ++ return stlink_usb_write_ap_mem(stlink_dap_handle, ap->ap_num, ++ STLINK_HLA_CSW, address, size, count, buffer); ++ ++ count *= size; ++ max_count = TAR_AUTOINCR_BLOCK - (address & (TAR_AUTOINCR_BLOCK - 1)); ++ if (max_count > stlink_usb_block(&stlink_dap_handle)) ++ max_count = stlink_usb_block(&stlink_dap_handle); ++ ++ while (count) { ++ bytes_remaining = (count < max_count) ? count : max_count; ++ ++ retval = stlink_usb_write_mem32(stlink_dap_handle, ap->ap_num, ++ STLINK_HLA_CSW, address, bytes_remaining, buffer); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ buffer += bytes_remaining; ++ count -= bytes_remaining; ++ } ++ return ERROR_OK; ++} ++ ++static int stlink_dap_op_ap_mem_write(struct adiv5_ap *ap, const uint8_t *buffer, ++ uint32_t size, uint32_t count, uint32_t address, bool addrinc) ++{ ++ int retval; ++ uint32_t bytes_remaining; ++ ++ if (!addrinc && size != 4) ++ return ERROR_OP_NOT_SUPPORTED; ++ ++ retval = stlink_dap_op_run(ap->dap); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ retval = stlink_dap_open_ap(ap->ap_num); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ dap_invalidate_cache(ap->dap); ++ ++ if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_CSW)) ++ return stlink_dap_hack_csw_mem_write(ap, buffer, size, count, address, addrinc); ++ ++ if (addrinc) ++ return stlink_usb_write_ap_mem(stlink_dap_handle, ap->ap_num, ++ ap->csw_default, address, size, count, buffer); ++ ++ count *= size; ++ while (count) { ++ bytes_remaining = (count < STLINK_DATA_SIZE) ? count : STLINK_DATA_SIZE; ++ ++ retval = stlink_usb_write_mem32_noaddrinc(stlink_dap_handle, ap->ap_num, ++ ap->csw_default, address, bytes_remaining, buffer); ++ if (retval != ERROR_OK) ++ return retval; ++ ++ buffer += bytes_remaining; ++ count -= bytes_remaining; ++ } ++ return ERROR_OK; ++} ++ + /** */ + static void stlink_dap_op_quit(struct adiv5_dap *dap) + { +@@ -3803,6 +4176,10 @@ static const struct dap_ops stlink_dap_ops = { + .run = stlink_dap_op_run, + .sync = NULL, /* optional */ + .quit = stlink_dap_op_quit, /* optional */ ++ .ap_ops = { ++ .ap_mem_read = stlink_dap_op_ap_mem_read, ++ .ap_mem_write = stlink_dap_op_ap_mem_write, ++ }, + }; + + static const struct swim_driver stlink_swim_ops = { +diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c +index 8f5ad59c3..d7c920e91 100644 +--- a/src/target/arm_adi_v5.c ++++ b/src/target/arm_adi_v5.c +@@ -596,24 +596,52 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint + int mem_ap_read_buf(struct adiv5_ap *ap, + uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + { ++ int retval; ++ ++ if (ap->dap->ops->ap_ops.ap_mem_read) { ++ retval = ap->dap->ops->ap_ops.ap_mem_read(ap, buffer, size, count, address, true); ++ if (retval != ERROR_OP_NOT_SUPPORTED) ++ return retval; ++ } + return mem_ap_read(ap, buffer, size, count, address, true); + } + + int mem_ap_write_buf(struct adiv5_ap *ap, + const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + { ++ int retval; ++ ++ if (ap->dap->ops->ap_ops.ap_mem_write) { ++ retval = ap->dap->ops->ap_ops.ap_mem_write(ap, buffer, size, count, address, true); ++ if (retval != ERROR_OP_NOT_SUPPORTED) ++ return retval; ++ } + return mem_ap_write(ap, buffer, size, count, address, true); + } + + int mem_ap_read_buf_noincr(struct adiv5_ap *ap, + uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + { ++ int retval; ++ ++ if (ap->dap->ops->ap_ops.ap_mem_read) { ++ retval = ap->dap->ops->ap_ops.ap_mem_read(ap, buffer, size, count, address, false); ++ if (retval != ERROR_OP_NOT_SUPPORTED) ++ return retval; ++ } + return mem_ap_read(ap, buffer, size, count, address, false); + } + + int mem_ap_write_buf_noincr(struct adiv5_ap *ap, + const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address) + { ++ int retval; ++ ++ if (ap->dap->ops->ap_ops.ap_mem_write) { ++ retval = ap->dap->ops->ap_ops.ap_mem_write(ap, buffer, size, count, address, false); ++ if (retval != ERROR_OP_NOT_SUPPORTED) ++ return retval; ++ } + return mem_ap_write(ap, buffer, size, count, address, false); + } + +diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h +index 8edfaa816..587bb3dd9 100644 +--- a/src/target/arm_adi_v5.h ++++ b/src/target/arm_adi_v5.h +@@ -296,6 +296,26 @@ struct adiv5_dap { + bool ignore_syspwrupack; + }; + ++/** ++ * Optional optimized implementation of AP access. ++ * Use of low-level primitives in struct dap_ops already allows implementing ++ * any type of AP access. Some adapter offer faster API at higher level for ++ * specific AP types or mode. ++ * Specific request not available or not implemented should return error ++ * ERROR_OP_NOT_SUPPORTED. ++ */ ++struct ap_ops { ++ /** Optional interface-specific optimized AP memory read */ ++ int (*ap_mem_read)(struct adiv5_ap *ap, uint8_t *buffer, ++ uint32_t size, uint32_t count, uint32_t address, ++ bool addrinc); ++ ++ /** Optional interface-specific optimized AP memory write */ ++ int (*ap_mem_write)(struct adiv5_ap *ap, const uint8_t *buffer, ++ uint32_t size, uint32_t count, uint32_t address, ++ bool addrinc); ++}; ++ + /** + * Transport-neutral representation of queued DAP transactions, supporting + * both JTAG and SWD transports. All submitted transactions are logically +@@ -336,6 +356,8 @@ struct dap_ops { + + /** Optional; called at OpenOCD exit */ + void (*quit)(struct adiv5_dap *dap); ++ ++ struct ap_ops ap_ops; + }; + + /* +diff --git a/tcl/board/stm32mp15x_ev1_jlink_jtag.cfg b/tcl/board/stm32mp15x_ev1_jlink_jtag.cfg +new file mode 100644 +index 000000000..ce0c56cdb +--- /dev/null ++++ b/tcl/board/stm32mp15x_ev1_jlink_jtag.cfg +@@ -0,0 +1,9 @@ ++# This is a STM32MP15x board set MB1262C + MB1263B. ++ ++source [find interface/jlink.cfg] ++ ++transport select jtag ++ ++source [find target/stm32mp15x.cfg] ++ ++reset_config trst_and_srst separate +diff --git a/tcl/board/stm32mp15x_ev1_jlink_swd.cfg b/tcl/board/stm32mp15x_ev1_jlink_swd.cfg +new file mode 100644 +index 000000000..58286d3f8 +--- /dev/null ++++ b/tcl/board/stm32mp15x_ev1_jlink_swd.cfg +@@ -0,0 +1,9 @@ ++# This is a STM32MP15x board set MB1262C + MB1263B. ++ ++source [find interface/jlink.cfg] ++ ++transport select swd ++ ++source [find target/stm32mp15x.cfg] ++ ++reset_config srst_only +diff --git a/tcl/board/stm32mp15x_ev1_stlink_jtag.cfg b/tcl/board/stm32mp15x_ev1_stlink_jtag.cfg +new file mode 100644 +index 000000000..b0cba47c3 +--- /dev/null ++++ b/tcl/board/stm32mp15x_ev1_stlink_jtag.cfg +@@ -0,0 +1,9 @@ ++# This is a STM32MP15x board set MB1262C + MB1263B. ++ ++source [find interface/stlink-dap.cfg] ++ ++transport select dapdirect_jtag ++ ++source [find target/stm32mp15x.cfg] ++ ++reset_config srst_only +diff --git a/tcl/board/stm32mp15x_ev1_stlink_swd.cfg b/tcl/board/stm32mp15x_ev1_stlink_swd.cfg +new file mode 100644 +index 000000000..793b2c771 +--- /dev/null ++++ b/tcl/board/stm32mp15x_ev1_stlink_swd.cfg +@@ -0,0 +1,9 @@ ++# This is a STM32MP15x board set MB1262C + MB1263B. ++ ++source [find interface/stlink-dap.cfg] ++ ++transport select dapdirect_swd ++ ++source [find target/stm32mp15x.cfg] ++ ++reset_config srst_only +diff --git a/tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg b/tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg +new file mode 100644 +index 000000000..fcf62d4f3 +--- /dev/null ++++ b/tcl/board/stm32mp15x_ev1_ulink2_jtag.cfg +@@ -0,0 +1,9 @@ ++# This is a STM32MP15x board set MB1262C + MB1263B. ++ ++source [find interface/cmsis-dap.cfg] ++ ++transport select jtag ++ ++source [find target/stm32mp15x.cfg] ++ ++reset_config trst_and_srst separate +diff --git a/tcl/board/stm32mp15x_ev1_ulink2_swd.cfg b/tcl/board/stm32mp15x_ev1_ulink2_swd.cfg +new file mode 100644 +index 000000000..2c0528bf1 +--- /dev/null ++++ b/tcl/board/stm32mp15x_ev1_ulink2_swd.cfg +@@ -0,0 +1,9 @@ ++# This is a STM32MP15x board set MB1262C + MB1263B. ++ ++source [find interface/cmsis-dap.cfg] ++ ++transport select swd ++ ++source [find target/stm32mp15x.cfg] ++ ++reset_config srst_only +-- +2.30.0 + diff --git a/recipes-devtools/openocd/openocd-stm32mp/0002-fixes-for-gcc-10-build-macos-build-CM4-halt-stlink-J.patch b/recipes-devtools/openocd/openocd-stm32mp/0002-fixes-for-gcc-10-build-macos-build-CM4-halt-stlink-J.patch deleted file mode 100644 index d5d28f5..0000000 --- a/recipes-devtools/openocd/openocd-stm32mp/0002-fixes-for-gcc-10-build-macos-build-CM4-halt-stlink-J.patch +++ /dev/null @@ -1,295 +0,0 @@ -From 2f115dde2ef6e6e72ff6439f27bc2e20f83b5d10 Mon Sep 17 00:00:00 2001 -From: Antonio Borneo -Date: Fri, 29 May 2020 17:22:33 +0200 -Subject: [PATCH] fixes for gcc-10 build, macos build, CM4 halt, stlink J28 and - j37 - -Change-Id: If6c44bc94debc305aff1837d74b282f97e7c596a -Signed-off-by: Antonio Borneo ---- - src/flash/nor/jtagspi.c | 19 +++++++++++++++---- - src/flash/nor/nrf5.c | 10 +++++++--- - src/jtag/drivers/bitbang.h | 2 +- - src/jtag/drivers/stlink_usb.c | 32 ++++++++++++++++++++++++++------ - src/server/gdb_server.c | 2 +- - src/target/cortex_m.c | 21 +++++++++++++++++---- - src/target/startup.tcl | 2 +- - tcl/target/stm32mp15x.cfg | 2 +- - 8 files changed, 69 insertions(+), 21 deletions(-) - -diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c -index f6e311ab8..73b1c7a26 100644 ---- a/src/flash/nor/jtagspi.c -+++ b/src/flash/nor/jtagspi.c -@@ -228,13 +228,16 @@ static int jtagspi_probe(struct flash_bank *bank) - return ERROR_OK; - } - --static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status) -+static int jtagspi_read_status(struct flash_bank *bank, uint32_t *status) - { - uint8_t buf; -- if (jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8) == ERROR_OK) { -+ int err = jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8); -+ if (err == ERROR_OK) { - *status = buf; - /* LOG_DEBUG("status=0x%08" PRIx32, *status); */ - } -+ -+ return err; - } - - static int jtagspi_wait(struct flash_bank *bank, int timeout_ms) -@@ -245,7 +248,11 @@ static int jtagspi_wait(struct flash_bank *bank, int timeout_ms) - - do { - dt = timeval_ms() - t0; -- jtagspi_read_status(bank, &status); -+ -+ int retval = jtagspi_read_status(bank, &status); -+ if (retval != ERROR_OK) -+ return retval; -+ - if ((status & SPIFLASH_BSY_BIT) == 0) { - LOG_DEBUG("waited %" PRId64 " ms", dt); - return ERROR_OK; -@@ -262,7 +269,11 @@ static int jtagspi_write_enable(struct flash_bank *bank) - uint32_t status; - - jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0); -- jtagspi_read_status(bank, &status); -+ -+ int retval = jtagspi_read_status(bank, &status); -+ if (retval != ERROR_OK) -+ return retval; -+ - if ((status & SPIFLASH_WE_BIT) == 0) { - LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status); - return ERROR_FAIL; -diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c -index 8422589b8..5bef8487c 100644 ---- a/src/flash/nor/nrf5.c -+++ b/src/flash/nor/nrf5.c -@@ -570,10 +570,14 @@ static int nrf5_protect(struct flash_bank *bank, int set, int first, int last) - - static bool nrf5_info_variant_to_str(uint32_t variant, char *bf) - { -- h_u32_to_be((uint8_t *)bf, variant); -- bf[4] = '\0'; -- if (isalnum(bf[0]) && isalnum(bf[1]) && isalnum(bf[2]) && isalnum(bf[3])) -+ uint8_t b[4]; -+ -+ h_u32_to_be(b, variant); -+ if (isalnum(b[0]) && isalnum(b[1]) && isalnum(b[2]) && isalnum(b[3])) { -+ memcpy(bf, b, 4); -+ bf[4] = 0; - return true; -+ } - - strcpy(bf, "xxxx"); - return false; -diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h -index edb779cad..bbbc693df 100644 ---- a/src/jtag/drivers/bitbang.h -+++ b/src/jtag/drivers/bitbang.h -@@ -56,7 +56,7 @@ struct bitbang_interface { - void (*swdio_drive)(bool on); - }; - --const struct swd_driver bitbang_swd; -+extern const struct swd_driver bitbang_swd; - - extern bool swd_mode; - -diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c -index 6c0601d0e..83bb89046 100644 ---- a/src/jtag/drivers/stlink_usb.c -+++ b/src/jtag/drivers/stlink_usb.c -@@ -335,6 +335,7 @@ enum stlink_mode { - #define STLINK_F_HAS_AP_INIT BIT(7) - #define STLINK_F_HAS_DPBANKSEL BIT(8) - #define STLINK_F_HAS_RW8_512BYTES BIT(9) -+#define STLINK_F_FIX_CLOSE_AP BIT(10) - - /* aliases */ - #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE -@@ -379,6 +380,7 @@ static int stlink_swim_status(void *handle); - void stlink_dump_speed_map(const struct speed_map *map, unsigned int map_size); - static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map); - static int stlink_speed(void *handle, int khz, bool query); -+static int stlink_usb_open_ap(void *handle, unsigned short apsel); - - /** */ - static unsigned int stlink_usb_block(void *handle) -@@ -852,7 +854,7 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) - - res = stlink_usb_error_check(handle); - if (res == ERROR_WAIT && retries < MAX_WAIT_RETRIES) { -- useconds_t delay_us = (1<version.jtag >= 28) - flags |= STLINK_F_HAS_AP_INIT; - -+ /* API required to return proper error code on close AP from J29 */ -+ if (h->version.jtag >= 29) -+ flags |= STLINK_F_FIX_CLOSE_AP; -+ - /* Banked regs (DPv1 & DPv2) support from V2J32 */ - /* API to read memory without address increment from V2J32 */ - /* Memory R/W supports CSW from V2J32 */ -@@ -1080,6 +1086,9 @@ static int stlink_usb_version(void *handle) - /* API required to init AP before any AP access */ - flags |= STLINK_F_HAS_AP_INIT; - -+ /* API required to return proper error code on close AP */ -+ flags |= STLINK_F_FIX_CLOSE_AP; -+ - /* Banked regs (DPv1 & DPv2) support from V3J2 */ - /* API to read memory without address increment from V3J2 */ - /* Memory R/W supports CSW from V3J2 */ -@@ -3121,6 +3130,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) - h->max_mem_packet = (1 << 10); - - uint8_t buffer[4]; -+ stlink_usb_open_ap(h, STLINK_HLA_AP_NUM); - err = stlink_usb_read_mem32(h, STLINK_HLA_AP_NUM, STLINK_HLA_CSW, CPUID, 4, buffer); - if (err == ERROR_OK) { - uint32_t cpuid = le_to_h_u32(buffer); -@@ -3225,7 +3235,12 @@ static int stlink_usb_close_access_port(void *handle, unsigned char ap_num) - h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_CLOSE_AP_DBG; - h->cmdbuf[h->cmdidx++] = ap_num; - -- return stlink_usb_xfer_errcheck(handle, h->databuf, 2); -+ /* ignore incorrectly returned error on bogus FW */ -+ if (h->version.flags & STLINK_F_FIX_CLOSE_AP) -+ return stlink_usb_xfer_errcheck(handle, h->databuf, 2); -+ else -+ return stlink_usb_xfer_noerrcheck(handle, h->databuf, 2); -+ - } - - /** */ -@@ -3343,13 +3358,13 @@ static int stlink_dap_get_and_clear_error(void) - return retval; - } - --/** */ --static int stlink_dap_open_ap(unsigned short apsel) -+static int stlink_usb_open_ap(void *handle, unsigned short apsel) - { -+ struct stlink_usb_handle_s *h = handle; - int retval; - - /* nothing to do on old versions */ -- if (!(stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT)) -+ if (!(h->version.flags & STLINK_F_HAS_AP_INIT)) - return ERROR_OK; - - if (apsel > DP_APSEL_MAX) -@@ -3358,7 +3373,7 @@ static int stlink_dap_open_ap(unsigned short apsel) - if (test_bit(apsel, opened_ap)) - return ERROR_OK; - -- retval = stlink_usb_init_access_port(stlink_dap_handle, apsel); -+ retval = stlink_usb_init_access_port(h, apsel); - if (retval != ERROR_OK) - return retval; - -@@ -3367,6 +3382,11 @@ static int stlink_dap_open_ap(unsigned short apsel) - return ERROR_OK; - } - -+static int stlink_dap_open_ap(unsigned short apsel) -+{ -+ return stlink_usb_open_ap(stlink_dap_handle, apsel); -+} -+ - /** */ - static int stlink_dap_closeall_ap(void) - { -diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c -index 0ca4fa4ee..3f2632b03 100644 ---- a/src/server/gdb_server.c -+++ b/src/server/gdb_server.c -@@ -3489,7 +3489,7 @@ static int gdb_target_start(struct target *target, const char *port) - if (NULL == gdb_service) - return -ENOMEM; - -- LOG_DEBUG("starting gdb server for %s on %s", target_name(target), port); -+ LOG_INFO("starting gdb server for %s on %s", target_name(target), port); - - gdb_service->target = target; - gdb_service->core[0] = -1; -diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c -index 9a1f2b16f..dbd8ee088 100644 ---- a/src/target/cortex_m.c -+++ b/src/target/cortex_m.c -@@ -710,11 +710,11 @@ static int cortex_m_soft_reset_halt(struct target *target) - uint32_t dcb_dhcsr = 0; - int retval, timeout = 0; - -- /* soft_reset_halt is deprecated on cortex_m as the same functionality -- * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset' -- * As this reset only used VC_CORERESET it would only ever reset the cortex_m -+ /* on single cortex_m MCU soft_reset_halt should be avoided as same functionality -+ * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'. -+ * As this reset only uses VC_CORERESET it would only ever reset the cortex_m - * core, not the peripherals */ -- LOG_WARNING("soft_reset_halt is deprecated, please use 'reset halt' instead."); -+ LOG_DEBUG("soft_reset_halt is discouraged, please use 'reset halt' instead."); - - /* Set C_DEBUGEN */ - retval = cortex_m_write_debug_halt_mask(target, 0, C_STEP | C_MASKINTS); -@@ -2231,6 +2231,19 @@ int cortex_m_examine(struct target *target) - armv7m->debug_ap->tar_autoincr_block = (1 << 10); - } - -+ /* Enable debug requests */ -+ retval = target_read_u32(target, DCB_DHCSR, &cortex_m->dcb_dhcsr); -+ if (retval != ERROR_OK) -+ return retval; -+ if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { -+ uint32_t dhcsr = (cortex_m->dcb_dhcsr | C_DEBUGEN) & ~(C_HALT | C_STEP | C_MASKINTS); -+ -+ retval = target_write_u32(target, DCB_DHCSR, DBGKEY | (dhcsr & 0x0000FFFFUL)); -+ if (retval != ERROR_OK) -+ return retval; -+ cortex_m->dcb_dhcsr = dhcsr; -+ } -+ - /* Configure trace modules */ - retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr); - if (retval != ERROR_OK) -diff --git a/src/target/startup.tcl b/src/target/startup.tcl -index 976cd2af5..164a0bad8 100644 ---- a/src/target/startup.tcl -+++ b/src/target/startup.tcl -@@ -205,7 +205,7 @@ proc init_target_events {} { - foreach t $targets { - set_default_target_event $t gdb-flash-erase-start "reset init" - set_default_target_event $t gdb-flash-write-end "reset halt" -- set_default_target_event $t gdb-attach "halt" -+ set_default_target_event $t gdb-attach "halt 1000" - } - } - -diff --git a/tcl/target/stm32mp15x.cfg b/tcl/target/stm32mp15x.cfg -index 7f0d19c4d..f2ba94eec 100644 ---- a/tcl/target/stm32mp15x.cfg -+++ b/tcl/target/stm32mp15x.cfg -@@ -114,7 +114,7 @@ $_CHIPNAME.ap2 configure -event reset-deassert-pre {dbgmcu_enable_debug} - $_CHIPNAME.cpu0 configure -event reset-deassert-pre {$::_CHIPNAME.cpu0 arp_examine} - $_CHIPNAME.cpu1 configure -event reset-deassert-pre {$::_CHIPNAME.cpu1 arp_examine allow-defer} - $_CHIPNAME.cpu0 configure -event reset-deassert-post {toggle_cpu0_dbg_claim0} --$_CHIPNAME.cm4 configure -event reset-deassert-post {$::_CHIPNAME.cm4 arp_examine;if {[$::_CHIPNAME.ap2 curstate] == "halted"} {$::_CHIPNAME.cm4 arp_halt}} -+$_CHIPNAME.cm4 configure -event reset-deassert-post {$::_CHIPNAME.cm4 arp_examine;if {[$::_CHIPNAME.ap2 curstate] == "halted"} {$::_CHIPNAME.cm4 arp_poll;$::_CHIPNAME.cm4 arp_poll;$::_CHIPNAME.cm4 arp_halt}} - $_CHIPNAME.ap1 configure -event examine-start {dap init} - $_CHIPNAME.ap2 configure -event examine-start {dbgmcu_enable_debug} - $_CHIPNAME.cpu0 configure -event examine-end {detect_cpu1} --- -2.26.2 - diff --git a/recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb b/recipes-devtools/openocd/openocd-stm32mp_0.11.0.bb similarity index 60% rename from recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb rename to recipes-devtools/openocd/openocd-stm32mp_0.11.0.bb index 54c98d2..753d11e 100644 --- a/recipes-devtools/openocd/openocd-stm32mp_0.10.0.bb +++ b/recipes-devtools/openocd/openocd-stm32mp_0.11.0.bb @@ -8,11 +8,10 @@ require openocd-stm32mp.inc SRC_URI_prepend = "git://repo.or.cz/openocd.git;name=openocd " SRCREV_FORMAT = "openocd" -SRCREV_openocd = "b5d2b1224fed3909aa3314339611ac5ac7ab0f82" +SRCREV_openocd = "a5e526d8575cf63fe11babec85c0798ac3f4ad74" -PV = "0.10.0-release.${SRCPV}" +PV = "0.11.0-rc2.${SRCPV}" SRC_URI += " \ - file://0001-M4-visible-rebase-on-b5d2b1224fed-fixes.patch \ - file://0002-fixes-for-gcc-10-build-macos-build-CM4-halt-stlink-J.patch \ + file://0001-rebase-on-v0.11.0-rc2.patch \ "