You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(75) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(70) |
Feb
(20) |
Mar
(52) |
Apr
(149) |
May
(387) |
Jun
(466) |
Jul
(133) |
Aug
(87) |
Sep
(122) |
Oct
(140) |
Nov
(185) |
Dec
(105) |
2010 |
Jan
(85) |
Feb
(45) |
Mar
(75) |
Apr
(17) |
May
(41) |
Jun
(52) |
Jul
(33) |
Aug
(29) |
Sep
(36) |
Oct
(15) |
Nov
(26) |
Dec
(34) |
2011 |
Jan
(26) |
Feb
(25) |
Mar
(26) |
Apr
(29) |
May
(20) |
Jun
(27) |
Jul
(15) |
Aug
(32) |
Sep
(13) |
Oct
(64) |
Nov
(60) |
Dec
(10) |
2012 |
Jan
(64) |
Feb
(63) |
Mar
(39) |
Apr
(43) |
May
(54) |
Jun
(11) |
Jul
(30) |
Aug
(45) |
Sep
(11) |
Oct
(70) |
Nov
(24) |
Dec
(23) |
2013 |
Jan
(17) |
Feb
(8) |
Mar
(35) |
Apr
(40) |
May
(20) |
Jun
(24) |
Jul
(36) |
Aug
(25) |
Sep
(42) |
Oct
(40) |
Nov
(9) |
Dec
(21) |
2014 |
Jan
(29) |
Feb
(24) |
Mar
(60) |
Apr
(22) |
May
(22) |
Jun
(46) |
Jul
(11) |
Aug
(23) |
Sep
(26) |
Oct
(10) |
Nov
(14) |
Dec
(2) |
2015 |
Jan
(28) |
Feb
(47) |
Mar
(33) |
Apr
(58) |
May
(5) |
Jun
(1) |
Jul
|
Aug
(8) |
Sep
(12) |
Oct
(25) |
Nov
(58) |
Dec
(21) |
2016 |
Jan
(12) |
Feb
(40) |
Mar
(2) |
Apr
(1) |
May
(67) |
Jun
(2) |
Jul
(5) |
Aug
(36) |
Sep
|
Oct
(24) |
Nov
(17) |
Dec
(50) |
2017 |
Jan
(14) |
Feb
(16) |
Mar
(2) |
Apr
(35) |
May
(14) |
Jun
(16) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
(19) |
Nov
|
Dec
(16) |
2018 |
Jan
(55) |
Feb
(11) |
Mar
(34) |
Apr
(14) |
May
(4) |
Jun
(20) |
Jul
(39) |
Aug
(16) |
Sep
(17) |
Oct
(16) |
Nov
(20) |
Dec
(30) |
2019 |
Jan
(29) |
Feb
(24) |
Mar
(37) |
Apr
(26) |
May
(19) |
Jun
(21) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(12) |
Nov
(12) |
Dec
(12) |
2020 |
Jan
(47) |
Feb
(36) |
Mar
(54) |
Apr
(44) |
May
(37) |
Jun
(19) |
Jul
(32) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(32) |
Dec
(11) |
2021 |
Jan
(14) |
Feb
(5) |
Mar
(40) |
Apr
(32) |
May
(42) |
Jun
(31) |
Jul
(29) |
Aug
(47) |
Sep
(38) |
Oct
(17) |
Nov
(74) |
Dec
(33) |
2022 |
Jan
(11) |
Feb
(15) |
Mar
(40) |
Apr
(21) |
May
(39) |
Jun
(44) |
Jul
(19) |
Aug
(46) |
Sep
(79) |
Oct
(35) |
Nov
(21) |
Dec
(15) |
2023 |
Jan
(56) |
Feb
(13) |
Mar
(43) |
Apr
(28) |
May
(60) |
Jun
(15) |
Jul
(29) |
Aug
(28) |
Sep
(32) |
Oct
(21) |
Nov
(42) |
Dec
(39) |
2024 |
Jan
(35) |
Feb
(17) |
Mar
(28) |
Apr
(7) |
May
(14) |
Jun
(35) |
Jul
(30) |
Aug
(35) |
Sep
(30) |
Oct
(28) |
Nov
(38) |
Dec
(18) |
2025 |
Jan
(21) |
Feb
(28) |
Mar
(36) |
Apr
(35) |
May
(34) |
Jun
(58) |
Jul
(9) |
Aug
(20) |
Sep
|
Oct
|
Nov
|
Dec
|
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-24 21:36:11
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 8f8fb0fa79742c5e6357e9a2a1609d0500d91293 (commit) from edb575800ae26b4088b71b7531ba3948351bd7a9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8f8fb0fa79742c5e6357e9a2a1609d0500d91293 Author: Kevin Burke <ke...@os...> Date: Fri Aug 6 11:56:13 2021 +0200 adiv6: add low level jtag transport swd and dap-direct are not implemented yet Split from change https://review.openocd.org/6077/ Change-Id: I6d73d8adf6a6090001c5d4771325fb1d63c45e3c Signed-off-by: Kevin Burke <ke...@os...> Signed-off-by: Daniel Goehring <dgo...@os...> Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6459 Tested-by: jenkins diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index 881b23f19..f977ca7c8 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -282,6 +282,14 @@ static int rshim_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t addr; int rc = ERROR_OK, tile; + if (is_adiv6(ap->dap)) { + static bool error_flagged; + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode"); + error_flagged = true; + return ERROR_FAIL; + } + switch (reg) { case ADIV5_MEM_AP_REG_CSW: *data = ap_csw; @@ -338,6 +346,14 @@ static int rshim_ap_q_write(struct adiv5_ap *ap, unsigned int reg, int rc = ERROR_OK, tile; uint32_t addr; + if (is_adiv6(ap->dap)) { + static bool error_flagged; + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode"); + error_flagged = true; + return ERROR_FAIL; + } + if (ap_bank != 0) { rshim_dap_retval = ERROR_FAIL; return ERROR_FAIL; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index ca2893ccc..8a9028bd1 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -4286,6 +4286,14 @@ static int stlink_dap_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *d uint32_t dummy; int retval; + if (is_adiv6(dap)) { + static bool error_flagged; + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by stlink dap-direct mode"); + error_flagged = true; + return ERROR_FAIL; + } + if (reg != ADIV5_AP_REG_IDR) { retval = stlink_dap_open_ap(ap->ap_num); if (retval != ERROR_OK) @@ -4304,6 +4312,14 @@ static int stlink_dap_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t d struct adiv5_dap *dap = ap->dap; int retval; + if (is_adiv6(dap)) { + static bool error_flagged; + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by stlink dap-direct mode"); + error_flagged = true; + return ERROR_FAIL; + } + retval = stlink_dap_open_ap(ap->ap_num); if (retval != ERROR_OK) return retval; diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 37019808f..810a5ab76 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -29,7 +29,7 @@ /** * @file * This file implements JTAG transport support for cores implementing - the ARM Debug Interface version 5 (ADIv5). + the ARM Debug Interface version 5 (ADIv5) and version 6 (ADIv6). */ #ifdef HAVE_CONFIG_H @@ -51,8 +51,10 @@ #define JTAG_DP_IDCODE 0xFE /* three-bit ACK values for DPACC and APACC reads */ -#define JTAG_ACK_OK_FAULT 0x2 -#define JTAG_ACK_WAIT 0x1 +#define JTAG_ACK_WAIT 0x1 /* ADIv5 and ADIv6 */ +#define JTAG_ACK_OK_FAULT 0x2 /* ADIv5 */ +#define JTAG_ACK_FAULT 0x2 /* ADIv6 */ +#define JTAG_ACK_OK 0x4 /* ADIV6 */ static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack); @@ -125,7 +127,7 @@ struct dap_cmd { uint8_t *invalue; uint8_t ack; uint32_t memaccess_tck; - uint32_t dp_select; + uint64_t dp_select; struct scan_field fields[2]; uint8_t out_addr_buf; @@ -143,14 +145,35 @@ struct dap_cmd_pool { static void log_dap_cmd(struct adiv5_dap *dap, const char *header, struct dap_cmd *el) { #ifdef DEBUG_WAIT + const char *ack; + switch (el->ack) { + case JTAG_ACK_WAIT: /* ADIv5 and ADIv6 */ + ack = "WAIT"; + break; + case JTAG_ACK_OK_FAULT: /* ADIv5, same value as JTAG_ACK_FAULT */ + /* case JTAG_ACK_FAULT: */ /* ADIv6 */ + if (is_adiv6(dap)) + ack = "FAULT"; + else + ack = "OK"; + break; + case JTAG_ACK_OK: /* ADIv6 */ + if (is_adiv6(dap)) { + ack = "OK"; + break; + } + /* fall-through */ + default: + ack = "INVAL"; + break; + } LOG_DEBUG("%s: %2s %6s %5s 0x%08x 0x%08x %2s", header, el->instr == JTAG_DP_APACC ? "AP" : "DP", dap_reg_name(dap, el->instr, el->reg_addr), el->rnw == DPAP_READ ? "READ" : "WRITE", buf_get_u32(el->outvalue_buf, 0, 32), buf_get_u32(el->invalue, 0, 32), - el->ack == JTAG_ACK_OK_FAULT ? "OK" : - (el->ack == JTAG_ACK_WAIT ? "WAIT" : "INVAL")); + ack); #endif } @@ -264,7 +287,7 @@ static int adi_jtag_dp_scan_cmd(struct adiv5_dap *dap, struct dap_cmd *cmd, uint /* Add specified number of tck clocks after starting memory bus * access, giving the hardware time to complete the access. * They provide more time for the (MEM) AP to complete the read ... - * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. + * See "Minimum Response Time" for JTAG-DP, in the ADIv5/ADIv6 spec. */ if (cmd->instr == JTAG_DP_APACC) { if ((cmd->reg_addr == MEM_AP_REG_DRW(dap) || @@ -289,7 +312,7 @@ static int adi_jtag_dp_scan_cmd_sync(struct adiv5_dap *dap, struct dap_cmd *cmd, /** * Scan DPACC or APACC using target ordered uint8_t buffers. No endianness - * conversions are performed. See section 4.4.3 of the ADIv5 spec, which + * conversions are performed. See section 4.4.3 of the ADIv5/ADIv6 spec, which * discusses operations which access these registers. * * Note that only one scan is performed. If rnw is set, a separate scan @@ -335,13 +358,27 @@ static int adi_jtag_dp_scan(struct adiv5_dap *dap, * must be different). */ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, - uint8_t instr, uint8_t reg_addr, uint8_t rnw, + uint8_t instr, uint16_t reg_addr, uint8_t rnw, uint32_t outvalue, uint32_t *invalue, uint32_t memaccess_tck, uint8_t *ack) { uint8_t out_value_buf[4]; int retval; - + uint64_t sel = (reg_addr >> 4) & 0xf; + + /* No need to change SELECT or RDBUFF as they are not banked */ + if (instr == JTAG_DP_DPACC && reg_addr != DP_SELECT && reg_addr != DP_RDBUFF && + sel != (dap->select & 0xf)) { + if (dap->select != DP_SELECT_INVALID) + sel |= dap->select & ~0xfull; + dap->select = sel; + LOG_DEBUG("DP BANKSEL: %x", (uint32_t)sel); + buf_set_u32(out_value_buf, 0, 32, (uint32_t)sel); + retval = adi_jtag_dp_scan(dap, JTAG_DP_DPACC, + DP_SELECT, DPAP_WRITE, out_value_buf, NULL, 0, NULL); + if (retval != ERROR_OK) + return retval; + } buf_set_u32(out_value_buf, 0, 32, outvalue); retval = adi_jtag_dp_scan(dap, instr, reg_addr, rnw, @@ -409,7 +446,12 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) /* skip all completed transactions up to the first WAIT */ list_for_each_entry(el, &dap->cmd_journal, lh) { - if (el->ack == JTAG_ACK_OK_FAULT) { + /* + * JTAG_ACK_OK_FAULT (ADIv5) and JTAG_ACK_FAULT (ADIv6) are equal so + * the following statement is checking to see if an acknowledgment of + * OK or FAULT is generated for ADIv5 or ADIv6 + */ + if (el->ack == JTAG_ACK_OK_FAULT || (is_adiv6(dap) && el->ack == JTAG_ACK_OK)) { log_dap_cmd(dap, "LOG", el); } else if (el->ack == JTAG_ACK_WAIT) { found_wait = 1; @@ -434,7 +476,8 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) * the result of the previous READ */ tmp = el; list_for_each_entry_from(tmp, &dap->cmd_journal, lh) { - if (tmp->ack == JTAG_ACK_OK_FAULT) { + /* The following check covers OK and FAULT ACKs for both ADIv5 and ADIv6 */ + if (tmp->ack == JTAG_ACK_OK_FAULT || (is_adiv6(dap) && tmp->ack == JTAG_ACK_OK)) { /* recover the read value */ log_dap_cmd(dap, "FND", tmp); if (el->invalue != el->invalue_buf) { @@ -469,7 +512,8 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) retval = adi_jtag_dp_scan_cmd_sync(dap, tmp, NULL); if (retval != ERROR_OK) break; - if (tmp->ack == JTAG_ACK_OK_FAULT) { + /* The following check covers OK and FAULT ACKs for both ADIv5 and ADIv6 */ + if (tmp->ack == JTAG_ACK_OK_FAULT || (is_adiv6(dap) && tmp->ack == JTAG_ACK_OK)) { log_dap_cmd(dap, "FND", tmp); if (el->invalue != el->invalue_buf) { uint32_t invalue = le_to_h_u32(tmp->invalue); @@ -488,7 +532,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) if (retval == ERROR_OK) { /* timeout happened */ - if (tmp->ack != JTAG_ACK_OK_FAULT) { + if (tmp->ack == JTAG_ACK_WAIT) { LOG_ERROR("Timeout during WAIT recovery"); dap->select = DP_SELECT_INVALID; jtag_ap_q_abort(dap, NULL); @@ -554,7 +598,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) if (retval != ERROR_OK) break; log_dap_cmd(dap, "REC", el); - if (el->ack == JTAG_ACK_OK_FAULT) { + if (el->ack == JTAG_ACK_OK_FAULT || (is_adiv6(dap) && el->ack == JTAG_ACK_OK)) { if (el->invalue != el->invalue_buf) { uint32_t invalue = le_to_h_u32(el->invalue); memcpy(el->invalue, &invalue, sizeof(uint32_t)); @@ -577,7 +621,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) } while (timeval_ms() - time_now < 1000); if (retval == ERROR_OK) { - if (el->ack != JTAG_ACK_OK_FAULT) { + if (el->ack == JTAG_ACK_WAIT) { LOG_ERROR("Timeout during WAIT recovery"); dap->select = DP_SELECT_INVALID; jtag_ap_q_abort(dap, NULL); @@ -715,15 +759,38 @@ static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, /** Select the AP register bank matching bits 7:4 of reg. */ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) { + int retval; struct adiv5_dap *dap = ap->dap; - uint32_t sel = ((uint32_t)ap->ap_num << 24) | (reg & 0x000000F0); + uint64_t sel; + + if (is_adiv6(dap)) { + sel = ap->ap_num | (reg & 0x00000FF0); + if (sel == (dap->select & ~0xfull)) + return ERROR_OK; + + if (dap->select != DP_SELECT_INVALID) + sel |= dap->select & 0xf; + dap->select = sel; + LOG_DEBUG("AP BANKSEL: %" PRIx64, sel); + + retval = jtag_dp_q_write(dap, DP_SELECT, (uint32_t)sel); + if (retval != ERROR_OK) + return retval; + + if (dap->asize > 32) + return jtag_dp_q_write(dap, DP_SELECT1, (uint32_t)(sel >> 32)); + return ERROR_OK; + } + + /* ADIv5 */ + sel = (ap->ap_num << 24) | (reg & 0x000000F0); if (sel == dap->select) return ERROR_OK; dap->select = sel; - return jtag_dp_q_write(dap, DP_SELECT, sel); + return jtag_dp_q_write(dap, DP_SELECT, (uint32_t)sel); } static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg, diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 683504243..6ef138aa7 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -497,6 +497,14 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, const struct swd_driver *swd = adiv5_dap_swd_driver(dap); assert(swd); + if (is_adiv6(dap)) { + static bool error_flagged; + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported in SWD mode"); + error_flagged = true; + return ERROR_FAIL; + } + int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; @@ -522,6 +530,14 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, const struct swd_driver *swd = adiv5_dap_swd_driver(dap); assert(swd); + if (is_adiv6(dap)) { + static bool error_flagged; + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported in SWD mode"); + error_flagged = true; + return ERROR_FAIL; + } + int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 4cba62ae1..4eab35d6e 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -348,7 +348,7 @@ struct adiv5_dap { * Cache for DP_SELECT register. A value of DP_SELECT_INVALID * indicates no cached value and forces rewrite of the register. */ - uint32_t select; + uint64_t select; /* information about current pending SWjDP-AHBAP transaction */ uint8_t ack; ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/rshim.c | 16 +++++++ src/jtag/drivers/stlink_usb.c | 16 +++++++ src/target/adi_v5_jtag.c | 103 ++++++++++++++++++++++++++++++++++-------- src/target/adi_v5_swd.c | 16 +++++++ src/target/arm_adi_v5.h | 2 +- 5 files changed, 134 insertions(+), 19 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-24 21:35:52
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via edb575800ae26b4088b71b7531ba3948351bd7a9 (commit) from 513aba19302cc6ad7bdb33390622fd5821571e8f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit edb575800ae26b4088b71b7531ba3948351bd7a9 Author: Antonio Borneo <bor...@gm...> Date: Fri Aug 6 23:37:23 2021 +0200 adi_v5_jtag: clear sticky overrun error By accessing invalid AP in JTAG mode, it's possible to trigger the error: JTAG-DP STICKY ERROR After that the sticky error is never cleared and the whole DAP gets not anymore accessible. Clean-up the sticky error once detected. Change-Id: I8b07263b30f9e46645f0c29084b8f1626e241f45 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6430 Tested-by: jenkins diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 9355b84c3..37019808f 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -633,10 +633,10 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap) if (ctrlstat & SSTICKYORUN) LOG_DEBUG("JTAG-DP STICKY OVERRUN"); - /* Clear Sticky Error Bits */ + /* Clear Sticky Error and Sticky Overrun Bits */ retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, DP_CTRL_STAT, DPAP_WRITE, - dap->dp_ctrl_stat | SSTICKYERR, NULL, 0); + dap->dp_ctrl_stat | SSTICKYERR | SSTICKYORUN, NULL, 0); if (retval != ERROR_OK) goto done; ----------------------------------------------------------------------- Summary of changes: src/target/adi_v5_jtag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-24 21:35:36
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 513aba19302cc6ad7bdb33390622fd5821571e8f (commit) from a6e4aabc66a2335c1bc0da1640df4eefd9a4d604 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 513aba19302cc6ad7bdb33390622fd5821571e8f Author: Kevin Burke <ke...@os...> Date: Sat Aug 21 23:59:38 2021 +0200 adiv6: read ROM Table address size Required for parsing ADIv6 ROM tables. Split from change https://review.openocd.org/6077/ Change-Id: I849543b7b4a4455b10bd9fc7da38a37849d71700 Signed-off-by: Kevin Burke <ke...@os...> Signed-off-by: Daniel Goehring <dgo...@os...> Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6458 Tested-by: jenkins diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 7706fc935..4cba62ae1 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -395,6 +395,9 @@ struct adiv5_dap { /** Indicates ADI version (5, 6 or 0 for unknown) being used */ unsigned int adi_version; + + /* ADIv6 only field indicating ROM Table address size */ + unsigned int asize; }; /** diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 59d577e7f..d2e3f9997 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -140,6 +140,23 @@ static int dap_init_all(void) retval = dap->ops->connect(dap); if (retval != ERROR_OK) return retval; + + /* see if address size of ROM Table is greater than 32-bits */ + if (is_adiv6(dap)) { + uint32_t dpidr1; + + retval = dap->ops->queue_dp_read(dap, DP_DPIDR1, &dpidr1); + if (retval != ERROR_OK) { + LOG_ERROR("DAP read of DPIDR1 failed..."); + return retval; + } + retval = dap_run(dap); + if (retval != ERROR_OK) { + LOG_ERROR("DAP read of DPIDR1 failed..."); + return retval; + } + dap->asize = dpidr1 & DP_DPIDR1_ASIZE_MASK; + } } return ERROR_OK; ----------------------------------------------------------------------- Summary of changes: src/target/arm_adi_v5.h | 3 +++ src/target/arm_dap.c | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-24 21:35:17
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via a6e4aabc66a2335c1bc0da1640df4eefd9a4d604 (commit) from 1fe82f9f1db62f0ab59471e1cdaf02643bf7a66c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a6e4aabc66a2335c1bc0da1640df4eefd9a4d604 Author: Kevin Burke <ke...@os...> Date: Sat Aug 21 19:12:01 2021 +0200 adiv6: re-organize mem_ap registers definition ADIv5 MEM-AP registers are a subset of ADIv6 MEM-AP registers and are located at different offset. To prepare for introducing ADIv6, add 'struct adiv5_dap *' as argument to ADIv5 registers macro. Check the ADI version and use the proper address. Both adapter drivers rshim and stlink are ADIv5 only, so let them use the ADIv5 macros only. Split from change https://review.openocd.org/6077/ Change-Id: Ib861ddcdab74637b2082cc9f2612dea0007d77b1 Signed-off-by: Kevin Burke <ke...@os...> Signed-off-by: Daniel Goehring <dgo...@os...> Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6457 Tested-by: jenkins diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index 246e931c2..881b23f19 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -283,35 +283,35 @@ static int rshim_ap_q_read(struct adiv5_ap *ap, unsigned int reg, int rc = ERROR_OK, tile; switch (reg) { - case MEM_AP_REG_CSW: + case ADIV5_MEM_AP_REG_CSW: *data = ap_csw; break; - case MEM_AP_REG_CFG: + case ADIV5_MEM_AP_REG_CFG: *data = 0; break; - case MEM_AP_REG_BASE: + case ADIV5_MEM_AP_REG_BASE: *data = RSH_CS_ROM_BASE; break; - case AP_REG_IDR: + case ADIV5_AP_REG_IDR: if (ap->ap_num == 0) *data = APB_AP_IDR; else *data = 0; break; - case MEM_AP_REG_BD0: - case MEM_AP_REG_BD1: - case MEM_AP_REG_BD2: - case MEM_AP_REG_BD3: + case ADIV5_MEM_AP_REG_BD0: + case ADIV5_MEM_AP_REG_BD1: + case ADIV5_MEM_AP_REG_BD2: + case ADIV5_MEM_AP_REG_BD3: addr = (ap_tar & ~0xf) + (reg & 0x0C); ap_addr_2_tile(&tile, &addr); rc = coresight_read(tile, addr, data); break; - case MEM_AP_REG_DRW: + case ADIV5_MEM_AP_REG_DRW: addr = (ap_tar & ~0x3) + ap_tar_inc; ap_addr_2_tile(&tile, &addr); rc = coresight_read(tile, addr, data); @@ -344,25 +344,25 @@ static int rshim_ap_q_write(struct adiv5_ap *ap, unsigned int reg, } switch (reg) { - case MEM_AP_REG_CSW: + case ADIV5_MEM_AP_REG_CSW: ap_csw = data; break; - case MEM_AP_REG_TAR: + case ADIV5_MEM_AP_REG_TAR: ap_tar = data; ap_tar_inc = 0; break; - case MEM_AP_REG_BD0: - case MEM_AP_REG_BD1: - case MEM_AP_REG_BD2: - case MEM_AP_REG_BD3: + case ADIV5_MEM_AP_REG_BD0: + case ADIV5_MEM_AP_REG_BD1: + case ADIV5_MEM_AP_REG_BD2: + case ADIV5_MEM_AP_REG_BD3: addr = (ap_tar & ~0xf) + (reg & 0x0C); ap_addr_2_tile(&tile, &addr); rc = coresight_write(tile, addr, data); break; - case MEM_AP_REG_DRW: + case ADIV5_MEM_AP_REG_DRW: ap_drw = data; addr = (ap_tar & ~0x3) + ap_tar_inc; ap_addr_2_tile(&tile, &addr); diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index bb2c8174a..ca2893ccc 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -4286,7 +4286,7 @@ static int stlink_dap_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *d uint32_t dummy; int retval; - if (reg != AP_REG_IDR) { + if (reg != ADIV5_AP_REG_IDR) { retval = stlink_dap_open_ap(ap->ap_num); if (retval != ERROR_OK) return retval; @@ -4591,7 +4591,7 @@ static void stlink_dap_run_internal(struct adiv5_dap *dap) break; case CMD_AP_WRITE: /* ignore increment packed, not supported */ - if (q->ap_w.reg == MEM_AP_REG_CSW) + if (q->ap_w.reg == ADIV5_MEM_AP_REG_CSW) q->ap_w.data &= ~CSW_ADDRINC_PACKED; retval = stlink_dap_ap_write(q->ap_w.ap, q->ap_w.reg, q->ap_w.data); break; @@ -4736,18 +4736,18 @@ static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, /* test STLINK_F_HAS_CSW implicitly tests STLINK_F_HAS_MEM_16BIT, STLINK_F_HAS_MEM_RD_NO_INC * and STLINK_F_HAS_RW_MISC */ if ((stlink_dap_handle->version.flags & STLINK_F_HAS_CSW) && - (reg == MEM_AP_REG_DRW || reg == MEM_AP_REG_BD0 || reg == MEM_AP_REG_BD1 || - reg == MEM_AP_REG_BD2 || reg == MEM_AP_REG_BD3)) { + (reg == ADIV5_MEM_AP_REG_DRW || reg == ADIV5_MEM_AP_REG_BD0 || reg == ADIV5_MEM_AP_REG_BD1 || + reg == ADIV5_MEM_AP_REG_BD2 || reg == ADIV5_MEM_AP_REG_BD3)) { /* de-queue previous write-TAR */ struct dap_queue *prev_q = q - 1; - if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_TAR) { + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == ADIV5_MEM_AP_REG_TAR) { stlink_dap_handle->queue_index = i; i--; q = prev_q; prev_q--; } /* de-queue previous write-CSW if it didn't changed ap->csw_default */ - if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW && + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == ADIV5_MEM_AP_REG_CSW && !prev_q->ap_w.changes_csw_default) { stlink_dap_handle->queue_index = i; q = prev_q; @@ -4769,7 +4769,7 @@ static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, return ERROR_FAIL; } - q->mem_ap.addr = (reg == MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c)); + q->mem_ap.addr = (reg == ADIV5_MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c)); q->mem_ap.ap = ap; q->mem_ap.p_data = data; q->mem_ap.csw = ap->csw_default; @@ -4802,18 +4802,18 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, /* test STLINK_F_HAS_CSW implicitly tests STLINK_F_HAS_MEM_16BIT, STLINK_F_HAS_MEM_WR_NO_INC * and STLINK_F_HAS_RW_MISC */ if ((stlink_dap_handle->version.flags & STLINK_F_HAS_CSW) && - (reg == MEM_AP_REG_DRW || reg == MEM_AP_REG_BD0 || reg == MEM_AP_REG_BD1 || - reg == MEM_AP_REG_BD2 || reg == MEM_AP_REG_BD3)) { + (reg == ADIV5_MEM_AP_REG_DRW || reg == ADIV5_MEM_AP_REG_BD0 || reg == ADIV5_MEM_AP_REG_BD1 || + reg == ADIV5_MEM_AP_REG_BD2 || reg == ADIV5_MEM_AP_REG_BD3)) { /* de-queue previous write-TAR */ struct dap_queue *prev_q = q - 1; - if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_TAR) { + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == ADIV5_MEM_AP_REG_TAR) { stlink_dap_handle->queue_index = i; i--; q = prev_q; prev_q--; } /* de-queue previous write-CSW if it didn't changed ap->csw_default */ - if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW && + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == ADIV5_MEM_AP_REG_CSW && !prev_q->ap_w.changes_csw_default) { stlink_dap_handle->queue_index = i; q = prev_q; @@ -4835,7 +4835,7 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, return ERROR_FAIL; } - q->mem_ap.addr = (reg == MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c)); + q->mem_ap.addr = (reg == ADIV5_MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c)); q->mem_ap.ap = ap; q->mem_ap.data = data; q->mem_ap.csw = ap->csw_default; @@ -4848,7 +4848,7 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, q->ap_w.reg = reg; q->ap_w.ap = ap; q->ap_w.data = data; - if (reg == MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap->ap_num]) { + if (reg == ADIV5_MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap->ap_num]) { q->ap_w.changes_csw_default = true; last_csw_default[ap->ap_num] = ap->csw_default; } else { diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 94ee8cf41..9355b84c3 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -10,6 +10,8 @@ * * Copyright (C) 2009-2010 by David Brownell * + * Copyright (C) 2020-2021, Ampere Computing LLC * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -55,7 +57,7 @@ static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack); #ifdef DEBUG_WAIT -static const char *dap_reg_name(int instr, int reg_addr) +static const char *dap_reg_name(struct adiv5_dap *dap, uint8_t instr, uint16_t reg_addr) { char *reg_name = "UNK"; @@ -83,41 +85,32 @@ static const char *dap_reg_name(int instr, int reg_addr) } if (instr == JTAG_DP_APACC) { - switch (reg_addr) { - case MEM_AP_REG_CSW: + if (reg_addr == MEM_AP_REG_CSW(dap)) reg_name = "CSW"; - break; - case MEM_AP_REG_TAR: + else if (reg_addr == MEM_AP_REG_TAR(dap)) reg_name = "TAR"; - break; - case MEM_AP_REG_DRW: + else if (reg_addr == MEM_AP_REG_TAR64(dap)) + reg_name = "TAR64"; + else if (reg_addr == MEM_AP_REG_DRW(dap)) reg_name = "DRW"; - break; - case MEM_AP_REG_BD0: + else if (reg_addr == MEM_AP_REG_BD0(dap)) reg_name = "BD0"; - break; - case MEM_AP_REG_BD1: + else if (reg_addr == MEM_AP_REG_BD1(dap)) reg_name = "BD1"; - break; - case MEM_AP_REG_BD2: + else if (reg_addr == MEM_AP_REG_BD2(dap)) reg_name = "BD2"; - break; - case MEM_AP_REG_BD3: + else if (reg_addr == MEM_AP_REG_BD3(dap)) reg_name = "BD3"; - break; - case MEM_AP_REG_CFG: + else if (reg_addr == MEM_AP_REG_CFG(dap)) reg_name = "CFG"; - break; - case MEM_AP_REG_BASE: + else if (reg_addr == MEM_AP_REG_BASE(dap)) reg_name = "BASE"; - break; - case AP_REG_IDR: + else if (reg_addr == MEM_AP_REG_BASE64(dap)) + reg_name = "BASE64"; + else if (reg_addr == AP_REG_IDR(dap)) reg_name = "IDR"; - break; - default: + else reg_name = "UNK"; - break; - } } return reg_name; @@ -127,7 +120,7 @@ static const char *dap_reg_name(int instr, int reg_addr) struct dap_cmd { struct list_head lh; uint8_t instr; - uint8_t reg_addr; + uint16_t reg_addr; uint8_t rnw; uint8_t *invalue; uint8_t ack; @@ -147,12 +140,12 @@ struct dap_cmd_pool { struct dap_cmd cmd; }; -static void log_dap_cmd(const char *header, struct dap_cmd *el) +static void log_dap_cmd(struct adiv5_dap *dap, const char *header, struct dap_cmd *el) { #ifdef DEBUG_WAIT LOG_DEBUG("%s: %2s %6s %5s 0x%08x 0x%08x %2s", header, el->instr == JTAG_DP_APACC ? "AP" : "DP", - dap_reg_name(el->instr, el->reg_addr), + dap_reg_name(dap, el->instr, el->reg_addr), el->rnw == DPAP_READ ? "READ" : "WRITE", buf_get_u32(el->outvalue_buf, 0, 32), buf_get_u32(el->invalue, 0, 32), @@ -170,7 +163,7 @@ static int jtag_limit_queue_size(struct adiv5_dap *dap) } static struct dap_cmd *dap_cmd_new(struct adiv5_dap *dap, uint8_t instr, - uint8_t reg_addr, uint8_t rnw, + uint16_t reg_addr, uint8_t rnw, uint8_t *outvalue, uint8_t *invalue, uint32_t memaccess_tck) { @@ -274,9 +267,9 @@ static int adi_jtag_dp_scan_cmd(struct adiv5_dap *dap, struct dap_cmd *cmd, uint * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. */ if (cmd->instr == JTAG_DP_APACC) { - if (((cmd->reg_addr == MEM_AP_REG_DRW) - || ((cmd->reg_addr & 0xF0) == MEM_AP_REG_BD0)) - && (cmd->memaccess_tck != 0)) + if ((cmd->reg_addr == MEM_AP_REG_DRW(dap) || + (cmd->reg_addr & 0xFF0) == MEM_AP_REG_BD0(dap)) && + cmd->memaccess_tck != 0) jtag_add_runtest(cmd->memaccess_tck, TAP_IDLE); } @@ -315,7 +308,7 @@ static int adi_jtag_dp_scan_cmd_sync(struct adiv5_dap *dap, struct dap_cmd *cmd, */ static int adi_jtag_dp_scan(struct adiv5_dap *dap, - uint8_t instr, uint8_t reg_addr, uint8_t rnw, + uint8_t instr, uint16_t reg_addr, uint8_t rnw, uint8_t *outvalue, uint8_t *invalue, uint32_t memaccess_tck, uint8_t *ack) { @@ -377,7 +370,7 @@ static int adi_jtag_finish_read(struct adiv5_dap *dap) } static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap, - uint8_t instr, uint8_t reg_addr, uint8_t rnw, + uint8_t instr, uint16_t reg_addr, uint8_t rnw, uint32_t outvalue, uint32_t *invalue, uint32_t memaccess_tck) { int retval; @@ -417,13 +410,13 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) /* skip all completed transactions up to the first WAIT */ list_for_each_entry(el, &dap->cmd_journal, lh) { if (el->ack == JTAG_ACK_OK_FAULT) { - log_dap_cmd("LOG", el); + log_dap_cmd(dap, "LOG", el); } else if (el->ack == JTAG_ACK_WAIT) { found_wait = 1; break; } else { LOG_ERROR("Invalid ACK (%1x) in DAP response", el->ack); - log_dap_cmd("ERR", el); + log_dap_cmd(dap, "ERR", el); retval = ERROR_JTAG_DEVICE_ERROR; goto done; } @@ -436,14 +429,14 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) if (found_wait && el != list_first_entry(&dap->cmd_journal, struct dap_cmd, lh)) { prev = list_entry(el->lh.prev, struct dap_cmd, lh); if (prev->rnw == DPAP_READ) { - log_dap_cmd("PND", prev); + log_dap_cmd(dap, "PND", prev); /* search for the next OK transaction, it contains * the result of the previous READ */ tmp = el; list_for_each_entry_from(tmp, &dap->cmd_journal, lh) { if (tmp->ack == JTAG_ACK_OK_FAULT) { /* recover the read value */ - log_dap_cmd("FND", tmp); + log_dap_cmd(dap, "FND", tmp); if (el->invalue != el->invalue_buf) { uint32_t invalue = le_to_h_u32(tmp->invalue); memcpy(el->invalue, &invalue, sizeof(uint32_t)); @@ -454,7 +447,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) } if (prev) { - log_dap_cmd("LST", el); + log_dap_cmd(dap, "LST", el); /* * At this point we're sure that no previous @@ -477,7 +470,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) if (retval != ERROR_OK) break; if (tmp->ack == JTAG_ACK_OK_FAULT) { - log_dap_cmd("FND", tmp); + log_dap_cmd(dap, "FND", tmp); if (el->invalue != el->invalue_buf) { uint32_t invalue = le_to_h_u32(tmp->invalue); memcpy(el->invalue, &invalue, sizeof(uint32_t)); @@ -486,7 +479,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) } if (tmp->ack != JTAG_ACK_WAIT) { LOG_ERROR("Invalid ACK (%1x) in DAP response", tmp->ack); - log_dap_cmd("ERR", tmp); + log_dap_cmd(dap, "ERR", tmp); retval = ERROR_JTAG_DEVICE_ERROR; break; } @@ -523,7 +516,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) /* move all remaining transactions over to the replay list */ list_for_each_entry_safe_from(el, tmp, &dap->cmd_journal, lh) { - log_dap_cmd("REP", el); + log_dap_cmd(dap, "REP", el); list_move_tail(&el->lh, &replay_list); } @@ -560,7 +553,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) retval = adi_jtag_dp_scan_cmd_sync(dap, el, NULL); if (retval != ERROR_OK) break; - log_dap_cmd("REC", el); + log_dap_cmd(dap, "REC", el); if (el->ack == JTAG_ACK_OK_FAULT) { if (el->invalue != el->invalue_buf) { uint32_t invalue = le_to_h_u32(el->invalue); @@ -570,7 +563,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) } if (el->ack != JTAG_ACK_WAIT) { LOG_ERROR("Invalid ACK (%1x) in DAP response", el->ack); - log_dap_cmd("ERR", el); + log_dap_cmd(dap, "ERR", el); retval = ERROR_JTAG_DEVICE_ERROR; break; } diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 7dd523ef0..a74e47f79 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -107,7 +107,7 @@ static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) if (csw != ap->csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ - int retval = dap_queue_ap_write(ap, MEM_AP_REG_CSW, csw); + int retval = dap_queue_ap_write(ap, MEM_AP_REG_CSW(ap->dap), csw); if (retval != ERROR_OK) { ap->csw_value = 0; return retval; @@ -121,11 +121,11 @@ static int mem_ap_setup_tar(struct adiv5_ap *ap, target_addr_t tar) { if (!ap->tar_valid || tar != ap->tar_value) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ - int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR, (uint32_t)(tar & 0xffffffffUL)); + int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR(ap->dap), (uint32_t)(tar & 0xffffffffUL)); if (retval == ERROR_OK && is_64bit_ap(ap)) { /* See if bits 63:32 of tar is different from last setting */ if ((ap->tar_value >> 32) != (tar >> 32)) - retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR64, (uint32_t)(tar >> 32)); + retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR64(ap->dap), (uint32_t)(tar >> 32)); } if (retval != ERROR_OK) { ap->tar_valid = false; @@ -142,9 +142,9 @@ static int mem_ap_read_tar(struct adiv5_ap *ap, target_addr_t *tar) uint32_t lower; uint32_t upper = 0; - int retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR, &lower); + int retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR(ap->dap), &lower); if (retval == ERROR_OK && is_64bit_ap(ap)) - retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR64, &upper); + retval = dap_queue_ap_read(ap, MEM_AP_REG_TAR64(ap->dap), &upper); if (retval != ERROR_OK) { ap->tar_valid = false; @@ -252,7 +252,7 @@ int mem_ap_read_u32(struct adiv5_ap *ap, target_addr_t address, if (retval != ERROR_OK) return retval; - return dap_queue_ap_read(ap, MEM_AP_REG_BD0 | (address & 0xC), value); + return dap_queue_ap_read(ap, MEM_AP_REG_BD0(ap->dap) | (address & 0xC), value); } /** @@ -304,7 +304,7 @@ int mem_ap_write_u32(struct adiv5_ap *ap, target_addr_t address, if (retval != ERROR_OK) return retval; - return dap_queue_ap_write(ap, MEM_AP_REG_BD0 | (address & 0xC), + return dap_queue_ap_write(ap, MEM_AP_REG_BD0(ap->dap) | (address & 0xC), value); } @@ -436,7 +436,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz nbytes -= this_size; - retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW, outvalue); + retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue); if (retval != ERROR_OK) break; @@ -533,7 +533,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint if (retval != ERROR_OK) break; - retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW, read_ptr++); + retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++); if (retval != ERROR_OK) break; @@ -780,7 +780,7 @@ int mem_ap_init(struct adiv5_ap *ap) /* Set ap->cfg_reg before calling mem_ap_setup_transfer(). */ /* mem_ap_setup_transfer() needs to know if the MEM_AP supports LPAE. */ - retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &cfg); + retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG(dap), &cfg); if (retval != ERROR_OK) return retval; @@ -795,7 +795,7 @@ int mem_ap_init(struct adiv5_ap *ap) if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW, &csw); + retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(dap), &csw); if (retval != ERROR_OK) return retval; @@ -983,7 +983,7 @@ int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adi /* read the IDR register of the Access Port */ uint32_t id_val = 0; - int retval = dap_queue_ap_read(ap, AP_REG_IDR, &id_val); + int retval = dap_queue_ap_read(ap, AP_REG_IDR(dap), &id_val); if (retval != ERROR_OK) { dap_put_ap(ap); return retval; @@ -1074,19 +1074,19 @@ static int dap_get_debugbase(struct adiv5_ap *ap, uint32_t baseptr_upper, baseptr_lower; if (ap->cfg_reg == MEM_AP_REG_CFG_INVALID) { - retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &ap->cfg_reg); + retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG(dap), &ap->cfg_reg); if (retval != ERROR_OK) return retval; } - retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseptr_lower); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE(dap), &baseptr_lower); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(ap, AP_REG_IDR, apid); + retval = dap_queue_ap_read(ap, AP_REG_IDR(dap), apid); if (retval != ERROR_OK) return retval; /* MEM_AP_REG_BASE64 is defined as 'RES0'; can be read and then ignored on 32 bits AP */ if (ap->cfg_reg == MEM_AP_REG_CFG_INVALID || is_64bit_ap(ap)) { - retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseptr_upper); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64(dap), &baseptr_upper); if (retval != ERROR_OK) return retval; } @@ -2230,14 +2230,14 @@ COMMAND_HANDLER(dap_baseaddr_command) return ERROR_FAIL; } - retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseaddr_lower); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE(dap), &baseaddr_lower); if (retval == ERROR_OK && ap->cfg_reg == MEM_AP_REG_CFG_INVALID) - retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &ap->cfg_reg); + retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG(dap), &ap->cfg_reg); if (retval == ERROR_OK && (ap->cfg_reg == MEM_AP_REG_CFG_INVALID || is_64bit_ap(ap))) { /* MEM_AP_REG_BASE64 is defined as 'RES0'; can be read and then ignored on 32 bits AP */ - retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseaddr_upper); + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64(dap), &baseaddr_upper); } if (retval == ERROR_OK) @@ -2400,7 +2400,7 @@ COMMAND_HANDLER(dap_apid_command) command_print(CMD, "Cannot get AP"); return ERROR_FAIL; } - retval = dap_queue_ap_read(ap, AP_REG_IDR, &apid); + retval = dap_queue_ap_read(ap, AP_REG_IDR(dap), &apid); if (retval != ERROR_OK) { dap_put_ap(ap); return retval; @@ -2445,14 +2445,13 @@ COMMAND_HANDLER(dap_apreg_command) if (CMD_ARGC == 3) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); - switch (reg) { - case MEM_AP_REG_CSW: + /* see if user supplied register address is a match for the CSW or TAR register */ + if (reg == MEM_AP_REG_CSW(dap)) { ap->csw_value = 0; /* invalid, in case write fails */ retval = dap_queue_ap_write(ap, reg, value); if (retval == ERROR_OK) ap->csw_value = value; - break; - case MEM_AP_REG_TAR: + } else if (reg == MEM_AP_REG_TAR(dap)) { retval = dap_queue_ap_write(ap, reg, value); if (retval == ERROR_OK) ap->tar_value = (ap->tar_value & ~0xFFFFFFFFull) | value; @@ -2463,8 +2462,7 @@ COMMAND_HANDLER(dap_apreg_command) /* if tar_valid is false. */ ap->tar_valid = false; } - break; - case MEM_AP_REG_TAR64: + } else if (reg == MEM_AP_REG_TAR64(dap)) { retval = dap_queue_ap_write(ap, reg, value); if (retval == ERROR_OK) ap->tar_value = (ap->tar_value & 0xFFFFFFFFull) | (((target_addr_t)value) << 32); @@ -2472,10 +2470,8 @@ COMMAND_HANDLER(dap_apreg_command) /* See above comment for the MEM_AP_REG_TAR failed write case */ ap->tar_valid = false; } - break; - default: + } else { retval = dap_queue_ap_write(ap, reg, value); - break; } } else { retval = dap_queue_ap_read(ap, reg, &value); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index d7824cedf..7706fc935 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -5,6 +5,8 @@ * Copyright (C) 2008 by Spencer Oliver * * sp...@sp... * * * + * Copyright (C) 2019-2021, Ampere Computing LLC * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -53,11 +55,15 @@ */ #define DP_DPIDR BANK_REG(0x0, 0x0) /* DPv1+: ro */ #define DP_ABORT BANK_REG(0x0, 0x0) /* DPv1+: SWD: wo */ +#define DP_DPIDR1 BANK_REG(0x1, 0x0) /* DPv3: ro */ +#define DP_BASEPTR0 BANK_REG(0x2, 0x0) /* DPv3: ro */ +#define DP_BASEPTR1 BANK_REG(0x3, 0x0) /* DPv3: ro */ #define DP_CTRL_STAT BANK_REG(0x0, 0x4) /* DPv0+: rw */ #define DP_DLCR BANK_REG(0x1, 0x4) /* DPv1+: SWD: rw */ #define DP_TARGETID BANK_REG(0x2, 0x4) /* DPv2: ro */ #define DP_DLPIDR BANK_REG(0x3, 0x4) /* DPv2: ro */ #define DP_EVENTSTAT BANK_REG(0x4, 0x4) /* DPv2: ro */ +#define DP_SELECT1 BANK_REG(0x5, 0x4) /* DPv3: ro */ #define DP_RESEND BANK_REG(0x0, 0x8) /* DPv1+: SWD: ro */ #define DP_SELECT BANK_REG(0x0, 0x8) /* DPv0+: JTAG: rw; SWD: wo */ #define DP_RDBUFF BANK_REG(0x0, 0xC) /* DPv0+: ro */ @@ -76,6 +82,10 @@ #define WDERRCLR (1UL << 3) /* SWD-only */ #define ORUNERRCLR (1UL << 4) /* SWD-only */ +/* Fields of register DP_DPIDR1 */ +#define DP_DPIDR1_ASIZE_MASK (0x7F) +#define DP_DPIDR1_ERRMODE BIT(7) + /* Fields of the DP's CTRL/STAT register */ #define CORUNDETECT (1UL << 0) #define SSTICKYORUN (1UL << 1) @@ -110,20 +120,49 @@ /* MEM-AP register addresses */ -#define MEM_AP_REG_CSW 0x00 -#define MEM_AP_REG_TAR 0x04 -#define MEM_AP_REG_TAR64 0x08 /* RW: Large Physical Address Extension */ -#define MEM_AP_REG_DRW 0x0C /* RW: Data Read/Write register */ -#define MEM_AP_REG_BD0 0x10 /* RW: Banked Data register 0-3 */ -#define MEM_AP_REG_BD1 0x14 -#define MEM_AP_REG_BD2 0x18 -#define MEM_AP_REG_BD3 0x1C -#define MEM_AP_REG_MBT 0x20 /* --: Memory Barrier Transfer register */ -#define MEM_AP_REG_BASE64 0xF0 /* RO: Debug Base Address (LA) register */ -#define MEM_AP_REG_CFG 0xF4 /* RO: Configuration register */ -#define MEM_AP_REG_BASE 0xF8 /* RO: Debug Base Address register */ +#define ADIV5_MEM_AP_REG_CSW (0x00) +#define ADIV5_MEM_AP_REG_TAR (0x04) +#define ADIV5_MEM_AP_REG_TAR64 (0x08) /* RW: Large Physical Address Extension */ +#define ADIV5_MEM_AP_REG_DRW (0x0C) /* RW: Data Read/Write register */ +#define ADIV5_MEM_AP_REG_BD0 (0x10) /* RW: Banked Data register 0-3 */ +#define ADIV5_MEM_AP_REG_BD1 (0x14) +#define ADIV5_MEM_AP_REG_BD2 (0x18) +#define ADIV5_MEM_AP_REG_BD3 (0x1C) +#define ADIV5_MEM_AP_REG_MBT (0x20) /* --: Memory Barrier Transfer register */ +#define ADIV5_MEM_AP_REG_BASE64 (0xF0) /* RO: Debug Base Address (LA) register */ +#define ADIV5_MEM_AP_REG_CFG (0xF4) /* RO: Configuration register */ +#define ADIV5_MEM_AP_REG_BASE (0xF8) /* RO: Debug Base Address register */ + +#define ADIV6_MEM_AP_REG_CSW (0xD00 + ADIV5_MEM_AP_REG_CSW) +#define ADIV6_MEM_AP_REG_TAR (0xD00 + ADIV5_MEM_AP_REG_TAR) +#define ADIV6_MEM_AP_REG_TAR64 (0xD00 + ADIV5_MEM_AP_REG_TAR64) +#define ADIV6_MEM_AP_REG_DRW (0xD00 + ADIV5_MEM_AP_REG_DRW) +#define ADIV6_MEM_AP_REG_BD0 (0xD00 + ADIV5_MEM_AP_REG_BD0) +#define ADIV6_MEM_AP_REG_BD1 (0xD00 + ADIV5_MEM_AP_REG_BD1) +#define ADIV6_MEM_AP_REG_BD2 (0xD00 + ADIV5_MEM_AP_REG_BD2) +#define ADIV6_MEM_AP_REG_BD3 (0xD00 + ADIV5_MEM_AP_REG_BD3) +#define ADIV6_MEM_AP_REG_MBT (0xD00 + ADIV5_MEM_AP_REG_MBT) +#define ADIV6_MEM_AP_REG_BASE64 (0xD00 + ADIV5_MEM_AP_REG_BASE64) +#define ADIV6_MEM_AP_REG_CFG (0xD00 + ADIV5_MEM_AP_REG_CFG) +#define ADIV6_MEM_AP_REG_BASE (0xD00 + ADIV5_MEM_AP_REG_BASE) + +#define MEM_AP_REG_CSW(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_CSW : ADIV5_MEM_AP_REG_CSW) +#define MEM_AP_REG_TAR(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_TAR : ADIV5_MEM_AP_REG_TAR) +#define MEM_AP_REG_TAR64(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_TAR64 : ADIV5_MEM_AP_REG_TAR64) +#define MEM_AP_REG_DRW(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_DRW : ADIV5_MEM_AP_REG_DRW) +#define MEM_AP_REG_BD0(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD0 : ADIV5_MEM_AP_REG_BD0) +#define MEM_AP_REG_BD1(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD1 : ADIV5_MEM_AP_REG_BD1) +#define MEM_AP_REG_BD2(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD2 : ADIV5_MEM_AP_REG_BD2) +#define MEM_AP_REG_BD3(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD3 : ADIV5_MEM_AP_REG_BD3) +#define MEM_AP_REG_MBT(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_MBT : ADIV5_MEM_AP_REG_MBT) +#define MEM_AP_REG_BASE64(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BASE64 : ADIV5_MEM_AP_REG_BASE64) +#define MEM_AP_REG_CFG(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_CFG : ADIV5_MEM_AP_REG_CFG) +#define MEM_AP_REG_BASE(dap) (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BASE : ADIV5_MEM_AP_REG_BASE) + /* Generic AP register address */ -#define AP_REG_IDR 0xFC /* RO: Identification Register */ +#define ADIV5_AP_REG_IDR (0xFC) /* RO: Identification Register */ +#define ADIV6_AP_REG_IDR (0xD00 + ADIV5_AP_REG_IDR) +#define AP_REG_IDR(dap) (is_adiv6(dap) ? ADIV6_AP_REG_IDR : ADIV5_AP_REG_IDR) /* Fields of the MEM-AP's CSW register */ #define CSW_SIZE_MASK 7 ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/rshim.c | 32 ++++++++--------- src/jtag/drivers/stlink_usb.c | 26 +++++++------- src/target/adi_v5_jtag.c | 81 ++++++++++++++++++++----------------------- src/target/arm_adi_v5.c | 54 +++++++++++++---------------- src/target/arm_adi_v5.h | 65 +++++++++++++++++++++++++++------- 5 files changed, 143 insertions(+), 115 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-24 21:34:59
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 1fe82f9f1db62f0ab59471e1cdaf02643bf7a66c (commit) from 35a503b08d145edbd81519f9471b480292062bb5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 1fe82f9f1db62f0ab59471e1cdaf02643bf7a66c Author: Kevin Burke <ke...@os...> Date: Fri Aug 6 15:01:34 2021 +0200 adiv6: add dap flags -adiv5 and -adiv6 Add flags to 'dap create' command and set the field adi_version in struct adiv5_dap. Actually only ADIv5 is functional. Other patches are needed to get ADIv6 working. Split from change https://review.openocd.org/6077/ Change-Id: I63d3902f99a7f139c15ee4e07c19eae9ed4534b9 Signed-off-by: Kevin Burke <ke...@os...> Signed-off-by: Daniel Goehring <dgo...@os...> Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6456 Tested-by: jenkins diff --git a/doc/openocd.texi b/doc/openocd.texi index 85be06ea6..e8535b7a1 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4646,8 +4646,12 @@ There can only be one DAP for each JTAG tap in the system. A DAP may also provide optional @var{configparams}: @itemize @bullet +@item @code{-adiv5} +Specify that it's an ADIv5 DAP. This is the default if not specified. +@item @code{-adiv6} +Specify that it's an ADIv6 DAP. @item @code{-ignore-syspwrupack} -@*Specify this to ignore the CSYSPWRUPACK bit in the ARM DAP DP CTRL/STAT +Specify this to ignore the CSYSPWRUPACK bit in the ARM DAP DP CTRL/STAT register during initial examination and when checking the sticky error bit. This bit is normally checked after setting the CSYSPWRUPREQ bit, but some devices do not set the ack bit until sometime later. diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index c7ffe7b31..d7824cedf 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -353,6 +353,9 @@ struct adiv5_dap { * Record if enter in SWD required passing through DORMANT */ bool switch_through_dormant; + + /** Indicates ADI version (5, 6 or 0 for unknown) being used */ + unsigned int adi_version; }; /** @@ -426,6 +429,18 @@ static inline bool is_64bit_ap(struct adiv5_ap *ap) return (ap->cfg_reg & MEM_AP_REG_CFG_LA) != 0; } +/** + * Check if DAP is ADIv6 + * + * @param dap The DAP to test + * + * @return true for ADIv6, false for either ADIv5 or unknown version + */ +static inline bool is_adiv6(const struct adiv5_dap *dap) +{ + return dap->adi_version == 6; +} + /** * Send an adi-v5 sequence to the DAP. * diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 46e054e69..59d577e7f 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -129,6 +129,14 @@ static int dap_init_all(void) } else dap->ops = &jtag_dp_ops; + if (dap->adi_version == 0) { + LOG_DEBUG("DAP %s configured by default to use ADIv5 protocol", jtag_tap_name(dap->tap)); + dap->adi_version = 5; + } else { + LOG_DEBUG("DAP %s configured to use %s protocol by user cfg file", jtag_tap_name(dap->tap), + is_adiv6(dap) ? "ADIv6" : "ADIv5"); + } + retval = dap->ops->connect(dap); if (retval != ERROR_OK) return retval; @@ -163,6 +171,8 @@ enum dap_cfg_param { CFG_IGNORE_SYSPWRUPACK, CFG_DP_ID, CFG_INSTANCE_ID, + CFG_ADIV6, + CFG_ADIV5, }; static const struct jim_nvp nvp_config_opts[] = { @@ -170,6 +180,8 @@ static const struct jim_nvp nvp_config_opts[] = { { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK }, { .name = "-dp-id", .value = CFG_DP_ID }, { .name = "-instance-id", .value = CFG_INSTANCE_ID }, + { .name = "-adiv6", .value = CFG_ADIV6 }, + { .name = "-adiv5", .value = CFG_ADIV5 }, { .name = NULL, .value = -1 } }; @@ -249,6 +261,12 @@ static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap dap->dap.multidrop_instance_id_valid = true; break; } + case CFG_ADIV6: + dap->dap.adi_version = 6; + break; + case CFG_ADIV5: + dap->dap.adi_version = 5; + break; default: break; } ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 6 +++++- src/target/arm_adi_v5.h | 15 +++++++++++++++ src/target/arm_dap.c | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-24 21:33:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 35a503b08d145edbd81519f9471b480292062bb5 (commit) from 480d4e17727864f75dc60e22cb1a42e022cb1db3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 35a503b08d145edbd81519f9471b480292062bb5 Author: Antonio Borneo <bor...@gm...> Date: Wed Aug 4 23:07:57 2021 +0200 arm_adi_v5: add ap refcount and add get/put around ap use While an ADIv5 DAP can only have 256 AP, ADIv6 can provide till 2**40 (1,099,511,627,776) AP per DAP. The actual trivial code implementation for ADIv5 (that uses an array of 256 ap in the struct adiv5_dap) cannot be extended as-is to handle ADIv6. The simple array of 256 AP can be reused as a dynamic storage for ADIv6 ap: - the ADIv5 AP number is replaced by the ADIv6 base address; - the index of the array (equal to ADIv5 AP number) has no link to any ADIv6 property; - the ADIv6 base_address has to be searched in the array of AP. The 256 elements in the AP array should be enough for any device available today. In future it can be easily increased, if needed. To efficiently use the 256 elements in the AP array, the code should associate one element of the array to an ADIv6 AP (through the AP base address), then cancel the association when the AP is not anymore needed. This is important to avoid saturating the AP array while exploring the device through 'dap apreg' commands. Add a reference counter in the struct adiv5_ap to track how many times the struct has been associated with the same base address. Introduce the function dap_get_ap() to associate and return the struct, and dap_put_ap() to release the struct. For the moment the code covers ADIv5 only, so the association is through the index. Use the two functions above and dap_find_get_ap() throughout the code. Check the return value of dap_get_ap(). It is always not NULL in the current ADIv5-only implementation, but can be NULL for ADIv6 when there are no more available AP in the array. Instrument dap_queue_ap_read() and dap_queue_ap_write() to log an error message if the AP has reference counter zero, meaning that the AP has not been 'get' yet. This helps identifying AP used without get/put, e.g. code missed by this patch, or merged later. Instrument dap_cleanup_all() to log an error message if an AP has reference counter not zero at openocd exit, meaning that the AP has not been 'put' yet. Change-Id: I98316eb42b9f3d9c9bbbb6c73b1091b53f629092 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6455 Reviewed-by: Daniel Goehring <dgo...@os...> Tested-by: jenkins diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index edb4eb58f..c1a49fd54 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -402,16 +402,23 @@ static int kinetis_auto_probe(struct flash_bank *bank); static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { - int retval; LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, MDM_AP), reg, value); + struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_write(ap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a write request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; @@ -423,15 +430,21 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3 static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { - int retval; + struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } - retval = dap_queue_ap_read(dap_ap(dap, MDM_AP), reg, result); + int retval = dap_queue_ap_read(ap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a read request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; @@ -787,12 +800,18 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) { uint32_t stats[32]; + struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); + if (!ap) { + LOG_ERROR("MDM: failed to get AP"); + return ERROR_OK; + } for (unsigned int i = 0; i < 32; i++) { stats[i] = MDM_STAT_FREADY; - dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]); + dap_queue_ap_read(ap, MDM_REG_STAT, &stats[i]); } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed when validating secured state"); return ERROR_OK; diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index 48749e617..fe2072865 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -147,16 +147,23 @@ struct kinetis_ke_flash_bank { static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { - int retval; LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value); + struct adiv5_ap *ap = dap_get_ap(dap, 1); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_write(ap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a write request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; @@ -167,14 +174,21 @@ static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, ui static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { - int retval; - retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result); + struct adiv5_ap *ap = dap_get_ap(dap, 1); + if (!ap) { + LOG_DEBUG("MDM: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_read(ap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a read request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("MDM: dap_run failed"); return retval; diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index 891383860..1d42ffef4 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -872,16 +872,23 @@ static int sim3x_flash_info(struct flash_bank *bank, struct command_invocation * */ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { - int retval; LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, SIM3X_AP), reg, value); + struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP); + if (!ap) { + LOG_DEBUG("DAP: failed to get AP"); + return ERROR_FAIL; + } + + int retval = dap_queue_ap_write(ap, reg, value); if (retval != ERROR_OK) { LOG_DEBUG("DAP: failed to queue a write request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("DAP: dap_run failed"); return retval; @@ -892,15 +899,21 @@ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) { - int retval; + struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP); + if (!ap) { + LOG_DEBUG("DAP: failed to get AP"); + return ERROR_FAIL; + } - retval = dap_queue_ap_read(dap_ap(dap, SIM3X_AP), reg, result); + int retval = dap_queue_ap_read(ap, reg, result); if (retval != ERROR_OK) { LOG_DEBUG("DAP: failed to queue a read request"); + dap_put_ap(ap); return retval; } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) { LOG_DEBUG("DAP: dap_run failed"); return retval; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ecd93248c..8a8f21d13 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2558,15 +2558,24 @@ static int aarch64_examine_first(struct target *target) if (!pc) return ERROR_FAIL; + if (armv8->debug_ap) { + dap_put_ap(armv8->debug_ap); + armv8->debug_ap = NULL; + } + if (pc->adiv5_config.ap_num == DP_APSEL_INVALID) { /* Search for the APB-AB */ - retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap); + retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); return retval; } } else { - armv8->debug_ap = dap_ap(swjdp, pc->adiv5_config.ap_num); + armv8->debug_ap = dap_get_ap(swjdp, pc->adiv5_config.ap_num); + if (!armv8->debug_ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } } retval = mem_ap_init(armv8->debug_ap); @@ -2755,6 +2764,9 @@ static void aarch64_deinit_target(struct target *target) struct armv8_common *armv8 = &aarch64->armv8_common; struct arm_dpm *dpm = &armv8->dpm; + if (armv8->debug_ap) + dap_put_ap(armv8->debug_ap); + armv8_free_reg_cache(target); free(aarch64->brp_list); free(dpm->dbp); diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 4d5f02b32..7dd523ef0 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -968,20 +968,26 @@ static const char *ap_type_to_description(enum ap_type type) /* * This function checks the ID for each access port to find the requested Access Port type + * It also calls dap_get_ap() to increment the AP refcount */ -int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out) +int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out) { int ap_num; /* Maximum AP number is 255 since the SELECT register is 8 bits */ for (ap_num = 0; ap_num <= DP_APSEL_MAX; ap_num++) { + struct adiv5_ap *ap = dap_get_ap(dap, ap_num); + if (!ap) + continue; /* read the IDR register of the Access Port */ uint32_t id_val = 0; - int retval = dap_queue_ap_read(dap_ap(dap, ap_num), AP_REG_IDR, &id_val); - if (retval != ERROR_OK) + int retval = dap_queue_ap_read(ap, AP_REG_IDR, &id_val); + if (retval != ERROR_OK) { + dap_put_ap(ap); return retval; + } retval = dap_run(dap); @@ -993,15 +999,73 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_a ap_type_to_description(type_to_find), ap_num, id_val); - *ap_out = &dap->ap[ap_num]; + *ap_out = ap; return ERROR_OK; } + dap_put_ap(ap); } LOG_DEBUG("No %s found", ap_type_to_description(type_to_find)); return ERROR_FAIL; } +static inline bool is_ap_in_use(struct adiv5_ap *ap) +{ + return ap->refcount > 0 || ap->config_ap_never_release; +} + +static struct adiv5_ap *_dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num) +{ + if (ap_num > DP_APSEL_MAX) { + LOG_ERROR("Invalid AP#%u", ap_num); + return NULL; + } + struct adiv5_ap *ap = &dap->ap[ap_num]; + ++ap->refcount; + return ap; +} + +/* Return AP with specified ap_num. Increment AP refcount */ +struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num) +{ + struct adiv5_ap *ap = _dap_get_ap(dap, ap_num); + if (ap) + LOG_DEBUG("refcount AP#%u get %u", ap_num, ap->refcount); + return ap; +} + +/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ +struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num) +{ + struct adiv5_ap *ap = _dap_get_ap(dap, ap_num); + if (ap) { + ap->config_ap_never_release = true; + LOG_DEBUG("refcount AP#%u get_config %u", ap_num, ap->refcount); + } + return ap; +} + +/* Decrement AP refcount and release the AP when refcount reaches zero */ +int dap_put_ap(struct adiv5_ap *ap) +{ + if (ap->refcount == 0) { + LOG_ERROR("BUG: refcount AP#%" PRIu8 " put underflow", ap->ap_num); + return ERROR_FAIL; + } + + --ap->refcount; + + LOG_DEBUG("refcount AP#%" PRIu8 " put %u", ap->ap_num, ap->refcount); + if (!is_ap_in_use(ap)) { + /* defaults from dap_instance_init() */ + ap->memaccess_tck = 255; + ap->tar_autoincr_block = (1 << 10); + ap->csw_default = CSW_AHB_DEFAULT; + ap->cfg_reg = MEM_AP_REG_CFG_INVALID; + } + return ERROR_OK; +} + static int dap_get_debugbase(struct adiv5_ap *ap, target_addr_t *dbgbase, uint32_t *apid) { @@ -2117,7 +2181,15 @@ COMMAND_HANDLER(handle_dap_info_command) return ERROR_COMMAND_SYNTAX_ERROR; } - return dap_info_command(CMD, &dap->ap[apsel]); + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + + int retval = dap_info_command(CMD, ap); + dap_put_ap(ap); + return retval; } COMMAND_HANDLER(dap_baseaddr_command) @@ -2152,7 +2224,12 @@ COMMAND_HANDLER(dap_baseaddr_command) * use the ID register to verify it's a MEM-AP. */ - ap = dap_ap(dap, apsel); + ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseaddr_lower); if (retval == ERROR_OK && ap->cfg_reg == MEM_AP_REG_CFG_INVALID) @@ -2165,6 +2242,7 @@ COMMAND_HANDLER(dap_baseaddr_command) if (retval == ERROR_OK) retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) return retval; @@ -2180,22 +2258,35 @@ COMMAND_HANDLER(dap_baseaddr_command) COMMAND_HANDLER(dap_memaccess_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); + struct adiv5_ap *ap; uint32_t memaccess_tck; switch (CMD_ARGC) { case 0: - memaccess_tck = dap->ap[dap->apsel].memaccess_tck; + ap = dap_get_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + memaccess_tck = ap->memaccess_tck; break; case 1: + ap = dap_get_config_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], memaccess_tck); + ap->memaccess_tck = memaccess_tck; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->ap[dap->apsel].memaccess_tck = memaccess_tck; + + dap_put_ap(ap); command_print(CMD, "memory bus access delay set to %" PRIu32 " tck", - dap->ap[dap->apsel].memaccess_tck); + memaccess_tck); return ERROR_OK; } @@ -2228,14 +2319,19 @@ COMMAND_HANDLER(dap_apsel_command) COMMAND_HANDLER(dap_apcsw_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); - uint32_t apcsw = dap->ap[dap->apsel].csw_default; + struct adiv5_ap *ap; uint32_t csw_val, csw_mask; switch (CMD_ARGC) { case 0: + ap = dap_get_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } command_print(CMD, "ap %" PRIu32 " selected, csw 0x%8.8" PRIx32, - dap->apsel, apcsw); - return ERROR_OK; + dap->apsel, ap->csw_default); + break; case 1: if (strcmp(CMD_ARGV[0], "default") == 0) csw_val = CSW_AHB_DEFAULT; @@ -2246,7 +2342,12 @@ COMMAND_HANDLER(dap_apcsw_command) LOG_ERROR("CSW value cannot include 'Size' and 'AddrInc' bit-fields"); return ERROR_COMMAND_ARGUMENT_INVALID; } - apcsw = csw_val; + ap = dap_get_config_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + ap->csw_default = csw_val; break; case 2: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], csw_val); @@ -2255,14 +2356,19 @@ COMMAND_HANDLER(dap_apcsw_command) LOG_ERROR("CSW mask cannot include 'Size' and 'AddrInc' bit-fields"); return ERROR_COMMAND_ARGUMENT_INVALID; } - apcsw = (apcsw & ~csw_mask) | (csw_val & csw_mask); + ap = dap_get_config_ap(dap, dap->apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + ap->csw_default = (ap->csw_default & ~csw_mask) | (csw_val & csw_mask); break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->ap[dap->apsel].csw_default = apcsw; + dap_put_ap(ap); - return 0; + return ERROR_OK; } @@ -2289,10 +2395,18 @@ COMMAND_HANDLER(dap_apid_command) return ERROR_COMMAND_SYNTAX_ERROR; } - retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid); - if (retval != ERROR_OK) + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + retval = dap_queue_ap_read(ap, AP_REG_IDR, &apid); + if (retval != ERROR_OK) { + dap_put_ap(ap); return retval; + } retval = dap_run(dap); + dap_put_ap(ap); if (retval != ERROR_OK) return retval; @@ -2305,7 +2419,6 @@ COMMAND_HANDLER(dap_apreg_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); uint32_t apsel, reg, value; - struct adiv5_ap *ap; int retval; if (CMD_ARGC < 2 || CMD_ARGC > 3) @@ -2318,14 +2431,18 @@ COMMAND_HANDLER(dap_apreg_command) return ERROR_COMMAND_ARGUMENT_INVALID; } - ap = dap_ap(dap, apsel); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg); if (reg >= 256 || (reg & 3)) { command_print(CMD, "Invalid reg value (should be less than 256 and 4 bytes aligned)"); return ERROR_COMMAND_ARGUMENT_INVALID; } + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + if (CMD_ARGC == 3) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); switch (reg) { @@ -2366,6 +2483,8 @@ COMMAND_HANDLER(dap_apreg_command) if (retval == ERROR_OK) retval = dap_run(dap); + dap_put_ap(ap); + if (retval != ERROR_OK) return retval; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 8c9a60f25..c7ffe7b31 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -259,6 +259,12 @@ struct adiv5_ap { /* MEM AP configuration register indicating LPAE support */ uint32_t cfg_reg; + + /* references counter */ + unsigned int refcount; + + /* AP referenced during config. Never put it, even when refcount reaches zero */ + bool config_ap_never_release; }; @@ -486,6 +492,10 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap, unsigned reg, uint32_t *data) { assert(ap->dap->ops); + if (ap->refcount == 0) { + ap->refcount = 1; + LOG_ERROR("BUG: refcount AP#%" PRIu8 " used without get", ap->ap_num); + } return ap->dap->ops->queue_ap_read(ap, reg, data); } @@ -502,6 +512,10 @@ static inline int dap_queue_ap_write(struct adiv5_ap *ap, unsigned reg, uint32_t data) { assert(ap->dap->ops); + if (ap->refcount == 0) { + ap->refcount = 1; + LOG_ERROR("BUG: refcount AP#%" PRIu8 " used without get", ap->ap_num); + } return ap->dap->ops->queue_ap_write(ap, reg, data); } @@ -619,15 +633,19 @@ int mem_ap_init(struct adiv5_ap *ap); /* Invalidate cached DP select and cached TAR and CSW of all APs */ void dap_invalidate_cache(struct adiv5_dap *dap); -/* Probe Access Ports to find a particular type */ -int dap_find_ap(struct adiv5_dap *dap, +/* Probe Access Ports to find a particular type. Increment AP refcount */ +int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out); -static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num) -{ - return &dap->ap[ap_num]; -} +/* Return AP with specified ap_num. Increment AP refcount */ +struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num); + +/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ +struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num); + +/* Decrement AP refcount and release the AP when refcount reaches zero */ +int dap_put_ap(struct adiv5_ap *ap); /** Check if SWD multidrop configuration is valid */ static inline bool dap_is_multidrop(struct adiv5_dap *dap) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 96927bf94..74388aef9 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -34,6 +34,7 @@ struct arm_cti { struct list_head lh; char *name; struct adiv5_mem_ap_spot spot; + struct adiv5_ap *ap; }; static LIST_HEAD(all_cti); @@ -65,7 +66,7 @@ struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); + struct adiv5_ap *ap = self->ap; uint32_t tmp; /* Read register */ @@ -84,15 +85,14 @@ static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t int arm_cti_enable(struct arm_cti *self, bool enable) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); uint32_t val = enable ? 1 : 0; - return mem_ap_write_atomic_u32(ap, self->spot.base + CTI_CTR, val); + return mem_ap_write_atomic_u32(self->ap, self->spot.base + CTI_CTR, val); } int arm_cti_ack_events(struct arm_cti *self, uint32_t event) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); + struct adiv5_ap *ap = self->ap; int retval; uint32_t tmp; @@ -134,19 +134,15 @@ int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel) int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); - - return mem_ap_write_atomic_u32(ap, self->spot.base + reg, value); + return mem_ap_write_atomic_u32(self->ap, self->spot.base + reg, value); } int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value) { - struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num); - if (!p_value) return ERROR_COMMAND_ARGUMENT_INVALID; - return mem_ap_read_atomic_u32(ap, self->spot.base + reg, p_value); + return mem_ap_read_atomic_u32(self->ap, self->spot.base + reg, p_value); } int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel) @@ -228,6 +224,8 @@ int arm_cti_cleanup_all(void) struct arm_cti *obj, *tmp; list_for_each_entry_safe(obj, tmp, &all_cti, lh) { + if (obj->ap) + dap_put_ap(obj->ap); free(obj->name); free(obj); } @@ -238,7 +236,7 @@ int arm_cti_cleanup_all(void) COMMAND_HANDLER(handle_cti_dump) { struct arm_cti *cti = CMD_DATA; - struct adiv5_ap *ap = dap_ap(cti->spot.dap, cti->spot.ap_num); + struct adiv5_ap *ap = cti->ap; int retval = ERROR_OK; for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++) @@ -518,6 +516,12 @@ static int cti_create(struct jim_getopt_info *goi) list_add_tail(&cti->lh, &all_cti); + cti->ap = dap_get_ap(cti->spot.dap, cti->spot.ap_num); + if (!cti->ap) { + Jim_SetResultString(goi->interp, "Cannot get AP", -1); + return JIM_ERR; + } + return JIM_OK; } diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 2dba45d0b..46e054e69 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -58,6 +58,8 @@ static void dap_instance_init(struct adiv5_dap *dap) /* default CSW value */ dap->ap[i].csw_default = CSW_AHB_DEFAULT; dap->ap[i].cfg_reg = MEM_AP_REG_CFG_INVALID; /* mem_ap configuration reg (large physical addr, etc.) */ + dap->ap[i].refcount = 0; + dap->ap[i].config_ap_never_release = false; } INIT_LIST_HEAD(&dap->cmd_journal); INIT_LIST_HEAD(&dap->cmd_pool); @@ -142,6 +144,10 @@ int dap_cleanup_all(void) list_for_each_entry_safe(obj, tmp, &all_dap, lh) { dap = &obj->dap; + for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) { + if (dap->ap[i].refcount != 0) + LOG_ERROR("BUG: refcount AP#%u still %u at exit", i, dap->ap[i].refcount); + } if (dap->ops && dap->ops->quit) dap->ops->quit(dap); @@ -438,7 +444,14 @@ COMMAND_HANDLER(handle_dap_info_command) return ERROR_COMMAND_SYNTAX_ERROR; } - return dap_info_command(CMD, &dap->ap[apsel]); + struct adiv5_ap *ap = dap_get_ap(dap, apsel); + if (!ap) { + command_print(CMD, "Cannot get AP"); + return ERROR_FAIL; + } + int retval = dap_info_command(CMD, ap); + dap_put_ap(ap); + return retval; } static const struct command_registration dap_subcommand_handlers[] = { diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index fba3fec4f..5cbd89b86 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -90,6 +90,7 @@ struct arm_tpiu_swo_event_action { struct arm_tpiu_swo_object { struct list_head lh; struct adiv5_mem_ap_spot spot; + struct adiv5_ap *ap; char *name; struct arm_tpiu_swo_event_action *event_action; /* record enable before init */ @@ -233,6 +234,9 @@ int arm_tpiu_swo_cleanup_all(void) ea = next; } + if (obj->ap) + dap_put_ap(obj->ap); + free(obj->name); free(obj->out_filename); free(obj); @@ -596,7 +600,6 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const struct command *c = jim_to_command(interp); struct arm_tpiu_swo_object *obj = c->jim_handler_data; struct command_context *cmd_ctx = current_command_context(interp); - struct adiv5_ap *tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num); uint32_t value; int retval; @@ -644,7 +647,6 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const struct cortex_m_common *cm = target_to_cm(target); obj->recheck_ap_cur_target = false; obj->spot.ap_num = cm->armv7m.debug_ap->ap_num; - tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num); if (obj->spot.ap_num == 0) LOG_INFO(MSG "Confirmed TPIU %s is on AP 0", obj->name); else @@ -655,10 +657,18 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const } /* END_DEPRECATED_TPIU */ + if (!obj->ap) { + obj->ap = dap_get_ap(obj->spot.dap, obj->spot.ap_num); + if (!obj->ap) { + LOG_ERROR("Cannot get AP"); + return JIM_ERR; + } + } + /* trigger the event before any attempt to R/W in the TPIU/SWO */ arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_ENABLE); - retval = wrap_read_u32(target, tpiu_ap, obj->spot.base + TPIU_DEVID_OFFSET, &value); + retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_DEVID_OFFSET, &value); if (retval != ERROR_OK) { LOG_ERROR("Unable to read %s", obj->name); return JIM_ERR; @@ -684,7 +694,7 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const } if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_SYNC) { - retval = wrap_read_u32(target, tpiu_ap, obj->spot.base + TPIU_SSPSR_OFFSET, &value); + retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_SSPSR_OFFSET, &value); if (retval != ERROR_OK) { LOG_ERROR("Cannot read TPIU register SSPSR"); return JIM_ERR; @@ -759,26 +769,26 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const obj->swo_pin_freq = swo_pin_freq; } - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_CSPSR_OFFSET, BIT(obj->port_width - 1)); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_CSPSR_OFFSET, BIT(obj->port_width - 1)); if (retval != ERROR_OK) goto error_exit; - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_ACPR_OFFSET, prescaler - 1); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_ACPR_OFFSET, prescaler - 1); if (retval != ERROR_OK) goto error_exit; - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_SPPR_OFFSET, obj->pin_protocol); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_SPPR_OFFSET, obj->pin_protocol); if (retval != ERROR_OK) goto error_exit; - retval = wrap_read_u32(target, tpiu_ap, obj->spot.base + TPIU_FFCR_OFFSET, &value); + retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_FFCR_OFFSET, &value); if (retval != ERROR_OK) goto error_exit; if (obj->en_formatter) value |= BIT(1); else value &= ~BIT(1); - retval = wrap_write_u32(target, tpiu_ap, obj->spot.base + TPIU_FFCR_OFFSET, value); + retval = wrap_write_u32(target, obj->ap, obj->spot.base + TPIU_FFCR_OFFSET, value); if (retval != ERROR_OK) goto error_exit; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 20b2e5173..a20339f4b 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2885,15 +2885,24 @@ static int cortex_a_examine_first(struct target *target) int retval = ERROR_OK; uint32_t didr, cpuid, dbg_osreg, dbg_idpfr1; + if (armv7a->debug_ap) { + dap_put_ap(armv7a->debug_ap); + armv7a->debug_ap = NULL; + } + if (pc->ap_num == DP_APSEL_INVALID) { /* Search for the APB-AP - it is needed for access to debug registers */ - retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); + retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); return retval; } } else { - armv7a->debug_ap = dap_ap(swjdp, pc->ap_num); + armv7a->debug_ap = dap_get_ap(swjdp, pc->ap_num); + if (!armv7a->debug_ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } } retval = mem_ap_init(armv7a->debug_ap); @@ -3172,6 +3181,9 @@ static void cortex_a_deinit_target(struct target *target) dscr & ~DSCR_HALT_DBG_MODE); } + if (armv7a->debug_ap) + dap_put_ap(armv7a->debug_ap); + free(cortex_a->wrp_list); free(cortex_a->brp_list); arm_free_reg_cache(dpm->arm); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 344cfcf61..0a7668ddf 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1984,6 +1984,10 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, void cortex_m_deinit_target(struct target *target) { struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = target_to_armv7m(target); + + if (!armv7m->is_hla_target && armv7m->debug_ap) + dap_put_ap(armv7m->debug_ap); free(cortex_m->fp_comparator_list); @@ -2262,10 +2266,10 @@ static void cortex_m_dwt_free(struct target *target) static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp, struct adiv5_ap **debug_ap) { - if (dap_find_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK) + if (dap_find_get_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK) return ERROR_OK; - return dap_find_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap); + return dap_find_get_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap); } int cortex_m_examine(struct target *target) @@ -2279,6 +2283,11 @@ int cortex_m_examine(struct target *target) /* hla_target shares the examine handler but does not support * all its calls */ if (!armv7m->is_hla_target) { + if (armv7m->debug_ap) { + dap_put_ap(armv7m->debug_ap); + armv7m->debug_ap = NULL; + } + if (cortex_m->apsel == DP_APSEL_INVALID) { /* Search for the MEM-AP */ retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap); @@ -2287,7 +2296,11 @@ int cortex_m_examine(struct target *target) return retval; } } else { - armv7m->debug_ap = dap_ap(swjdp, cortex_m->apsel); + armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel); + if (!armv7m->debug_ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } } armv7m->debug_ap->memaccess_tck = 8; diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index eef05b44b..86bb29f21 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -74,8 +74,13 @@ static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *ta static void mem_ap_deinit_target(struct target *target) { + struct mem_ap *mem_ap = target->arch_info; + LOG_DEBUG("%s", __func__); + if (mem_ap->ap) + dap_put_ap(mem_ap->ap); + free(target->private_config); free(target->arch_info); return; @@ -139,7 +144,16 @@ static int mem_ap_examine(struct target *target) struct mem_ap *mem_ap = target->arch_info; if (!target_was_examined(target)) { - mem_ap->ap = dap_ap(mem_ap->dap, mem_ap->ap_num); + if (mem_ap->ap) { + dap_put_ap(mem_ap->ap); + mem_ap->ap = NULL; + } + + mem_ap->ap = dap_get_ap(mem_ap->dap, mem_ap->ap_num); + if (!mem_ap->ap) { + LOG_ERROR("Cannot get AP"); + return ERROR_FAIL; + } target_set_examined(target); target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED; ----------------------------------------------------------------------- Summary of changes: src/flash/nor/kinetis.c | 29 ++++++-- src/flash/nor/kinetis_ke.c | 22 +++++-- src/flash/nor/sim3x.c | 21 ++++-- src/target/aarch64.c | 16 ++++- src/target/arm_adi_v5.c | 161 +++++++++++++++++++++++++++++++++++++++------ src/target/arm_adi_v5.h | 30 +++++++-- src/target/arm_cti.c | 26 ++++---- src/target/arm_dap.c | 15 ++++- src/target/arm_tpiu_swo.c | 28 +++++--- src/target/cortex_a.c | 16 ++++- src/target/cortex_m.c | 19 +++++- src/target/mem_ap.c | 16 ++++- 12 files changed, 330 insertions(+), 69 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:57:09
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 480d4e17727864f75dc60e22cb1a42e022cb1db3 (commit) from 70338509ca52a9b78c52a5d464ba2605fbaf193b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 480d4e17727864f75dc60e22cb1a42e022cb1db3 Author: Erhan Kurubas <erh...@es...> Date: Sat May 28 08:30:21 2022 +0200 semihosting: fix accessing memory outside the bounds of the fn array There is an accsess to wrong index, when arm semihosting_basedir command not used or basedir set to empty string. Signed-off-by: Erhan Kurubas <erh...@es...> Change-Id: I3afa049d74b30496f5c03ba4ef67431784f81bdc Fixes: ce5027ab019a ("semihosting: add semihosting_basedir command") Reviewed-on: https://review.openocd.org/c/openocd/+/7005 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index 2df6e38ae..0a60eb121 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -877,9 +877,11 @@ int semihosting_common(struct target *target) semihosting->result = -1; semihosting->sys_errno = ENOMEM; } else { - strncpy((char *)fn, semihosting->basedir, basedir_len); - if (fn[basedir_len - 1] != '/') - fn[basedir_len++] = '/'; + if (basedir_len > 0) { + strcpy((char *)fn, semihosting->basedir); + if (fn[basedir_len - 1] != '/') + fn[basedir_len++] = '/'; + } retval = target_read_memory(target, addr, 1, len, fn + basedir_len); if (retval != ERROR_OK) { free(fn); ----------------------------------------------------------------------- Summary of changes: src/target/semihosting_common.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:56:43
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 70338509ca52a9b78c52a5d464ba2605fbaf193b (commit) from d1b882f2c014258be5397067e45848fa5465b78b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 70338509ca52a9b78c52a5d464ba2605fbaf193b Author: Erhan Kurubas <erh...@es...> Date: Sat Jun 4 00:25:19 2022 +0200 tcl: add get_bit & get_bitfield memory helper functions Signed-off-by: Erhan Kurubas <erh...@es...> Change-Id: I21506526e3ebd9c3a70a25ba60bf83aee431feb6 Reviewed-on: https://review.openocd.org/c/openocd/+/7016 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/tcl/mmr_helpers.tcl b/tcl/mmr_helpers.tcl index d9b6e6383..61c58e7ca 100644 --- a/tcl/mmr_helpers.tcl +++ b/tcl/mmr_helpers.tcl @@ -70,3 +70,22 @@ proc show_mmr_bitfield { MSB LSB VAL FIELDNAME FIELDVALUES } { } echo [format "%-15s: %d (0x%0*x) %s" $FIELDNAME $nval $width $nval $sval ] } + +# Give: ADDR - address of the register. +# BIT - bit's number. + +proc get_mmr_bit { ADDR BIT } { + set val [memread32 $ADDR] + set bit_val [expr {$val & [expr {1 << $BIT}]}] + return $bit_val +} + + +# Give: ADDR - address of the register. +# MSB - MSB bit's number. +# LSB - LSB bit's number. + +proc get_mmr_bitfield { ADDR MSB LSB } { + set rval [memread32 $ADDR] + return normalize_bitfield $rval $MSB $LSB +} ----------------------------------------------------------------------- Summary of changes: tcl/mmr_helpers.tcl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:56:04
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via d1b882f2c014258be5397067e45848fa5465b78b (commit) from 7cc79a8d62e0c98b52de04f71ef04167b8055385 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d1b882f2c014258be5397067e45848fa5465b78b Author: Tarek BOCHKATI <tar...@gm...> Date: Sat May 28 18:45:35 2022 +0100 telnet_server: fix scan-build warning fix "Declared variable-length array (VLA) has zero size" warning raised in .../src/server/telnet_server.c:633:2: Change-Id: Icff5228b02790c472b212a86a3849b1a3df98fdb Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6565 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 4fc71f384..8e796264c 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -615,7 +615,11 @@ static void telnet_auto_complete(struct connection *connection) while ((usr_cmd_pos < t_con->line_cursor) && isspace(t_con->line[usr_cmd_pos])) usr_cmd_pos++; - /* user command length */ + /* check user command length */ + if (t_con->line_cursor < usr_cmd_pos) { + telnet_bell(connection); + return; + } size_t usr_cmd_len = t_con->line_cursor - usr_cmd_pos; /* optimize multiple spaces in the user command, ----------------------------------------------------------------------- Summary of changes: src/server/telnet_server.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:55:06
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 7cc79a8d62e0c98b52de04f71ef04167b8055385 (commit) via 54f0cab18efadd7c132021228a3ef04ae1fea3ea (commit) from 95135b39ccc3d8cec79053a71d0289e7fdeeafe9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7cc79a8d62e0c98b52de04f71ef04167b8055385 Author: Antonio Borneo <bor...@gm...> Date: Thu Jun 2 11:17:49 2022 +0200 arm_adi_v5: check for calloc() return value In function adiv5_jim_configure() check that calloc() returns a valid allocated memory pointer. Change-Id: I97287e168834693900341add9d9eb9a5f38c55b4 Signed-off-by: Antonio Borneo <bor...@gm...> Reported-by: Tomas Vanek <va...@fb...> Reviewed-on: https://review.openocd.org/c/openocd/+/7014 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 52b12cb93..4d5f02b32 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -2044,6 +2044,10 @@ int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi) pc = (struct adiv5_private_config *)target->private_config; if (!pc) { pc = calloc(1, sizeof(struct adiv5_private_config)); + if (!pc) { + LOG_ERROR("Out of memory"); + return JIM_ERR; + } pc->ap_num = DP_APSEL_INVALID; target->private_config = pc; } commit 54f0cab18efadd7c132021228a3ef04ae1fea3ea Author: Antonio Borneo <bor...@gm...> Date: Wed Jun 1 19:47:48 2022 +0200 drivers/bitbang: silence scan-build warning The array is partially initialized with buf_set_u32(,5,32,), then the rest of the array is read from SWD. But scan-build report the array to have garbage content after the initialization, due to the offset of 5 bit that only inits part of the first byte. Silence the false positive from scan-build by initializing the array. Change-Id: Ic38d50280f67939e3ec5fa05741f66d5f993f8c2 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/7013 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 898d6d3df..78dcb2947 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -532,8 +532,9 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ bool check_ack = swd_cmd_returns_ack(cmd); + /* init the array to silence scan-build */ + uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)] = {0}; for (;;) { - uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value); buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value)); ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/bitbang.c | 3 ++- src/target/arm_adi_v5.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:54:45
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 95135b39ccc3d8cec79053a71d0289e7fdeeafe9 (commit) via aee7c70a1a710ba8442b1aabff16d2f28eec2db2 (commit) from 63e22d5fb97fd99d88d840e88a25aff721e0424b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 95135b39ccc3d8cec79053a71d0289e7fdeeafe9 Author: Antonio Borneo <bor...@gm...> Date: Wed Jun 1 19:21:44 2022 +0200 arm_adi_v5: fix scan-build warning [3/3] While scan-build complains that dap_p or ap_num_p could be NULL, the current code never passes NULL pointers. Add an assert() to silent scan-build and prevent any further use of the function with incorrect parameters. Change-Id: I656810dddcea61e85d85b13efb114f7607ef837c Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/7012 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 0b11e815d..52b12cb93 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1938,6 +1938,8 @@ static const struct jim_nvp nvp_config_opts[] = { static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, struct adiv5_dap **dap_p, int *ap_num_p, uint32_t *base_p) { + assert(dap_p && ap_num_p); + if (!goi->argc) return JIM_OK; commit aee7c70a1a710ba8442b1aabff16d2f28eec2db2 Author: Antonio Borneo <bor...@gm...> Date: Wed Jun 1 19:02:54 2022 +0200 arm_adi_v5: fix scan-build warning [2/3] Commit d01b3d69ec17 ("arm_adi_v5: separate ROM table parsing from command output [3/3]") introduces a new scan-build warning because removing one return in case of error causes using uninitialized values. Add back the return on error. Change-Id: I10ddc548b756d34aaccc0511f091b4caa5ec271a Signed-off-by: Antonio Borneo <bor...@gm...> Fixes: d01b3d69ec17 ("arm_adi_v5: separate ROM table parsing from command output [3/3]") Reviewed-on: https://review.openocd.org/c/openocd/+/7011 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index f7b335d95..0b11e815d 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1552,8 +1552,10 @@ static int rtp_rom_loop(const struct rtp_ops *ops, } if (retval == ERROR_OK) retval = dap_run(ap->dap); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { LOG_DEBUG("Failed read ROM table entry"); + return retval; + } if (width == 64) { romentry = (((uint64_t)romentry_high) << 32) | romentry_low; ----------------------------------------------------------------------- Summary of changes: src/target/arm_adi_v5.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:54:31
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 63e22d5fb97fd99d88d840e88a25aff721e0424b (commit) from e78b96421c6c782605127332011043d01c393ea7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 63e22d5fb97fd99d88d840e88a25aff721e0424b Author: Antonio Borneo <bor...@gm...> Date: Wed Jun 1 18:26:35 2022 +0200 arm_adi_v5: fix scan-build warning [1/3] Commit 21f7885d1c2a ("arm_adi_v5: separate ROM table parsing from command output [1/3]") introduces a new scan-build warning because continues the execution even when dap_get_debugbase() returns error. The value of 'apid' can be uninitialized: 5th function call argument is an uninitialized value Check the return value and quit on error. While there, remove the useless initialization of 'dbgbase' that was apparently required for the same problem. Change-Id: Iade26a152925ee0f1bf114ed829b94f7ed5b254f Signed-off-by: Antonio Borneo <bor...@gm...> Fixes: 21f7885d1c2a ("arm_adi_v5: separate ROM table parsing from command output [1/3]") Reviewed-on: https://review.openocd.org/c/openocd/+/7010 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 24de30530..f7b335d95 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1641,11 +1641,12 @@ static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap) { int retval; uint32_t apid; - target_addr_t dbgbase = 0; /* GCC complains can be used uninitialized */ - target_addr_t invalid_entry; + target_addr_t dbgbase, invalid_entry; /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ retval = dap_get_debugbase(ap, &dbgbase, &apid); + if (retval != ERROR_OK) + return retval; retval = rtp_ops_mem_ap_header(ops, retval, ap, dbgbase, apid); if (retval != ERROR_OK) return retval; ----------------------------------------------------------------------- Summary of changes: src/target/arm_adi_v5.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-10 21:52:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via e78b96421c6c782605127332011043d01c393ea7 (commit) from 822097a351f8aef0036359bc3f4ad3972c1ddbe3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e78b96421c6c782605127332011043d01c393ea7 Author: Tomas Vanek <va...@fb...> Date: Wed Nov 24 20:44:49 2021 +0100 flash/nor/numicro: remove useless architecture check target_to_armv7m() just returns a type-cast of target->arch_info, so the test has no value. Following target_run_algorithm() checks magic number so we need not worry about execution on mismatched architecture. Change-Id: Ic9892a488a42af1d8e8731eddb39240deeb26020 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: https://review.openocd.org/c/openocd/+/6755 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c index cb7c1df83..34875084c 100644 --- a/src/flash/nor/numicro.c +++ b/src/flash/nor/numicro.c @@ -1385,13 +1385,6 @@ static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer, init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */ - struct armv7m_common *armv7m = target_to_armv7m(target); - if (!armv7m) { - /* something is very wrong if armv7m is NULL */ - LOG_ERROR("unable to get armv7m target"); - return retval; - } - /* write code buffer and use Flash programming code within NuMicro */ /* Set breakpoint to 0 with time-out of 1000 ms */ while (count > 0) { ----------------------------------------------------------------------- Summary of changes: src/flash/nor/numicro.c | 7 ------- 1 file changed, 7 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-08 08:46:59
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 822097a351f8aef0036359bc3f4ad3972c1ddbe3 (commit) from 4f42600541d2f96a3a134699091e12179c82401a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 822097a351f8aef0036359bc3f4ad3972c1ddbe3 Author: Erhan Kurubas <erh...@es...> Date: Sat May 28 22:31:34 2022 +0200 telnet_server: fix valgrind error Error: Uninitialised value was created by a heap allocation at telnet_new_connection (telnet_server.c:227) Signed-off-by: Erhan Kurubas <erh...@es...> Change-Id: I698a3648be698c93a2395a718ee1ade028226995 Reviewed-on: https://review.openocd.org/c/openocd/+/7006 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 791a1a548..4fc71f384 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -222,9 +222,8 @@ static int telnet_new_connection(struct connection *connection) { struct telnet_connection *telnet_connection; struct telnet_service *telnet_service = connection->service->priv; - int i; - telnet_connection = malloc(sizeof(struct telnet_connection)); + telnet_connection = calloc(1, sizeof(struct telnet_connection)); if (!telnet_connection) { LOG_ERROR("Failed to allocate telnet connection."); @@ -234,9 +233,6 @@ static int telnet_new_connection(struct connection *connection) connection->priv = telnet_connection; /* initialize telnet connection information */ - telnet_connection->closed = false; - telnet_connection->line_size = 0; - telnet_connection->line_cursor = 0; telnet_connection->prompt = strdup("> "); telnet_connection->prompt_visible = true; telnet_connection->state = TELNET_STATE_DATA; @@ -257,11 +253,6 @@ static int telnet_new_connection(struct connection *connection) telnet_write(connection, "\r", 1); telnet_prompt(connection); - /* initialize history */ - for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++) - telnet_connection->history[i] = NULL; - telnet_connection->next_history = 0; - telnet_connection->current_history = 0; telnet_load_history(telnet_connection); log_add_callback(telnet_log_callback, connection); ----------------------------------------------------------------------- Summary of changes: src/server/telnet_server.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-04 08:25:54
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 4f42600541d2f96a3a134699091e12179c82401a (commit) from 4a20a1d1c01f0abb8cc8aabecb19c1f900582136 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4f42600541d2f96a3a134699091e12179c82401a Author: Tarek BOCHKATI <tar...@gm...> Date: Thu May 26 16:20:19 2022 +0100 flash/stm32l4x: fix scan-build warnings fix "Declared variable-length array (VLA) has zero size" warnings while at there instrument the probe function to ensure the flash bank contains at least 1 sector Change-Id: I3ba0e6345881557ad1aab2d1b41eee438b49fe04 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6470 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 7b35a0635..0a9d59ccf 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1078,7 +1078,7 @@ static int stm32l4_get_all_wrpxy(struct flash_bank *bank, enum stm32_bank_id dev if (dev_bank_id != STM32_BANK1 && stm32l4_info->dual_bank_mode) wrp2y_sectors_offset = stm32l4_info->bank1_sectors; - if (wrp2y_sectors_offset > -1) { + if (wrp2y_sectors_offset >= 0) { /* get WRP2AR */ ret = stm32l4_get_one_wrpxy(bank, &wrpxy[(*n_wrp)++], STM32_FLASH_WRP2AR_INDEX, wrp2y_sectors_offset); if (ret != ERROR_OK) @@ -1220,49 +1220,11 @@ err_lock: return retval2; } -static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) +static int stm32l4_protect_same_bank(struct flash_bank *bank, enum stm32_bank_id bank_id, int set, + unsigned int first, unsigned int last) { - struct target *target = bank->target; - struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; - int ret = ERROR_OK; unsigned int i; - if (stm32l4_is_otp(bank)) { - LOG_ERROR("cannot protect/unprotect OTP memory"); - return ERROR_FLASH_OPER_UNSUPPORTED; - } - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - /* the requested sectors could be located into bank1 and/or bank2 */ - bool use_bank2 = false; - if (last >= stm32l4_info->bank1_sectors) { - if (first < stm32l4_info->bank1_sectors) { - /* the requested sectors for (un)protection are shared between - * bank 1 and 2, then split the operation */ - - /* 1- deal with bank 1 sectors */ - LOG_DEBUG("The requested sectors for %s are shared between bank 1 and 2", - set ? "protection" : "unprotection"); - ret = stm32l4_protect(bank, set, first, stm32l4_info->bank1_sectors - 1); - if (ret != ERROR_OK) - return ret; - - /* 2- then continue with bank 2 sectors */ - first = stm32l4_info->bank1_sectors; - } - - use_bank2 = true; - } - - /* refresh the sectors' protection */ - ret = stm32l4_protect_check(bank); - if (ret != ERROR_OK) - return ret; - /* check if the desired protection is already configured */ for (i = first; i <= last; i++) { if (bank->sectors[i].is_protected != set) @@ -1278,7 +1240,7 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int n_wrp; struct stm32l4_wrp wrpxy[4]; - ret = stm32l4_get_all_wrpxy(bank, use_bank2 ? STM32_BANK2 : STM32_BANK1, wrpxy, &n_wrp); + int ret = stm32l4_get_all_wrpxy(bank, bank_id, wrpxy, &n_wrp); if (ret != ERROR_OK) return ret; @@ -1349,6 +1311,40 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, return stm32l4_write_all_wrpxy(bank, wrpxy, n_wrp); } +static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) +{ + struct target *target = bank->target; + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + + if (stm32l4_is_otp(bank)) { + LOG_ERROR("cannot protect/unprotect OTP memory"); + return ERROR_FLASH_OPER_UNSUPPORTED; + } + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* refresh the sectors' protection */ + int ret = stm32l4_protect_check(bank); + if (ret != ERROR_OK) + return ret; + + /* the requested sectors could be located into bank1 and/or bank2 */ + if (last < stm32l4_info->bank1_sectors) { + return stm32l4_protect_same_bank(bank, STM32_BANK1, set, first, last); + } else if (first >= stm32l4_info->bank1_sectors) { + return stm32l4_protect_same_bank(bank, STM32_BANK2, set, first, last); + } else { + ret = stm32l4_protect_same_bank(bank, STM32_BANK1, set, first, stm32l4_info->bank1_sectors - 1); + if (ret != ERROR_OK) + return ret; + + return stm32l4_protect_same_bank(bank, STM32_BANK2, set, stm32l4_info->bank1_sectors, last); + } +} + /* count is the size divided by stm32l4_info->data_width */ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) @@ -1987,6 +1983,15 @@ static int stm32l4_probe(struct flash_bank *bank) return ERROR_FAIL; } + /* ensure that at least there is 1 flash sector / page */ + if (num_pages == 0) { + if (stm32l4_info->user_bank_size) + LOG_ERROR("The specified flash size is less than page size"); + + LOG_ERROR("Flash pages count cannot be zero"); + return ERROR_FAIL; + } + LOG_INFO("flash mode : %s-bank", stm32l4_info->dual_bank_mode ? "dual" : "single"); const int gap_size_kb = stm32l4_info->hole_sectors * page_size_kb; ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 89 +++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 42 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-04 08:22:42
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 4a20a1d1c01f0abb8cc8aabecb19c1f900582136 (commit) from 7e9e5dca073d7a11c2391f57872e97372d94ad48 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4a20a1d1c01f0abb8cc8aabecb19c1f900582136 Author: Tarek BOCHKATI <tar...@gm...> Date: Tue May 24 11:32:51 2022 +0100 stlink: manage TCP_BUSY status code when using RW MISC Change-Id: I4f9eed3781b549742565a3a8ac5245a4b94ceb53 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6994 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 2785d9b96..bb2c8174a 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -504,6 +504,8 @@ static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, i #define STLINK_TCP_SS_CMD_NOT_AVAILABLE 0x00001053 #define STLINK_TCP_SS_TCP_ERROR 0x00002001 #define STLINK_TCP_SS_TCP_CANT_CONNECT 0x00002002 +#define STLINK_TCP_SS_TCP_CLOSE_ERROR 0x00002003 +#define STLINK_TCP_SS_TCP_BUSY 0x00002004 #define STLINK_TCP_SS_WIN32_ERROR 0x00010000 /* @@ -971,6 +973,11 @@ static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, bool if (check_tcp_status) { uint32_t tcp_ss = le_to_h_u32(h->tcp_backend_priv.recv_buf); if (tcp_ss != STLINK_TCP_SS_OK) { + if (tcp_ss == STLINK_TCP_SS_TCP_BUSY) { + LOG_DEBUG("TCP busy"); + return ERROR_WAIT; + } + LOG_ERROR("TCP error status 0x%X", tcp_ss); return ERROR_FAIL; } ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/stlink_usb.c | 7 +++++++ 1 file changed, 7 insertions(+) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-04 08:20:38
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 7e9e5dca073d7a11c2391f57872e97372d94ad48 (commit) from 78c87f5e81f8b3ee2a72aa546f87985596cb2b9f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7e9e5dca073d7a11c2391f57872e97372d94ad48 Author: Tomas Vanek <va...@fb...> Date: Thu May 26 09:26:14 2022 +0200 target/riscv: drop unused variable registers_initialized Change-Id: If7bfe38ac273ce9e54003e003807e128cced1568 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: https://review.openocd.org/c/openocd/+/6995 Tested-by: jenkins Reviewed-by: Tim Newsome <ti...@si...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index a266f5da3..e2d8e7098 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -3202,7 +3202,6 @@ void riscv_info_init(struct target *target, riscv_info_t *r) { memset(r, 0, sizeof(*r)); r->dtm_version = 1; - r->registers_initialized = false; r->current_hartid = target->coreid; r->version_specific = NULL; @@ -3301,16 +3300,12 @@ int riscv_set_current_hartid(struct target *target, int hartid) void riscv_invalidate_register_cache(struct target *target) { - RISCV_INFO(r); - LOG_DEBUG("[%d]", target->coreid); register_cache_invalidate(target->reg_cache); for (size_t i = 0; i < target->reg_cache->num_regs; ++i) { struct reg *reg = &target->reg_cache->reg_list[i]; reg->valid = false; } - - r->registers_initialized = true; } int riscv_current_hartid(const struct target *target) diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 0ae8945da..6eb915847 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -118,9 +118,6 @@ typedef struct { /* The number of entries in the debug buffer. */ int debug_buffer_size; - /* This avoids invalidating the register cache too often. */ - bool registers_initialized; - /* This hart contains an implicit ebreak at the end of the program buffer. */ bool impebreak; ----------------------------------------------------------------------- Summary of changes: src/target/riscv/riscv.c | 5 ----- src/target/riscv/riscv.h | 3 --- 2 files changed, 8 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-04 08:19:40
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 78c87f5e81f8b3ee2a72aa546f87985596cb2b9f (commit) from b470b664ca7ba3f21684848c3819d696fb3c890a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 78c87f5e81f8b3ee2a72aa546f87985596cb2b9f Author: Erhan Kurubas <erh...@es...> Date: Thu Apr 21 07:53:54 2022 +0200 target: add Espressif ESP32-S2 basic support ESP32-S2 is a single core Xtensa chip. Not full featured yet. Some of the missing functionality: -Semihosting -Flash breakpoints -Flash loader -Apptrace -FreeRTOS Signed-off-by: Erhan Kurubas <erh...@es...> Change-Id: I2fb32978e801af5aa21616c581691406ad7cd6bb Reviewed-on: https://review.openocd.org/c/openocd/+/6940 Reviewed-by: Tomas Vanek <va...@fb...> Reviewed-by: Ian Thompson <ia...@ca...> Reviewed-by: Antonio Borneo <bor...@gm...> Tested-by: jenkins diff --git a/doc/openocd.texi b/doc/openocd.texi index cc1d10441..85be06ea6 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4895,6 +4895,7 @@ compact Thumb2 instruction set. Supports also ARMv6-M and ARMv8-M cores @item @code{dsp5680xx} -- implements Freescale's 5680x DSP. @item @code{esirisc} -- this is an EnSilica eSi-RISC core. The current implementation supports eSi-32xx cores. +@item @code{esp32s2} -- this is an Espressif SoC with single Xtensa core. @item @code{fa526} -- resembles arm920 (w/o Thumb). @item @code{feroceon} -- resembles arm926. @item @code{hla_target} -- a Cortex-M alternative to work with HL adapters like ST-Link. @@ -10956,6 +10957,94 @@ STMicroelectronics, based on a proprietary 8-bit core architecture. OpenOCD supports debugging STM8 through the STMicroelectronics debug protocol SWIM, @pxref{swimtransport,,SWIM}. +@section Xtensa Architecture +Xtensa processors are based on a modular, highly flexible 32-bit RISC architecture +that can easily scale from a tiny, cache-less controller or task engine to a high-performance +SIMD/VLIW DSP provided by Cadence. +@url{https://www.cadence.com/en_US/home/tools/ip/tensilica-ip/tensilica-xtensa-controllers-and-extensible-processors.html}. + +OpenOCD supports generic Xtensa processors implementation which can be customized by +simply providing vendor-specific core configuration which controls every configurable +Xtensa architecture option, e.g. number of address registers, exceptions, reduced +size instructions support, memory banks configuration etc. Also OpenOCD supports SMP +configurations for Xtensa processors with any number of cores and allows to configure +their debug signals interconnection (so-called "break/stall networks") which control how +debug signals are distributed among cores. Xtensa "break networks" are compatible with +ARM's Cross Trigger Interface (CTI). For debugging code on Xtensa chips OpenOCD +uses JTAG protocol. Currently OpenOCD implements several Epsressif Xtensa-based chips of +@uref{https://www.espressif.com/en/products/socs, ESP32 family}. + +@subsection General Xtensa Commands + +@deffn {Command} {xtensa set_permissive} (0|1) +By default accessing memory beyond defined regions is forbidden. This commnd controls memory access address check. +When set to (1), skips access controls and address range check before read/write memory. +@end deffn + +@deffn {Command} {xtensa maskisr} (on|off) +Selects whether interrupts will be disabled during stepping over single instruction. The default configuration is (off). +@end deffn + +@deffn {Command} {xtensa smpbreak} [none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut] +Configures debug signals connection ("break network") for currently selected core. +@itemize @bullet +@item @code{none} - Core's "break/stall network" is disconnected. Core is not affected by any debug +signal from other cores. +@item @code{breakinout} - Core's "break network" is fully connected (break inputs and outputs are enabled). +Core will receive debug break signals from other cores and send such signals to them. For example when another core +is stopped due to breakpoint hit this core will be stopped too and vice versa. +@item @code{runstall} - Core's "stall network" is fully connected (stall inputs and outputs are enabled). +This feature is not well implemented and tested yet. +@item @code{BreakIn} - Core's "break-in" signal is enabled. +Core will receive debug break signals from other cores. For example when another core is +stopped due to breakpoint hit this core will be stopped too. +@item @code{BreakOut} - Core's "break-out" signal is enabled. +Core will send debug break signal to other cores. For example when this core is +stopped due to breakpoint hit other cores with enabled break-in signals will be stopped too. +@item @code{RunStallIn} - Core's "runstall-in" signal is enabled. +This feature is not well implemented and tested yet. +@item @code{DebugModeOut} - Core's "debugmode-out" signal is enabled. +This feature is not well implemented and tested yet. +@end itemize +@end deffn + +@deffn {Command} {xtensa perfmon_enable} <counter_id> <select> [mask] [kernelcnt] [tracelevel] +Enable and start performance counter. +@itemize @bullet +@item @code{counter_id} - Counter ID (0-1). +@item @code{select} - Selects performance metric to be counted by the counter, +e.g. 0 - CPU cycles, 2 - retired instructions. +@item @code{mask} - Selects input subsets to be counted (counter will +increment only once even if more than one condition corresponding to a mask bit occurs). +@item @code{kernelcnt} - 0 - count events with "CINTLEVEL <= tracelevel", +1 - count events with "CINTLEVEL > tracelevel". +@item @code{tracelevel} - Compares this value to "CINTLEVEL" when deciding +whether to count. +@end itemize +@end deffn + +@deffn {Command} {xtensa perfmon_dump} (counter_id) +Dump performance counter value. If no argument specified, dumps all counters. +@end deffn + +@deffn {Command} {xtensa tracestart} [pc <pcval>/[<maskbitcount>]] [after <n> [ins|words]] +Set up and start a HW trace. Optionally set PC address range to trigger tracing stop when reached during program execution. +This command also allows to specify the amount of data to capture after stop trigger activation. +@itemize @bullet +@item @code{pcval} - PC value which will trigger trace data collection stop. +@item @code{maskbitcount} - PC value mask. +@item @code{n} - Maximum number of instructions/words to capture after trace stop trigger. +@end itemize +@end deffn + +@deffn {Command} {xtensa tracestop} +Stop current trace as started by the tracestart command. +@end deffn + +@deffn {Command} {xtensa tracedump} <outfile> +Dump trace memory to a file. +@end deffn + @anchor{softwaredebugmessagesandtracing} @section Software Debug Messages and Tracing @cindex Linux-ARM DCC support diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 49e882fe6..799c3dd07 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -1,5 +1,7 @@ %C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la \ - %D%/riscv/libriscv.la + %D%/riscv/libriscv.la \ + %D%/xtensa/libxtensa.la \ + %D%/espressif/libespressif.la %C%_libtarget_la_CPPFLAGS = $(AM_CPPFLAGS) @@ -260,3 +262,5 @@ ARC_SRC = \ include %D%/openrisc/Makefile.am include %D%/riscv/Makefile.am +include %D%/xtensa/Makefile.am +include %D%/espressif/Makefile.am \ No newline at end of file diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am new file mode 100644 index 000000000..c681e09aa --- /dev/null +++ b/src/target/espressif/Makefile.am @@ -0,0 +1,6 @@ +noinst_LTLIBRARIES += %D%/libespressif.la +%C%_libespressif_la_SOURCES = \ + %D%/esp_xtensa.c \ + %D%/esp_xtensa.h \ + %D%/esp32s2.c \ + %D%/esp32s2.h diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c new file mode 100644 index 000000000..212533ff8 --- /dev/null +++ b/src/target/espressif/esp32s2.c @@ -0,0 +1,715 @@ +/*************************************************************************** + * ESP32-S2 target for OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + * Author: Alexey Gerenkov <al...@es...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "assert.h" +#include <target/target.h> +#include <target/target_type.h> +#include "esp_xtensa.h" +#include "esp32s2.h" + +/* Overall memory map + * TODO: read memory configuration from target registers */ +#define ESP32_S2_IROM_MASK_LOW 0x40000000 +#define ESP32_S2_IROM_MASK_HIGH 0x40020000 +#define ESP32_S2_IRAM_LOW 0x40020000 +#define ESP32_S2_IRAM_HIGH 0x40070000 +#define ESP32_S2_DRAM_LOW 0x3ffb0000 +#define ESP32_S2_DRAM_HIGH 0x40000000 +#define ESP32_S2_RTC_IRAM_LOW 0x40070000 +#define ESP32_S2_RTC_IRAM_HIGH 0x40072000 +#define ESP32_S2_RTC_DRAM_LOW 0x3ff9e000 +#define ESP32_S2_RTC_DRAM_HIGH 0x3ffa0000 +#define ESP32_S2_RTC_DATA_LOW 0x50000000 +#define ESP32_S2_RTC_DATA_HIGH 0x50002000 +#define ESP32_S2_EXTRAM_DATA_LOW 0x3f500000 +#define ESP32_S2_EXTRAM_DATA_HIGH 0x3ff80000 +#define ESP32_S2_DR_REG_LOW 0x3f400000 +#define ESP32_S2_DR_REG_HIGH 0x3f4d3FFC +#define ESP32_S2_SYS_RAM_LOW 0x60000000UL +#define ESP32_S2_SYS_RAM_HIGH (ESP32_S2_SYS_RAM_LOW + 0x20000000UL) +/* ESP32-S2 DROM mapping is not contiguous. */ +/* IDF declares this as 0x3F000000..0x3FF80000, but there are peripheral registers mapped to + * 0x3f400000..0x3f4d3FFC. */ +#define ESP32_S2_DROM0_LOW ESP32_S2_DROM_LOW +#define ESP32_S2_DROM0_HIGH ESP32_S2_DR_REG_LOW +#define ESP32_S2_DROM1_LOW ESP32_S2_DR_REG_HIGH +#define ESP32_S2_DROM1_HIGH ESP32_S2_DROM_HIGH + +/* ESP32 WDT */ +#define ESP32_S2_WDT_WKEY_VALUE 0x50d83aa1 +#define ESP32_S2_TIMG0_BASE 0x3f41F000 +#define ESP32_S2_TIMG1_BASE 0x3f420000 +#define ESP32_S2_TIMGWDT_CFG0_OFF 0x48 +#define ESP32_S2_TIMGWDT_PROTECT_OFF 0x64 +#define ESP32_S2_TIMG0WDT_CFG0 (ESP32_S2_TIMG0_BASE + ESP32_S2_TIMGWDT_CFG0_OFF) +#define ESP32_S2_TIMG1WDT_CFG0 (ESP32_S2_TIMG1_BASE + ESP32_S2_TIMGWDT_CFG0_OFF) +#define ESP32_S2_TIMG0WDT_PROTECT (ESP32_S2_TIMG0_BASE + ESP32_S2_TIMGWDT_PROTECT_OFF) +#define ESP32_S2_TIMG1WDT_PROTECT (ESP32_S2_TIMG1_BASE + ESP32_S2_TIMGWDT_PROTECT_OFF) +#define ESP32_S2_RTCCNTL_BASE 0x3f408000 +#define ESP32_S2_RTCWDT_CFG_OFF 0x94 +#define ESP32_S2_RTCWDT_PROTECT_OFF 0xAC +#define ESP32_S2_SWD_CONF_OFF 0xB0 +#define ESP32_S2_SWD_WPROTECT_OFF 0xB4 +#define ESP32_S2_RTC_CNTL_DIG_PWC_REG_OFF 0x8C +#define ESP32_S2_RTC_CNTL_DIG_PWC_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTC_CNTL_DIG_PWC_REG_OFF) +#define ESP32_S2_RTCWDT_CFG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTCWDT_CFG_OFF) +#define ESP32_S2_RTCWDT_PROTECT (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTCWDT_PROTECT_OFF) +#define ESP32_S2_SWD_CONF_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_SWD_CONF_OFF) +#define ESP32_S2_SWD_WPROTECT_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_SWD_WPROTECT_OFF) +#define ESP32_S2_SWD_AUTO_FEED_EN_M BIT(31) +#define ESP32_S2_SWD_WKEY_VALUE 0x8F1D312AU +#define ESP32_S2_OPTIONS0 (ESP32_S2_RTCCNTL_BASE + 0x0000) +#define ESP32_S2_SW_SYS_RST_M 0x80000000 +#define ESP32_S2_SW_SYS_RST_V 0x1 +#define ESP32_S2_SW_SYS_RST_S 31 +#define ESP32_S2_SW_STALL_PROCPU_C0_M ((ESP32_S2_SW_STALL_PROCPU_C0_V) << (ESP32_S2_SW_STALL_PROCPU_C0_S)) +#define ESP32_S2_SW_STALL_PROCPU_C0_V 0x3 +#define ESP32_S2_SW_STALL_PROCPU_C0_S 2 +#define ESP32_S2_SW_CPU_STALL (ESP32_S2_RTCCNTL_BASE + 0x00B8) +#define ESP32_S2_SW_STALL_PROCPU_C1_M ((ESP32_S2_SW_STALL_PROCPU_C1_V) << (ESP32_S2_SW_STALL_PROCPU_C1_S)) +#define ESP32_S2_SW_STALL_PROCPU_C1_V 0x3FU +#define ESP32_S2_SW_STALL_PROCPU_C1_S 26 +#define ESP32_S2_CLK_CONF (ESP32_S2_RTCCNTL_BASE + 0x0074) +#define ESP32_S2_CLK_CONF_DEF 0x1583218 +#define ESP32_S2_STORE4 (ESP32_S2_RTCCNTL_BASE + 0x00BC) +#define ESP32_S2_STORE5 (ESP32_S2_RTCCNTL_BASE + 0x00C0) +#define ESP32_S2_DPORT_PMS_OCCUPY_3 0x3F4C10E0 + +#define ESP32_S2_TRACEMEM_BLOCK_SZ 0x4000 + +#define ESP32_S2_DR_REG_UART_BASE 0x3f400000 +#define ESP32_S2_REG_UART_BASE(i) (ESP32_S2_DR_REG_UART_BASE + (i) * 0x10000) +#define ESP32_S2_UART_DATE_REG(i) (ESP32_S2_REG_UART_BASE(i) + 0x74) + +/* this should map local reg IDs to GDB reg mapping as defined in xtensa-config.c 'rmap' in + * xtensa-overlay */ +static const unsigned int esp32s2_gdb_regs_mapping[ESP32_S2_NUM_REGS] = { + XT_REG_IDX_PC, + XT_REG_IDX_AR0, XT_REG_IDX_AR1, XT_REG_IDX_AR2, XT_REG_IDX_AR3, + XT_REG_IDX_AR4, XT_REG_IDX_AR5, XT_REG_IDX_AR6, XT_REG_IDX_AR7, + XT_REG_IDX_AR8, XT_REG_IDX_AR9, XT_REG_IDX_AR10, XT_REG_IDX_AR11, + XT_REG_IDX_AR12, XT_REG_IDX_AR13, XT_REG_IDX_AR14, XT_REG_IDX_AR15, + XT_REG_IDX_AR16, XT_REG_IDX_AR17, XT_REG_IDX_AR18, XT_REG_IDX_AR19, + XT_REG_IDX_AR20, XT_REG_IDX_AR21, XT_REG_IDX_AR22, XT_REG_IDX_AR23, + XT_REG_IDX_AR24, XT_REG_IDX_AR25, XT_REG_IDX_AR26, XT_REG_IDX_AR27, + XT_REG_IDX_AR28, XT_REG_IDX_AR29, XT_REG_IDX_AR30, XT_REG_IDX_AR31, + XT_REG_IDX_AR32, XT_REG_IDX_AR33, XT_REG_IDX_AR34, XT_REG_IDX_AR35, + XT_REG_IDX_AR36, XT_REG_IDX_AR37, XT_REG_IDX_AR38, XT_REG_IDX_AR39, + XT_REG_IDX_AR40, XT_REG_IDX_AR41, XT_REG_IDX_AR42, XT_REG_IDX_AR43, + XT_REG_IDX_AR44, XT_REG_IDX_AR45, XT_REG_IDX_AR46, XT_REG_IDX_AR47, + XT_REG_IDX_AR48, XT_REG_IDX_AR49, XT_REG_IDX_AR50, XT_REG_IDX_AR51, + XT_REG_IDX_AR52, XT_REG_IDX_AR53, XT_REG_IDX_AR54, XT_REG_IDX_AR55, + XT_REG_IDX_AR56, XT_REG_IDX_AR57, XT_REG_IDX_AR58, XT_REG_IDX_AR59, + XT_REG_IDX_AR60, XT_REG_IDX_AR61, XT_REG_IDX_AR62, XT_REG_IDX_AR63, + XT_REG_IDX_SAR, + XT_REG_IDX_WINDOWBASE, XT_REG_IDX_WINDOWSTART, XT_REG_IDX_CONFIGID0, XT_REG_IDX_CONFIGID1, + XT_REG_IDX_PS, XT_REG_IDX_THREADPTR, + ESP32_S2_REG_IDX_GPIOOUT, + XT_REG_IDX_MMID, XT_REG_IDX_IBREAKENABLE, XT_REG_IDX_OCD_DDR, + XT_REG_IDX_IBREAKA0, XT_REG_IDX_IBREAKA1, XT_REG_IDX_DBREAKA0, XT_REG_IDX_DBREAKA1, + XT_REG_IDX_DBREAKC0, XT_REG_IDX_DBREAKC1, + XT_REG_IDX_EPC1, XT_REG_IDX_EPC2, XT_REG_IDX_EPC3, XT_REG_IDX_EPC4, + XT_REG_IDX_EPC5, XT_REG_IDX_EPC6, XT_REG_IDX_EPC7, XT_REG_IDX_DEPC, + XT_REG_IDX_EPS2, XT_REG_IDX_EPS3, XT_REG_IDX_EPS4, XT_REG_IDX_EPS5, + XT_REG_IDX_EPS6, XT_REG_IDX_EPS7, + XT_REG_IDX_EXCSAVE1, XT_REG_IDX_EXCSAVE2, XT_REG_IDX_EXCSAVE3, XT_REG_IDX_EXCSAVE4, + XT_REG_IDX_EXCSAVE5, XT_REG_IDX_EXCSAVE6, XT_REG_IDX_EXCSAVE7, XT_REG_IDX_CPENABLE, + XT_REG_IDX_INTERRUPT, XT_REG_IDX_INTSET, XT_REG_IDX_INTCLEAR, XT_REG_IDX_INTENABLE, + XT_REG_IDX_VECBASE, XT_REG_IDX_EXCCAUSE, XT_REG_IDX_DEBUGCAUSE, XT_REG_IDX_CCOUNT, + XT_REG_IDX_PRID, XT_REG_IDX_ICOUNT, XT_REG_IDX_ICOUNTLEVEL, XT_REG_IDX_EXCVADDR, + XT_REG_IDX_CCOMPARE0, XT_REG_IDX_CCOMPARE1, XT_REG_IDX_CCOMPARE2, + XT_REG_IDX_MISC0, XT_REG_IDX_MISC1, XT_REG_IDX_MISC2, XT_REG_IDX_MISC3, + XT_REG_IDX_A0, XT_REG_IDX_A1, XT_REG_IDX_A2, XT_REG_IDX_A3, + XT_REG_IDX_A4, XT_REG_IDX_A5, XT_REG_IDX_A6, XT_REG_IDX_A7, + XT_REG_IDX_A8, XT_REG_IDX_A9, XT_REG_IDX_A10, XT_REG_IDX_A11, + XT_REG_IDX_A12, XT_REG_IDX_A13, XT_REG_IDX_A14, XT_REG_IDX_A15, + XT_REG_IDX_PWRCTL, XT_REG_IDX_PWRSTAT, XT_REG_IDX_ERISTAT, + XT_REG_IDX_CS_ITCTRL, XT_REG_IDX_CS_CLAIMSET, XT_REG_IDX_CS_CLAIMCLR, + XT_REG_IDX_CS_LOCKACCESS, XT_REG_IDX_CS_LOCKSTATUS, XT_REG_IDX_CS_AUTHSTATUS, + XT_REG_IDX_FAULT_INFO, + XT_REG_IDX_TRAX_ID, XT_REG_IDX_TRAX_CTRL, XT_REG_IDX_TRAX_STAT, + XT_REG_IDX_TRAX_DATA, XT_REG_IDX_TRAX_ADDR, XT_REG_IDX_TRAX_PCTRIGGER, + XT_REG_IDX_TRAX_PCMATCH, XT_REG_IDX_TRAX_DELAY, XT_REG_IDX_TRAX_MEMSTART, + XT_REG_IDX_TRAX_MEMEND, + XT_REG_IDX_PMG, XT_REG_IDX_PMPC, XT_REG_IDX_PM0, XT_REG_IDX_PM1, + XT_REG_IDX_PMCTRL0, XT_REG_IDX_PMCTRL1, XT_REG_IDX_PMSTAT0, XT_REG_IDX_PMSTAT1, + XT_REG_IDX_OCD_ID, XT_REG_IDX_OCD_DCRCLR, XT_REG_IDX_OCD_DCRSET, XT_REG_IDX_OCD_DSR, +}; + +static const struct xtensa_user_reg_desc esp32s2_user_regs[ESP32_S2_NUM_REGS - XT_NUM_REGS] = { + { "gpio_out", 0x00, 0, 32, &xtensa_user_reg_u32_type }, +}; + +static const struct xtensa_config esp32s2_xtensa_cfg = { + .density = true, + .aregs_num = XT_AREGS_NUM_MAX, + .windowed = true, + .coproc = true, + .miscregs_num = 4, + .reloc_vec = true, + .proc_id = true, + .threadptr = true, + .user_regs_num = ARRAY_SIZE(esp32s2_user_regs), + .user_regs = esp32s2_user_regs, + .fetch_user_regs = xtensa_fetch_user_regs_u32, + .queue_write_dirty_user_regs = xtensa_queue_write_dirty_user_regs_u32, + .gdb_general_regs_num = ESP32_S2_NUM_REGS_G_COMMAND, + .gdb_regs_mapping = esp32s2_gdb_regs_mapping, + .irom = { + .count = 2, + .regions = { + { + .base = ESP32_S2_IROM_LOW, + .size = ESP32_S2_IROM_HIGH - ESP32_S2_IROM_LOW, + .access = XT_MEM_ACCESS_READ, + }, + { + .base = ESP32_S2_IROM_MASK_LOW, + .size = ESP32_S2_IROM_MASK_HIGH - ESP32_S2_IROM_MASK_LOW, + .access = XT_MEM_ACCESS_READ, + }, + } + }, + .iram = { + .count = 2, + .regions = { + { + .base = ESP32_S2_IRAM_LOW, + .size = ESP32_S2_IRAM_HIGH - ESP32_S2_IRAM_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + { + .base = ESP32_S2_RTC_IRAM_LOW, + .size = ESP32_S2_RTC_IRAM_HIGH - ESP32_S2_RTC_IRAM_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + } + }, + .drom = { + .count = 2, + .regions = { + { + .base = ESP32_S2_DROM0_LOW, + .size = ESP32_S2_DROM0_HIGH - ESP32_S2_DROM0_LOW, + .access = XT_MEM_ACCESS_READ, + }, + { + .base = ESP32_S2_DROM1_LOW, + .size = ESP32_S2_DROM1_HIGH - ESP32_S2_DROM1_LOW, + .access = XT_MEM_ACCESS_READ, + }, + } + }, + .dram = { + .count = 6, + .regions = { + { + .base = ESP32_S2_DRAM_LOW, + .size = ESP32_S2_DRAM_HIGH - ESP32_S2_DRAM_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + { + .base = ESP32_S2_RTC_DRAM_LOW, + .size = ESP32_S2_RTC_DRAM_HIGH - ESP32_S2_RTC_DRAM_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + { + .base = ESP32_S2_RTC_DATA_LOW, + .size = ESP32_S2_RTC_DATA_HIGH - ESP32_S2_RTC_DATA_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + { + .base = ESP32_S2_EXTRAM_DATA_LOW, + .size = ESP32_S2_EXTRAM_DATA_HIGH - ESP32_S2_EXTRAM_DATA_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + { + .base = ESP32_S2_DR_REG_LOW, + .size = ESP32_S2_DR_REG_HIGH - ESP32_S2_DR_REG_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + { + .base = ESP32_S2_SYS_RAM_LOW, + .size = ESP32_S2_SYS_RAM_HIGH - ESP32_S2_SYS_RAM_LOW, + .access = XT_MEM_ACCESS_READ | XT_MEM_ACCESS_WRITE, + }, + } + }, + .exc = { + .enabled = true, + }, + .irq = { + .enabled = true, + .irq_num = 32, + }, + .high_irq = { + .enabled = true, + .excm_level = 3, + .nmi_num = 1, + }, + .tim_irq = { + .enabled = true, + .comp_num = 3, + }, + .debug = { + .enabled = true, + .irq_level = 6, + .ibreaks_num = 2, + .dbreaks_num = 2, + .icount_sz = 32, + }, + .trace = { + .enabled = true, + .mem_sz = ESP32_S2_TRACEMEM_BLOCK_SZ, + }, +}; + +struct esp32s2_common { + struct esp_xtensa_common esp_xtensa; +}; + +static int esp32s2_soc_reset(struct target *target); +static int esp32s2_disable_wdts(struct target *target); + +static int esp32s2_assert_reset(struct target *target) +{ + return ERROR_OK; +} + +static int esp32s2_deassert_reset(struct target *target) +{ + struct xtensa *xtensa = target_to_xtensa(target); + + LOG_TARGET_DEBUG(target, "begin"); + + int res = xtensa_deassert_reset(target); + if (res != ERROR_OK) + return res; + + /* restore configured value + esp32s2_soc_reset() modified it, but can not restore just after SW reset for some reason (???) */ + res = xtensa_smpbreak_write(xtensa, xtensa->smp_break); + if (res != ERROR_OK) { + LOG_ERROR("Failed to restore smpbreak (%d)!", res); + return res; + } + return ERROR_OK; +} + +int esp32s2_soft_reset_halt(struct target *target) +{ + LOG_TARGET_DEBUG(target, "begin"); + + /* Reset the SoC first */ + int res = esp32s2_soc_reset(target); + if (res != ERROR_OK) + return res; + return xtensa_assert_reset(target); +} + +static int esp32s2_set_peri_reg_mask(struct target *target, + target_addr_t addr, + uint32_t mask, + uint32_t val) +{ + uint32_t reg_val; + int res = target_read_u32(target, addr, ®_val); + if (res != ERROR_OK) + return res; + reg_val = (reg_val & (~mask)) | val; + res = target_write_u32(target, addr, reg_val); + if (res != ERROR_OK) + return res; + + return ERROR_OK; +} + +static int esp32s2_stall_set(struct target *target, bool stall) +{ + LOG_TARGET_DEBUG(target, "begin"); + + int res = esp32s2_set_peri_reg_mask(target, + ESP32_S2_SW_CPU_STALL, + ESP32_S2_SW_STALL_PROCPU_C1_M, + stall ? 0x21U << ESP32_S2_SW_STALL_PROCPU_C1_S : 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_SW_CPU_STALL (%d)!", res); + return res; + } + res = esp32s2_set_peri_reg_mask(target, + ESP32_S2_OPTIONS0, + ESP32_S2_SW_STALL_PROCPU_C0_M, + stall ? 0x2 << ESP32_S2_SW_STALL_PROCPU_C0_S : 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_OPTIONS0 (%d)!", res); + return res; + } + return ERROR_OK; +} + +static inline int esp32s2_stall(struct target *target) +{ + return esp32s2_stall_set(target, true); +} + +static inline int esp32s2_unstall(struct target *target) +{ + return esp32s2_stall_set(target, false); +} + +/* Reset ESP32-S2's peripherals. +Postconditions: all peripherals except RTC_CNTL are reset, CPU's PC is undefined, PRO CPU is halted, APP CPU is in reset +How this works: +0. make sure target is halted; if not, try to halt it; if that fails, try to reset it (via OCD) and then halt +1. Resets clock related registers +2. Stalls CPU +3. trigger SoC reset using RTC_CNTL_SW_SYS_RST bit +4. CPU is reset and stalled at the first reset vector instruction +5. wait for the OCD to be reset +6. halt the target +7. Unstalls CPU +8. Disables WDTs and trace memory mapping +*/ +static int esp32s2_soc_reset(struct target *target) +{ + int res; + struct xtensa *xtensa = target_to_xtensa(target); + + LOG_DEBUG("start"); + + /* In order to write to peripheral registers, target must be halted first */ + if (target->state != TARGET_HALTED) { + LOG_TARGET_DEBUG(target, "Target not halted before SoC reset, trying to halt it first"); + xtensa_halt(target); + res = target_wait_state(target, TARGET_HALTED, 1000); + if (res != ERROR_OK) { + LOG_TARGET_DEBUG(target, "Couldn't halt target before SoC reset, trying to do reset-halt"); + res = xtensa_assert_reset(target); + if (res != ERROR_OK) { + LOG_TARGET_ERROR( + target, + "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)", + res); + return res; + } + alive_sleep(10); + xtensa_poll(target); + int reset_halt_save = target->reset_halt; + target->reset_halt = 1; + res = xtensa_deassert_reset(target); + target->reset_halt = reset_halt_save; + if (res != ERROR_OK) { + LOG_TARGET_ERROR( + target, + "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)", + res); + return res; + } + alive_sleep(10); + xtensa_poll(target); + xtensa_halt(target); + res = target_wait_state(target, TARGET_HALTED, 1000); + if (res != ERROR_OK) { + LOG_TARGET_ERROR(target, "Couldn't halt target before SoC reset"); + return res; + } + } + } + + assert(target->state == TARGET_HALTED); + + /* Set some clock-related RTC registers to the default values */ + res = target_write_u32(target, ESP32_S2_STORE4, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_STORE4 (%d)!", res); + return res; + } + res = target_write_u32(target, ESP32_S2_STORE5, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_STORE5 (%d)!", res); + return res; + } + res = target_write_u32(target, ESP32_S2_RTC_CNTL_DIG_PWC_REG, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_RTC_CNTL_DIG_PWC_REG (%d)!", res); + return res; + } + res = target_write_u32(target, ESP32_S2_CLK_CONF, ESP32_S2_CLK_CONF_DEF); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_CLK_CONF (%d)!", res); + return res; + } + /* Stall CPU */ + res = esp32s2_stall(target); + if (res != ERROR_OK) + return res; + /* enable stall */ + res = xtensa_smpbreak_write(xtensa, OCDDCR_RUNSTALLINEN); + if (res != ERROR_OK) { + LOG_ERROR("Failed to set smpbreak (%d)!", res); + return res; + } + /* Reset CPU */ + xtensa->suppress_dsr_errors = true; + res = esp32s2_set_peri_reg_mask(target, + ESP32_S2_OPTIONS0, + ESP32_S2_SW_SYS_RST_M, + 1U << ESP32_S2_SW_SYS_RST_S); + xtensa->suppress_dsr_errors = false; + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_OPTIONS0 (%d)!", res); + return res; + } + /* Wait for SoC to reset */ + alive_sleep(100); + int timeout = 100; + while (target->state != TARGET_RESET && target->state != TARGET_RUNNING && --timeout > 0) { + alive_sleep(10); + xtensa_poll(target); + } + if (timeout == 0) { + LOG_ERROR("Timed out waiting for CPU to be reset, target->state=%d", target->state); + return ERROR_TARGET_TIMEOUT; + } + xtensa_halt(target); + res = target_wait_state(target, TARGET_HALTED, 1000); + if (res != ERROR_OK) { + LOG_TARGET_ERROR(target, "Couldn't halt target before SoC reset"); + return res; + } + /* Unstall CPU */ + res = esp32s2_unstall(target); + if (res != ERROR_OK) + return res; + /* Disable WDTs */ + res = esp32s2_disable_wdts(target); + if (res != ERROR_OK) + return res; + /* Disable trace memory mapping */ + res = target_write_u32(target, ESP32_S2_DPORT_PMS_OCCUPY_3, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_DPORT_PMS_OCCUPY_3 (%d)!", res); + return res; + } + return ERROR_OK; +} + +static int esp32s2_disable_wdts(struct target *target) +{ + /* TIMG1 WDT */ + int res = target_write_u32(target, ESP32_S2_TIMG0WDT_PROTECT, ESP32_S2_WDT_WKEY_VALUE); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_TIMG0WDT_PROTECT (%d)!", res); + return res; + } + res = target_write_u32(target, ESP32_S2_TIMG0WDT_CFG0, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_TIMG0WDT_CFG0 (%d)!", res); + return res; + } + /* TIMG2 WDT */ + res = target_write_u32(target, ESP32_S2_TIMG1WDT_PROTECT, ESP32_S2_WDT_WKEY_VALUE); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_TIMG1WDT_PROTECT (%d)!", res); + return res; + } + res = target_write_u32(target, ESP32_S2_TIMG1WDT_CFG0, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_TIMG1WDT_CFG0 (%d)!", res); + return res; + } + /* RTC WDT */ + res = target_write_u32(target, ESP32_S2_RTCWDT_PROTECT, ESP32_S2_WDT_WKEY_VALUE); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_RTCWDT_PROTECT (%d)!", res); + return res; + } + res = target_write_u32(target, ESP32_S2_RTCWDT_CFG, 0); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_RTCWDT_CFG (%d)!", res); + return res; + } + /* Enable SWD auto-feed */ + res = target_write_u32(target, ESP32_S2_SWD_WPROTECT_REG, ESP32_S2_SWD_WKEY_VALUE); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_SWD_WPROTECT_REG (%d)!", res); + return res; + } + uint32_t swd_conf_reg = 0; + res = target_read_u32(target, ESP32_S2_SWD_CONF_REG, &swd_conf_reg); + if (res != ERROR_OK) { + LOG_ERROR("Failed to read ESP32_S2_SWD_CONF_REG (%d)!", res); + return res; + } + swd_conf_reg |= ESP32_S2_SWD_AUTO_FEED_EN_M; + res = target_write_u32(target, ESP32_S2_SWD_CONF_REG, swd_conf_reg); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write ESP32_S2_SWD_CONF_REG (%d)!", res); + return res; + } + return ERROR_OK; +} + +static int esp32s2_arch_state(struct target *target) +{ + return ERROR_OK; +} + +static int esp32s2_on_halt(struct target *target) +{ + return esp32s2_disable_wdts(target); +} + +static int esp32s2_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +{ + int ret = xtensa_step(target, current, address, handle_breakpoints); + if (ret == ERROR_OK) { + esp32s2_on_halt(target); + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + } + return ret; +} + +static int esp32s2_poll(struct target *target) +{ + enum target_state old_state = target->state; + int ret = esp_xtensa_poll(target); + + if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) { + /* Call any event callbacks that are applicable */ + if (old_state == TARGET_DEBUG_RUNNING) { + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); + } else { + esp32s2_on_halt(target); + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + } + } + + return ret; +} + +static int esp32s2_virt2phys(struct target *target, + target_addr_t virtual, target_addr_t *physical) +{ + *physical = virtual; + return ERROR_OK; +} + +static int esp32s2_target_init(struct command_context *cmd_ctx, struct target *target) +{ + return esp_xtensa_target_init(cmd_ctx, target); +} + +static const struct xtensa_debug_ops esp32s2_dbg_ops = { + .queue_enable = xtensa_dm_queue_enable, + .queue_reg_read = xtensa_dm_queue_reg_read, + .queue_reg_write = xtensa_dm_queue_reg_write +}; + +static const struct xtensa_power_ops esp32s2_pwr_ops = { + .queue_reg_read = xtensa_dm_queue_pwr_reg_read, + .queue_reg_write = xtensa_dm_queue_pwr_reg_write +}; + +static int esp32s2_target_create(struct target *target, Jim_Interp *interp) +{ + struct xtensa_debug_module_config esp32s2_dm_cfg = { + .dbg_ops = &esp32s2_dbg_ops, + .pwr_ops = &esp32s2_pwr_ops, + .tap = target->tap, + .queue_tdi_idle = NULL, + .queue_tdi_idle_arg = NULL + }; + + /* creates xtensa object */ + struct esp32s2_common *esp32 = calloc(1, sizeof(*esp32)); + if (!esp32) { + LOG_ERROR("Failed to alloc memory for arch info!"); + return ERROR_FAIL; + } + + int ret = esp_xtensa_init_arch_info(target, &esp32->esp_xtensa, &esp32s2_xtensa_cfg, &esp32s2_dm_cfg); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to init arch info!"); + free(esp32); + return ret; + } + + /* Assume running target. If different, the first poll will fix this */ + target->state = TARGET_RUNNING; + target->debug_reason = DBG_REASON_NOTHALTED; + return ERROR_OK; +} + +static const struct command_registration esp32s2_command_handlers[] = { + { + .name = "xtensa", + .mode = COMMAND_ANY, + .help = "Xtensa commands group", + .usage = "", + .chain = xtensa_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +/* Holds methods for Xtensa targets. */ +struct target_type esp32s2_target = { + .name = "esp32s2", + + .poll = esp32s2_poll, + .arch_state = esp32s2_arch_state, + + .halt = xtensa_halt, + .resume = xtensa_resume, + .step = esp32s2_step, + + .assert_reset = esp32s2_assert_reset, + .deassert_reset = esp32s2_deassert_reset, + .soft_reset_halt = esp32s2_soft_reset_halt, + + .virt2phys = esp32s2_virt2phys, + .mmu = xtensa_mmu_is_enabled, + .read_memory = xtensa_read_memory, + .write_memory = xtensa_write_memory, + + .read_buffer = xtensa_read_buffer, + .write_buffer = xtensa_write_buffer, + + .checksum_memory = xtensa_checksum_memory, + + .get_gdb_arch = xtensa_get_gdb_arch, + .get_gdb_reg_list = xtensa_get_gdb_reg_list, + + .add_breakpoint = esp_xtensa_breakpoint_add, + .remove_breakpoint = esp_xtensa_breakpoint_remove, + + .add_watchpoint = xtensa_watchpoint_add, + .remove_watchpoint = xtensa_watchpoint_remove, + + .target_create = esp32s2_target_create, + .init_target = esp32s2_target_init, + .examine = xtensa_examine, + .deinit_target = esp_xtensa_target_deinit, + + .commands = esp32s2_command_handlers, +}; diff --git a/src/target/espressif/esp32s2.h b/src/target/espressif/esp32s2.h new file mode 100644 index 000000000..2c43e3ec4 --- /dev/null +++ b/src/target/espressif/esp32s2.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * ESP32-S2 target for OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + * Author: Alexey Gerenkov <al...@es...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ESP32S2_H +#define OPENOCD_TARGET_ESP32S2_H + +#include <target/xtensa/xtensa_regs.h> + +#define ESP32_S2_DROM_LOW 0x3f000000 +#define ESP32_S2_DROM_HIGH 0x3ff80000 +#define ESP32_S2_IROM_LOW 0x40080000 +#define ESP32_S2_IROM_HIGH 0x40800000 + +/* Number of registers returned directly by the G command + * Corresponds to the amount of regs listed in regformats/reg-xtensa.dat in the gdb source */ +#define ESP32_S2_NUM_REGS_G_COMMAND 72 + +enum esp32s2_reg_id { + /* chip specific registers that extend ISA go after ISA-defined ones */ + ESP32_S2_REG_IDX_GPIOOUT = XT_USR_REG_START, + ESP32_S2_NUM_REGS, +}; + +#endif /* OPENOCD_TARGET_ESP32S2_H */ diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c new file mode 100644 index 000000000..89393f442 --- /dev/null +++ b/src/target/espressif/esp_xtensa.c @@ -0,0 +1,71 @@ +/*************************************************************************** + * Espressif Xtensa target API for OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + * Author: Alexey Gerenkov <al...@es...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdbool.h> +#include <stdint.h> +#include <target/smp.h> +#include "esp_xtensa.h" +#include <target/register.h> + +int esp_xtensa_init_arch_info(struct target *target, + struct esp_xtensa_common *esp_xtensa, + const struct xtensa_config *xtensa_cfg, + struct xtensa_debug_module_config *dm_cfg) +{ + return xtensa_init_arch_info(target, &esp_xtensa->xtensa, xtensa_cfg, dm_cfg); +} + +int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target *target) +{ + return xtensa_target_init(cmd_ctx, target); +} + +void esp_xtensa_target_deinit(struct target *target) +{ + LOG_DEBUG("start"); + + xtensa_target_deinit(target); + free(target_to_esp_xtensa(target)); /* same as free(xtensa) */ +} + +int esp_xtensa_arch_state(struct target *target) +{ + return ERROR_OK; +} + +int esp_xtensa_poll(struct target *target) +{ + return xtensa_poll(target); +} + +int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint) +{ + return xtensa_breakpoint_add(target, breakpoint); + /* flash breakpoints will be handled in another patch */ +} + +int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint) +{ + return xtensa_breakpoint_remove(target, breakpoint); + /* flash breakpoints will be handled in another patch */ +} diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h new file mode 100644 index 000000000..6badb1bd3 --- /dev/null +++ b/src/target/espressif/esp_xtensa.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Generic ESP xtensa target implementation for OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + * Author: Alexey Gerenkov <al...@es...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ESP_XTENSA_H +#define OPENOCD_TARGET_ESP_XTENSA_H + +#include <helper/command.h> +#include <target/target.h> +#include <target/xtensa/xtensa.h> + +struct esp_xtensa_common { + struct xtensa xtensa; /* must be the first element */ +}; + +static inline struct esp_xtensa_common *target_to_esp_xtensa(struct target *target) +{ + return container_of(target->arch_info, struct esp_xtensa_common, xtensa); +} + +int esp_xtensa_init_arch_info(struct target *target, + struct esp_xtensa_common *esp_xtensa, + const struct xtensa_config *xtensa_cfg, + struct xtensa_debug_module_config *dm_cfg); +int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target *target); +void esp_xtensa_target_deinit(struct target *target); +int esp_xtensa_arch_state(struct target *target); +void esp_xtensa_queue_tdi_idle(struct target *target); +int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint); +int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint); +int esp_xtensa_poll(struct target *target); + +#endif /* OPENOCD_TARGET_ESP_XTENSA_H */ diff --git a/src/target/target.c b/src/target/target.c index 76327b1c7..e2004e4a9 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -105,6 +105,7 @@ extern struct target_type hla_target; extern struct target_type nds32_v2_target; extern struct target_type nds32_v3_target; extern struct target_type nds32_v3m_target; +extern struct target_type esp32s2_target; extern struct target_type or1k_target; extern struct target_type quark_x10xx_target; extern struct target_type quark_d20xx_target; @@ -141,6 +142,7 @@ static struct target_type *target_types[] = { &nds32_v2_target, &nds32_v3_target, &nds32_v3m_target, + &esp32s2_target, &or1k_target, &quark_x10xx_target, &quark_d20xx_target, diff --git a/src/target/xtensa/Makefile.am b/src/target/xtensa/Makefile.am new file mode 100644 index 000000000..f6cee99c2 --- /dev/null +++ b/src/target/xtensa/Makefile.am @@ -0,0 +1,7 @@ +noinst_LTLIBRARIES += %D%/libxtensa.la +%C%_libxtensa_la_SOURCES = \ + %D%/xtensa.c \ + %D%/xtensa.h \ + %D%/xtensa_debug_module.c \ + %D%/xtensa_debug_module.h \ + %D%/xtensa_regs.h diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c new file mode 100644 index 000000000..a9559600f --- /dev/null +++ b/src/target/xtensa/xtensa.c @@ -0,0 +1,2731 @@ +/*************************************************************************** + * Generic Xtensa target API for OpenOCD * + * Copyright (C) 2016-2019 Espressif Systems Ltd. * + * Derived from esp108.c * + * Author: Angus Gratton gu...@pr... * + * Author: Jeroen Domburg <je...@es...> * + * Author: Alexey Gerenkov <al...@es...> * + * Author: Andrey Gramakov <and...@es...> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <helper/time_support.h> +#include <helper/align.h> +#include <target/register.h> + +#include "xtensa.h" + + +#define _XT_INS_FORMAT_RSR(OPCODE, SR, T) ((OPCODE) \ + | (((SR) & 0xFF) << 8) \ + | (((T) & 0x0F) << 4)) + +#define _XT_INS_FORMAT_RRR(OPCODE, ST, R) ((OPCODE) \ + | (((ST) & 0xFF) << 4) \ + | (((R) & 0x0F) << 12)) + +#define _XT_INS_FORMAT_RRRN(OPCODE, S, T, IMM4) ((OPCODE) \ + | (((T) & 0x0F) << 4) \ + | (((S) & 0x0F) << 8) \ + | (((IMM4) & 0x0F) << 12)) + +#define _XT_INS_FORMAT_RRI8(OPCODE, R, S, T, IMM8) ((OPCODE) \ + | (((IMM8) & 0xFF) << 16) \ + | (((R) & 0x0F) << 12) \ + | (((S) & 0x0F) << 8) \ + | (((T) & 0x0F) << 4)) + +#define _XT_INS_FORMAT_RRI4(OPCODE, IMM4, R, S, T) ((OPCODE) \ + | (((IMM4) & 0x0F) << 20) \ + | (((R) & 0x0F) << 12) \ + | (((S) & 0x0F) << 8) \ + | (((T) & 0x0F) << 4)) + +/* Xtensa processor instruction opcodes + * "Return From Debug Operation" to Normal */ +#define XT_INS_RFDO 0xf1e000 +/* "Return From Debug and Dispatch" - allow sw debugging stuff to take over */ +#define XT_INS_RFDD 0xf1e010 + +/* Load to DDR register, increase addr register */ +#define XT_INS_LDDR32P(S) (0x0070E0 | ((S) << 8)) +/* Store from DDR register, increase addr register */ +#define XT_INS_SDDR32P(S) (0x0070F0 | ((S) << 8)) + +/* Load 32-bit Indirect from A(S) + 4 * IMM8 to A(T) */ +#define XT_INS_L32I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x002002, 0, S, T, IMM8) +/* Load 16-bit Unsigned from A(S) + 2 * IMM8 to A(T) */ +#define XT_INS_L16UI(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x001002, 0, S, T, IMM8) +/* Load 8-bit Unsigned from A(S) + IMM8 to A(T) */ +#define XT_INS_L8UI(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x000002, 0, S, T, IMM8) + +/* Store 32-bit Indirect to A(S) + 4 * IMM8 from A(T) */ +#define XT_INS_S32I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x006002, 0, S, T, IMM8) +/* Store 16-bit to A(S) + 2 * IMM8 from A(T) */ +#define XT_INS_S16I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x005002, 0, S, T, IMM8) +/* Store 8-bit to A(S) + IMM8 from A(T) */ +#define XT_INS_S8I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x004002, 0, S, T, IMM8) + +/* Read Special Register */ +#define XT_INS_RSR(SR, T) _XT_INS_FORMAT_RSR(0x030000, SR, T) +/* Write Special Register */ +#define XT_INS_WSR(SR, T) _XT_INS_FORMAT_RSR(0x130000, SR, T) +/* Swap Special Register */ +#define XT_INS_XSR(SR, T) _XT_INS_FORMAT_RSR(0x610000, SR, T) + +/* Rotate Window by (-8..7) */ +#define XT_INS_ROTW(N) ((0x408000) | (((N) & 15) << 4)) + +/* Read User Register */ +#define XT_INS_RUR(UR, T) _XT_INS_FORMAT_RRR(0xE30000, UR, T) +/* Write User Register */ +#define XT_INS_WUR(UR, T) _XT_INS_FORMAT_RSR(0xF30000, UR, T) + +/* Read Floating-Point Register */ +#define XT_INS_RFR(FR, T) _XT_INS_FORMAT_RRR(0xFA0000, (((FR) << 4) | 0x4), T) +/* Write Floating-Point Register */ +#define XT_INS_WFR(FR, T) _XT_INS_FORMAT_RRR(0xFA0000, (((FR) << 4) | 0x5), T) + +/* 32-bit break */ +#define XT_INS_BREAK(IMM1, IMM2) _XT_INS_FORMAT_RRR(0x000000, \ + (((IMM1) & 0x0F) << 4) | ((IMM2) & 0x0F), 0x4) +/* 16-bit break */ +#define XT_INS_BREAKN(IMM4) _XT_INS_FORMAT_RRRN(0x00000D, IMM4, 0x2, 0xF) + +#define XT_INS_L32E(R, S, T) _XT_INS_FORMAT_RRI4(0x90000, 0, R, S, T) +#define XT_INS_S32E(R, S, T) _XT_INS_FORMAT_RRI4(0x490000, 0, R, S, T) +#define XT_INS_L32E_S32E_MASK 0xFF000F + +#define XT_INS_RFWO 0x3400 +#define XT_INS_RFWU 0x3500 +#define XT_INS_RFWO_RFWU_MASK 0xFFFFFF + +#define XT_WATCHPOINTS_NUM_MAX 2 + +/* Special register number macro for DDR register. +* this gets used a lot so making a shortcut to it is +* useful. +*/ +#define XT_SR_DDR (xtensa_regs[XT_REG_IDX_OCD_DDR].reg_num) + +/*Same thing for A3/A4 */ +#define XT_REG_A3 (xtensa_regs[XT_REG_IDX_AR3].reg_num) +#define XT_REG_A4 (xtensa_regs[XT_REG_IDX_AR4].reg_num) + +#define XT_PC_REG_NUM_BASE (176) +#define XT_SW_BREAKPOINTS_MAX_NUM 32 + +const struct xtensa_reg_desc xtensa_regs[XT_NUM_REGS] = { + { "pc", XT_PC_REG_NUM_BASE /*+XT_DEBUGLEVEL*/, XT_REG_SPECIAL, 0 }, /* actually epc[debuglevel] */ + { "ar0", 0x00, XT_REG_GENERAL, 0 }, + { "ar1", 0x01, XT_REG_GENERAL, 0 }, + { "ar2", 0x02, XT_REG_GENERAL, 0 }, + { "ar3", 0x03, XT_REG_GENERAL, 0 }, + { "ar4", 0x04, XT_REG_GENERAL, 0 }, + { "ar5", 0x05, XT_REG_GENERAL, 0 }, + { "ar6", 0x06, XT_REG_GENERAL, 0 }, + { "ar7", 0x07, XT_REG_GENERAL, 0 }, + { "ar8", 0x08, XT_REG_GENERAL, 0 }, + { "ar9", 0x09, XT_REG_GENERAL, 0 }, + { "ar10", 0x0A, XT_REG_GENERAL, 0 }, + { "ar11", 0x0B, XT_REG_GENERAL, 0 }, + { "ar12", 0x0C, XT_REG_GENERAL, 0 }, + { "ar13", 0x0D, XT_REG_GENERAL, 0 }, + { "ar14", 0x0E, XT_REG_GENERAL, 0 }, + { "ar15", 0x0F, XT_REG_GENERAL, 0 }, + { "ar16", 0x10, XT_REG_GENERAL, 0 }, + { "ar17", 0x11, XT_REG_GENERAL, 0 }, + { "ar18", 0x12, XT_REG_GENERAL, 0 }, + { "ar19", 0x13, XT_REG_GENERAL, 0 }, + { "ar20", 0x14, XT_REG_GENERAL, 0 }, + { "ar21", 0x15, XT_REG_GENERAL, 0 }, + { "ar22", 0x16, XT_REG_GENERAL, 0 }, + { "ar23", 0x17, XT_REG_GENERAL, 0 }, + { "ar24", 0x18, XT_REG_GENERAL, 0 }, + { "ar25", 0x19, XT_REG_GENERAL, 0 }, + { "ar26", 0x1A, XT_REG_GENERAL, 0 }, + { "ar27", 0x1B, XT_REG_GENERAL, 0 }, + { "ar28", 0x1C, XT_REG_GENERAL, 0 }, + { "ar29", 0x1D, XT_REG_GENERAL, 0 }, + { "ar30", 0x1E, XT_REG_GENERAL, 0 }, + { "ar31", 0x1F, XT_REG_GENERAL, 0 }, + { "ar32", 0x20, XT_REG_GENERAL, 0 }, + { "ar33", 0x21, XT_REG_GENERAL, 0 }, + { "ar34", 0x22, XT_REG_GENERAL, 0 }, + { "ar35", 0x23, XT_REG_GENERAL, 0 }, + { "ar36", 0x24, XT_REG_GENERAL, 0 }, + { "ar37", 0x25, XT_REG_GENERAL, 0 }, + { "ar38", 0x26, XT_REG_GENERAL, 0 }, + { "ar39", 0x27, XT_REG_GENERAL, 0 }, + { "ar40", 0x28, XT_REG_GENERAL, 0 }, + { "ar41", 0x29, XT_REG_GENERAL, 0 }, + { "ar42", 0x2A, XT_REG_GENERAL, 0 }, + { "ar43", 0x2B, XT_REG_GENERAL, 0 }, + { "ar44", 0x2C, XT_REG_GENERAL, 0 }, + { "ar45", 0x2D, XT_REG_GENERAL, 0 }, + { "ar46", 0x2E, XT_REG_GENERAL, 0 }, + { "ar47", 0x2F, XT_REG_GENERAL, 0 }, + { "ar48", 0x30, XT_REG_GENERAL, 0 }, + { "ar49", 0x31, XT_REG_GENERAL, 0 }, + { "ar50", 0x32, XT_REG_GENERAL, 0 }, + { "ar51", 0x33, XT_REG_GENERAL, 0 }, + { "ar52", 0x34, XT_REG_GENERAL, 0 }, + { "ar53", 0x35, XT_REG_GENERAL, 0 }, + { "ar54", 0x36, XT_REG_GENERAL, 0 }, + { "ar55", 0x37, XT_REG_GENERAL, 0 }, + { "ar56", 0x38, XT_REG_GENERAL, 0 }, + { "ar57", 0x39, XT_REG_GENERAL, 0 }, + { "ar58", 0x3A, XT_REG_GENERAL, 0 }, + { "ar59", 0x3B, XT_REG_GENERAL, 0 }, + { "ar60", 0x3C, XT_REG_GENERAL, 0 }, + { "ar61", 0x3D, XT_REG_GENERAL, 0 }, + { "ar62", 0x3E, XT_REG_GENERAL, 0 }, + { "ar63", 0x3F, XT_REG_GENERAL, 0 }, + { "lbeg", 0x00, XT_REG_SPECIAL, 0 }, + { "lend", 0x01, XT_REG_SPECIAL, 0 }, + { "lcount", 0x02, XT_REG_SPECIAL, 0 }, + { "sar", 0x03, XT_REG_SPECIAL, 0 }, + { "windowbase", 0x48, XT_REG_SPECIAL, 0 }, + { "windowstart", 0x49, XT_REG_SPECIAL, 0 }, + { "configid0", 0xB0, XT_REG_SPECIAL, 0 }, + { "configid1", 0xD0, XT_REG_SPECIAL, 0 }, + { "ps", 0xC6, XT_REG_SPECIAL, 0 }, /* actually EPS[debuglevel] */ + { "threadptr", 0xE7, XT_REG_USER, 0 }, + { "br", 0x04, XT_REG_SPECIAL, 0 }, + { "scompare1", 0x0C, XT_REG_SPECIAL, 0 }, + { "acclo", 0x10, XT_REG_SPECIAL, 0 }, + { "acchi", 0x11, XT_REG_SPECIAL, 0 }, + { "m0", 0x20, XT_REG_SPECIAL, 0 }, + { "m1", 0x21, XT_REG_SPECIAL, 0 }, + { "m2", 0x22, XT_REG_SPECIAL, 0 }, + { "m3", 0x23, XT_REG_SPECIAL, 0 }, + { "f0", 0x00, XT_REG_FR, XT_REGF_COPROC0 }, + { "f1", 0x01, XT_REG_FR, XT_REGF_COPROC0 }, + { "f2", 0x02, XT_REG_FR, XT_REGF_COPROC0 }, + { "f3", 0x03, XT_REG_FR, XT_REGF_COPROC0 }, + { "f4", 0x04, XT_REG_FR, XT_REGF_COPROC0 }, + { "f5", 0x05, XT_REG_FR, XT_REGF_COPROC0 }, + { "f6", 0x06, XT_REG_FR, XT_REGF_COPROC0 }, + { "f7", 0x07, XT_REG_FR, XT_REGF_COPROC0 }, + { "f8", 0x08, XT_REG_FR, XT_REGF_COPROC0 }, + { "f9", 0x09, XT_REG_FR, XT_REGF_COPROC0 }, + { "f10", 0x0A, XT_REG_FR, XT_REGF_COPROC0 }, + { "f11", 0x0B, XT_REG_FR, XT_REGF_COPROC0 }, + { "f12", 0x0C, XT_REG_FR, XT_REGF_COPROC0 }, + { "f13", 0x0D, XT_REG_FR, XT_REGF_COPROC0 }, + { "f14", 0x0E, XT_REG_FR, XT_REGF_COPROC0 }, + { "f15", 0x0F, XT_REG_FR, XT_REGF_COPROC0 }, + { "fcr", 0xE8, XT_REG_USER, XT_REGF_COPROC0 }, + { "fsr", 0xE9, XT_REG_USER, XT_REGF_COPROC0 }, + { "mmid", 0x59, XT_REG_SPECIAL, XT_REGF_NOREAD }, + { "ibreakenable", 0x60, XT_REG_SPECIAL, 0 }, + { "memctl", 0x61, XT_REG_SPECIAL, 0 }, + { "atomctl", 0x63, XT_REG_SPECIAL, 0 }, + { "ibreaka0", 0x80, XT_REG_SPECIAL, 0 }, + { "ibreaka1", 0x81, XT_REG_SPECIAL, 0 }, + { "dbreaka0", 0x90, XT_REG_SPECIAL, 0 }, + { "dbreaka1", 0x91, XT_REG_SPECIAL, 0 }, + { "dbreakc0", 0xA0, XT_REG_SPECIAL, 0 }, + { "dbreakc1", 0xA1, XT_REG_SPECIAL, 0 }, + { "epc1", 0xB1, XT_REG_SPECIAL, 0 }, + { "epc2", 0xB2, XT_REG_SPECIAL, 0 }, + { "epc3", 0xB3, XT_REG_SPECIAL, 0 }, + { "epc4", 0xB4, XT_REG_SPECIAL, 0 }, + { "epc5", 0xB5, XT_REG_SPECIAL, 0 }, + { "epc6", 0xB6, XT_REG_SPECIAL, 0 }, + { "epc7", 0xB7, XT_REG_SPECIAL, 0 }, + { "depc", 0xC0, XT_REG_SPECIAL, 0 }, + { "eps2", 0xC2, XT_REG_SPECIAL, 0 }, + { "eps3", 0xC3, XT_REG_SPECIAL, 0 }, + { "eps4", 0xC4, XT_REG_SPECIAL, 0 }, + { "eps5", 0xC5, XT_REG_SPECIAL, 0 }, + { "eps6", 0xC6, XT_REG_SPECIAL, 0 }, + { "eps7", 0xC7, XT_REG_SPECIAL, 0 }, + { "excsave1", 0xD1, XT_REG_SPECIAL, 0 }, + { "excsave2", 0xD2, XT_REG_SPECIAL, 0 }, + { "excsave3", 0xD3, XT_REG_SPECIAL, 0 }, + { "excsave4", 0xD4, XT_REG_SPECIAL, 0 }, + { "excsave5", 0xD5, XT_REG_SPECIAL, 0 }, + { "excsave6", 0xD6, XT_REG_SPECIAL, 0 }, + { "excsave7", 0xD7, XT_REG_SPECIAL, 0 }, + { "cpenable", 0xE0, XT_REG_SPECIAL, 0 }, + { "interrupt", 0xE2, XT_REG_SPECIAL, 0 }, + { "intset", 0xE2, XT_REG_SPECIAL, XT_REGF_NOREAD }, + { "intclear", 0xE3, XT_REG_SPECIAL, XT_REGF_NOREAD }, + { "intenable", 0xE4, XT_REG_SPECIAL, 0 }, + { "vecbase", 0xE7, XT_REG_SPECIAL, 0 }, + { "exccause", 0xE8, XT_REG_SPECIAL, 0 }, + { "debugcause", 0xE9, XT_REG_SPECIAL, 0 }, + { "ccount", 0xEA, XT_REG_SPECIAL, 0 }, + { "prid", 0xEB, XT_REG_SPECIAL, 0 }, + { "icount", 0xEC, XT_REG_SPECIAL, 0 }, + { "icountlevel", 0xED, XT_REG_SPECIAL, 0 }, + { "excvaddr", 0xEE, XT_REG_SPECIAL, 0 }, + { "ccompare0", 0xF0, XT_REG_SPECIAL, 0 }, + { "ccompare1", 0xF1, XT_REG_SPECIAL, 0 }, + { "ccompare2", 0xF2, XT_REG_SPECIAL, 0 }, + { "misc0", 0xF4, XT_REG_SPECIAL, 0 }, + { "misc1", 0xF5, XT_REG_SPECIAL, 0 }, + { "misc2", 0xF6, XT_REG_SPECIAL, 0 }, + { "misc3", 0xF7, XT_REG_SPECIAL, 0 }, + { "litbase", 0x05, XT_REG_SPECIAL, 0 }, + { "ptevaddr", 0x53, XT_REG_SPECIAL, 0 }, + { "rasid", 0x5A, XT_REG_SPECIAL, 0 }, + { "itlbcfg", 0x5B, XT_REG_SPECIAL, 0 }, + { "dtlbcfg", 0x5C, XT_REG_SPECIAL, 0 }, + { "mepc", 0x6A, XT_REG_SPECIAL, 0 }, + { "meps", 0x6B, XT_REG_SPECIAL, 0 }, + { "mesave", 0x6C, XT_REG_SPECIAL, 0 }, + { "mesr", 0x6D, XT_REG_SPECIAL, 0 }, + { "mecr", 0x6E, XT_REG_SPECIAL, 0 }, + { "mevaddr", 0x6F, XT_REG_SPECIAL, 0 }, + { "a0", XT_REG_IDX_AR0, XT_REG_RELGEN, 0 }, /* WARNING: For these registers, regnum points to the */ + { "a1", XT_REG_IDX_AR1, XT_REG_RELGEN, 0 }, /* index of the corresponding ARxregisters, NOT to */ + { "a2", XT_REG_IDX_AR2, XT_REG_RELGEN, 0 }, /* the processor register number! */ + { "a3", XT_REG_IDX_AR3, XT_REG_RELGEN, 0 }, + { "a4", XT_REG_IDX_AR4, XT_REG_RELGEN, 0 }, + { "a5", XT_REG_IDX_AR5, XT_REG_RELGEN, 0 }, + { "a6", XT_REG_IDX_AR6, XT_REG_RELGEN, 0 }, + { "a7", XT_REG_IDX_AR7, XT_REG_RELGEN, 0 }, + { "a8", XT_REG_IDX_AR8, XT_REG_RELGEN, 0 }, + { "a9", XT_REG_IDX_AR9, XT_REG_RELGEN, 0 }, + { "a10", XT_REG_IDX_AR10, XT_REG_RELGEN, 0 }, + { "a11", XT_REG_IDX_AR11, XT_REG_RELGEN, 0 }, + { "a12", XT_REG_IDX_AR12, XT_REG_RELGEN, 0 }, + { "a13", XT_REG_IDX_AR13, XT_REG_RELGEN, 0 }, + { "a14", XT_REG_IDX_AR14, XT_REG_RELGEN, 0 }, + { "a15", XT_REG_IDX_AR15, XT_REG_RELGEN, 0 }, + + { "pwrctl", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pwrstat", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "eristat", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "cs_itctrl", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "cs_claimset", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "cs_claimclr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "cs_lockaccess", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "cs_lockstatus", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "cs_authstatus", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "fault_info", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_id", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_ctrl", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_stat", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_data", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_addr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_pctrigger", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_pcmatch", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_delay", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_memstart", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "trax_memend", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pmg", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pmoc", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pm0", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pm1", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pmctrl0", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pmctrl1", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pmstat0", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "pmstat1", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "ocd_id", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "ocd_dcrclr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "ocd_dcrset", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "ocd_dsr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, + { "ddr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD }, +}; + + +/** + * Types of memory used at xtensa target + */ +enum xtensa_mem_region_type { + XTENSA_MEM_REG_IROM = 0x0, + XTENSA_MEM_REG_IRAM, + XTENSA_MEM_REG_DROM, + XTENSA_MEM_REG_DRAM, + XTENSA_MEM_REG_URAM, + XTENSA_MEM_REG_XLMI, + XTENSA_MEM_REGS_NUM +}; + +/** + * Gets a config for the specific mem type + */ +static inline const struct xtensa_local_mem_config *xtensa_get_mem_config( + struct xtensa *xtensa, + enum xtensa_mem_region_type type) +{ + switch (type) { + case XTENSA_MEM_REG_IROM: + return &xtensa->core_config->irom; + case XTENSA_MEM_REG_IRAM: + return &xtensa->core_config->iram; + case XTENSA_MEM_REG_DROM: + return &xtensa->core_config->drom; + case XTENSA_MEM_REG_DRAM: + return &xtensa->core_config->dram; + case XTENSA_MEM_REG_URAM: + return &xtensa->core_config->uram; + case XTENSA_MEM_REG_XLMI: + return &xtensa->core_config->xlmi; + default: + return NULL; + } +} + +/** + * Extracts an exact xtensa_local_mem_region_config from xtensa_local_mem_config + * for a given address + * Returns NULL if nothing found + */ +static inline const struct xtensa_local_mem_region_config *xtensa_memory_region_find( + const struct xtensa_local_mem_config *mem, + target_addr_t address) +{ + for (unsigned int i = 0; i < mem->count; i++) { + const struct xtensa_local_mem_region_config *region = &mem->regions[i]; + if (address >= region->base && address < (region->base + region->size)) + return region; + } + return NULL; +} + +/** + * Returns a corresponding xtensa_local_mem_region_config from the xtensa target + * for a given address + * Returns NULL if nothing found + */ +static inline const struct xtensa_local_mem_region_config *xtensa_target_memory_region_find( + struct xtensa *xtensa, + target_addr_t address) +{ + const struct xtensa_local_mem_region_config *result; + const struct xtensa_local_mem_config *mcgf; + for (unsigned int mtype = 0; mtype < XTENSA_MEM_REGS_NUM; mtype++) { + mcgf = xtensa_get_mem_config(xtensa, mtype); + result = xtensa_memory_region_find(mcgf, address); + if (result) + return result; + } + return NULL; +} + +static int xtensa_core_reg_get(struct reg *reg) +{ + /*We don't need this because we read all registers on halt anyway. */ + struct xtensa *xtensa = (struct xtensa *)reg->arch_info; + struct target *target = xtensa->target; + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + return ERROR_OK; +} + +static int xtensa_core_reg_set(struct reg *reg, uint8_t *buf) +{ + struct xtensa *xtensa = (struct xtensa *)reg->arch_info; + struct target *target = xtensa->target; + + assert(reg->size <= 64 && "up to 64-bit regs are supported only!"); + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + buf_cpy(buf, reg->value, reg->size); + reg->dirty = true; + reg->valid = true; + + return ERROR_OK; +} + +static const struct reg_arch_... [truncated message content] |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-03 23:46:54
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via b470b664ca7ba3f21684848c3819d696fb3c890a (commit) from 975fb2a4faaaabbacae16a468840dab4b3eb3618 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b470b664ca7ba3f21684848c3819d696fb3c890a Author: Tarek BOCHKATI <tar...@gm...> Date: Thu Apr 14 14:53:10 2022 +0100 cortex_a: get rid of not needed log messages when using semi-hosting with cortex_a this LOG_INFO pollutes openocd console, so just reduce the log level of this message. Change-Id: I91aa70492f4e361b25a0e5517d0cf73f2f8ed599 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: https://gerrit.st.com/c/stm32ide/official/openocd/+/248225 Tested-by: Tarek BOCHKATI <tar...@st...> Reviewed-by: Tarek BOCHKATI <tar...@st...> Reviewed-on: https://review.openocd.org/c/openocd/+/6993 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/armv7a.c b/src/target/armv7a.c index d564f19ae..1e425aa51 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -112,7 +112,7 @@ static int armv7a_read_midr(struct target *target) armv7a->arch = (midr >> 16) & 0xf; armv7a->variant = (midr >> 20) & 0xf; armv7a->implementor = (midr >> 24) & 0xff; - LOG_INFO("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 + LOG_DEBUG("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 ", variant %" PRIx32 ", implementor %" PRIx32, target->cmd_name, armv7a->rev, ----------------------------------------------------------------------- Summary of changes: src/target/armv7a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-03 23:46:41
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 975fb2a4faaaabbacae16a468840dab4b3eb3618 (commit) from 93e2c082d60586a765d925fb59604b315fbf9dc9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 975fb2a4faaaabbacae16a468840dab4b3eb3618 Author: Tarek BOCHKATI <tar...@gm...> Date: Mon May 30 14:48:06 2022 +0100 github/workflow: enable libftdi based adapters Change-Id: I74b07b21573294dd7d9d3caf41c5755622c77149 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/7008 Tested-by: jenkins Reviewed-by: Xiaofan Chen <xia...@gm...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 0de0cf3f6..e5997a055 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -38,6 +38,14 @@ jobs: cd hidapi-hidapi-${HIDAPI_VER} ./bootstrap echo "HIDAPI_SRC=$PWD" >> $GITHUB_ENV + - name: Prepare libftdi + env: + LIBFTDI_VER: 1.5 + run: | + mkdir -p $DL_DIR && cd $DL_DIR + wget "http://www.intra2net.com/en/developer/libftdi/download/libftdi1-${LIBFTDI_VER}.tar.bz2" + tar -xjf libftdi1-${LIBFTDI_VER}.tar.bz2 + echo "LIBFTDI_SRC=$PWD/libftdi1-${LIBFTDI_VER}" >> $GITHUB_ENV - name: Prepare capstone env: CAPSTONE_VER: 4.0.2 @@ -54,6 +62,7 @@ jobs: HOST: i686-w64-mingw32 LIBUSB1_CONFIG: --enable-shared --disable-static HIDAPI_CONFIG: --enable-shared --disable-static --disable-testgui + LIBFTDI_CONFIG: -DSTATICLIBS=OFF -DEXAMPLES=OFF -DFTDI_EEPROM=OFF CAPSTONE_CONFIG: "CAPSTONE_BUILD_CORE_ONLY=yes CAPSTONE_STATIC=yes CAPSTONE_SHARED=no" run: | # check if there is tag pointing at HEAD, otherwise take the HEAD SHA-1 as OPENOCD_TAG diff --git a/contrib/cross-build.sh b/contrib/cross-build.sh index 7c572f55d..9328c3ab6 100755 --- a/contrib/cross-build.sh +++ b/contrib/cross-build.sh @@ -121,11 +121,17 @@ fi if [ -d $LIBFTDI_SRC ] ; then mkdir -p $LIBFTDI_BUILD_DIR cd $LIBFTDI_BUILD_DIR - # libftdi requires libusb1 static libraries, granted by: - # export LIBUSB1_CONFIG="--enable-static ..." + # note : libftdi versions < 1.5 requires libusb1 static + # hint use : # export LIBUSB1_CONFIG="--enable-static ..." + # not needed since libftdi-1.5 when LIBFTDI_CONFIG="-DSTATICLIBS=OFF ..." + + # fix <toolchain>.cmake file + ESCAPED_SYSROOT=$(printf '%s\n' "$SYSROOT" | sed -e 's/[\/&]/\\&/g') + sed -i -E "s/(SET\(CMAKE_FIND_ROOT_PATH\s+).+\)/\1${ESCAPED_SYSROOT})/" \ + ${LIBFTDI_SRC}/cmake/Toolchain-${HOST_TRIPLET}.cmake + cmake $LIBFTDI_CONFIG \ - -DLIBUSB_INCLUDE_DIR=${SYSROOT}${PREFIX}/include/libusb-1.0 \ - -DLIBUSB_LIBRARIES=${SYSROOT}${PREFIX}/lib/libusb-1.0.a \ + -DCMAKE_TOOLCHAIN_FILE=${LIBFTDI_SRC}/cmake/Toolchain-${HOST_TRIPLET}.cmake \ -DCMAKE_INSTALL_PREFIX=${PREFIX} \ -DPKG_CONFIG_EXECUTABLE=`which pkg-config` \ $LIBFTDI_SRC ----------------------------------------------------------------------- Summary of changes: .github/workflows/snapshot.yml | 9 +++++++++ contrib/cross-build.sh | 14 ++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-06-03 23:46:23
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 93e2c082d60586a765d925fb59604b315fbf9dc9 (commit) from cc8b491856c9fee675732dc21a2307f5c9617f54 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 93e2c082d60586a765d925fb59604b315fbf9dc9 Author: Tarek BOCHKATI <tar...@gm...> Date: Mon May 23 13:57:16 2022 +0100 github workflow: use libusb 1.0.26 and hidapi 0.11.2 Change-Id: Id5348f86026330581d4bae081c9ab2bef435e6a6 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: https://review.openocd.org/c/openocd/+/6992 Tested-by: jenkins Reviewed-by: Xiaofan Chen <xia...@gm...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 96a2d34f2..0de0cf3f6 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -22,7 +22,7 @@ jobs: - run: ./bootstrap - name: Prepare libusb1 env: - LIBUSB1_VER: 1.0.24 + LIBUSB1_VER: 1.0.26 run: | mkdir -p $DL_DIR && cd $DL_DIR wget "https://github.com/libusb/libusb/releases/download/v${LIBUSB1_VER}/libusb-${LIBUSB1_VER}.tar.bz2" @@ -30,7 +30,7 @@ jobs: echo "LIBUSB1_SRC=$PWD/libusb-${LIBUSB1_VER}" >> $GITHUB_ENV - name: Prepare hidapi env: - HIDAPI_VER: 0.10.1 + HIDAPI_VER: 0.11.2 run: | mkdir -p $DL_DIR && cd $DL_DIR wget "https://github.com/libusb/hidapi/archive/hidapi-${HIDAPI_VER}.tar.gz" ----------------------------------------------------------------------- Summary of changes: .github/workflows/snapshot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-05-29 15:48:24
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via cc8b491856c9fee675732dc21a2307f5c9617f54 (commit) from bce93f6d513b373c1fbfb42a12cfeb2305d5e822 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit cc8b491856c9fee675732dc21a2307f5c9617f54 Author: Tomas Vanek <va...@fb...> Date: Fri Nov 19 22:03:44 2021 +0100 flash/nor/core, target: don't ask for working mem if no target algo The command 'flash erase_check' showed the message 'Running slow fallback erase check - add working memory' even in the case the target didn't implement blank_check_memory. Change return code of target_blank_check_memory() in this case and sense it in default_flash_blank_check() and show a message without a request for working memory. Change-Id: I7cf9bf77742964b4f377c9ce48ca689e57d0882f Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: https://review.openocd.org/c/openocd/+/6765 Tested-by: jenkins Reviewed-by: Tim Newsome <ti...@si...> diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 30d387ae0..f4ff5dfb3 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -429,7 +429,11 @@ int default_flash_blank_check(struct flash_bank *bank) bank->sectors[i].is_erased = block_array[i].result; retval = ERROR_OK; } else { - LOG_USER("Running slow fallback erase check - add working memory"); + if (retval == ERROR_NOT_IMPLEMENTED) + LOG_USER("Running slow fallback erase check"); + else + LOG_USER("Running slow fallback erase check - add working memory"); + retval = default_flash_mem_blank_check(bank); } free(block_array); diff --git a/src/target/target.c b/src/target/target.c index 596364cdc..76327b1c7 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2590,7 +2590,7 @@ int target_blank_check_memory(struct target *target, } if (!target->type->blank_check_memory) - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + return ERROR_NOT_IMPLEMENTED; return target->type->blank_check_memory(target, blocks, num_blocks, erased_value); } ----------------------------------------------------------------------- Summary of changes: src/flash/nor/core.c | 6 +++++- src/target/target.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-05-27 22:53:03
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via bce93f6d513b373c1fbfb42a12cfeb2305d5e822 (commit) from 390720c283992a0a6e8d7aea94924a15d3c8e900 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit bce93f6d513b373c1fbfb42a12cfeb2305d5e822 Author: Tim Newsome <ti...@si...> Date: Mon May 16 10:22:32 2022 -0700 Give each SMP group a unique number. This helps e.g. if there are 8 cores, and cores 0--3 are in one SMP group while 4--7 are in another group. (And there are 2 gdb instances connected, one debugging the first group, and one the second.) Signed-off-by: Tim Newsome <ti...@si...> Change-Id: I7b6c9382eadf964529105eaf0411a42d48768668 Reviewed-on: https://review.openocd.org/c/openocd/+/6979 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/target.c b/src/target/target.c index 8edd63291..596364cdc 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -6444,6 +6444,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int i; const char *targetname; int retval, len; + static int smp_group = 1; struct target *target = NULL; struct target_list *head, *new; @@ -6475,9 +6476,10 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* now parse the list of cpu and put the target in smp mode*/ foreach_smp_target(head, lh) { target = head->target; - target->smp = 1; + target->smp = smp_group; target->smp_targets = lh; } + smp_group++; if (target && target->rtos) retval = rtos_smp_init(target); diff --git a/src/target/target.h b/src/target/target.h index 1f1a35420..45ef96269 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -200,7 +200,7 @@ struct target { bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto" * and must be detected when symbols are offered */ struct backoff_timer backoff; - int smp; /* add some target attributes for smp support */ + int smp; /* Unique non-zero number for each SMP group */ struct list_head *smp_targets; /* list all targets in this smp group/cluster * The head of the list is shared between the * cluster, thus here there is a pointer */ ----------------------------------------------------------------------- Summary of changes: src/target/target.c | 4 +++- src/target/target.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-05-27 22:51:11
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 390720c283992a0a6e8d7aea94924a15d3c8e900 (commit) from 9d8b98da69f1cbbce3f8963be643cc2b4d07ff56 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 390720c283992a0a6e8d7aea94924a15d3c8e900 Author: Sean Anderson <sea...@se...> Date: Fri May 13 11:12:58 2022 -0400 tcl: Add support for Kontron SMARC-sAL28 This commit is adapted from [1]. [1] https://review.openocd.org/c/openocd/+/4999 Signed-off-by: Michael Walle <mic...@ko...> Signed-off-by: Heiko Thiery <hei...@ko...> [ adapted to use common configuration ] Signed-off-by: Sean Anderson <sea...@se...> Change-Id: I9a428371694e7864e03055b8de18a55a7843b8c2 Reviewed-on: https://review.openocd.org/c/openocd/+/6977 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/tcl/board/kontron_sl28.cfg b/tcl/board/kontron_sl28.cfg new file mode 100644 index 000000000..9816f3802 --- /dev/null +++ b/tcl/board/kontron_sl28.cfg @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Kontron SMARC-sAL28 + +transport select jtag +reset_config srst_only srst_nogate + +jtag newtap unknown0 tap -irlen 12 + +set _CPUS 2 +source [find target/ls1028a.cfg] + +source [find tcl/cpld/altera-epm240.cfg] + +adapter speed 2000 ----------------------------------------------------------------------- Summary of changes: tcl/board/kontron_sl28.cfg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tcl/board/kontron_sl28.cfg hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2022-05-27 22:49:14
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 9d8b98da69f1cbbce3f8963be643cc2b4d07ff56 (commit) from 32b3859258abb97248a52e4c65b1fbce7581fab5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9d8b98da69f1cbbce3f8963be643cc2b4d07ff56 Author: Sean Anderson <sea...@se...> Date: Fri May 13 11:07:29 2022 -0400 target: Add LS1028A The LS1028A is similar to the LS1088A, except that it has 2 CPUs (and different ethernet capabilities). From a JTAG perspective, all that's different is the number of CPUs and the TAPID. Signed-off-by: Sean Anderson <sea...@se...> Change-Id: Iba3a0ecfbf82cfcfeb7eea42d52121c3b9dc93a2 Reviewed-on: https://review.openocd.org/c/openocd/+/6976 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/tcl/target/ls1028a.cfg b/tcl/target/ls1028a.cfg new file mode 100644 index 000000000..463ec7dda --- /dev/null +++ b/tcl/target/ls1028a.cfg @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# NXP LS1028A + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME ls1028a +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x6ba00477 +} + +set _CPUS 2 + +source [find target/lsch3_common.cfg] ----------------------------------------------------------------------- Summary of changes: tcl/target/{ls1088a.cfg => ls1028a.cfg} | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) copy tcl/target/{ls1088a.cfg => ls1028a.cfg} (63%) hooks/post-receive -- Main OpenOCD repository |