adi_v5: search for Debug and Memory AP support
[openocd.git] / src / target / arm_adi_v5.c
index 1ef7c1a004aa6e202befe704984a27459ca08cda..1572861dc2c2157ad630d3cbcbd033eb9acaff2f 100644 (file)
@@ -69,6 +69,7 @@
 #include "config.h"
 #endif
 
+#include "jtag/interface.h"
 #include "arm.h"
 #include "arm_adi_v5.h"
 #include <helper/time_support.h>
@@ -261,16 +262,17 @@ int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address,
 
 /*****************************************************************************
 *                                                                            *
-* mem_ap_write_buf(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address) *
+* mem_ap_write_buf(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address, bool addr_incr) *
 *                                                                            *
 * Write a buffer in target order (little endian)                             *
 *                                                                            *
 *****************************************************************************/
-int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count, uint32_t address)
+int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count, uint32_t address, bool addr_incr)
 {
        int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
        uint32_t adr = address;
        const uint8_t *pBuffer = buffer;
+       uint32_t incr_flag = CSW_ADDRINC_OFF;
 
        count >>= 2;
        wcount = count;
@@ -301,13 +303,17 @@ int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count
                if (blocksize == 0)
                        blocksize = 1;
 
-               retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               if (addr_incr)
+                       incr_flag = CSW_ADDRINC_SINGLE;
+
+               retval = dap_setup_accessport(dap, CSW_32BIT | incr_flag, address);
                if (retval != ERROR_OK)
                        return retval;
 
                for (writecount = 0; writecount < blocksize; writecount++) {
-                       retval = dap_queue_ap_write(dap, AP_REG_DRW,
-                               *(uint32_t *) ((void *) (buffer + 4 * writecount)));
+                       uint32_t tmp;
+                       tmp = buf_get_u32(buffer + 4 * writecount, 0, 32);
+                       retval = dap_queue_ap_write(dap, AP_REG_DRW, tmp);
                        if (retval != ERROR_OK)
                                break;
                }
@@ -315,7 +321,8 @@ int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count
                retval = dap_run(dap);
                if (retval == ERROR_OK) {
                        wcount = wcount - blocksize;
-                       address = address + 4 * blocksize;
+                       if (addr_incr)
+                               address = address + 4 * blocksize;
                        buffer = buffer + 4 * blocksize;
                } else
                        errorcount++;
@@ -545,14 +552,16 @@ extern int adi_jtag_dp_scan(struct adiv5_dap *dap,
  * @param buffer where the words will be stored (in host byte order).
  * @param count How many words to read.
  * @param address Memory address from which to read words; all the
+ * @param addr_incr if true, increment the source address for each u32
  *     words must be readable by the currently selected MEM-AP.
  */
 int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
-               int count, uint32_t address)
+               int count, uint32_t address, bool addr_incr)
 {
        int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
        uint32_t adr = address;
        uint8_t *pBuffer = buffer;
+       uint32_t incr_flag = CSW_ADDRINC_OFF;
 
        count >>= 2;
        wcount = count;
@@ -571,7 +580,10 @@ int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
                if (blocksize == 0)
                        blocksize = 1;
 
-               retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_SINGLE,
+               if (addr_incr)
+                       incr_flag = CSW_ADDRINC_SINGLE;
+
+               retval = dap_setup_accessport(dap, CSW_32BIT | incr_flag,
                                address);
                if (retval != ERROR_OK)
                        return retval;
@@ -620,7 +632,8 @@ int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
                        return retval;
                }
                wcount = wcount - blocksize;
-               address += 4 * blocksize;
+               if (addr_incr)
+                       address += 4 * blocksize;
                buffer += 4 * blocksize;
        }
 
@@ -879,11 +892,18 @@ int mem_ap_sel_read_buf_u16(struct adiv5_dap *swjdp, uint8_t ap,
        return mem_ap_read_buf_u16(swjdp, buffer, count, address);
 }
 
+int mem_ap_sel_read_buf_u32_noincr(struct adiv5_dap *swjdp, uint8_t ap,
+               uint8_t *buffer, int count, uint32_t address)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_read_buf_u32(swjdp, buffer, count, address, false);
+}
+
 int mem_ap_sel_read_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
                uint8_t *buffer, int count, uint32_t address)
 {
        dap_ap_select(swjdp, ap);
-       return mem_ap_read_buf_u32(swjdp, buffer, count, address);
+       return mem_ap_read_buf_u32(swjdp, buffer, count, address, true);
 }
 
 int mem_ap_sel_write_buf_u8(struct adiv5_dap *swjdp, uint8_t ap,
@@ -904,7 +924,14 @@ int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
                const uint8_t *buffer, int count, uint32_t address)
 {
        dap_ap_select(swjdp, ap);
-       return mem_ap_write_buf_u32(swjdp, buffer, count, address);
+       return mem_ap_write_buf_u32(swjdp, buffer, count, address, true);
+}
+
+int mem_ap_sel_write_buf_u32_noincr(struct adiv5_dap *swjdp, uint8_t ap,
+               const uint8_t *buffer, int count, uint32_t address)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_write_buf_u32(swjdp, buffer, count, address, false);
 }
 
 #define MDM_REG_STAT           0x00
@@ -977,10 +1004,7 @@ int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
                        /* we need to assert reset */
                        if (jtag_reset_config & RESET_HAS_SRST) {
                                /* default to asserting srst */
-                               if (jtag_reset_config & RESET_SRST_PULLS_TRST)
-                                       jtag_add_reset(1, 1);
-                               else
-                                       jtag_add_reset(0, 1);
+                               adapter_assert_reset();
                        } else {
                                LOG_DEBUG("SRST not configured");
                                dap_ap_select(dap, 0);
@@ -1098,14 +1122,6 @@ int ahbap_debugport_init(struct adiv5_dap *dap)
 
        LOG_DEBUG(" ");
 
-       /* test for initialized low level jtag hardware
-        * this always fails for stlink hardware
-        */
-       if (!dap->jtag_info) {
-               LOG_DEBUG("No low level jtag hardware found");
-               return ERROR_OK;
-       }
-
        /* JTAG-DP or SWJ-DP, in JTAG mode
         * ... for SWD mode this is patched as part
         * of link switchover
@@ -1205,6 +1221,60 @@ static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t
                        && ((cid1 & 0x0f) == 0) && cid0 == 0x0d;
 }
 
+/*
+ * This function checks the ID for each access port to find the requested Access Port type
+ */
+int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_num_out)
+{
+       int ap;
+
+       /* Maximum AP number is 255 since the SELECT register is 8 bits */
+       for (ap = 0; ap <= 255; ap++) {
+
+               /* read the IDR register of the Access Port */
+               uint32_t id_val = 0;
+               dap_ap_select(dap, ap);
+
+               int retval = dap_queue_ap_read(dap, AP_REG_IDR, &id_val);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = dap_run(dap);
+
+               /* IDR bits:
+                * 31-28 : Revision
+                * 27-24 : JEDEC bank (0x4 for ARM)
+                * 23-17 : JEDEC code (0x3B for ARM)
+                * 16    : Mem-AP
+                * 15-8  : Reserved
+                *  7-0  : AP Identity (1=AHB-AP 2=APB-AP 0x10=JTAG-AP)
+                */
+
+               /* Reading register for a non-existant AP should not cause an error,
+                * but just to be sure, try to continue searching if an error does happen.
+                */
+               if ((retval == ERROR_OK) &&                  /* Register read success */
+                       ((id_val & 0x0FFF0000) == 0x04770000) && /* Jedec codes match */
+                       ((id_val & 0xFF) == type_to_find)) {     /* type matches*/
+
+                       LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08X)",
+                                               (type_to_find == AP_TYPE_AHB_AP)  ? "AHB-AP"  :
+                                               (type_to_find == AP_TYPE_APB_AP)  ? "APB-AP"  :
+                                               (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown",
+                                               ap, id_val);
+
+                       *ap_num_out = ap;
+                       return ERROR_OK;
+               }
+       }
+
+       LOG_DEBUG("No %s found",
+                               (type_to_find == AP_TYPE_AHB_AP)  ? "AHB-AP"  :
+                               (type_to_find == AP_TYPE_APB_AP)  ? "APB-AP"  :
+                               (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown");
+       return ERROR_FAIL;
+}
+
 int dap_get_debugbase(struct adiv5_dap *dap, int ap,
                        uint32_t *out_dbgbase, uint32_t *out_apid)
 {
@@ -1275,6 +1345,8 @@ int dap_lookup_cs_component(struct adiv5_dap *dap, int ap,
                        retval = mem_ap_read_atomic_u32(dap,
                                        (component_base & 0xfffff000) | 0xfcc,
                                        &devtype);
+                       if (retval != ERROR_OK)
+                               return retval;
                        if ((devtype & 0xff) == type) {
                                *addr = component_base;
                                retval = ERROR_OK;
@@ -1594,6 +1666,10 @@ static int dap_info_command(struct command_context *cmd_ctx,
                                        type = "Cortex-M3 FBP";
                                        full = "(Flash Patch and Breakpoint)";
                                        break;
+                               case 0x00c:
+                                       type = "Cortex-M4 SCS";
+                                       full = "(System Control Space)";
+                                       break;
                                case 0x00d:
                                        type = "CoreSight ETM11";
                                        full = "(Embedded Trace)";
@@ -1643,10 +1719,18 @@ static int dap_info_command(struct command_context *cmd_ctx,
                                        type = "Cortex-M3 ETM";
                                        full = "(Embedded Trace)";
                                        break;
+                               case 0x925:
+                                       type = "Cortex-M4 ETM";
+                                       full = "(Embedded Trace)";
+                                       break;
                                case 0x930:
                                        type = "Cortex-R4 ETM";
                                        full = "(Embedded Trace)";
                                        break;
+                               case 0x9a1:
+                                       type = "Cortex-M4 TPUI";
+                                       full = "(Trace Port Interface Unit)";
+                                       break;
                                case 0xc08:
                                        type = "Cortex-A8 Debug";
                                        full = "(Debug Unit)";

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)