From f97915f248d7e3e7db49139b4fbb40e1e480ed53 Mon Sep 17 00:00:00 2001 From: Jacek Wuwer Date: Wed, 4 May 2022 10:15:57 +0200 Subject: [PATCH 0001/1312] drivers/vdebug: add support for DAP level interface This patch adds support for DAP interface to Cadence vdebug driver. It implements a new transport layer for dapdirect_swd. Change-Id: I64b02a9e1ce91e552e07fca692879655496f88b6 Signed-off-by: Jacek Wuwer Reviewed-on: https://review.openocd.org/c/openocd/+/6965 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 4 +- src/jtag/drivers/vdebug.c | 534 +++++++++++++++++++++++-------- tcl/board/vd_a53x2_dap.cfg | 29 ++ tcl/board/vd_a53x2_jtag.cfg | 2 +- tcl/board/vd_m4_dap.cfg | 26 ++ tcl/board/vd_m4_jtag.cfg | 2 +- tcl/board/vd_m7_jtag.cfg | 30 ++ tcl/board/vd_pulpissimo_jtag.cfg | 2 +- tcl/board/vd_swerv_jtag.cfg | 2 +- tcl/target/vd_riscv.cfg | 3 +- 10 files changed, 488 insertions(+), 146 deletions(-) create mode 100644 tcl/board/vd_a53x2_dap.cfg create mode 100644 tcl/board/vd_m4_dap.cfg create mode 100644 tcl/board/vd_m7_jtag.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index b213798c31..03bb508479 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -594,8 +594,8 @@ produced, PDF schematics are easily found and it is easy to make. @item @b{vdebug} @* A driver for Cadence virtual Debug Interface to emulated or simulated targets. It implements a client connecting to the vdebug server, which in turn communicates -with the emulated or simulated RTL model through a transactor. The current version -supports only JTAG as a transport, but other virtual transports, like DAP are planned. +with the emulated or simulated RTL model through a transactor. The driver supports +JTAG and DAP-level transports. @item @b{jtag_dpi} @* A JTAG driver acting as a client for the SystemVerilog Direct Programming diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index a81740cb18..035c1bee26 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ /*---------------------------------------------------------------------------- - * Copyright 2020-2021 Cadence Design Systems, Inc. + * Copyright 2020-2022 Cadence Design Systems, Inc. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -27,9 +27,9 @@ * @file * * @brief the virtual debug interface provides a connection between a sw debugger - * and the simulated, emulated core over a soft connection, implemented by DPI - * The vdebug debug driver currently supports JTAG transport - * TODO: implement support and test big endian platforms + * and the simulated, emulated core. The openOCD client connects via TCP sockets + * with vdebug server and over DPI-based transactor with the emulation or simulation + * The vdebug debug driver supports JTAG and DAP-level transports * */ @@ -68,16 +68,18 @@ #include "jtag/interface.h" #include "jtag/commands.h" #include "transport/transport.h" +#include "target/arm_adi_v5.h" #include "helper/time_support.h" #include "helper/replacements.h" #include "helper/log.h" +#include "helper/list.h" -#define VD_VERSION 43 +#define VD_VERSION 44 #define VD_BUFFER_LEN 4024 #define VD_CHEADER_LEN 24 #define VD_SHEADER_LEN 16 -#define VD_MAX_MEMORIES 4 +#define VD_MAX_MEMORIES 20 #define VD_POLL_INTERVAL 500 #define VD_SCALE_PSTOMS 1000000000 @@ -149,12 +151,21 @@ enum { VD_CMD_SIGSET = 0x0a, VD_CMD_SIGGET = 0x0b, VD_CMD_JTAGCLOCK = 0x0f, + VD_CMD_REGWRITE = 0x15, + VD_CMD_REGREAD = 0x16, VD_CMD_JTAGSHTAP = 0x1a, VD_CMD_MEMOPEN = 0x21, VD_CMD_MEMCLOSE = 0x22, VD_CMD_MEMWRITE = 0x23, }; +enum { + VD_ASPACE_AP = 0x01, + VD_ASPACE_DP = 0x02, + VD_ASPACE_ID = 0x03, + VD_ASPACE_AB = 0x04, +}; + enum { VD_BATCH_NO = 0, VD_BATCH_WO = 1, @@ -165,37 +176,32 @@ struct vd_shm { struct { /* VD_CHEADER_LEN written by client */ uint8_t cmd; /* 000; command */ uint8_t type; /* 001; interface type */ - uint16_t waddr; /* 002; write pointer */ - uint16_t wbytes; /* 004; data bytes */ - uint16_t rbytes; /* 006; data bytes to read */ - uint16_t wwords; /* 008; data words */ - uint16_t rwords; /* 00a; data words to read */ - uint32_t rwdata; /* 00c; read/write data */ - uint32_t offset; /* 010; address offset */ - uint16_t offseth; /* 014; address offset 47:32 */ - uint16_t wid; /* 016; request id*/ - }; - union { /* 018; */ - uint8_t wd8[VD_BUFFER_LEN]; - uint16_t wd16[VD_BUFFER_LEN / 2]; - uint32_t wd32[VD_BUFFER_LEN / 4]; - uint64_t wd64[VD_BUFFER_LEN / 8]; + uint8_t waddr[2]; /* 002; write pointer */ + uint8_t wbytes[2]; /* 004; data bytes */ + uint8_t rbytes[2]; /* 006; data bytes to read */ + uint8_t wwords[2]; /* 008; data words */ + uint8_t rwords[2]; /* 00a; data words to read */ + uint8_t rwdata[4]; /* 00c; read/write data */ + uint8_t offset[4]; /* 010; address offset */ + uint8_t offseth[2]; /* 014; address offset 47:32 */ + uint8_t wid[2]; /* 016; request id*/ }; + uint8_t wd8[VD_BUFFER_LEN]; /* 018; */ struct { /* VD_SHEADER_LEN written by server */ - uint16_t rid; /* fd0: request id read */ - uint16_t awords; /* fd2: actual data words read back */ - int32_t status; /* fd4; */ - uint64_t duttime; /* fd8; */ + uint8_t rid[2]; /* fd0: request id read */ + uint8_t awords[2]; /* fd2: actual data words read back */ + uint8_t status[4]; /* fd4; */ + uint8_t duttime[8]; /* fd8; */ }; - union { /* fe0: */ - uint8_t rd8[VD_BUFFER_LEN]; - uint16_t rd16[VD_BUFFER_LEN / 2]; - uint32_t rd32[VD_BUFFER_LEN / 4]; - uint64_t rd64[VD_BUFFER_LEN / 8]; - }; - uint32_t state; /* 1f98; connection state */ - uint32_t count; /* 1f9c; */ + uint8_t rd8[VD_BUFFER_LEN]; /* fe0: */ + uint8_t state[4]; /* 1f98; connection state */ + uint8_t count[4]; /* 1f9c; */ uint8_t dummy[96]; /* 1fa0; 48+40B+8B; */ +} __attribute__((packed)); + +struct vd_rdata { + struct list_head lh; + uint8_t *rdata; }; struct vd_client { @@ -222,7 +228,7 @@ struct vd_client { char server_name[32]; char bfm_path[128]; char mem_path[VD_MAX_MEMORIES][128]; - uint8_t *tdo; + struct vd_rdata rdataq; }; struct vd_jtag_hdr { @@ -234,6 +240,16 @@ struct vd_jtag_hdr { uint64_t rlen:16; }; +struct vd_reg_hdr { + uint64_t prot:3; + uint64_t nonincr:1; + uint64_t haddr:12; + uint64_t tlen:11; + uint64_t asize:3; + uint64_t cmd:2; + uint64_t addr:32; +}; + static struct vd_shm *pbuf; static struct vd_client vdc; @@ -277,7 +293,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port) LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr, vdebug_socket_error()); rc = VD_ERR_SOC_ADDR; } else { - ((struct sockaddr_in *)(ainfo->ai_addr))->sin_port = htons(port); + buf_set_u32((uint8_t *)ainfo->ai_addr->sa_data, 0, 16, htons(port)); if (connect(hsock, ainfo->ai_addr, sizeof(struct sockaddr)) < 0) { LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr, port, vdebug_socket_error()); rc = VD_ERR_SOC_CONN; @@ -299,8 +315,8 @@ static int vdebug_socket_receive(int hsock, struct vd_shm *pmem) { int rc; int dreceived = 0; - int offset = (uint8_t *)&pmem->rid - &pmem->cmd; - int to_receive = VD_SHEADER_LEN + pmem->rbytes; + int offset = &pmem->rid[0] - &pmem->cmd; + int to_receive = VD_SHEADER_LEN + le_to_h_u16(pmem->rbytes); char *pb = (char *)pmem; do { @@ -320,7 +336,7 @@ static int vdebug_socket_receive(int hsock, struct vd_shm *pmem) static int vdebug_socket_send(int hsock, struct vd_shm *pmem) { - int rc = send(hsock, (const char *)&pmem->cmd, VD_CHEADER_LEN + pmem->wbytes, 0); + int rc = send(hsock, (const char *)&pmem->cmd, VD_CHEADER_LEN + le_to_h_u16(pmem->wbytes), 0); if (rc <= 0) LOG_WARNING("socket_send: send failed, error %d", vdebug_socket_error()); else @@ -333,6 +349,7 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem) { if (!hsock) return VD_ERR_SOC_OPEN; + int st = vdebug_socket_send(hsock, pmem); if (st <= 0) return VD_ERR_SOC_SEND; @@ -341,9 +358,9 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem) if (rd <= 0) return VD_ERR_SOC_RECV; - int rc = pmem->status; + int rc = le_to_h_u32(pmem->status); LOG_DEBUG_IO("wait_server: cmd %02" PRIx8 " done, sent %d, rcvd %d, status %d", - pmem->cmd, st, rd, rc); + pmem->cmd, st, rd, rc); return rc; } @@ -356,22 +373,23 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count) int64_t ts, te; uint8_t *tdo; int rc; - struct vd_jtag_hdr *hdr; + uint64_t jhdr; + struct vd_rdata *rd; req = 0; /* beginning of request */ waddr = 0; rwords = 0; - pm->wbytes = pm->wwords * vdc.buf_width; - pm->rbytes = pm->rwords * vdc.buf_width; + h_u16_to_le(pm->wbytes, le_to_h_u16(pm->wwords) * vdc.buf_width); + h_u16_to_le(pm->rbytes, le_to_h_u16(pm->rwords) * vdc.buf_width); ts = timeval_ms(); rc = vdebug_wait_server(hsock, pm); while (!rc && (req < count)) { /* loop over requests to read data and print out */ - hdr = (struct vd_jtag_hdr *)&pm->wd8[waddr * 4]; - hwords = hdr->wlen; - words = hdr->rlen; - anum = hdr->tlen; - num_pre = hdr->pre; - num_post = hdr->post; + jhdr = le_to_h_u64(&pm->wd8[waddr * 4]); + words = jhdr >> 48; + hwords = (jhdr >> 32) & 0xffff; + anum = jhdr & 0xffffff; + num_pre = (jhdr >> 27) & 0x7; + num_post = (jhdr >> 24) & 0x7; if (num_post) num = anum - num_pre - num_post + 1; else @@ -379,21 +397,29 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count) bytes = (num + 7) / 8; vdc.trans_last = (req + 1) < count ? 0 : 1; vdc.trans_first = waddr ? 0 : 1; - if (hdr->cmd == 3) { /* read */ - tdo = vdc.tdo; + if (((jhdr >> 30) & 0x3) == 3) { /* cmd is read */ + if (!rwords) { + rd = &vdc.rdataq; + tdo = rd->rdata; + } else { + rd = list_first_entry(&vdc.rdataq.lh, struct vd_rdata, lh); + tdo = rd->rdata; + list_del(&rd->lh); + free(rd); + } for (unsigned int j = 0; j < bytes; j++) { tdo[j] = (pm->rd8[rwords * 8 + j] >> num_pre) | (pm->rd8[rwords * 8 + j + 1] << (8 - num_pre)); - LOG_DEBUG_IO("%04x D0[%02x]:%02x", pm->wid - count + req, j, tdo[j]); + LOG_DEBUG_IO("%04x D0[%02x]:%02x", le_to_h_u16(pm->wid) - count + req, j, tdo[j]); } rwords += words; /* read data offset */ } else { tdo = NULL; } - waddr += sizeof(struct vd_jtag_hdr) / 4; /* waddr past header */ + waddr += sizeof(uint64_t) / 4; /* waddr past header */ tdi = (pm->wd8[waddr * 4] >> num_pre) | (pm->wd8[waddr * 4 + 1] << (8 - num_pre)); tms = (pm->wd8[waddr * 4 + 4] >> num_pre) | (pm->wd8[waddr * 4 + 4 + 1] << (8 - num_pre)); - LOG_DEBUG("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x", - pm->wid - count + req, num, (vdc.trans_first << 14) | (vdc.trans_last << 15), + LOG_DEBUG_IO("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x", + le_to_h_u16(pm->wid) - count + req, num, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr - 2, tdi, tms, (tdo ? tdo[0] : 0xdd)); waddr += hwords * 2; /* start of next request */ req += 1; @@ -406,10 +432,83 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count) te = timeval_ms(); vdc.targ_time += (uint32_t)(te - ts); - pm->offseth = 0; /* reset buffer write address */ - pm->offset = 0; - pm->rwords = 0; - pm->waddr = 0; + h_u16_to_le(pm->offseth, 0); /* reset buffer write address */ + h_u32_to_le(pm->offset, 0); + h_u16_to_le(pm->rwords, 0); + h_u16_to_le(pm->waddr, 0); + assert(list_empty(&vdc.rdataq.lh));/* list should be empty after run queue */ + + return rc; +} + +int vdebug_run_reg_queue(int hsock, struct vd_shm *pm, unsigned int count) +{ + unsigned int num, awidth, wwidth; + unsigned int req, waddr, rwords; + uint8_t aspace; + uint32_t addr; + int64_t ts, te; + uint8_t *data; + int rc; + uint64_t rhdr; + struct vd_rdata *rd; + + req = 0; /* beginning of request */ + waddr = 0; + rwords = 0; + h_u16_to_le(pm->wbytes, le_to_h_u16(pm->wwords) * vdc.buf_width); + h_u16_to_le(pm->rbytes, le_to_h_u16(pm->rwords) * vdc.buf_width); + ts = timeval_ms(); + rc = vdebug_wait_server(hsock, pm); + while (!rc && (req < count)) { /* loop over requests to read data and print out */ + rhdr = le_to_h_u64(&pm->wd8[waddr * 4]); + addr = rhdr >> 32; /* reconstruct data for a single request */ + num = (rhdr >> 16) & 0x7ff; + aspace = rhdr & 0x3; + awidth = (1 << ((rhdr >> 27) & 0x7)); + wwidth = (awidth + vdc.buf_width - 1) / vdc.buf_width; + vdc.trans_last = (req + 1) < count ? 0 : 1; + vdc.trans_first = waddr ? 0 : 1; + if (((rhdr >> 30) & 0x3) == 2) { /* cmd is read */ + if (num) { + if (!rwords) { + rd = &vdc.rdataq; + data = rd->rdata; + } else { + rd = list_first_entry(&vdc.rdataq.lh, struct vd_rdata, lh); + data = rd->rdata; + list_del(&rd->lh); + free(rd); + } + for (unsigned int j = 0; j < num; j++) + memcpy(&data[j * awidth], &pm->rd8[(rwords + j) * awidth], awidth); + } + LOG_DEBUG_IO("read %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, + aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, + (num ? le_to_h_u32(&pm->rd8[rwords * 4]) : 0xdead)); + rwords += num * wwidth; + waddr += sizeof(uint64_t) / 4; /* waddr past header */ + } else { + LOG_DEBUG_IO("write %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, + aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, + le_to_h_u32(&pm->wd8[(waddr + num + 1) * 4])); + waddr += sizeof(uint64_t) / 4 + (num * wwidth * awidth + 3) / 4; + } + req += 1; + } + + if (rc) { + LOG_ERROR("0x%x executing transaction", rc); + rc = ERROR_FAIL; + } + + te = timeval_ms(); + vdc.targ_time += (uint32_t)(te - ts); + h_u16_to_le(pm->offseth, 0); /* reset buffer write address */ + h_u32_to_le(pm->offset, 0); + h_u16_to_le(pm->rwords, 0); + h_u16_to_le(pm->waddr, 0); + assert(list_empty(&vdc.rdataq.lh));/* list should be empty after run queue */ return rc; } @@ -420,35 +519,35 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path, int rc = VD_ERR_NOT_OPEN; pm->cmd = VD_CMD_OPEN; - pm->wid = VD_VERSION; /* client version */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u16_to_le(pm->wid, VD_VERSION); /* client version */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); rc = vdebug_wait_server(hsock, pm); if (rc != 0) { /* communication problem */ LOG_ERROR("0x%x connecting to server", rc); - } else if (pm->rid < pm->wid) { - LOG_ERROR("server version %d too old for the client %d", pm->rid, pm->wid); + } else if (le_to_h_u16(pm->rid) < le_to_h_u16(pm->wid)) { + LOG_ERROR("server version %d too old for the client %d", le_to_h_u16(pm->rid), le_to_h_u16(pm->wid)); pm->cmd = VD_CMD_CLOSE; /* let server close the connection */ vdebug_wait_server(hsock, pm); rc = VD_ERR_VERSION; } else { pm->cmd = VD_CMD_CONNECT; pm->type = type; /* BFM type to connect to, here JTAG */ - pm->rwdata = sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16); - pm->wbytes = strlen(path) + 1; - pm->rbytes = 12; - pm->wid = 0; /* reset wid for transaction ID */ - pm->wwords = 0; - pm->rwords = 0; - memcpy(pm->wd8, path, pm->wbytes + 1); + h_u32_to_le(pm->rwdata, sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16)); + h_u16_to_le(pm->wbytes, strlen(path) + 1); + h_u16_to_le(pm->rbytes, 12); + h_u16_to_le(pm->wid, 0); /* reset wid for transaction ID */ + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); + memcpy(pm->wd8, path, le_to_h_u16(pm->wbytes)); rc = vdebug_wait_server(hsock, pm); - vdc.sig_read = pm->rwdata >> 16; /* signal read mask */ - vdc.sig_write = pm->rwdata; /* signal write mask */ + vdc.sig_read = le_to_h_u32(pm->rwdata) >> 16; /* signal read mask */ + vdc.sig_write = le_to_h_u32(pm->rwdata); /* signal write mask */ vdc.bfm_period = period_ps; - vdc.buf_width = pm->rd32[0] / 8;/* access width in bytes */ - vdc.addr_bits = pm->rd32[2]; /* supported address bits */ + vdc.buf_width = le_to_h_u32(&pm->rd8[0]) / 8;/* access width in bytes */ + vdc.addr_bits = le_to_h_u32(&pm->rd8[2 * 4]); /* supported address bits */ } if (rc) { @@ -456,6 +555,7 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path, return ERROR_FAIL; } + INIT_LIST_HEAD(&vdc.rdataq.lh); LOG_DEBUG("%s type %0x, period %dps, buffer %dx%dB signals r%04xw%04x", path, type, vdc.bfm_period, VD_BUFFER_LEN / vdc.buf_width, vdc.buf_width, vdc.sig_read, vdc.sig_write); @@ -467,17 +567,17 @@ static int vdebug_close(int hsock, struct vd_shm *pm, uint8_t type) { pm->cmd = VD_CMD_DISCONNECT; pm->type = type; /* BFM type, here JTAG */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); vdebug_wait_server(hsock, pm); pm->cmd = VD_CMD_CLOSE; - pm->wid = VD_VERSION; /* client version */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u16_to_le(pm->wid, VD_VERSION); /* client version */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); vdebug_wait_server(hsock, pm); LOG_DEBUG("type %0x", type); @@ -488,9 +588,9 @@ static int vdebug_wait(int hsock, struct vd_shm *pm, uint32_t cycles) { if (cycles) { pm->cmd = VD_CMD_WAIT; - pm->wbytes = 0; - pm->rbytes = 0; - pm->rwdata = cycles; /* clock sycles to wait */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u32_to_le(pm->rwdata, cycles); /* clock sycles to wait */ int rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x waiting %" PRIx32 " cycles", rc, cycles); @@ -505,9 +605,9 @@ static int vdebug_wait(int hsock, struct vd_shm *pm, uint32_t cycles) static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uint32_t value) { pm->cmd = VD_CMD_SIGSET; - pm->wbytes = 0; - pm->rbytes = 0; - pm->rwdata = (write_mask << 16) | (value & 0xffff); /* mask and value of signals to set */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u32_to_le(pm->rwdata, (write_mask << 16) | (value & 0xffff)); /* mask and value of signals to set */ int rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x setting signals %04" PRIx32, rc, write_mask); @@ -522,9 +622,9 @@ static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uin static int vdebug_jtag_clock(int hsock, struct vd_shm *pm, uint32_t value) { pm->cmd = VD_CMD_JTAGCLOCK; - pm->wbytes = 0; - pm->rbytes = 0; - pm->rwdata = value; /* divider value */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u32_to_le(pm->rwdata, value); /* divider value */ int rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x setting jtag_clock", rc); @@ -546,11 +646,11 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre, int rc = 0; pm->cmd = VD_CMD_JTAGSHTAP; - vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO) || tdo; + vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO); if (vdc.trans_first) waddr = 0; /* reset buffer offset */ else - waddr = pm->offseth; /* continue from the previous transaction */ + waddr = le_to_h_u32(pm->offseth); /* continue from the previous transaction */ if (num_post) /* actual number of bits to shift */ anum = num + num_pre + num_post - 1; else @@ -559,25 +659,22 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre, words = (hwords + 1) / 2; /* in 8B TDO words to read */ bytes = (num + 7) / 8; /* data only portion in bytes */ /* buffer overflow check and flush */ - if (4 * waddr + sizeof(struct vd_jtag_hdr) + 8 * hwords + 64 > VD_BUFFER_LEN) { + if (4 * waddr + sizeof(uint64_t) + 8 * hwords + 64 > VD_BUFFER_LEN) { vdc.trans_last = 1; /* force flush within 64B of buffer end */ - } else if (4 * waddr + sizeof(struct vd_jtag_hdr) + 8 * hwords > VD_BUFFER_LEN) { + } else if (4 * waddr + sizeof(uint64_t) + 8 * hwords > VD_BUFFER_LEN) { /* this req does not fit, discard it */ LOG_ERROR("%04x L:%02d O:%05x @%04x too many bits to shift", - pm->wid, anum, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr); + le_to_h_u16(pm->wid), anum, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr); rc = ERROR_FAIL; } if (!rc && anum) { - uint16_t i, j; - struct vd_jtag_hdr *hdr = (struct vd_jtag_hdr *)&pm->wd8[4 * waddr]; /* 8 bytes header */ - hdr->cmd = (tdo ? 3 : 1); /* R and W bits */ - hdr->pre = num_pre; - hdr->post = num_post; - hdr->tlen = anum; - hdr->wlen = hwords; - hdr->rlen = words; - pm->wid++; /* transaction ID */ + uint16_t i, j; /* portability requires to use bit operations for 8B JTAG header */ + uint64_t jhdr = (tdo ? ((uint64_t)(words) << 48) : 0) + ((uint64_t)(hwords) << 32) + + ((tdo ? 3UL : 1UL) << 30) + (num_pre << 27) + (num_post << 24) + anum; + h_u64_to_le(&pm->wd8[4 * waddr], jhdr); + + h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); /* transaction ID */ waddr += 2; /* waddr past header */ /* TDI/TMS data follows as 32 bit word pairs {TMS,TDI} */ pm->wd8[4 * waddr] = (tdi ? (tdi[0] << num_pre) : 0); @@ -615,19 +712,102 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre, } if (tdo) { - pm->rwords += words; /* keep track of the words to read */ - vdc.tdo = tdo; + struct vd_rdata *rd; + if (le_to_h_u16(pm->rwords) == 0) { + rd = &vdc.rdataq; + } else { + rd = calloc(1, sizeof(struct vd_rdata)); + if (!rd) /* check allocation for 24B */ + return ERROR_FAIL; + list_add_tail(&rd->lh, &vdc.rdataq.lh); + } + rd->rdata = tdo; + h_u16_to_le(pm->rwords, le_to_h_u16(pm->rwords) + words);/* keep track of the words to read */ } - pm->wwords = waddr / 2 + hwords; /* payload size *2 to include both TDI and TMS data */ - pm->waddr++; + h_u16_to_le(pm->wwords, waddr / 2 + hwords); /* payload size *2 to include both TDI and TMS data */ + h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1); } if (!waddr) /* flush issued, but buffer empty */ ; else if (!vdc.trans_last) /* buffered request */ - pm->offseth = waddr + hwords * 2; /* offset for next transaction, must be even */ + h_u16_to_le(pm->offseth, waddr + hwords * 2); /* offset for next transaction, must be even */ else /* execute batch of requests */ - rc = vdebug_run_jtag_queue(hsock, pm, pm->waddr); + rc = vdebug_run_jtag_queue(hsock, pm, le_to_h_u16(pm->waddr)); + vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */ + + return rc; +} + +static int vdebug_reg_write(int hsock, struct vd_shm *pm, const uint32_t reg, + const uint32_t data, uint8_t aspace, uint8_t f_last) +{ + uint32_t waddr; + int rc = ERROR_OK; + + pm->cmd = VD_CMD_REGWRITE; + vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO); + if (vdc.trans_first) + waddr = 0; /* reset buffer offset */ + else + waddr = le_to_h_u16(pm->offseth); /* continue from the previous transaction */ + + if (4 * waddr + 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN) + vdc.trans_last = 1; /* force flush, no room for next request */ + + uint64_t rhdr = ((uint64_t)reg << 32) + (1UL << 30) + (2UL << 27) + (1UL << 16) + aspace; + h_u64_to_le(&pm->wd8[4 * waddr], rhdr); + h_u32_to_le(&pm->wd8[4 * (waddr + 2)], data); + h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); + h_u16_to_le(pm->wwords, waddr + 3); + h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1); + if (!vdc.trans_last) /* buffered request */ + h_u16_to_le(pm->offseth, waddr + 3); + else + rc = vdebug_run_reg_queue(hsock, pm, le_to_h_u16(pm->waddr)); + vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */ + + return rc; +} + +static int vdebug_reg_read(int hsock, struct vd_shm *pm, const uint32_t reg, + uint32_t *data, uint8_t aspace, uint8_t f_last) +{ + uint32_t waddr; + int rc = ERROR_OK; + + pm->cmd = VD_CMD_REGREAD; + vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO); + if (vdc.trans_first) + waddr = 0; /* reset buffer offset */ + else + waddr = le_to_h_u16(pm->offseth); /* continue from the previous transaction */ + + if (4 * waddr + 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN) + vdc.trans_last = 1; /* force flush, no room for next request */ + + uint64_t rhdr = ((uint64_t)reg << 32) + (2UL << 30) + (2UL << 27) + ((data ? 1UL : 0UL) << 16) + aspace; + h_u64_to_le(&pm->wd8[4 * waddr], rhdr); + h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); + if (data) { + struct vd_rdata *rd; + if (le_to_h_u16(pm->rwords) == 0) { + rd = &vdc.rdataq; + } else { + rd = calloc(1, sizeof(struct vd_rdata)); + if (!rd) /* check allocation for 24B */ + return ERROR_FAIL; + list_add_tail(&rd->lh, &vdc.rdataq.lh); + } + rd->rdata = (uint8_t *)data; + h_u16_to_le(pm->rwords, le_to_h_u16(pm->rwords) + 1); + } + h_u16_to_le(pm->wwords, waddr + 2); + h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1); + if (!vdc.trans_last) /* buffered request */ + h_u16_to_le(pm->offseth, waddr + 2); + else + rc = vdebug_run_reg_queue(hsock, pm, le_to_h_u16(pm->waddr)); vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */ return rc; @@ -641,19 +821,19 @@ static int vdebug_mem_open(int hsock, struct vd_shm *pm, const char *path, uint8 return ERROR_OK; pm->cmd = VD_CMD_MEMOPEN; - pm->wbytes = strlen(path) + 1; /* includes terminating 0 */ - pm->rbytes = 8; - pm->wwords = 0; - pm->rwords = 0; - memcpy(pm->wd8, path, pm->wbytes); + h_u16_to_le(pm->wbytes, strlen(path) + 1); /* includes terminating 0 */ + h_u16_to_le(pm->rbytes, 8); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); + memcpy(pm->wd8, path, le_to_h_u16(pm->wbytes)); rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x opening memory %s", rc, path); - } else if (ndx != pm->rd16[1]) { - LOG_WARNING("Invalid memory index %" PRIu16 " returned. Direct memory access disabled", pm->rd16[1]); + } else if (ndx != pm->rd8[2]) { + LOG_WARNING("Invalid memory index %" PRIu16 " returned. Direct memory access disabled", pm->rd8[2]); } else { - vdc.mem_width[ndx] = pm->rd16[0] / 8; /* memory width in bytes */ - vdc.mem_depth[ndx] = pm->rd32[1]; /* memory depth in words */ + vdc.mem_width[ndx] = le_to_h_u16(&pm->rd8[0]) / 8; /* memory width in bytes */ + vdc.mem_depth[ndx] = le_to_h_u32(&pm->rd8[4]); /* memory depth in words */ LOG_DEBUG("%" PRIx8 ": %s memory %" PRIu32 "x%" PRIu32 "B, buffer %" PRIu32 "x%" PRIu32 "B", ndx, path, vdc.mem_depth[ndx], vdc.mem_width[ndx], VD_BUFFER_LEN / vdc.mem_width[ndx], vdc.mem_width[ndx]); } @@ -664,15 +844,16 @@ static int vdebug_mem_open(int hsock, struct vd_shm *pm, const char *path, uint8 static void vdebug_mem_close(int hsock, struct vd_shm *pm, uint8_t ndx) { pm->cmd = VD_CMD_MEMCLOSE; - pm->rwdata = ndx; /* which memory */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u32_to_le(pm->rwdata, ndx); /* which memory */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); vdebug_wait_server(hsock, pm); LOG_DEBUG("%" PRIx8 ": %s", ndx, vdc.mem_path[ndx]); } + static int vdebug_init(void) { vdc.hsocket = vdebug_socket_open(vdc.server_name, vdc.server_port); @@ -680,7 +861,7 @@ static int vdebug_init(void) if (!pbuf) { close_socket(vdc.hsocket); vdc.hsocket = 0; - LOG_ERROR("cannot allocate %lu bytes", sizeof(struct vd_shm)); + LOG_ERROR("cannot allocate %zu bytes", sizeof(struct vd_shm)); return ERROR_FAIL; } if (vdc.hsocket <= 0) { @@ -692,10 +873,13 @@ static int vdebug_init(void) } vdc.trans_first = 1; vdc.poll_cycles = vdc.poll_max; - uint32_t sig_mask = VD_SIG_RESET | VD_SIG_TRST | VD_SIG_TCKDIV; + uint32_t sig_mask = VD_SIG_RESET; + if (transport_is_jtag()) + sig_mask |= VD_SIG_TRST | VD_SIG_TCKDIV; + int rc = vdebug_open(vdc.hsocket, pbuf, vdc.bfm_path, vdc.bfm_type, vdc.bfm_period, sig_mask); if (rc != 0) { - LOG_ERROR("cannot connect to %s, rc 0x%x", vdc.bfm_path, rc); + LOG_ERROR("0x%x cannot connect to %s", rc, vdc.bfm_path); close_socket(vdc.hsocket); vdc.hsocket = 0; free(pbuf); @@ -704,7 +888,7 @@ static int vdebug_init(void) for (uint8_t i = 0; i < vdc.mem_ndx; i++) { rc = vdebug_mem_open(vdc.hsocket, pbuf, vdc.mem_path[i], i); if (rc != 0) - LOG_ERROR("cannot connect to %s, rc 0x%x", vdc.mem_path[i], rc); + LOG_ERROR("0x%x cannot connect to %s", rc, vdc.mem_path[i]); } LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16, @@ -754,7 +938,7 @@ static int vdebug_reset(int trst, int srst) static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush) { - LOG_INFO("tms len:%d tms:%x", num, *(const uint32_t *)tms); + LOG_INFO("tms len:%d tms:%x", num, *tms); return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num, *tms, 0, NULL, 0, 0, NULL, f_flush); } @@ -811,8 +995,8 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) uint8_t cur_tms_post = i == cmd->num_fields - 1 ? tms_post : 0; uint8_t cur_flush = i == cmd->num_fields - 1 ? f_flush : 0; rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, cur_num_pre, cur_tms_pre, - cmd->fields[i].num_bits, cmd->fields[i].out_value, cur_num_post, cur_tms_post, - cmd->fields[i].in_value, cur_flush); + cmd->fields[i].num_bits, cmd->fields[i].out_value, cur_num_post, cur_tms_post, + cmd->fields[i].in_value, cur_flush); if (rc) break; } @@ -913,6 +1097,61 @@ static int vdebug_jtag_execute_queue(void) return rc; } +static int vdebug_dap_connect(struct adiv5_dap *dap) +{ + return dap_dp_init(dap); +} + +static int vdebug_dap_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) +{ + return ERROR_OK; +} + +static int vdebug_dap_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) +{ + return vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0); +} + +static int vdebug_dap_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) +{ + return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0); +} + +static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) +{ + if ((reg & DP_SELECT_APBANK) != ap->dap->select) { + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0); + ap->dap->select = reg & DP_SELECT_APBANK; + } + + vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0); + + return vdebug_reg_read(vdc.hsocket, pbuf, DP_RDBUFF >> 2, data, VD_ASPACE_DP, 0); +} + +static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) +{ + if ((reg & DP_SELECT_APBANK) != ap->dap->select) { + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0); + ap->dap->select = reg & DP_SELECT_APBANK; + } + + return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0); +} + +static int vdebug_dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) +{ + return vdebug_reg_write(vdc.hsocket, pbuf, 0, 0x1, VD_ASPACE_AB, 0); +} + +static int vdebug_dap_run(struct adiv5_dap *dap) +{ + if (pbuf->waddr) + return vdebug_run_reg_queue(vdc.hsocket, pbuf, le_to_h_u16(pbuf->waddr)); + + return ERROR_OK; +} + COMMAND_HANDLER(vdebug_set_server) { if ((CMD_ARGC != 1) || !strchr(CMD_ARGV[0], ':')) @@ -951,7 +1190,10 @@ COMMAND_HANDLER(vdebug_set_bfm) default: break; } - vdc.bfm_type = VD_BFM_JTAG; + if (transport_is_dapdirect_swd()) + vdc.bfm_type = VD_BFM_SWDP; + else + vdc.bfm_type = VD_BFM_JTAG; LOG_DEBUG("bfm_path: %s clk_period %ups", vdc.bfm_path, vdc.bfm_period); return ERROR_OK; @@ -1062,9 +1304,24 @@ static struct jtag_interface vdebug_jtag_ops = { .execute_queue = vdebug_jtag_execute_queue, }; +static const struct dap_ops vdebug_dap_ops = { + .connect = vdebug_dap_connect, + .send_sequence = vdebug_dap_send_sequence, + .queue_dp_read = vdebug_dap_queue_dp_read, + .queue_dp_write = vdebug_dap_queue_dp_write, + .queue_ap_read = vdebug_dap_queue_ap_read, + .queue_ap_write = vdebug_dap_queue_ap_write, + .queue_ap_abort = vdebug_dap_queue_ap_abort, + .run = vdebug_dap_run, + .sync = NULL, /* optional */ + .quit = NULL, /* optional */ +}; + +static const char *const vdebug_transports[] = { "jtag", "dapdirect_swd", NULL }; + struct adapter_driver vdebug_adapter_driver = { .name = "vdebug", - .transports = jtag_only, + .transports = vdebug_transports, .speed = vdebug_jtag_speed, .khz = vdebug_jtag_khz, .speed_div = vdebug_jtag_div, @@ -1073,4 +1330,5 @@ struct adapter_driver vdebug_adapter_driver = { .quit = vdebug_quit, .reset = vdebug_reset, .jtag_ops = &vdebug_jtag_ops, + .dap_swd_ops = &vdebug_dap_ops, }; diff --git a/tcl/board/vd_a53x2_dap.cfg b/tcl/board/vd_a53x2_dap.cfg new file mode 100644 index 0000000000..4cf5594d32 --- /dev/null +++ b/tcl/board/vd_a53x2_dap.cfg @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex A53x2 through DAP + +source [find interface/vdebug.cfg] + +set _CORES 2 +set _CHIPNAME a53 +set _MEMSTART 0x00000000 +set _MEMSIZE 0x1000000 + +# vdebug select transport +transport select dapdirect_swd + +# JTAG reset config, frequency and reset delay +adapter speed 50000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_swdp_bfm 10ns + +# DMA Memories to access backdoor (up to 4) +vdebug mem_path tbench.u_memory.mem_array $_MEMSTART $_MEMSIZE + +source [find target/swj-dp.tcl] + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf + +source [find target/vd_aarch64.cfg] diff --git a/tcl/board/vd_a53x2_jtag.cfg b/tcl/board/vd_a53x2_jtag.cfg index 869bc4db01..a5e8d24e55 100644 --- a/tcl/board/vd_a53x2_jtag.cfg +++ b/tcl/board/vd_a53x2_jtag.cfg @@ -11,7 +11,7 @@ set _MEMSIZE 0x1000000 set _CPUTAPID 0x5ba00477 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/board/vd_m4_dap.cfg b/tcl/board/vd_m4_dap.cfg new file mode 100644 index 0000000000..691b6235f6 --- /dev/null +++ b/tcl/board/vd_m4_dap.cfg @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex m4 through DAP + +source [find interface/vdebug.cfg] + +set _CHIPNAME m4 +set _MEMSTART 0x00000000 +set _MEMSIZE 0x10000 + +# vdebug select transport +transport select dapdirect_swd +adapter speed 25000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_swdp_bfm 20ns + +# DMA Memories to access backdoor (up to 4) +vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $_MEMSTART $_MEMSIZE + +source [find target/swj-dp.tcl] + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf + +source [find target/vd_cortex_m.cfg] diff --git a/tcl/board/vd_m4_jtag.cfg b/tcl/board/vd_m4_jtag.cfg index ca21476d29..4c795ebfd0 100644 --- a/tcl/board/vd_m4_jtag.cfg +++ b/tcl/board/vd_m4_jtag.cfg @@ -10,7 +10,7 @@ set _MEMSIZE 0x10000 set _CPUTAPID 0x4ba00477 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/board/vd_m7_jtag.cfg b/tcl/board/vd_m7_jtag.cfg new file mode 100644 index 0000000000..880ef9b4c2 --- /dev/null +++ b/tcl/board/vd_m7_jtag.cfg @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex m7 through JTAG + +source [find interface/vdebug.cfg] + +set _CHIPNAME m7 +set _MEMSTART 0x00000000 +set _MEMSIZE 0x100000 +set _CPUTAPID 0x0ba02477 + +# vdebug select JTAG transport +transport select jtag + +# JTAG reset config, frequency and reset delay +reset_config trst_and_srst +adapter speed 50000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_jtag_bfm 10ns + +# DMA Memories to access backdoor (up to 4) +vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $_MEMSTART $_MEMSIZE + +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +jtag arp_init-reset + +source [find target/vd_cortex_m.cfg] diff --git a/tcl/board/vd_pulpissimo_jtag.cfg b/tcl/board/vd_pulpissimo_jtag.cfg index 69dd9e6dbe..a3f5a84886 100644 --- a/tcl/board/vd_pulpissimo_jtag.cfg +++ b/tcl/board/vd_pulpissimo_jtag.cfg @@ -9,7 +9,7 @@ set _HARTID 0x20 set _CPUTAPID 0x249511c3 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/board/vd_swerv_jtag.cfg b/tcl/board/vd_swerv_jtag.cfg index ff6c6835fc..c5d33f268a 100644 --- a/tcl/board/vd_swerv_jtag.cfg +++ b/tcl/board/vd_swerv_jtag.cfg @@ -11,7 +11,7 @@ set _MEMSTART 0x00000000 set _MEMSIZE 0x10000 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/target/vd_riscv.cfg b/tcl/target/vd_riscv.cfg index b42b25a3a5..f08cb1ac8b 100644 --- a/tcl/target/vd_riscv.cfg +++ b/tcl/target/vd_riscv.cfg @@ -14,5 +14,4 @@ target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid $_HARTID riscv set_reset_timeout_sec 120 riscv set_command_timeout_sec 120 -# prefer to use sba for system bus access -riscv set_prefer_sba on +riscv set_mem_access sysbus progbuf From 2c6571b9b1152098410c18a9f6bcd5cbb318f881 Mon Sep 17 00:00:00 2001 From: Ben Bender Date: Tue, 5 Oct 2021 10:58:57 +0300 Subject: [PATCH 0002/1312] arm_adi_v5: Adding Nuvoton NPCX quirk We found that the NPCX has an issue with the byte lanes so that non byte aligned writes aren't working. To overcome this, for byte accesses we copy the byte to be written to all of the byte lanes. doc: Document command nu_npcx_quirks Signed-off-by: benjbender [Andreas Fritiofson: Squashed commits] Signed-off-by: Andreas Fritiofson Change-Id: I9ef63bf692f4e68f57459e1ec33f3abcbf533cd2 Reviewed-on: https://review.openocd.org/c/openocd/+/6630 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 4 ++++ src/target/arm_adi_v5.c | 34 ++++++++++++++++++++++++++++++++++ src/target/arm_adi_v5.h | 4 ++++ 3 files changed, 42 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 03bb508479..1d63b20b7a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4836,6 +4836,10 @@ Set/get quirks mode for TI TMS450/TMS570 processors Disabled by default @end deffn +@deffn {Config Command} {$dap_name nu_npcx_quirks} [@option{enable}] +Set/get quirks mode for Nuvoton NPCX/NPCD MCU families +Disabled by default +@end deffn @node CPU Configuration @chapter CPU Configuration diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index ff0d9b5495..cc5f077750 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -409,6 +409,26 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (drw_byte_idx & 3) ^ addr_xor); break; } + } else if (dap->nu_npcx_quirks) { + switch (this_size) { + case 4: + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); + break; + case 2: + outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*(buffer+1) << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); + break; + case 1: + outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); + } } else { switch (this_size) { case 4: @@ -2755,6 +2775,13 @@ COMMAND_HANDLER(dap_ti_be_32_quirks_command) "TI BE-32 quirks mode"); } +COMMAND_HANDLER(dap_nu_npcx_quirks_command) +{ + struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); + return CALL_COMMAND_HANDLER(handle_command_parse_bool, &dap->nu_npcx_quirks, + "Nuvoton NPCX quirks mode"); +} + const struct command_registration dap_instance_commands[] = { { .name = "info", @@ -2827,5 +2854,12 @@ const struct command_registration dap_instance_commands[] = { .help = "set/get quirks mode for TI TMS450/TMS570 processors", .usage = "[enable]", }, + { + .name = "nu_npcx_quirks", + .handler = dap_nu_npcx_quirks_command, + .mode = COMMAND_CONFIG, + .help = "set/get quirks mode for Nuvoton NPCX controllers", + .usage = "[enable]", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 7ee6591497..3eddbc0e2d 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -359,6 +359,10 @@ struct adiv5_dap { * swizzle appropriately. */ bool ti_be_32_quirks; + /* The Nuvoton NPCX M4 has an issue with writing to non-4-byte-aligned mmios. + * The work around is to repeat the data in all 4 bytes of DRW */ + bool nu_npcx_quirks; + /** * STLINK adapter need to know if last AP operation was read or write, and * in case of write has to flush it with a dummy read from DP_RDBUFF From 82e76262a13299f11d0a73418a8e76558761dccc Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 26 May 2022 13:08:48 +0200 Subject: [PATCH 0003/1312] target/riscv: use struct riscv_info instead of typedef riscv_info_t Make the main RISC-V structure more compliant with OpenOCD coding style. Other typedefs remains as is. Change-Id: I5657ad28fea8108fd66ab27b2dfe1c868dc5805b Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/6998 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tim Newsome --- src/target/riscv/riscv-011.c | 11 +++++++---- src/target/riscv/riscv-013.c | 13 ++++++++----- src/target/riscv/riscv.c | 26 ++++++++++++++------------ src/target/riscv/riscv.h | 12 ++++++------ 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index ae0b6e481b..e2ae5b51a6 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -227,10 +227,10 @@ static int get_register(struct target *target, riscv_reg_t *value, int regid); static riscv011_info_t *get_info(const struct target *target) { - riscv_info_t *info = (riscv_info_t *) target->arch_info; + struct riscv_info *info = target->arch_info; assert(info); assert(info->version_specific); - return (riscv011_info_t *) info->version_specific; + return info->version_specific; } static unsigned int slot_offset(const struct target *target, slot_t slot) @@ -1408,7 +1408,10 @@ static int halt(struct target *target) static void deinit_target(struct target *target) { LOG_DEBUG("riscv_deinit_target()"); - riscv_info_t *info = (riscv_info_t *) target->arch_info; + struct riscv_info *info = target->arch_info; + if (!info) + return; + free(info->version_specific); info->version_specific = NULL; } @@ -1549,7 +1552,7 @@ static int examine(struct target *target) uint32_t word0 = cache_get32(target, 0); uint32_t word1 = cache_get32(target, 1); - riscv_info_t *generic_info = (riscv_info_t *) target->arch_info; + struct riscv_info *generic_info = riscv_info(target); if (word0 == 1 && word1 == 0) { generic_info->xlen = 32; } else if (word0 == 0xffffffff && word1 == 3) { diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 1b1450a7dc..b666f52462 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -34,7 +34,7 @@ static int riscv013_step_or_resume_current_hart(struct target *target, bool step, bool use_hasel); static void riscv013_clear_abstract_error(struct target *target); -/* Implementations of the functions in riscv_info_t. */ +/* Implementations of the functions in struct riscv_info. */ static int riscv013_get_register(struct target *target, riscv_reg_t *value, int rid); static int riscv013_set_register(struct target *target, int regid, uint64_t value); @@ -225,10 +225,10 @@ LIST_HEAD(dm_list); static riscv013_info_t *get_info(const struct target *target) { - riscv_info_t *info = (riscv_info_t *) target->arch_info; + struct riscv_info *info = target->arch_info; assert(info); assert(info->version_specific); - return (riscv013_info_t *) info->version_specific; + return info->version_specific; } /** @@ -1524,7 +1524,10 @@ static int wait_for_authbusy(struct target *target, uint32_t *dmstatus) static void deinit_target(struct target *target) { LOG_DEBUG("riscv_deinit_target()"); - riscv_info_t *info = (riscv_info_t *) target->arch_info; + struct riscv_info *info = target->arch_info; + if (!info) + return; + free(info->version_specific); /* TODO: free register arch_info */ info->version_specific = NULL; @@ -4173,7 +4176,7 @@ static int select_prepped_harts(struct target *target, bool *use_hasel) unsigned total_selected = 0; list_for_each_entry(entry, &dm->target_list, list) { struct target *t = entry->target; - riscv_info_t *r = riscv_info(t); + struct riscv_info *r = riscv_info(t); riscv013_info_t *info = get_info(t); unsigned index = info->index; LOG_DEBUG("index=%d, coreid=%d, prepped=%d", index, t->coreid, r->prepped); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index f79239a9d4..eccceade19 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -405,13 +405,12 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out) static struct target_type *get_target_type(struct target *target) { - riscv_info_t *info = (riscv_info_t *) target->arch_info; - - if (!info) { + if (!target->arch_info) { LOG_ERROR("Target has not been initialized"); return NULL; } + RISCV_INFO(info); switch (info->dtm_version) { case 0: return &riscv011_target; @@ -426,7 +425,7 @@ static struct target_type *get_target_type(struct target *target) static int riscv_create_target(struct target *target, Jim_Interp *interp) { LOG_DEBUG("riscv_create_target()"); - target->arch_info = calloc(1, sizeof(riscv_info_t)); + target->arch_info = calloc(1, sizeof(struct riscv_info)); if (!target->arch_info) { LOG_ERROR("Failed to allocate RISC-V target structure."); return ERROR_FAIL; @@ -489,14 +488,17 @@ static void riscv_deinit_target(struct target *target) { LOG_DEBUG("riscv_deinit_target()"); - riscv_info_t *info = target->arch_info; + struct riscv_info *info = target->arch_info; struct target_type *tt = get_target_type(target); - if (tt && info->version_specific) + if (tt && info && info->version_specific) tt->deinit_target(target); riscv_free_registers(target); + if (!info) + return; + range_list_t *entry, *tmp; list_for_each_entry_safe(entry, tmp, &info->expose_csr, list) { free(entry->name); @@ -1200,7 +1202,7 @@ int riscv_halt_go_all_harts(struct target *target) int halt_go(struct target *target) { - riscv_info_t *r = riscv_info(target); + RISCV_INFO(r); int result; if (!r->is_halted) { struct target_type *tt = get_target_type(target); @@ -1242,7 +1244,7 @@ int riscv_halt(struct target *target) foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; - riscv_info_t *i = riscv_info(t); + struct riscv_info *i = riscv_info(t); if (i->prepped) { if (halt_go(t) != ERROR_OK) result = ERROR_FAIL; @@ -1434,7 +1436,7 @@ static int resume_prep(struct target *target, int current, static int resume_go(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { - riscv_info_t *r = riscv_info(target); + RISCV_INFO(r); int result; if (!r->is_halted) { struct target_type *tt = get_target_type(target); @@ -1483,7 +1485,7 @@ int riscv_resume( foreach_smp_target_direction(resume_order == RO_NORMAL, tlist, target->smp_targets) { struct target *t = tlist->target; - riscv_info_t *i = riscv_info(t); + struct riscv_info *i = riscv_info(t); if (i->prepped) { if (resume_go(t, current, address, handle_breakpoints, debug_execution) != ERROR_OK) @@ -2189,7 +2191,7 @@ int riscv_openocd_poll(struct target *target) struct target_list *list; foreach_smp_target(list, target->smp_targets) { struct target *t = list->target; - riscv_info_t *r = riscv_info(t); + struct riscv_info *r = riscv_info(t); enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid); switch (out) { case RPH_NO_CHANGE: @@ -3197,7 +3199,7 @@ struct target_type riscv_target = { /*** RISC-V Interface ***/ -void riscv_info_init(struct target *target, riscv_info_t *r) +void riscv_info_init(struct target *target, struct riscv_info *r) { memset(r, 0, sizeof(*r)); r->dtm_version = 1; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index a6d27f79b9..efbd71c327 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -85,7 +85,7 @@ typedef struct { char *name; } range_list_t; -typedef struct { +struct riscv_info { unsigned dtm_version; struct command_context *cmd_ctx; @@ -225,7 +225,7 @@ typedef struct { riscv_sample_config_t sample_config; struct riscv_sample_buf sample_buf; -} riscv_info_t; +}; COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key, unsigned int value); @@ -261,13 +261,13 @@ extern bool riscv_ebreaku; /* Everything needs the RISC-V specific info structure, so here's a nice macro * that provides that. */ -static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused)); -static inline riscv_info_t *riscv_info(const struct target *target) +static inline struct riscv_info *riscv_info(const struct target *target) __attribute__((unused)); +static inline struct riscv_info *riscv_info(const struct target *target) { assert(target->arch_info); return target->arch_info; } -#define RISCV_INFO(R) riscv_info_t *R = riscv_info(target); +#define RISCV_INFO(R) struct riscv_info *R = riscv_info(target); extern uint8_t ir_dtmcontrol[4]; extern struct scan_field select_dtmcontrol; @@ -313,7 +313,7 @@ int riscv_openocd_deassert_reset(struct target *target); /*** RISC-V Interface ***/ /* Initializes the shared RISC-V structure. */ -void riscv_info_init(struct target *target, riscv_info_t *r); +void riscv_info_init(struct target *target, struct riscv_info *r); /* Steps the hart that's currently selected in the RTOS, or if there is no RTOS * then the only hart. */ From 1d8bc131a69b0216de08a8a0339cd26236448a44 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 26 May 2022 11:33:27 +0200 Subject: [PATCH 0004/1312] target/riscv: add common magic Add common_magic member to struct riscv_info. Introduce is_riscv() helper. Change-Id: I1af05988ad869342ba5dc6d4d0ba0ec6a8bf7bc7 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/6999 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tim Newsome --- src/target/riscv/riscv.c | 3 +++ src/target/riscv/riscv.h | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index eccceade19..42fc3742f7 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -3202,6 +3202,9 @@ struct target_type riscv_target = { void riscv_info_init(struct target *target, struct riscv_info *r) { memset(r, 0, sizeof(*r)); + + r->common_magic = RISCV_COMMON_MAGIC; + r->dtm_version = 1; r->current_hartid = target->coreid; r->version_specific = NULL; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index efbd71c327..fcb1380d48 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -13,6 +13,8 @@ struct riscv_program; #include "target/semihosting_common.h" #include +#define RISCV_COMMON_MAGIC 0x52495356U + /* The register cache is statically allocated. */ #define RISCV_MAX_HARTS 1024 #define RISCV_MAX_REGISTERS 5000 @@ -86,6 +88,8 @@ typedef struct { } range_list_t; struct riscv_info { + unsigned int common_magic; + unsigned dtm_version; struct command_context *cmd_ctx; @@ -269,6 +273,11 @@ static inline struct riscv_info *riscv_info(const struct target *target) } #define RISCV_INFO(R) struct riscv_info *R = riscv_info(target); +static inline bool is_riscv(const struct riscv_info *riscv_info) +{ + return riscv_info->common_magic == RISCV_COMMON_MAGIC; +} + extern uint8_t ir_dtmcontrol[4]; extern struct scan_field select_dtmcontrol; extern uint8_t ir_dbus[4]; From a895b3b4f830d24d714cb9f11fc8cef92b84df72 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 26 May 2022 13:51:18 +0200 Subject: [PATCH 0005/1312] flash/nor/fespi: check target type Change-Id: I09d3ed20966b37ec63c09c2ffb0e0403986cb1e5 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7001 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tim Newsome --- src/flash/nor/fespi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index d33c5260c7..c61b708b1f 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -512,6 +512,12 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer, } } + struct riscv_info *riscv = riscv_info(target); + if (!is_riscv(riscv)) { + LOG_ERROR("Unexpected target type"); + return ERROR_FAIL; + } + unsigned int xlen = riscv_xlen(target); struct working_area *algorithm_wa = NULL; struct working_area *data_wa = NULL; From b5dd6faf8d47781f2d7cba25decac79bd2310351 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 1 Aug 2022 11:05:47 +0200 Subject: [PATCH 0006/1312] target/cortex_a: remove unused CORTEX_A15_COMMON_MAGIC Change-Id: I7dddc6cb7b0ee8aec7164998f1124b522e899f3d Signed-off-by: Tomas Vanek Reported-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/7099 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_a.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index abf358d0d4..05c3730c25 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -20,7 +20,6 @@ #include "armv7a.h" #define CORTEX_A_COMMON_MAGIC 0x411fc082 -#define CORTEX_A15_COMMON_MAGIC 0x413fc0f1 #define CORTEX_A5_PARTNUM 0xc05 #define CORTEX_A7_PARTNUM 0xc07 From 3865c411eebf01192ee347a1bd5c201c97ed23a6 Mon Sep 17 00:00:00 2001 From: Frank Dischner Date: Sun, 17 Apr 2022 21:12:39 -0500 Subject: [PATCH 0007/1312] FreeRTOS: Fix current thread ID when no threads are active When there are no rtos threads or none are active, a fake thread with ID 1 is created for the current execution, but the current thread ID was never set to this new fake ID. This would lead to an incorrect attempt to read stacked registers for this fake thread. Explicitly setting the current thread ID to the fake ID ensures that the registers are read from the core instead of calling freertos_get_thread_reg_list. Signed-off-by: Frank Dischner Change-Id: I694509a0e01df089429b20ff1b879fc0592b532d Reviewed-on: https://review.openocd.org/c/openocd/+/6934 Tested-by: jenkins Reviewed-by: Asier Llano Reviewed-by: Tomas Vanek --- src/rtos/FreeRTOS.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index 499759ab3e..5f779ef70c 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -207,7 +207,8 @@ static int freertos_update_threads(struct rtos *rtos) LOG_ERROR("Error allocating memory for %d threads", thread_list_size); return ERROR_FAIL; } - rtos->thread_details->threadid = 1; + rtos->current_thread = 1; + rtos->thread_details->threadid = rtos->current_thread; rtos->thread_details->exists = true; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); From df75bbd53620c3a59e9fd3cfd0aaeae26ab795af Mon Sep 17 00:00:00 2001 From: Frank Dischner Date: Sun, 17 Apr 2022 21:24:28 -0500 Subject: [PATCH 0008/1312] FreeRTOS: Always show current execution before scheduler is started Previously, if the target was halted before the FreeRTOS scheduler was started but after at least one thread was created, then the current thread would be set to whichever thread had the highest priority. In addition to being misleading, because that thread is not actually running, it can cause issues with gdb. For instance, breaking somewhere before the first thread is created will show the current execution as the current thread, but stepping over a line that creates a thread will cause the current thread to switch to the newly created thread and the current execution to disappear. The sudden disappearance of the current execution thread seems to confuse some versions of gdb. With this change, the value of xSchedulerRunning is checked to determine whether the scheduler has been started. If it hasn't, then a fake 'current execution' thread is always created and made the current thread. Signed-off-by: Frank Dischner Change-Id: Ide0fe7d9ffb9fac95cee4c805735f434c7c4934d Reviewed-on: https://review.openocd.org/c/openocd/+/6935 Tested-by: jenkins Reviewed-by: Asier Llano Reviewed-by: Tomas Vanek --- src/rtos/FreeRTOS.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index 5f779ef70c..afea9db90c 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -116,6 +116,7 @@ enum freertos_symbol_values { FREERTOS_VAL_X_SUSPENDED_TASK_LIST = 8, FREERTOS_VAL_UX_CURRENT_NUMBER_OF_TASKS = 9, FREERTOS_VAL_UX_TOP_USED_PRIORITY = 10, + FREERTOS_VAL_X_SCHEDULER_RUNNING = 11, }; struct symbols { @@ -135,6 +136,7 @@ static const struct symbols freertos_symbol_list[] = { { "xSuspendedTaskList", true }, /* Only if INCLUDE_vTaskSuspend */ { "uxCurrentNumberOfTasks", false }, { "uxTopUsedPriority", true }, /* Unavailable since v7.5.3 */ + { "xSchedulerRunning", false }, { NULL, false } }; @@ -194,7 +196,20 @@ static int freertos_update_threads(struct rtos *rtos) rtos->symbols[FREERTOS_VAL_PX_CURRENT_TCB].address, rtos->current_thread); - if ((thread_list_size == 0) || (rtos->current_thread == 0)) { + /* read scheduler running */ + uint32_t scheduler_running; + retval = target_read_u32(rtos->target, + rtos->symbols[FREERTOS_VAL_X_SCHEDULER_RUNNING].address, + &scheduler_running); + if (retval != ERROR_OK) { + LOG_ERROR("Error reading FreeRTOS scheduler state"); + return retval; + } + LOG_DEBUG("FreeRTOS: Read xSchedulerRunning at 0x%" PRIx64 ", value 0x%" PRIx32, + rtos->symbols[FREERTOS_VAL_X_SCHEDULER_RUNNING].address, + scheduler_running); + + if ((thread_list_size == 0) || (rtos->current_thread == 0) || (scheduler_running != 1)) { /* Either : No RTOS threads - there is always at least the current execution though */ /* OR : No current thread - all threads suspended - show the current execution * of idling */ From d9940cc9bc6745825abbf7d338df0d1f21c58ab8 Mon Sep 17 00:00:00 2001 From: Martin Hierholzer Date: Fri, 27 May 2022 15:22:25 +0200 Subject: [PATCH 0009/1312] fix Kinetis 100 MHz rev 1.x programming Kinetis 100 MHz rev 1.x devices have no SMC and hence need different checking of the run mode. Details about the differences between rev 1.x and 2.x of the Kinetis 100 MHz series can be found here: https://www.nxp.com.cn/docs/en/application-note/AN4445.pdf Signed-off-by: Martin Hierholzer Change-Id: Ib705385a931275159bdae9b31caecc6ec9c0da1e Reviewed-on: https://review.openocd.org/c/openocd/+/7015 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/kinetis.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 6adc4ef73f..12e3f5fb9d 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -97,6 +97,8 @@ #define SMC_PMSTAT 0x4007E003 #define SMC32_PMCTRL 0x4007E00C #define SMC32_PMSTAT 0x4007E014 +#define PMC_REGSC 0x4007D002 +#define MC_PMCTRL 0x4007E003 #define MCM_PLACR 0xF000300C /* Offsets */ @@ -188,6 +190,9 @@ #define KINETIS_K_SDID_K60_M150 0x000001C0 #define KINETIS_K_SDID_K70_M150 0x000001D0 +#define KINETIS_K_REVID_MASK 0x0000F000 +#define KINETIS_K_REVID_SHIFT 12 + #define KINETIS_SDID_SERIESID_MASK 0x00F00000 #define KINETIS_SDID_SERIESID_K 0x00000000 #define KINETIS_SDID_SERIESID_KL 0x00100000 @@ -298,6 +303,7 @@ struct kinetis_chip { enum { KINETIS_SMC, KINETIS_SMC32, + KINETIS_MC, } sysmodectrlr_type; char name[40]; @@ -1537,6 +1543,17 @@ static int kinetis_read_pmstat(struct kinetis_chip *k_chip, uint8_t *pmstat) if (result == ERROR_OK) *pmstat = stat32 & 0xff; return result; + + case KINETIS_MC: + /* emulate SMC by reading PMC_REGSC bit 3 (VLPRS) */ + result = target_read_u8(target, PMC_REGSC, pmstat); + if (result == ERROR_OK) { + if (*pmstat & 0x08) + *pmstat = PM_STAT_VLPR; + else + *pmstat = PM_STAT_RUN; + } + return result; } return ERROR_FAIL; } @@ -1577,6 +1594,10 @@ static int kinetis_check_run_mode(struct kinetis_chip *k_chip) case KINETIS_SMC32: result = target_write_u32(target, SMC32_PMCTRL, PM_CTRL_RUNM_RUN); break; + + case KINETIS_MC: + result = target_write_u32(target, MC_PMCTRL, PM_CTRL_RUNM_RUN); + break; } if (result != ERROR_OK) return result; @@ -2143,6 +2164,24 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) } } + /* first revision of some devices has no SMC */ + switch (mcu_type) { + case KINETIS_K_SDID_K10_M100: + case KINETIS_K_SDID_K20_M100: + case KINETIS_K_SDID_K30_M100: + case KINETIS_K_SDID_K40_M100: + case KINETIS_K_SDID_K60_M100: + { + uint32_t revid = (k_chip->sim_sdid & KINETIS_K_REVID_MASK) >> KINETIS_K_REVID_SHIFT; + /* highest bit set corresponds to rev 2.x */ + if (revid <= 7) { + k_chip->sysmodectrlr_type = KINETIS_MC; + strcat(name, " Rev 1.x"); + } + } + break; + } + } else { /* Newer K-series or KL series MCU */ familyid = (k_chip->sim_sdid & KINETIS_SDID_FAMILYID_MASK) >> KINETIS_SDID_FAMILYID_SHIFT; From 2aaa991a503dc28b087d81b59531c66931ad74d8 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 30 Jul 2022 12:15:43 +0200 Subject: [PATCH 0010/1312] target: fix unaligned return of target_get_working_area_avail() The working area allocation routines use 4 byte word alignment. In the corner case the size of the working area is not aligned, target_alloc_working_area() of size = target_get_working_area_avail() will fail because the size gets aligned up and does not fit to the area which size is aligned down. Align down the result of target_get_working_area_avail() to cope with that corner case. While on it use fancy ALIGN_... macros instead of bitwise and operator. Change-Id: Ia2a1e861c401c2c78fe6323379a3776fb4f47b06 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7096 Tested-by: jenkins Reviewed-by: Erhan Kurubas Reviewed-by: Antonio Borneo --- src/target/target.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 78073f6807..553400df68 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2071,7 +2071,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w struct working_area *new_wa = malloc(sizeof(*new_wa)); if (new_wa) { new_wa->next = NULL; - new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */ + new_wa->size = ALIGN_DOWN(target->working_area_size, 4); /* 4-byte align */ new_wa->address = target->working_area; new_wa->backup = NULL; new_wa->user = NULL; @@ -2082,8 +2082,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w } /* only allocate multiples of 4 byte */ - if (size % 4) - size = (size + 3) & (~3UL); + size = ALIGN_UP(size, 4); struct working_area *c = target->working_areas; @@ -2237,7 +2236,7 @@ uint32_t target_get_working_area_avail(struct target *target) uint32_t max_size = 0; if (!c) - return target->working_area_size; + return ALIGN_DOWN(target->working_area_size, 4); while (c) { if (c->free && max_size < c->size) From b76a7a82b20fcf265a7b211e6ef97b759a8cb714 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 31 Jul 2022 08:01:23 +0200 Subject: [PATCH 0011/1312] flash/nor: remove useless setting of bus_width and chip_width The flash/nor subsystem uses bus_width and chip_width for CFI external flash only. Drop setting these values for internal flash. Change-Id: I64e79ab38b6e39e845ff96fbf4f60145e3b9690a Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7098 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/at91sam7.c | 11 +---------- src/flash/nor/psoc6.c | 3 +-- src/flash/nor/tms470.c | 3 --- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index fac8bb3787..e18635b6df 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -576,8 +576,6 @@ static int at91sam7_read_part_info(struct flash_bank *bank) t_bank->bank_number = bnk; t_bank->base = base_address + bnk * bank_size; t_bank->size = bank_size; - t_bank->chip_width = 0; - t_bank->bus_width = 4; t_bank->num_sectors = sectors_num; /* allocate sectors */ @@ -691,8 +689,6 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) uint32_t bank_size; uint32_t ext_freq = 0; - unsigned int chip_width; - unsigned int bus_width; unsigned int banks_num; unsigned int num_sectors; @@ -716,9 +712,6 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], base_address); - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[3], chip_width); - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[4], bus_width); - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], banks_num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[9], num_sectors); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[10], pages_per_sector); @@ -732,7 +725,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) at91sam7_info->ext_freq = ext_freq; } - if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) || + if ((banks_num == 0) || (num_sectors == 0) || (pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) { at91sam7_info->flash_autodetection = 1; return ERROR_OK; @@ -761,8 +754,6 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) t_bank->bank_number = bnk; t_bank->base = base_address + bnk * bank_size; t_bank->size = bank_size; - t_bank->chip_width = chip_width; - t_bank->bus_width = bus_width; t_bank->num_sectors = num_sectors; /* allocate sectors */ diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index ce615fc2a0..da07d84871 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -591,8 +591,7 @@ static int psoc6_probe(struct flash_bank *bank) unsigned int num_sectors = bank_size / row_sz; bank->size = bank_size; - bank->chip_width = 4; - bank->bus_width = 4; + bank->erased_value = 0; bank->default_padded_value = 0; diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index 7b24fff1cd..9fffae90ae 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -248,9 +248,6 @@ static int tms470_read_part_info(struct flash_bank *bank) target_write_u32(target, 0xFFFFFFE4, 0x00000000); target_write_u32(target, 0xFFFFFFE0, 0x00000000); - bank->chip_width = 32; - bank->bus_width = 32; - LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.", part_name, (int)(silicon_version), From 8f299c6aec299f7231005a1ba7526ed2758414c3 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 26 May 2022 10:01:45 +0200 Subject: [PATCH 0012/1312] target: consolidate existing target/algo common_magic Unify common_magic type to unsigned int Move common_magic to be the first member of the struct Add unsigned specifier to xxx_COMMON_MAGIC #defines Change-Id: If961d33232698529514ba3720e04418baf6dc6fe Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/6996 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/aarch64.h | 4 ++-- src/target/arc.h | 4 ++-- src/target/arm.h | 7 ++++--- src/target/arm720t.h | 5 +++-- src/target/arm7_9_common.h | 5 +++-- src/target/arm920t.h | 5 +++-- src/target/arm926ejs.h | 5 +++-- src/target/arm946e.h | 5 +++-- src/target/arm966e.h | 5 +++-- src/target/armv7a.h | 5 +++-- src/target/armv7m.h | 7 ++++--- src/target/armv8.h | 5 +++-- src/target/avr32_ap7k.h | 6 ++++-- src/target/cortex_a.h | 4 ++-- src/target/cortex_m.h | 4 ++-- src/target/mips32.h | 7 ++++--- src/target/mips64.h | 5 +++-- src/target/mips_m4k.h | 5 +++-- src/target/mips_mips64.h | 3 ++- src/target/nds32.h | 3 ++- src/target/stm8.h | 5 +++-- src/target/x86_32_common.h | 5 +++-- src/target/xscale.h | 6 +++--- 23 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/target/aarch64.h b/src/target/aarch64.h index 902a508e4f..52b3bafcdf 100644 --- a/src/target/aarch64.h +++ b/src/target/aarch64.h @@ -9,7 +9,7 @@ #include "armv8.h" -#define AARCH64_COMMON_MAGIC 0x411fc082 +#define AARCH64_COMMON_MAGIC 0x411fc082U #define CPUDBG_CPUID 0xD00 #define CPUDBG_CTYPR 0xD04 @@ -38,7 +38,7 @@ struct aarch64_brp { }; struct aarch64_common { - int common_magic; + unsigned int common_magic; /* Context information */ uint32_t system_control_reg; diff --git a/src/target/arc.h b/src/target/arc.h index 86d8d09d55..bb70a598e1 100644 --- a/src/target/arc.h +++ b/src/target/arc.h @@ -27,7 +27,7 @@ #include "arc_cmd.h" #include "arc_mem.h" -#define ARC_COMMON_MAGIC 0xB32EB324 /* just a unique number */ +#define ARC_COMMON_MAGIC 0xB32EB324U /* just a unique number */ #define AUX_DEBUG_REG 0x5 #define AUX_PC_REG 0x6 @@ -183,7 +183,7 @@ struct arc_actionpoint { }; struct arc_common { - uint32_t common_magic; + unsigned int common_magic; struct arc_jtag jtag_info; diff --git a/src/target/arm.h b/src/target/arm.h index e264293f4e..f262255ab3 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -155,7 +155,7 @@ enum arm_vfp_version { ARM_VFP_V3, }; -#define ARM_COMMON_MAGIC 0x0A450A45 +#define ARM_COMMON_MAGIC 0x0A450A45U /** * Represents a generic ARM core, with standard application registers. @@ -165,7 +165,8 @@ enum arm_vfp_version { * registers as traditional ARM cores, and only support Thumb2 instructions. */ struct arm { - int common_magic; + unsigned int common_magic; + struct reg_cache *core_cache; /** Handle to the PC; valid in all core modes. */ @@ -252,7 +253,7 @@ static inline bool is_arm(struct arm *arm) } struct arm_algorithm { - int common_magic; + unsigned int common_magic; enum arm_mode core_mode; enum arm_state core_state; diff --git a/src/target/arm720t.h b/src/target/arm720t.h index 81c6e1f6ad..65bd78ff08 100644 --- a/src/target/arm720t.h +++ b/src/target/arm720t.h @@ -11,11 +11,12 @@ #include "arm7tdmi.h" #include "armv4_5_mmu.h" -#define ARM720T_COMMON_MAGIC 0xa720a720 +#define ARM720T_COMMON_MAGIC 0xa720a720U struct arm720t_common { + unsigned int common_magic; + struct arm7_9_common arm7_9_common; - uint32_t common_magic; struct armv4_5_mmu_common armv4_5_mmu; uint32_t cp15_control_reg; uint32_t fsr_reg; diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 805fbc918e..92d0fd51a2 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -20,14 +20,15 @@ #include "arm.h" #include "arm_jtag.h" -#define ARM7_9_COMMON_MAGIC 0x0a790a79 /**< */ +#define ARM7_9_COMMON_MAGIC 0x0a790a79U /**< */ /** * Structure for items that are common between both ARM7 and ARM9 targets. */ struct arm7_9_common { + unsigned int common_magic; + struct arm arm; - uint32_t common_magic; struct arm_jtag jtag_info; /**< JTAG information for target */ struct reg_cache *eice_cache; /**< Embedded ICE register cache */ diff --git a/src/target/arm920t.h b/src/target/arm920t.h index 49ec3c0001..eba768ffff 100644 --- a/src/target/arm920t.h +++ b/src/target/arm920t.h @@ -11,11 +11,12 @@ #include "arm9tdmi.h" #include "armv4_5_mmu.h" -#define ARM920T_COMMON_MAGIC 0xa920a920 +#define ARM920T_COMMON_MAGIC 0xa920a920U struct arm920t_common { + unsigned int common_magic; + struct arm7_9_common arm7_9_common; - uint32_t common_magic; struct armv4_5_mmu_common armv4_5_mmu; uint32_t cp15_control_reg; uint32_t d_fsr; diff --git a/src/target/arm926ejs.h b/src/target/arm926ejs.h index c652a3b092..479128e615 100644 --- a/src/target/arm926ejs.h +++ b/src/target/arm926ejs.h @@ -11,11 +11,12 @@ #include "arm9tdmi.h" #include "armv4_5_mmu.h" -#define ARM926EJS_COMMON_MAGIC 0xa926a926 +#define ARM926EJS_COMMON_MAGIC 0xa926a926U struct arm926ejs_common { + unsigned int common_magic; + struct arm7_9_common arm7_9_common; - uint32_t common_magic; struct armv4_5_mmu_common armv4_5_mmu; int (*read_cp15)(struct target *target, uint32_t op1, uint32_t op2, uint32_t crn, uint32_t crm, uint32_t *value); diff --git a/src/target/arm946e.h b/src/target/arm946e.h index b205534fd9..7416878690 100644 --- a/src/target/arm946e.h +++ b/src/target/arm946e.h @@ -16,11 +16,12 @@ #include "arm9tdmi.h" -#define ARM946E_COMMON_MAGIC 0x20f920f9 +#define ARM946E_COMMON_MAGIC 0x20f920f9U struct arm946e_common { + unsigned int common_magic; + struct arm7_9_common arm7_9_common; - int common_magic; uint32_t cp15_control_reg; uint32_t cp15_cache_info; }; diff --git a/src/target/arm966e.h b/src/target/arm966e.h index e41b850376..be2b3391e8 100644 --- a/src/target/arm966e.h +++ b/src/target/arm966e.h @@ -13,11 +13,12 @@ #include "arm9tdmi.h" -#define ARM966E_COMMON_MAGIC 0x20f920f9 +#define ARM966E_COMMON_MAGIC 0x20f920f9U struct arm966e_common { + unsigned int common_magic; + struct arm7_9_common arm7_9_common; - int common_magic; uint32_t cp15_control_reg; }; diff --git a/src/target/armv7a.h b/src/target/armv7a.h index ebd38f0f68..6b9c2a68f4 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -19,7 +19,7 @@ enum { ARM_CPSR = 16 }; -#define ARMV7_COMMON_MAGIC 0x0A450999 +#define ARMV7_COMMON_MAGIC 0x0A450999U /* VA to PA translation operations opc2 values*/ #define V2PCWPR 0 @@ -87,8 +87,9 @@ struct armv7a_mmu_common { }; struct armv7a_common { + unsigned int common_magic; + struct arm arm; - int common_magic; struct reg_cache *core_cache; /* Core Debug Unit */ diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 6d97e4ac51..9ac6b9ec9d 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -215,12 +215,13 @@ enum { #define ARMV7M_NUM_CORE_REGS (ARMV7M_CORE_LAST_REG - ARMV7M_CORE_FIRST_REG + 1) -#define ARMV7M_COMMON_MAGIC 0x2A452A45 +#define ARMV7M_COMMON_MAGIC 0x2A452A45U struct armv7m_common { + unsigned int common_magic; + struct arm arm; - int common_magic; int exception_number; /* AP this processor is connected to in the DAP */ @@ -289,7 +290,7 @@ target_to_armv7m_safe(struct target *target) } struct armv7m_algorithm { - int common_magic; + unsigned int common_magic; enum arm_mode core_mode; diff --git a/src/target/armv8.h b/src/target/armv8.h index 912da675cd..e06067175b 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -108,7 +108,7 @@ enum run_control_op { ARMV8_RUNCONTROL_STEP = 3, }; -#define ARMV8_COMMON_MAGIC 0x0A450AAA +#define ARMV8_COMMON_MAGIC 0x0A450AAAU /* VA to PA translation operations opc2 values*/ #define V2PCWPR 0 @@ -178,8 +178,9 @@ struct armv8_mmu_common { }; struct armv8_common { + unsigned int common_magic; + struct arm arm; - int common_magic; struct reg_cache *core_cache; /* Core Debug Unit */ diff --git a/src/target/avr32_ap7k.h b/src/target/avr32_ap7k.h index 6984b61013..ac35754f47 100644 --- a/src/target/avr32_ap7k.h +++ b/src/target/avr32_ap7k.h @@ -9,9 +9,11 @@ struct target; -#define AP7K_COMMON_MAGIC 0x4150374b +#define AP7K_COMMON_MAGIC 0x4150374bU + struct avr32_ap7k_common { - int common_magic; + unsigned int common_magic; + struct avr32_jtag jtag; struct reg_cache *core_cache; uint32_t core_regs[AVR32NUMCOREREGS]; diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index 05c3730c25..656ccea8a5 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -19,7 +19,7 @@ #include "armv7a.h" -#define CORTEX_A_COMMON_MAGIC 0x411fc082 +#define CORTEX_A_COMMON_MAGIC 0x411fc082U #define CORTEX_A5_PARTNUM 0xc05 #define CORTEX_A7_PARTNUM 0xc07 @@ -67,7 +67,7 @@ struct cortex_a_wrp { }; struct cortex_a_common { - int common_magic; + unsigned int common_magic; /* Context information */ uint32_t cpudbg_dscr; diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 3f0d55c1c2..54767c5dfd 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -17,7 +17,7 @@ #include "armv7m.h" #include "helper/bits.h" -#define CORTEX_M_COMMON_MAGIC 0x1A451A45 +#define CORTEX_M_COMMON_MAGIC 0x1A451A45U #define SYSTEM_CONTROL_BASE 0x400FE000 @@ -199,7 +199,7 @@ enum cortex_m_isrmasking_mode { }; struct cortex_m_common { - int common_magic; + unsigned int common_magic; /* Context information */ uint32_t dcb_dhcsr; diff --git a/src/target/mips32.h b/src/target/mips32.h index ca02dda451..8837da1d08 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -16,7 +16,7 @@ #include "target.h" #include "mips32_pracc.h" -#define MIPS32_COMMON_MAGIC 0xB320B320 +#define MIPS32_COMMON_MAGIC 0xB320B320U /** * Memory segments (32bit kernel mode addresses) @@ -82,7 +82,8 @@ struct mips32_comparator { }; struct mips32_common { - uint32_t common_magic; + unsigned int common_magic; + void *arch_info; struct reg_cache *core_cache; struct mips_ejtag ejtag_info; @@ -119,7 +120,7 @@ struct mips32_core_reg { }; struct mips32_algorithm { - int common_magic; + unsigned int common_magic; enum mips32_isa_mode isa_mode; }; diff --git a/src/target/mips64.h b/src/target/mips64.h index 3453e4ed1a..9079c8013d 100644 --- a/src/target/mips64.h +++ b/src/target/mips64.h @@ -19,7 +19,7 @@ #include "register.h" #include "mips64_pracc.h" -#define MIPS64_COMMON_MAGIC 0xB640B640 +#define MIPS64_COMMON_MAGIC 0xB640B640U /* MIPS64 CP0 registers */ #define MIPS64_C0_INDEX 0 @@ -81,7 +81,8 @@ struct mips64_comparator { }; struct mips64_common { - uint32_t common_magic; + unsigned int common_magic; + void *arch_info; struct reg_cache *core_cache; struct mips_ejtag ejtag_info; diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h index ae4a0ff722..b563ea513a 100644 --- a/src/target/mips_m4k.h +++ b/src/target/mips_m4k.h @@ -15,10 +15,11 @@ struct target; -#define MIPSM4K_COMMON_MAGIC 0xB321B321 +#define MIPSM4K_COMMON_MAGIC 0xB321B321U struct mips_m4k_common { - uint32_t common_magic; + unsigned int common_magic; + bool is_pic32mx; struct mips32_common mips32; }; diff --git a/src/target/mips_mips64.h b/src/target/mips_mips64.h index 69fb2a6f98..9841deb2fd 100644 --- a/src/target/mips_mips64.h +++ b/src/target/mips_mips64.h @@ -17,7 +17,8 @@ #include "helper/types.h" struct mips_mips64_common { - int common_magic; + unsigned int common_magic; + struct mips64_common mips64_common; }; diff --git a/src/target/nds32.h b/src/target/nds32.h index 1c8675e731..d0b680a97c 100644 --- a/src/target/nds32.h +++ b/src/target/nds32.h @@ -224,7 +224,8 @@ struct nds32_misc_config { * Represents a generic Andes core. */ struct nds32 { - uint32_t common_magic; + unsigned int common_magic; + struct reg_cache *core_cache; /** Handle for the debug module. */ diff --git a/src/target/stm8.h b/src/target/stm8.h index bbda4feb68..55e1071aba 100644 --- a/src/target/stm8.h +++ b/src/target/stm8.h @@ -11,11 +11,12 @@ struct target; -#define STM8_COMMON_MAGIC 0x53544D38 +#define STM8_COMMON_MAGIC 0x53544D38U #define STM8_NUM_CORE_REGS 6 struct stm8_common { - uint32_t common_magic; + unsigned int common_magic; + void *arch_info; struct reg_cache *core_cache; uint32_t core_regs[STM8_NUM_CORE_REGS]; diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index 4f90ab4e67..7392447a68 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -148,7 +148,7 @@ enum { PMCR, }; -#define X86_32_COMMON_MAGIC 0x86328632 +#define X86_32_COMMON_MAGIC 0x86328632U enum { /* memory read/write */ @@ -200,7 +200,8 @@ struct swbp_mem_patch { #define NUM_PM_REGS 18 /* regs used in save/restore */ struct x86_32_common { - uint32_t common_magic; + unsigned int common_magic; + void *arch_info; enum x86_core_type core_type; struct reg_cache *cache; diff --git a/src/target/xscale.h b/src/target/xscale.h index 0087b8a43b..36a69bca39 100644 --- a/src/target/xscale.h +++ b/src/target/xscale.h @@ -15,7 +15,7 @@ #include "armv4_5_mmu.h" #include "trace.h" -#define XSCALE_COMMON_MAGIC 0x58534341 +#define XSCALE_COMMON_MAGIC 0x58534341U /* These four JTAG instructions are architecturally defined. * Lengths are core-specific; originally 5 bits, later 7. @@ -71,11 +71,11 @@ struct xscale_trace { }; struct xscale_common { + unsigned int common_magic; + /* armv4/5 common stuff */ struct arm arm; - int common_magic; - /* XScale registers (CP15, DBG) */ struct reg_cache *reg_cache; From ea49b2b2a21edf474236e3bdf0c681215c390787 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 26 May 2022 10:18:43 +0200 Subject: [PATCH 0013/1312] target/aarch64: fix duplicate common magic AARCH64_COMMON_MAGIC was same as CORTEX_A_COMMON_MAGIC, probably copy pasta. Define unique AARCH64_COMMON_MAGIC Change-Id: Ie30e0028453a1fce5624ecad9bf73d5ac3791281 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/6997 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/aarch64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/aarch64.h b/src/target/aarch64.h index 52b3bafcdf..be7f246b53 100644 --- a/src/target/aarch64.h +++ b/src/target/aarch64.h @@ -9,7 +9,7 @@ #include "armv8.h" -#define AARCH64_COMMON_MAGIC 0x411fc082U +#define AARCH64_COMMON_MAGIC 0x41413634U #define CPUDBG_CPUID 0xD00 #define CPUDBG_CTYPR 0xD04 From cae0c8b32b32202f3552860f12f6579e8ad8ce4a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 26 May 2022 16:25:34 +0200 Subject: [PATCH 0014/1312] target: move parent target structs just after common_magic Just a cosmetic refactoring. Change-Id: I7fbc05324e346fafc98d1b42691d33d3d8fbd04e Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7003 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/aarch64.h | 4 ++-- src/target/cortex_a.h | 5 ++--- src/target/cortex_m.h | 3 ++- src/target/mips_m4k.h | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/target/aarch64.h b/src/target/aarch64.h index be7f246b53..2721fe747d 100644 --- a/src/target/aarch64.h +++ b/src/target/aarch64.h @@ -40,6 +40,8 @@ struct aarch64_brp { struct aarch64_common { unsigned int common_magic; + struct armv8_common armv8_common; + /* Context information */ uint32_t system_control_reg; uint32_t system_control_reg_curr; @@ -55,8 +57,6 @@ struct aarch64_common { int wp_num_available; struct aarch64_brp *wp_list; - struct armv8_common armv8_common; - enum aarch64_isrmasking_mode isrmasking_mode; }; diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index 656ccea8a5..37fba1a885 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -69,6 +69,8 @@ struct cortex_a_wrp { struct cortex_a_common { unsigned int common_magic; + struct armv7a_common armv7a_common; + /* Context information */ uint32_t cpudbg_dscr; @@ -96,9 +98,6 @@ struct cortex_a_common { enum cortex_a_isrmasking_mode isrmasking_mode; enum cortex_a_dacrfixup_mode dacrfixup_mode; - - struct armv7a_common armv7a_common; - }; static inline struct cortex_a_common * diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 54767c5dfd..168613590f 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -201,6 +201,8 @@ enum cortex_m_isrmasking_mode { struct cortex_m_common { unsigned int common_magic; + struct armv7m_common armv7m; + /* Context information */ uint32_t dcb_dhcsr; uint32_t dcb_dhcsr_cumulated_sticky; @@ -226,7 +228,6 @@ struct cortex_m_common { enum cortex_m_isrmasking_mode isrmasking_mode; const struct cortex_m_part_info *core_info; - struct armv7m_common armv7m; bool slow_register_read; /* A register has not been ready, poll S_REGRDY */ diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h index b563ea513a..8026de2328 100644 --- a/src/target/mips_m4k.h +++ b/src/target/mips_m4k.h @@ -20,8 +20,9 @@ struct target; struct mips_m4k_common { unsigned int common_magic; - bool is_pic32mx; struct mips32_common mips32; + + bool is_pic32mx; }; static inline struct mips_m4k_common * From b6dad912b85d6bcd78c12a7a44065fb85dd8485a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 2 Aug 2022 11:33:07 +0200 Subject: [PATCH 0015/1312] target/cortex_m: prevent segmentation fault in cortex_m_poll() If a Cortex-M MCU become unresponsive during a debug session and re-examination fails to find MEM-AP, debug_ap pointer is set to NULL. Eventual call of cortex_m_poll() dereferences debug_ap. Check debug_ap validity at the begin of cortex_m_poll(). Change-Id: I9519f48760c91a48a9e5e8c34634d247098cb14a Fixes: 35a503b08d14 (arm_adi_v5: add ap refcount and add get/put around ap use) Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7108 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 1682f5dec9..9497aa0373 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -868,6 +868,16 @@ static int cortex_m_poll(struct target *target) struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; + /* Check if debug_ap is available to prevent segmentation fault. + * If the re-examination after an error does not find a MEM-AP + * (e.g. the target stopped communicating), debug_ap pointer + * can suddenly become NULL. + */ + if (!armv7m->debug_ap) { + target->state = TARGET_UNKNOWN; + return ERROR_TARGET_NOT_EXAMINED; + } + /* Read from Debug Halting Control and Status Register */ retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) { From dee7b7d8212dbe94d5afd6bba736de4fcd1a05ac Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 1 Aug 2022 19:06:35 +0200 Subject: [PATCH 0016/1312] target/arm: make 'arm core_state' command compatible with Cortex-M Tcl command 'arm core_state' was exposed even on Cortex-M devices. However it returned message "Unsupported Command" without error status on such device. Set the only possible arm->core_state ARM_STATE_THUMB in armv7m init. Block setting core_state to arm on Cortex-M. Change-Id: I9525553ac8863a6cf77bbacbcd57e354b6cfe1ca Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7100 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv4_5.c | 23 ++++++++++++----------- src/target/armv7m.c | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 2b347924fe..09cf143e65 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -905,32 +905,33 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) return ERROR_OK; } -COMMAND_HANDLER(handle_armv4_5_core_state_command) +COMMAND_HANDLER(handle_arm_core_state_command) { struct target *target = get_current_target(CMD_CTX); struct arm *arm = target_to_arm(target); + int ret = ERROR_OK; if (!is_arm(arm)) { command_print(CMD, "current target isn't an ARM"); return ERROR_FAIL; } - if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) { - /* armv7m not supported */ - command_print(CMD, "Unsupported Command"); - return ERROR_OK; - } - if (CMD_ARGC > 0) { - if (strcmp(CMD_ARGV[0], "arm") == 0) - arm->core_state = ARM_STATE_ARM; + if (strcmp(CMD_ARGV[0], "arm") == 0) { + if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) { + command_print(CMD, "arm mode not supported on Cortex-M"); + ret = ERROR_FAIL; + } else { + arm->core_state = ARM_STATE_ARM; + } + } if (strcmp(CMD_ARGV[0], "thumb") == 0) arm->core_state = ARM_STATE_THUMB; } command_print(CMD, "core state: %s", arm_state_strings[arm->core_state]); - return ERROR_OK; + return ret; } COMMAND_HANDLER(handle_arm_disassemble_command) @@ -1126,7 +1127,7 @@ static const struct command_registration arm_exec_command_handlers[] = { }, { .name = "core_state", - .handler = handle_armv4_5_core_state_command, + .handler = handle_arm_core_state_command, .mode = COMMAND_EXEC, .usage = "['arm'|'thumb']", .help = "display/change ARM core state", diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 4c46240f89..790e70e63d 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -854,6 +854,7 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) /* Enable stimulus port #0 by default */ armv7m->trace_config.itm_ter[0] = 1; + arm->core_state = ARM_STATE_THUMB; arm->core_type = ARM_CORE_TYPE_M_PROFILE; arm->arch_info = armv7m; arm->setup_semihosting = armv7m_setup_semihosting; From 0e1fe03f4ba2b313d80c0a2d3c2ecfb7aee85a77 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 1 Aug 2022 19:28:18 +0200 Subject: [PATCH 0017/1312] target/arm: do not expose 'arm reg', 'arm mcr/mrc' commands on Cortex-M Tcl commands 'arm reg', 'arm mcr/mrc' do not work on M-profile based devices. Isolate them from 'arm core_state' and 'arm disassemble' and do not chain them from armv7m_command_handlers. Change-Id: I2c6befdf82575e95cf05ed158ab5e6faa1a182c3 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7101 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/arm.h | 1 + src/target/armv4_5.c | 36 ++++++++++++++++++++++-------------- src/target/armv7m.c | 6 +++++- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/target/arm.h b/src/target/arm.h index f262255ab3..bcfa85c79c 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -273,6 +273,7 @@ void arm_free_reg_cache(struct arm *arm); struct reg_cache *armv8_build_reg_cache(struct target *target); extern const struct command_registration arm_command_handlers[]; +extern const struct command_registration arm_all_profiles_command_handlers[]; int arm_arch_state(struct target *target); const char *arm_get_gdb_arch(struct target *target); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 09cf143e65..321772699b 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1125,20 +1125,6 @@ static const struct command_registration arm_exec_command_handlers[] = { .help = "display ARM core registers", .usage = "", }, - { - .name = "core_state", - .handler = handle_arm_core_state_command, - .mode = COMMAND_EXEC, - .usage = "['arm'|'thumb']", - .help = "display/change ARM core state", - }, - { - .name = "disassemble", - .handler = handle_arm_disassemble_command, - .mode = COMMAND_EXEC, - .usage = "address [count ['thumb']]", - .help = "disassemble instructions", - }, { .name = "mcr", .mode = COMMAND_EXEC, @@ -1153,11 +1139,33 @@ static const struct command_registration arm_exec_command_handlers[] = { .help = "read coprocessor register", .usage = "cpnum op1 CRn CRm op2", }, + { + .chain = arm_all_profiles_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +const struct command_registration arm_all_profiles_command_handlers[] = { + { + .name = "core_state", + .handler = handle_arm_core_state_command, + .mode = COMMAND_EXEC, + .usage = "['arm'|'thumb']", + .help = "display/change ARM core state", + }, + { + .name = "disassemble", + .handler = handle_arm_disassemble_command, + .mode = COMMAND_EXEC, + .usage = "address [count ['thumb']]", + .help = "disassemble instructions", + }, { .chain = semihosting_common_handlers, }, COMMAND_REGISTRATION_DONE }; + const struct command_registration arm_command_handlers[] = { { .name = "arm", diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 790e70e63d..be0de509b7 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -1085,7 +1085,11 @@ int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found) const struct command_registration armv7m_command_handlers[] = { { - .chain = arm_command_handlers, + .name = "arm", + .mode = COMMAND_ANY, + .help = "ARM command group", + .usage = "", + .chain = arm_all_profiles_command_handlers, }, COMMAND_REGISTRATION_DONE }; From 81aa5fd6b477cb03b718625a48e50099fc2ae0f2 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Jul 2022 09:20:22 -0700 Subject: [PATCH 0018/1312] target/riscv: Update debug_defines.h. This one doesn't have the license in there, which means now it's acceptable to GPLv2 again. See https://github.com/riscv/riscv-openocd/pull/711 Change-Id: I8ba27801172ffa955470d2627fa656cad282ee99 Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/7087 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/riscv/debug_defines.h | 2382 ++++++++++++++++++------------ 1 file changed, 1445 insertions(+), 937 deletions(-) diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h index 5c9eef4eaf..8113d47664 100644 --- a/src/target/riscv/debug_defines.h +++ b/src/target/riscv/debug_defines.h @@ -1,22 +1,21 @@ /* * This file is auto-generated by running 'make debug_defines.h' in - * https://github.com/riscv/riscv-debug-spec/ (3dfe4f7) - * License: Creative Commons Attribution 4.0 International Public License (CC BY 4.0) + * https://github.com/riscv/riscv-debug-spec/ (d749752) */ #define DTM_IDCODE 0x01 /* * Identifies the release version of this part. */ -#define DTM_IDCODE_VERSION_OFFSET 28 +#define DTM_IDCODE_VERSION_OFFSET 0x1c #define DTM_IDCODE_VERSION_LENGTH 4 -#define DTM_IDCODE_VERSION (0xfU << DTM_IDCODE_VERSION_OFFSET) +#define DTM_IDCODE_VERSION 0xf0000000U /* * Identifies the designer's part number of this part. */ -#define DTM_IDCODE_PARTNUMBER_OFFSET 12 -#define DTM_IDCODE_PARTNUMBER_LENGTH 16 -#define DTM_IDCODE_PARTNUMBER (0xffffU << DTM_IDCODE_PARTNUMBER_OFFSET) +#define DTM_IDCODE_PARTNUMBER_OFFSET 0xc +#define DTM_IDCODE_PARTNUMBER_LENGTH 0x10 +#define DTM_IDCODE_PARTNUMBER 0xffff000 /* * Identifies the designer/manufacturer of this part. Bits 6:0 must be * bits 6:0 of the designer/manufacturer's Identification Code as @@ -25,11 +24,11 @@ * Identification Code. */ #define DTM_IDCODE_MANUFID_OFFSET 1 -#define DTM_IDCODE_MANUFID_LENGTH 11 -#define DTM_IDCODE_MANUFID (0x7ffU << DTM_IDCODE_MANUFID_OFFSET) +#define DTM_IDCODE_MANUFID_LENGTH 0xb +#define DTM_IDCODE_MANUFID 0xffe #define DTM_IDCODE_1_OFFSET 0 #define DTM_IDCODE_1_LENGTH 1 -#define DTM_IDCODE_1 (0x1U << DTM_IDCODE_1_OFFSET) +#define DTM_IDCODE_1 1 #define DTM_DTMCS 0x10 /* * Writing 1 to this bit does a hard reset of the DTM, @@ -40,16 +39,16 @@ * complete (e.g. a reset condition caused an inflight DMI transaction to * be cancelled). */ -#define DTM_DTMCS_DMIHARDRESET_OFFSET 17 +#define DTM_DTMCS_DMIHARDRESET_OFFSET 0x11 #define DTM_DTMCS_DMIHARDRESET_LENGTH 1 -#define DTM_DTMCS_DMIHARDRESET (0x1U << DTM_DTMCS_DMIHARDRESET_OFFSET) +#define DTM_DTMCS_DMIHARDRESET 0x20000 /* * Writing 1 to this bit clears the sticky error state, but does * not affect outstanding DMI transactions. */ -#define DTM_DTMCS_DMIRESET_OFFSET 16 +#define DTM_DTMCS_DMIRESET_OFFSET 0x10 #define DTM_DTMCS_DMIRESET_LENGTH 1 -#define DTM_DTMCS_DMIRESET (0x1U << DTM_DTMCS_DMIRESET_OFFSET) +#define DTM_DTMCS_DMIRESET 0x10000 /* * This is a hint to the debugger of the minimum number of * cycles a debugger should spend in @@ -65,76 +64,89 @@ * * And so on. */ -#define DTM_DTMCS_IDLE_OFFSET 12 +#define DTM_DTMCS_IDLE_OFFSET 0xc #define DTM_DTMCS_IDLE_LENGTH 3 -#define DTM_DTMCS_IDLE (0x7U << DTM_DTMCS_IDLE_OFFSET) +#define DTM_DTMCS_IDLE 0x7000 /* - * 0: No error. - * - * 1: Reserved. Interpret the same as 2. - * - * 2: An operation failed (resulted in \FdtmDmiOp of 2). - * - * 3: An operation was attempted while a DMI access was still in - * progress (resulted in \FdtmDmiOp of 3). + * Read-only alias of \FdtmDmiOp. */ -#define DTM_DTMCS_DMISTAT_OFFSET 10 +#define DTM_DTMCS_DMISTAT_OFFSET 0xa #define DTM_DTMCS_DMISTAT_LENGTH 2 -#define DTM_DTMCS_DMISTAT (0x3U << DTM_DTMCS_DMISTAT_OFFSET) +#define DTM_DTMCS_DMISTAT 0xc00 /* * The size of \FdmSbaddressZeroAddress in \RdtmDmi. */ #define DTM_DTMCS_ABITS_OFFSET 4 #define DTM_DTMCS_ABITS_LENGTH 6 -#define DTM_DTMCS_ABITS (0x3fU << DTM_DTMCS_ABITS_OFFSET) -/* - * 0: Version described in spec version 0.11. - * - * 1: Version described in spec versions 0.13 and 1.0. - * - * 15: Version not described in any available version of this spec. - */ +#define DTM_DTMCS_ABITS 0x3f0 #define DTM_DTMCS_VERSION_OFFSET 0 #define DTM_DTMCS_VERSION_LENGTH 4 -#define DTM_DTMCS_VERSION (0xfU << DTM_DTMCS_VERSION_OFFSET) +#define DTM_DTMCS_VERSION 0xf +/* + * 0.11: Version described in spec version 0.11. + */ +#define DTM_DTMCS_VERSION_0_11 0 +/* + * 1.0: Version described in spec versions 0.13 and 1.0. + */ +#define DTM_DTMCS_VERSION_1_0 1 +/* + * custom: Version not described in any available version of this spec. + */ +#define DTM_DTMCS_VERSION_CUSTOM 15 #define DTM_DMI 0x11 /* * Address used for DMI access. In Update-DR this value is used * to access the DM over the DMI. */ -#define DTM_DMI_ADDRESS_OFFSET 34 -#define DTM_DMI_ADDRESS_LENGTH abits -#define DTM_DMI_ADDRESS (((1L << abits) - 1) << DTM_DMI_ADDRESS_OFFSET) +#define DTM_DMI_ADDRESS_OFFSET 0x22 +#define DTM_DMI_ADDRESS_LENGTH(abits) abits +#define DTM_DMI_ADDRESS(abits) ((0x400000000ULL * (1ULL< Date: Thu, 21 Jul 2022 12:27:11 +0200 Subject: [PATCH 0019/1312] rtos: Support for "none" rtos After a certain RTOS has been configured there is no mechanism to go back to no RTOS support. It may be useful for debugging purposes. With the provided modification, the "none" option of RTOS is provided as a valid option. It has been tested in two different board (Cortex M4 and Cortex M33). Documentation has also been updated. Signed-off-by: Asier Llano Change-Id: I602210bff31ccadd41c41e9454c52b5fffa1671e Reviewed-on: https://review.openocd.org/c/openocd/+/7092 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- doc/openocd.texi | 7 ++++++- src/rtos/rtos.c | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 1d63b20b7a..995861d18c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5149,7 +5149,7 @@ The value should normally correspond to a static mapping for the @anchor{rtostype} @item @code{-rtos} @var{rtos_type} -- enable rtos support for target, -@var{rtos_type} can be one of @option{auto}, @option{eCos}, +@var{rtos_type} can be one of @option{auto}, @option{none}, @option{eCos}, @option{ThreadX}, @option{FreeRTOS}, @option{linux}, @option{ChibiOS}, @option{embKernel}, @option{mqx}, @option{uCOS-III}, @option{nuttx}, @option{RIOT}, @option{Zephyr} @@ -11848,6 +11848,11 @@ Currently supported rtos's include: @item @option{Zephyr} @end itemize +At any time, it's possible to drop the selected RTOS using: +@example +$_TARGETNAME configure -rtos none +@end example + Before an RTOS can be detected, it must export certain symbols; otherwise, it cannot be used by OpenOCD. Below is a list of the required symbols for each supported RTOS. diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 013080bb0c..3e43e828d1 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -129,6 +129,9 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target) if (e != JIM_OK) return e; + if (strcmp(cp, "none") == 0) + return JIM_OK; + if (strcmp(cp, "auto") == 0) { /* Auto detect tries to look up all symbols for each RTOS, * and runs the RTOS driver's _detect() function when GDB @@ -148,7 +151,7 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target) res = Jim_GetResult(goi->interp); for (x = 0; rtos_types[x]; x++) Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL); - Jim_AppendStrings(goi->interp, res, " or auto", NULL); + Jim_AppendStrings(goi->interp, res, ", auto or none", NULL); return JIM_ERR; } From 9903203d73c9243c327db9dc0d726491bb625d41 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 26 May 2022 22:43:41 +0200 Subject: [PATCH 0020/1312] adapter: run at default speed when clock speed not specified Signed-off-by: Erhan Kurubas Change-Id: I8d2db4a1f618790907265a45d28a212551800b6c Reviewed-on: https://review.openocd.org/c/openocd/+/7004 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- src/jtag/adapter.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 14452d42f2..519505dc32 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -36,6 +36,8 @@ enum adapter_clk_mode { CLOCK_MODE_RCLK }; +#define DEFAULT_CLOCK_SPEED_KHZ 100U + /** * Adapter configuration */ @@ -70,6 +72,18 @@ int adapter_init(struct command_context *cmd_ctx) } int retval; + + if (adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) { + LOG_WARNING("An adapter speed is not selected in the init scripts." + " OpenOCD will try to run the adapter at the low speed (%d kHz)", + DEFAULT_CLOCK_SPEED_KHZ); + LOG_WARNING("To remove this warnings and achieve reasonable communication speed with the target," + " set \"adapter speed\" or \"jtag_rclk\" in the init scripts."); + retval = adapter_config_khz(DEFAULT_CLOCK_SPEED_KHZ); + if (retval != ERROR_OK) + return ERROR_JTAG_INIT_FAILED; + } + retval = adapter_driver->init(); if (retval != ERROR_OK) return retval; @@ -80,12 +94,6 @@ int adapter_init(struct command_context *cmd_ctx) return ERROR_OK; } - if (adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) { - LOG_ERROR("An adapter speed is not selected in the init script." - " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed."); - return ERROR_JTAG_INIT_FAILED; - } - int requested_khz = adapter_get_speed_khz(); int actual_khz = requested_khz; int speed_var = 0; From c3138e2d805b94b81ba10bc7fcec47689704f60e Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Mon, 1 Aug 2022 15:22:32 -0700 Subject: [PATCH 0021/1312] gdb_server: add "not supported" Z-packet reply GDB remote serial protocol specifies breakpoint/watchpoint packet responses can be an empty string to indicate the specified breakpoint type is not supported. Add support for this response alongside existing "OK", "E NN" replies. Signed-off-by: Ian Thompson Change-Id: Iaf6280e4c936eb95a92bc80cc74d451ebb328dc3 Reviewed-on: https://review.openocd.org/c/openocd/+/7102 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 2e6c7304dd..28833c9ce3 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1770,7 +1770,10 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, case 1: if (packet[0] == 'Z') { retval = breakpoint_add(target, address, size, bp_type); - if (retval != ERROR_OK) { + if (retval == ERROR_NOT_IMPLEMENTED) { + /* Send empty reply to report that breakpoints of this type are not supported */ + gdb_put_packet(connection, "", 0); + } else if (retval != ERROR_OK) { retval = gdb_error(connection, retval); if (retval != ERROR_OK) return retval; @@ -1787,7 +1790,10 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, { if (packet[0] == 'Z') { retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu); - if (retval != ERROR_OK) { + if (retval == ERROR_NOT_IMPLEMENTED) { + /* Send empty reply to report that watchpoints of this type are not supported */ + gdb_put_packet(connection, "", 0); + } else if (retval != ERROR_OK) { retval = gdb_error(connection, retval); if (retval != ERROR_OK) return retval; From 0d56f379b55b24959c88e705a83e1fbb826b75e7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 30 May 2022 22:49:12 +0200 Subject: [PATCH 0022/1312] target: add API to temporarily mask target polling The same flag 'jtag_poll' is currently used as local data for the command 'poll' and to temporarily mask the target polling. This can cause unexpected behavior if the command 'poll' is executed while polling is temporarily masked. Add a new flag 'jtag_poll_en' to hold the temporarily mask condition and keep 'jtag_poll' for the 'poll' command only. While there, change the initial assignment of 'jtag_poll' using the proper boolean value. Change-Id: I18dcf7c65b07aefadf046caaa2fcd2d74fa6fbae Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/7009 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/flash/nor/psoc4.c | 6 +++--- src/helper/command.c | 6 ++---- src/jtag/core.c | 19 ++++++++++++++++++- src/jtag/jtag.h | 13 +++++++++++++ src/target/target.c | 12 +++++------- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c index 4b5aa55cf6..1bdd64aae5 100644 --- a/src/flash/nor/psoc4.c +++ b/src/flash/nor/psoc4.c @@ -651,8 +651,8 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer, if (row_offset) memset(row_buffer, bank->default_padded_value, row_offset); - bool save_poll = jtag_poll_get_enabled(); - jtag_poll_set_enabled(false); + /* Mask automatic polling triggered by execution of halted events */ + bool save_poll_mask = jtag_poll_mask(); while (count) { uint32_t chunk_size = psoc4_info->row_size - row_offset; @@ -693,7 +693,7 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer, } cleanup: - jtag_poll_set_enabled(save_poll); + jtag_poll_unmask(save_poll_mask); free(sysrq_buffer); return retval; diff --git a/src/helper/command.c b/src/helper/command.c index 43fe033f71..52f9eb6bf9 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -702,14 +702,12 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) * This is necessary in order to avoid accidentally getting a non-empty * string for tcl fn's. */ - bool save_poll = jtag_poll_get_enabled(); - - jtag_poll_set_enabled(false); + bool save_poll_mask = jtag_poll_mask(); const char *str = Jim_GetString(argv[1], NULL); int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); - jtag_poll_set_enabled(save_poll); + jtag_poll_unmask(save_poll_mask); command_log_capture_finish(state); diff --git a/src/jtag/core.c b/src/jtag/core.c index 27c7b3de49..806ee89265 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -136,14 +136,19 @@ int jtag_error_clear(void) /************/ -static bool jtag_poll = 1; +static bool jtag_poll = true; +static bool jtag_poll_en = true; bool is_jtag_poll_safe(void) { /* Polling can be disabled explicitly with set_enabled(false). + * It can also be masked with mask(). * It is also implicitly disabled while TRST is active and * while SRST is gating the JTAG clock. */ + if (!jtag_poll_en) + return false; + if (!transport_is_jtag()) return jtag_poll; @@ -162,6 +167,18 @@ void jtag_poll_set_enabled(bool value) jtag_poll = value; } +bool jtag_poll_mask(void) +{ + bool retval = jtag_poll_en; + jtag_poll_en = false; + return retval; +} + +void jtag_poll_unmask(bool saved) +{ + jtag_poll_en = saved; +} + /************/ struct jtag_tap *jtag_all_taps(void) diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 18e09ced34..4f94e99135 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -587,6 +587,19 @@ bool jtag_poll_get_enabled(void); */ void jtag_poll_set_enabled(bool value); +/** + * Mask (disable) polling and return the current mask status that should be + * feed to jtag_poll_unmask() to restore it. + * Multiple nested calls to jtag_poll_mask() are allowed, each balanced with + * its call to jtag_poll_unmask(). + */ +bool jtag_poll_mask(void); + +/** + * Restore saved mask for polling. + */ +void jtag_poll_unmask(bool saved); + #include int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv); diff --git a/src/target/target.c b/src/target/target.c index 553400df68..10a25efde6 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -654,10 +654,10 @@ int target_resume(struct target *target, int current, target_addr_t address, * Disable polling during resume() to guarantee the execution of handlers * in the correct order. */ - bool save_poll = jtag_poll_get_enabled(); - jtag_poll_set_enabled(false); + bool save_poll_mask = jtag_poll_mask(); retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); - jtag_poll_set_enabled(save_poll); + jtag_poll_unmask(save_poll_mask); + if (retval != ERROR_OK) return retval; @@ -685,14 +685,12 @@ static int target_process_reset(struct command_invocation *cmd, enum target_rese * more predictable, i.e. dr/irscan & pathmove in events will * not have JTAG operations injected into the middle of a sequence. */ - bool save_poll = jtag_poll_get_enabled(); - - jtag_poll_set_enabled(false); + bool save_poll_mask = jtag_poll_mask(); sprintf(buf, "ocd_process_reset %s", n->name); retval = Jim_Eval(cmd->ctx->interp, buf); - jtag_poll_set_enabled(save_poll); + jtag_poll_unmask(save_poll_mask); if (retval != JIM_OK) { Jim_MakeErrorMessage(cmd->ctx->interp); From e282d208321ed1661efa894b583cf8922d67ba3f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 30 May 2022 15:32:24 +0200 Subject: [PATCH 0023/1312] openocd: prevent target polling during 'init' The command 'init' causes the execution of few lower level commands, e.g. 'target init', and switches from command mode COMMAND_CONFIG to COMMAND_EXEC, with an intermediate switch back to mode COMMAND_CONFIG. A timed target polling can occur during the execution of 'init' and the target's status can trigger the execution of some events. E.g. if a target has been left halted by a previous execution of OpenOCD, the first poll will find the target halted, calling the corresponding 'halted' event. The event handler can use commands that can only be executed in mode COMMAND_EXEC. If the poll happens while OpenOCD is in mode COMMAND_CONFIG, the triggered handler will fail. Prevent the target polling to operate during the execution of the 'init' command. Change-Id: Ia435a5d2039be9b247e2336616dab53ed5d983ac Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/7007 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/openocd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/openocd.c b/src/openocd.c index 43c8523056..b65d471528 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -119,6 +119,8 @@ COMMAND_HANDLER(handle_init_command) initialized = 1; + bool save_poll_mask = jtag_poll_mask(); + retval = command_run_line(CMD_CTX, "target init"); if (retval != ERROR_OK) return ERROR_FAIL; @@ -166,6 +168,8 @@ COMMAND_HANDLER(handle_init_command) if (command_run_line(CMD_CTX, "tpiu init") != ERROR_OK) return ERROR_FAIL; + jtag_poll_unmask(save_poll_mask); + /* initialize telnet subsystem */ gdb_target_add_all(all_targets); From d9b2607ca094898d8d7180085a913e8a5b46ecac Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Mon, 1 Aug 2022 15:47:52 -0700 Subject: [PATCH 0024/1312] gdb_server: support sparse register maps Add additional error handling for targets where gaps may exist in reg_list[] Signed-off-by: Ian Thompson Change-Id: I65232429e2de08f5d54eeca53aea0db8ce2b58af Reviewed-on: https://review.openocd.org/c/openocd/+/7103 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 28833c9ce3..3052d0a0e1 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1323,6 +1323,8 @@ static int gdb_set_registers_packet(struct connection *connection, packet_p = packet; for (i = 0; i < reg_list_size; i++) { uint8_t *bin_buf; + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) + continue; int chars = (DIV_ROUND_UP(reg_list[i]->size, 8) * 2); if (packet_p + chars > packet + packet_size) @@ -1375,7 +1377,8 @@ static int gdb_get_register_packet(struct connection *connection, if (retval != ERROR_OK) return gdb_error(connection, retval); - if (reg_list_size <= reg_num) { + if ((reg_list_size <= reg_num) || !reg_list[reg_num] || + !reg_list[reg_num]->exist || reg_list[reg_num]->hidden) { LOG_ERROR("gdb requested a non-existing register (reg_num=%d)", reg_num); return ERROR_SERVER_REMOTE_CLOSED; } @@ -1437,7 +1440,8 @@ static int gdb_set_register_packet(struct connection *connection, return gdb_error(connection, retval); } - if (reg_list_size <= reg_num) { + if ((reg_list_size <= reg_num) || !reg_list[reg_num] || + !reg_list[reg_num]->exist || reg_list[reg_num]->hidden) { LOG_ERROR("gdb requested a non-existing register (reg_num=%d)", reg_num); free(bin_buf); free(reg_list); From 48db36f436fe212fdda8d3fb7f79db43d9a2aa99 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Sun, 10 Jul 2022 17:14:10 -0700 Subject: [PATCH 0025/1312] gdb_server: custom target-specific GDB queries Provide a customizable hook for handling target-specific GDB queries Valgrind-clean, no new Clang analyzer warnings Signed-off-by: Ian Thompson Change-Id: I684a259ed29f3651cbce668101cff421e522f79e Reviewed-on: https://review.openocd.org/c/openocd/+/7082 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 5 +++++ src/target/target_type.h | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 3052d0a0e1..1e50b43f3f 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2965,6 +2965,11 @@ static int gdb_query_packet(struct connection *connection, gdb_connection->noack_mode = 1; gdb_put_packet(connection, "OK", 2); return ERROR_OK; + } else if (target->type->gdb_query_custom) { + char *buffer = NULL; + int ret = target->type->gdb_query_custom(target, packet, &buffer); + gdb_put_packet(connection, buffer, strlen(buffer)); + return ret; } gdb_put_packet(connection, "", 0); diff --git a/src/target/target_type.h b/src/target/target_type.h index 1933e1cc7c..947080381c 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -286,6 +286,15 @@ struct target_type { */ int (*gdb_fileio_end)(struct target *target, int retcode, int fileio_errno, bool ctrl_c); + /* Parse target-specific GDB query commands. + * The string pointer "response_p" is always assigned by the called function + * to a pointer to a NULL-terminated string, even when the function returns + * an error. The string memory is not freed by the caller, so this function + * must pay attention for possible memory leaks if the string memory is + * dynamically allocated. + */ + int (*gdb_query_custom)(struct target *target, const char *packet, char **response_p); + /* do target profiling */ int (*profiling)(struct target *target, uint32_t *samples, From 7e8ea96345d58ad4d1f6da1a2c952560fe78fc60 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Tue, 2 Aug 2022 01:38:09 +0200 Subject: [PATCH 0026/1312] loaders/reset/espressif: replace the GPL-2.0-or-later license tag Replace the FSF boilerplate with the SPDX tag. Signed-off-by: Erhan Kurubas Change-Id: Iddccae2bd8906a3587a2aa2684124356a340fc74 Reviewed-on: https://review.openocd.org/c/openocd/+/7105 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/loaders/reset/espressif/common.mk | 15 ++------------- contrib/loaders/reset/espressif/esp32/Makefile | 15 ++------------- .../espressif/esp32/esp32_cpu_reset_handler.S | 15 ++------------- contrib/loaders/reset/espressif/esp32s3/Makefile | 15 ++------------- .../espressif/esp32s3/esp32s3_cpu_reset_handler.S | 15 ++------------- 5 files changed, 10 insertions(+), 65 deletions(-) diff --git a/contrib/loaders/reset/espressif/common.mk b/contrib/loaders/reset/espressif/common.mk index 4623583aa6..f77efe6769 100644 --- a/contrib/loaders/reset/espressif/common.mk +++ b/contrib/loaders/reset/espressif/common.mk @@ -1,18 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + # ESP32 Makefile to compile the SoC reset program # Copyright (C) 2022 Espressif Systems Ltd. -# -# 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 # Pass V=1 to see the commands being executed by make ifneq ("$(V)","1") diff --git a/contrib/loaders/reset/espressif/esp32/Makefile b/contrib/loaders/reset/espressif/esp32/Makefile index 3551b6a5ea..a63178065f 100644 --- a/contrib/loaders/reset/espressif/esp32/Makefile +++ b/contrib/loaders/reset/espressif/esp32/Makefile @@ -1,18 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + # ESP32 Makefile to compile the SoC reset program # Copyright (C) 2022 Espressif Systems Ltd. -# -# 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 # Prefix for ESP32 cross compilers (can include a directory path) CROSS ?= xtensa-esp32-elf- diff --git a/contrib/loaders/reset/espressif/esp32/esp32_cpu_reset_handler.S b/contrib/loaders/reset/espressif/esp32/esp32_cpu_reset_handler.S index 1132545568..506d41e85c 100644 --- a/contrib/loaders/reset/espressif/esp32/esp32_cpu_reset_handler.S +++ b/contrib/loaders/reset/espressif/esp32/esp32_cpu_reset_handler.S @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /*************************************************************************** * Reset stub used by esp32 target * * Copyright (C) 2017 Espressif Systems Ltd. * - * * - * 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 . * ***************************************************************************/ #define RTC_CNTL_RESET_STATE_REG 0x3ff48034 diff --git a/contrib/loaders/reset/espressif/esp32s3/Makefile b/contrib/loaders/reset/espressif/esp32s3/Makefile index 4dab161fd0..37d5f82815 100644 --- a/contrib/loaders/reset/espressif/esp32s3/Makefile +++ b/contrib/loaders/reset/espressif/esp32s3/Makefile @@ -1,18 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + # ESP32 Makefile to compile the SoC reset program # Copyright (C) 2022 Espressif Systems Ltd. -# -# 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 # Prefix for ESP32 cross compilers (can include a directory path) CROSS ?= xtensa-esp32s3-elf- diff --git a/contrib/loaders/reset/espressif/esp32s3/esp32s3_cpu_reset_handler.S b/contrib/loaders/reset/espressif/esp32s3/esp32s3_cpu_reset_handler.S index e70ac9ca7b..5fc635725f 100644 --- a/contrib/loaders/reset/espressif/esp32s3/esp32s3_cpu_reset_handler.S +++ b/contrib/loaders/reset/espressif/esp32s3/esp32s3_cpu_reset_handler.S @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /*************************************************************************** * Reset stub used by esp32s3 target * * Copyright (C) 2020 Espressif Systems (Shanghai) Co. Ltd. * - * * - * 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 . * ***************************************************************************/ #define RTC_CNTL_RESET_STATE_REG 0x60008038 From 3adbec9aab95808222071eb09014f28fbb6ad1be Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 2 Aug 2022 11:44:43 +0200 Subject: [PATCH 0027/1312] target/cortex_m: supress historical reset detection The S_RESET_ST sticky bit is reset after DHCSR read. It is set at power-on reset and keeps active until the debuger reads DHCSR. Ignore S_RESET_ST at the very first read after OpenOCD start and suppress possibly misleading message "external reset detected" if we cannot guarantee the reset happened recently. While on it add a TODO comment. Change-Id: I15217c2ca6f69ac97aff8be86bce67cba94a42cd Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7109 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 19 +++++++++++++++++++ src/target/cortex_m.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 9497aa0373..aeaeb18294 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -652,6 +652,11 @@ static int cortex_m_endreset_event(struct target *target) register_cache_invalidate(armv7m->arm.core_cache); + /* TODO: invalidate also working areas (needed in the case of detected reset). + * Doing so will require flash drivers to test if working area + * is still valid in all target algo calling loops. + */ + /* make sure we have latest dhcsr flags */ retval = cortex_m_read_dhcsr_atomic_sticky(target); if (retval != ERROR_OK) @@ -2396,6 +2401,20 @@ int cortex_m_examine(struct target *target) retval = target_read_u32(target, DCB_DHCSR, &cortex_m->dcb_dhcsr); if (retval != ERROR_OK) return retval; + + /* Don't cumulate sticky S_RESET_ST at the very first read of DHCSR + * as S_RESET_ST may indicate a reset that happened long time ago + * (most probably the power-on reset before OpenOCD was started). + * As we are just initializing the debug system we do not need + * to call cortex_m_endreset_event() in the following poll. + */ + if (!cortex_m->dcb_dhcsr_sticky_is_recent) { + cortex_m->dcb_dhcsr_sticky_is_recent = true; + if (cortex_m->dcb_dhcsr & S_RESET_ST) { + LOG_TARGET_DEBUG(target, "reset happened some time ago, ignore"); + cortex_m->dcb_dhcsr &= ~S_RESET_ST; + } + } cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr); if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 168613590f..69368a919e 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -206,6 +206,8 @@ struct cortex_m_common { /* Context information */ uint32_t dcb_dhcsr; uint32_t dcb_dhcsr_cumulated_sticky; + /* DCB DHCSR has been at least once read, so the sticky bits have been reset */ + bool dcb_dhcsr_sticky_is_recent; uint32_t nvic_dfsr; /* Debug Fault Status Register - shows reason for debug halt */ uint32_t nvic_icsr; /* Interrupt Control State Register - shows active and pending IRQ */ From 82fd4005427b6774a754b791bdf384f3ef45072d Mon Sep 17 00:00:00 2001 From: Steve Marple Date: Wed, 4 May 2022 22:51:48 +0100 Subject: [PATCH 0028/1312] jtag/adapter: Add command 'adapter gpio' Most adapters define their own commands to obtain the GPIO number and other GPIO configuration information such as chip number, output drive type, active high/low. Define a general command 'adapter gpio' as replacement for the driver-specific ones. Change-Id: I1ca9ca94f0c7df5713172e9f62ffb0ad64e9ee97 Signed-off-by: Steve Marple Reviewed-on: https://review.openocd.org/c/openocd/+/6967 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 50 +++++++ src/jtag/adapter.c | 301 +++++++++++++++++++++++++++++++++++++++++++ src/jtag/adapter.h | 63 +++++++++ src/jtag/startup.tcl | 60 +++++++++ 4 files changed, 474 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 995861d18c..083f946c4f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2412,7 +2412,57 @@ when external configuration (such as jumpering) changes what the hardware can support. @end deffn +@anchor{adapter gpio} +@deffn {Config Command} {adapter gpio [ @ + @option{tdo} | @option{tdi} | @option{tms} | @option{tck} | @option{trst} | @ + @option{swdio} | @option{swdio_dir} | @option{swclk} | @option{srst} | @ + @option{led} @ + [ @ + gpio_number | @option{-chip} chip_number | @ + @option{-active-high} | @option{-active-low} | @ + @option{-push-pull} | @option{-open-drain} | @option{-open-source} | @ + @option{-pull-none} | @option{-pull-up} | @option{-pull-down} | @ + @option{-init-inactive} | @option{-init-active} | @option{-init-input} @ + ] ]} + +Define the GPIO mapping that the adapter will use. The following signals can be +defined: +@itemize @minus +@item @option{tdo}, @option{tdi}, @option{tms}, @option{tck}, @option{trst}: +JTAG transport signals +@item @option{swdio}, @option{swclk}: SWD transport signals +@item @option{swdio_dir}: optional swdio buffer control signal +@item @option{srst}: system reset signal +@item @option{led}: optional activity led + +@end itemize + +Some adapters require that the GPIO chip number is set in addition to the GPIO +number. The configuration options enable signals to be defined as active-high or +active-low. The output drive mode can be set to push-pull, open-drain or +open-source. Most adapters will have to emulate open-drain or open-source drive +modes by switching between an input and output. Input and output signals can be +instructed to use a pull-up or pull-down resistor, assuming it is supported by +the adaptor driver and hardware. The initial state of outputs may also be set, +"active" state means 1 for active-high outputs and 0 for active-low outputs. +Bidirectional signals may also be initialized as an input. If the swdio signal +is buffered the buffer direction can be controlled with the swdio_dir signal; +the active state means that the buffer should be set as an output with respect +to the adapter. The command options are cumulative with later commands able to +override settings defined by earlier ones. The two commands @command{gpio led 7 +-active-high} and @command{gpio led -chip 1 -active-low} sent sequentially are +equivalent to issuing the single command @command{gpio led 7 -chip 1 +-active-low}. It is not permissible to set the drive mode or initial state for +signals which are inputs. The drive mode for the srst and trst signals must be +set with the @command{adapter reset_config} command. It is not permissible to +set the initial state of swdio_dir as it is derived from the initial state of +swdio. The command @command{adapter gpio} prints the current configuration for +all GPIOs while the command @command{adapter gpio gpio_name} prints the current +configuration for gpio_name. Not all adapters support this generic GPIO mapping, +some require their own commands to define the GPIOs used. Adapters that support +the generic mapping may not support all of the listed options. +@end deffn @deffn {Command} {adapter name} Returns the name of the debug adapter driver being used. diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 519505dc32..76a2aaba60 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -48,13 +48,74 @@ static struct { enum adapter_clk_mode clock_mode; int speed_khz; int rclk_fallback_speed_khz; + struct adapter_gpio_config gpios[ADAPTER_GPIO_IDX_NUM]; + bool gpios_initialized; /* Initialization of GPIOs to their unset values performed at run time */ } adapter_config; +static const struct gpio_map { + const char *name; + enum adapter_gpio_direction direction; + bool permit_drive_option; + bool permit_init_state_option; +} gpio_map[ADAPTER_GPIO_IDX_NUM] = { + [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, true, }, + [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, + [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, + [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, + [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, }, + [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, }, + [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, + [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, }, + [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, }, + [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, +}; + bool is_adapter_initialized(void) { return adapter_config.adapter_initialized; } +/* For convenience of the bit-banging drivers keep the gpio_config drive + * settings for srst and trst in sync with values set by the "adapter + * reset_config" command. + */ +static void sync_adapter_reset_with_gpios(void) +{ + enum reset_types cfg = jtag_get_reset_config(); + if (cfg & RESET_SRST_PUSH_PULL) + adapter_config.gpios[ADAPTER_GPIO_IDX_SRST].drive = ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL; + else + adapter_config.gpios[ADAPTER_GPIO_IDX_SRST].drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN; + if (cfg & RESET_TRST_OPEN_DRAIN) + adapter_config.gpios[ADAPTER_GPIO_IDX_TRST].drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN; + else + adapter_config.gpios[ADAPTER_GPIO_IDX_TRST].drive = ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL; +} + +static void adapter_driver_gpios_init(void) +{ + if (adapter_config.gpios_initialized) + return; + + for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) { + adapter_config.gpios[i].gpio_num = -1; + adapter_config.gpios[i].chip_num = -1; + if (gpio_map[i].direction == ADAPTER_GPIO_DIRECTION_INPUT) + adapter_config.gpios[i].init_state = ADAPTER_GPIO_INIT_STATE_INPUT; + } + + /* Drivers assume active low, and this is the normal behaviour for reset + * lines so should be the default. */ + adapter_config.gpios[ADAPTER_GPIO_IDX_SRST].active_low = true; + adapter_config.gpios[ADAPTER_GPIO_IDX_TRST].active_low = true; + sync_adapter_reset_with_gpios(); + + /* JTAG GPIOs should be inactive except for tms */ + adapter_config.gpios[ADAPTER_GPIO_IDX_TMS].init_state = ADAPTER_GPIO_INIT_STATE_ACTIVE; + + adapter_config.gpios_initialized = true; +} + /** * Do low-level setup like initializing registers, output signals, * and clocking. @@ -71,6 +132,8 @@ int adapter_init(struct command_context *cmd_ctx) return ERROR_JTAG_INVALID_INTERFACE; } + adapter_driver_gpios_init(); + int retval; if (adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) { @@ -540,6 +603,8 @@ COMMAND_HANDLER(handle_reset_config_command) old_cfg &= ~mask; new_cfg |= old_cfg; jtag_set_reset_config(new_cfg); + sync_adapter_reset_with_gpios(); + } else new_cfg = jtag_get_reset_config(); @@ -770,6 +835,218 @@ COMMAND_HANDLER(handle_adapter_reset_de_assert) (srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT); } +static int get_gpio_index(const char *signal_name) +{ + for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) { + if (strcmp(gpio_map[i].name, signal_name) == 0) + return i; + } + return -1; +} + +COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config_index gpio_idx) +{ + struct adapter_gpio_config *gpio_config = &adapter_config.gpios[gpio_idx]; + const char *active_state = gpio_config->active_low ? "low" : "high"; + const char *dir = ""; + const char *drive = ""; + const char *pull = ""; + const char *init_state = ""; + + switch (gpio_map[gpio_idx].direction) { + case ADAPTER_GPIO_DIRECTION_INPUT: + dir = "input"; + break; + case ADAPTER_GPIO_DIRECTION_OUTPUT: + dir = "output"; + break; + case ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL: + dir = "bidirectional"; + break; + } + + if (gpio_map[gpio_idx].permit_drive_option) { + switch (gpio_config->drive) { + case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL: + drive = ", push-pull"; + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN: + drive = ", open-drain"; + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE: + drive = ", open-source"; + break; + } + } + + switch (gpio_config->pull) { + case ADAPTER_GPIO_PULL_NONE: + pull = ", pull-none"; + break; + case ADAPTER_GPIO_PULL_UP: + pull = ", pull-up"; + break; + case ADAPTER_GPIO_PULL_DOWN: + pull = ", pull-down"; + break; + } + + if (gpio_map[gpio_idx].permit_init_state_option) { + switch (gpio_config->init_state) { + case ADAPTER_GPIO_INIT_STATE_INACTIVE: + init_state = ", init-state inactive"; + break; + case ADAPTER_GPIO_INIT_STATE_ACTIVE: + init_state = ", init-state active"; + break; + case ADAPTER_GPIO_INIT_STATE_INPUT: + init_state = ", init-state input"; + break; + } + } + + command_print(CMD, "adapter gpio %s (%s): num %d, chip %d, active-%s%s%s%s", + gpio_map[gpio_idx].name, dir, gpio_config->gpio_num, gpio_config->chip_num, active_state, + drive, pull, init_state); + + return ERROR_OK; +} + +COMMAND_HANDLER(helper_adapter_gpio_print_all_configs) +{ + for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) + CALL_COMMAND_HANDLER(helper_adapter_gpio_print_config, i); + return ERROR_OK; +} + +COMMAND_HANDLER(adapter_gpio_config_handler) +{ + unsigned int i = 1; + struct adapter_gpio_config *gpio_config; + + adapter_driver_gpios_init(); + + if (CMD_ARGC == 0) { + CALL_COMMAND_HANDLER(helper_adapter_gpio_print_all_configs); + return ERROR_OK; + } + + int gpio_idx = get_gpio_index(CMD_ARGV[0]); + if (gpio_idx == -1) { + LOG_ERROR("adapter has no gpio named %s", CMD_ARGV[0]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (CMD_ARGC == 1) { + CALL_COMMAND_HANDLER(helper_adapter_gpio_print_config, gpio_idx); + return ERROR_OK; + } + + gpio_config = &adapter_config.gpios[gpio_idx]; + while (i < CMD_ARGC) { + LOG_DEBUG("Processing %s", CMD_ARGV[i]); + + if (isdigit(*CMD_ARGV[i])) { + int gpio_num; /* Use a meaningful output parameter for more helpful error messages */ + COMMAND_PARSE_NUMBER(int, CMD_ARGV[i], gpio_num); + gpio_config->gpio_num = gpio_num; + ++i; + continue; + } + + if (strcmp(CMD_ARGV[i], "-chip") == 0) { + if (CMD_ARGC - i < 2) { + LOG_ERROR("-chip option requires a parameter"); + return ERROR_FAIL; + } + LOG_DEBUG("-chip arg is %s", CMD_ARGV[i + 1]); + int chip_num; /* Use a meaningful output parameter for more helpful error messages */ + COMMAND_PARSE_NUMBER(int, CMD_ARGV[i + 1], chip_num); + gpio_config->chip_num = chip_num; + i += 2; + continue; + } + + if (strcmp(CMD_ARGV[i], "-active-high") == 0) { + ++i; + gpio_config->active_low = false; + continue; + } + if (strcmp(CMD_ARGV[i], "-active-low") == 0) { + ++i; + gpio_config->active_low = true; + continue; + } + + if (gpio_map[gpio_idx].permit_drive_option) { + if (strcmp(CMD_ARGV[i], "-push-pull") == 0) { + ++i; + gpio_config->drive = ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL; + continue; + } + if (strcmp(CMD_ARGV[i], "-open-drain") == 0) { + ++i; + gpio_config->drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN; + continue; + } + if (strcmp(CMD_ARGV[i], "-open-source") == 0) { + ++i; + gpio_config->drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE; + continue; + } + } + + if (strcmp(CMD_ARGV[i], "-pull-none") == 0) { + ++i; + gpio_config->pull = ADAPTER_GPIO_PULL_NONE; + continue; + } + if (strcmp(CMD_ARGV[i], "-pull-up") == 0) { + ++i; + gpio_config->pull = ADAPTER_GPIO_PULL_UP; + continue; + } + if (strcmp(CMD_ARGV[i], "-pull-down") == 0) { + ++i; + gpio_config->pull = ADAPTER_GPIO_PULL_DOWN; + continue; + } + + if (gpio_map[gpio_idx].permit_init_state_option) { + if (strcmp(CMD_ARGV[i], "-init-inactive") == 0) { + ++i; + gpio_config->init_state = ADAPTER_GPIO_INIT_STATE_INACTIVE; + continue; + } + if (strcmp(CMD_ARGV[i], "-init-active") == 0) { + ++i; + gpio_config->init_state = ADAPTER_GPIO_INIT_STATE_ACTIVE; + continue; + } + + if (gpio_map[gpio_idx].direction == ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL && + strcmp(CMD_ARGV[i], "-init-input") == 0) { + ++i; + gpio_config->init_state = ADAPTER_GPIO_INIT_STATE_INPUT; + continue; + } + } + + LOG_ERROR("illegal option for adapter %s %s: %s", + CMD_NAME, gpio_map[gpio_idx].name, CMD_ARGV[i]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + /* Force swdio_dir init state to be compatible with swdio init state */ + if (gpio_idx == ADAPTER_GPIO_IDX_SWDIO) + adapter_config.gpios[ADAPTER_GPIO_IDX_SWDIO_DIR].init_state = + (gpio_config->init_state == ADAPTER_GPIO_INIT_STATE_INPUT) ? + ADAPTER_GPIO_INIT_STATE_INACTIVE : + ADAPTER_GPIO_INIT_STATE_ACTIVE; + + return ERROR_OK; +} + #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS COMMAND_HANDLER(handle_usb_location_command) { @@ -887,6 +1164,19 @@ static const struct command_registration adapter_command_handlers[] = { .help = "Controls SRST and TRST lines.", .usage = "|assert [srst|trst [deassert|assert srst|trst]]", }, + { + .name = "gpio", + .handler = adapter_gpio_config_handler, + .mode = COMMAND_CONFIG, + .help = "gpio adapter command group", + .usage = "[ tdo|tdi|tms|tck|trst|swdio|swdio_dir|swclk|srst|led" + "[gpio_number] " + "[-chip chip_number] " + "[-active-high|-active-low] " + "[-push-pull|-open-drain|-open-source] " + "[-pull-none|-pull-up|-pull-down]" + "[-init-inactive|-init-active|-init-input] ]", + }, COMMAND_REGISTRATION_DONE }; @@ -923,3 +1213,14 @@ int adapter_register_commands(struct command_context *ctx) { return register_commands(ctx, NULL, interface_command_handlers); } + +const char *adapter_gpio_get_name(enum adapter_gpio_config_index idx) +{ + return gpio_map[idx].name; +} + +/* Allow drivers access to the GPIO configuration */ +const struct adapter_gpio_config *adapter_gpio_get_config(void) +{ + return adapter_config.gpios; +} diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h index 300769c229..625a0b269a 100644 --- a/src/jtag/adapter.h +++ b/src/jtag/adapter.h @@ -11,6 +11,59 @@ #include #include +/** Supported output drive modes for adaptor GPIO */ +enum adapter_gpio_drive_mode { + ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL, + ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN, + ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE, +}; + +/** Supported GPIO directions */ +enum adapter_gpio_direction { + ADAPTER_GPIO_DIRECTION_INPUT, + ADAPTER_GPIO_DIRECTION_OUTPUT, + ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, +}; + +/** Supported initial states for GPIO */ +enum adapter_gpio_init_state { + ADAPTER_GPIO_INIT_STATE_INACTIVE, /* Should be zero so it is the default state */ + ADAPTER_GPIO_INIT_STATE_ACTIVE, + ADAPTER_GPIO_INIT_STATE_INPUT, +}; + +/** Supported pull directions for GPIO */ +enum adapter_gpio_pull { + ADAPTER_GPIO_PULL_NONE, + ADAPTER_GPIO_PULL_UP, + ADAPTER_GPIO_PULL_DOWN, +}; + +/** Adapter GPIO */ +enum adapter_gpio_config_index { + ADAPTER_GPIO_IDX_TDO, + ADAPTER_GPIO_IDX_TDI, + ADAPTER_GPIO_IDX_TMS, + ADAPTER_GPIO_IDX_TCK, + ADAPTER_GPIO_IDX_TRST, + ADAPTER_GPIO_IDX_SWDIO, + ADAPTER_GPIO_IDX_SWDIO_DIR, + ADAPTER_GPIO_IDX_SWCLK, + ADAPTER_GPIO_IDX_SRST, + ADAPTER_GPIO_IDX_LED, + ADAPTER_GPIO_IDX_NUM, /* must be the last item */ +}; + +/** Configuration options for a single GPIO */ +struct adapter_gpio_config { + int gpio_num; + int chip_num; + enum adapter_gpio_drive_mode drive; /* For outputs only */ + enum adapter_gpio_init_state init_state; + bool active_low; + enum adapter_gpio_pull pull; +}; + struct command_context; /** Register the adapter's commands */ @@ -58,4 +111,14 @@ unsigned int adapter_get_speed_khz(void); /** Retrieves the serial number set with command 'adapter serial' */ const char *adapter_get_required_serial(void); +/** + * Retrieves gpio name + */ +const char *adapter_gpio_get_name(enum adapter_gpio_config_index idx); + +/** + * Retrieves gpio configuration set with command 'adapter gpio ' + */ +const struct adapter_gpio_config *adapter_gpio_get_config(void); + #endif /* OPENOCD_JTAG_ADAPTER_H */ diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 238342061f..8791611e08 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -122,6 +122,66 @@ proc jtag_ntrst_assert_width args { # # FIXME phase these aids out after some releases # +lappend _telnet_autocomplete_skip adapter_gpio_helper_with_caller +# Helper for deprecated driver functions that should call "adapter gpio XXX". + +# Call this function as: +# adapter_gpio_helper_with_caller caller sig_name +# adapter_gpio_helper_with_caller caller sig_name gpio_num +# adapter_gpio_helper_with_caller caller sig_name chip_num gpio_num +proc adapter_gpio_helper_with_caller {caller sig_name args} { + echo "DEPRECATED! use 'adapter gpio $sig_name' not '$caller'" + switch [llength $args] { + 0 {} + 1 {eval adapter gpio $sig_name $args} + 2 {eval adapter gpio $sig_name [lindex $args 1] -chip [lindex $args 0]} + default {return -code 1 -level 1 "$caller: syntax error"} + } + eval adapter gpio $sig_name +} + +lappend _telnet_autocomplete_skip adapter_gpio_helper +# Call this function as: +# adapter_gpio_helper sig_name +# adapter_gpio_helper sig_name gpio_num +# adapter_gpio_helper sig_name chip_num gpio_num +proc adapter_gpio_helper {sig_name args} { + set caller [lindex [info level -1] 0] + eval adapter_gpio_helper_with_caller {"$caller"} $sig_name $args +} + +lappend _telnet_autocomplete_skip adapter_gpio_jtag_nums_with_caller +# Helper for deprecated driver functions that implemented jtag_nums +proc adapter_gpio_jtag_nums_with_caller {caller tck_num tms_num tdi_num tdo_num} { + echo "DEPRECATED! use 'adapter gpio tck; adapter gpio tms; adapter gpio tdi; adapter gpio tdo' not '$caller'" + eval adapter gpio tck $tck_num + eval adapter gpio tms $tms_num + eval adapter gpio tdi $tdi_num + eval adapter gpio tdo $tdo_num +} + +lappend _telnet_autocomplete_skip adapter_gpio_jtag_nums +# Helper for deprecated driver functions that implemented jtag_nums +proc adapter_gpio_jtag_nums {args} { + set caller [lindex [info level -1] 0] + eval adapter_gpio_jtag_nums_with_caller {"$caller"} $args +} + +lappend _telnet_autocomplete_skip adapter_gpio_swd_nums_with_caller +# Helper for deprecated driver functions that implemented swd_nums +proc adapter_gpio_swd_nums_with_caller {caller swclk_num swdio_num} { + echo "DEPRECATED! use 'adapter gpio swclk; adapter gpio swdio' not '$caller'" + eval adapter gpio swclk $swclk_num + eval adapter gpio swdio $swdio_num +} + +lappend _telnet_autocomplete_skip adapter_gpio_swd_nums +# Helper for deprecated driver functions that implemented jtag_nums +proc adapter_gpio_swd_nums {args} { + set caller [lindex [info level -1] 0] + eval adapter_gpio_swd_nums_with_caller {"$caller"} $args +} + lappend _telnet_autocomplete_skip jtag_reset proc jtag_reset args { echo "DEPRECATED! use 'adapter \[de\]assert' not 'jtag_reset'" From ace028262ba0bda0e921afb11e6eb7d87708d889 Mon Sep 17 00:00:00 2001 From: Steve Marple Date: Tue, 17 May 2022 21:51:17 +0100 Subject: [PATCH 0029/1312] drivers/am335xgpio: Migrate to adapter gpio commands Use the new "adapter gpio" commands to configure the GPIOs used by the am335xgpio driver. The AM335x has 4 GPIO 'chips' (chip number 0-3 inclusive), with each one providing 32 GPIOs (gpio_num 0-31 inclusive). Change-Id: I7c63c0e4763657ea51790c43fc40d32b7c3580bb Signed-off-by: Steve Marple Reviewed-on: https://review.openocd.org/c/openocd/+/6984 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 78 +-- src/jtag/drivers/am335xgpio.c | 628 ++++++------------ src/jtag/startup.tcl | 102 +++ tcl/interface/beaglebone-jtag-native.cfg | 22 +- tcl/interface/beaglebone-swd-native.cfg | 18 +- .../test-am335xgpio-deprecated-commands.cfg | 70 ++ 6 files changed, 403 insertions(+), 515 deletions(-) create mode 100644 testing/test-am335xgpio-deprecated-commands.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 083f946c4f..27a552286f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3387,86 +3387,16 @@ registers directly. The memory mapping requires read and write permission to kernel memory; if /dev/gpiomem exists it will be used, otherwise /dev/mem will be used. The driver restores the GPIO state on exit. -All four GPIO ports are available. GPIOs numbered 0 to 31 are mapped to GPIO port -0, GPIO numbers 32 to 63 are mapped to GPIO port 1 and so on. - -See @file{interface/beaglebone-swd-native.cfg} for a sample configuration file. - -@deffn {Config Command} {am335xgpio jtag_nums} @var{tck} @var{tms} @var{tdi} @var{tdo} -Set JTAG transport GPIO numbers for TCK, TMS, TDI, and TDO (in that order). -Must be specified to enable JTAG transport. These pins can also be specified -individually. -@end deffn - -@deffn {Config Command} {am335xgpio tck_num} @var{tck} -Set TCK GPIO number. Must be specified to enable JTAG transport. Can also be -specified using the configuration command @command{am335xgpio jtag_nums}. -@end deffn - -@deffn {Config Command} {am335xgpio tms_num} @var{tms} -Set TMS GPIO number. Must be specified to enable JTAG transport. Can also be -specified using the configuration command @command{am335xgpio jtag_nums}. -@end deffn - -@deffn {Config Command} {am335xgpio tdo_num} @var{tdo} -Set TDO GPIO number. Must be specified to enable JTAG transport. Can also be -specified using the configuration command @command{am335xgpio jtag_nums}. -@end deffn - -@deffn {Config Command} {am335xgpio tdi_num} @var{tdi} -Set TDI GPIO number. Must be specified to enable JTAG transport. Can also be -specified using the configuration command @command{am335xgpio jtag_nums}. -@end deffn - -@deffn {Config Command} {am335xgpio swd_nums} @var{swclk} @var{swdio} -Set SWD transport GPIO numbers for SWCLK and SWDIO (in that order). Must be -specified to enable SWD transport. These pins can also be specified individually. -@end deffn - -@deffn {Config Command} {am335xgpio swclk_num} @var{swclk} -Set SWCLK GPIO number. Must be specified to enable SWD transport. Can also be -specified using the configuration command @command{am335xgpio swd_nums}. -@end deffn - -@deffn {Config Command} {am335xgpio swdio_num} @var{swdio} -Set SWDIO GPIO number. Must be specified to enable SWD transport. Can also be -specified using the configuration command @command{am335xgpio swd_nums}. -@end deffn - -@deffn {Config Command} {am335xgpio swdio_dir_num} @var{swdio_dir} -Set SWDIO direction control pin GPIO number. If specified, this pin can be used -to control the direction of an external buffer on the SWDIO pin. The direction -control state can be set with the command @command{am335xgpio -swdio_dir_output_state}. If not specified this feature is disabled. -@end deffn - -@deffn {Config Command} {am335xgpio swdio_dir_output_state} @var{output_state} -Set the state required for an external SWDIO buffer to be an output. Valid -values are @option{on} (default) and @option{off}. -@end deffn - -@deffn {Config Command} {am335xgpio srst_num} @var{srst} -Set SRST GPIO number. Must be specified to enable SRST. -@end deffn - -@deffn {Config Command} {am335xgpio trst_num} @var{trst} -Set TRST GPIO number. Must be specified to enable TRST. -@end deffn - -@deffn {Config Command} {am335xgpio led_num} @var{led} -Set activity LED GPIO number. If not specified an activity LED is not enabled. -@end deffn - -@deffn {Config Command} {am335xgpio led_on_state} @var{on_state} -Set required logic level for the LED to be on. Valid values are @option{on} -(default) and @option{off}. -@end deffn +All four GPIO ports are available. GPIO configuration is handled by the generic +command @ref{adapter gpio, @command{adapter gpio}}. @deffn {Config Command} {am335xgpio speed_coeffs} @var{speed_coeff} @var{speed_offset} Set SPEED_COEFF and SPEED_OFFSET for delay calculations. If unspecified speed_coeff defaults to 600000 and speed_offset defaults to 575. @end deffn +See @file{interface/beaglebone-swd-native.cfg} for a sample configuration file. + @end deffn diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index 62e276737d..5b68b6d6f1 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -10,23 +10,24 @@ #include "config.h" #endif +#include #include #include #include "bitbang.h" #include -/* - * GPIO register base addresses. Values taken from "AM335x and AMIC110 Sitara +/* GPIO register base addresses. Values taken from "AM335x and AMIC110 Sitara * Processors Technical Reference Manual", Chapter 2 Memory Map. */ -#define AM335XGPIO_NUM_GPIO_PORTS 4 +#define AM335XGPIO_NUM_GPIO_PER_CHIP 32 +#define AM335XGPIO_NUM_GPIO_CHIPS 4 #define AM335XGPIO_GPIO0_HW_ADDR 0x44E07000 #define AM335XGPIO_GPIO1_HW_ADDR 0x4804C000 #define AM335XGPIO_GPIO2_HW_ADDR 0x481AC000 #define AM335XGPIO_GPIO3_HW_ADDR 0x481AE000 -/* 32-bit offsets from GPIO port base address. Values taken from "AM335x and +/* 32-bit offsets from GPIO chip base address. Values taken from "AM335x and * AMIC110 Sitara Processors Technical Reference Manual", Chapter 25 * General-Purpose Input/Output. */ @@ -36,34 +37,34 @@ #define AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET (0x190 / 4) #define AM335XGPIO_GPIO_SETDATAOUT_OFFSET (0x194 / 4) -/* GPIOs are integer values; need to map to a port module, and the pin within - * that module. GPIOs 0 to 31 map to GPIO0, 32 to 63 to GPIO1 etc. This scheme - * matches that used by Linux on the BeagleBone. - */ -#define AM335XGPIO_PORT_NUM(gpio_num) ((gpio_num) / 32) -#define AM335XGPIO_BIT_NUM(gpio_num) ((gpio_num) % 32) -#define AM335XGPIO_BIT_MASK(gpio_num) BIT(AM335XGPIO_BIT_NUM(gpio_num)) +#define AM335XGPIO_READ_REG(chip_num, offset) \ + (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset))) -#define AM335XGPIO_READ_REG(gpio_num, offset) \ - (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset))) +#define AM335XGPIO_WRITE_REG(chip_num, offset, value) \ + (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)) = (value)) -#define AM335XGPIO_WRITE_REG(gpio_num, offset, value) \ - (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) = (value)) +#define AM335XGPIO_SET_REG_BITS(chip_num, offset, bit_mask) \ + (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)) |= (bit_mask)) -#define AM335XGPIO_SET_REG_BITS(gpio_num, offset, bit_mask) \ - (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) |= (bit_mask)) +#define AM335XGPIO_CLEAR_REG_BITS(chip_num, offset, bit_mask) \ + (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)) &= ~(bit_mask)) -#define AM335XGPIO_CLEAR_REG_BITS(gpio_num, offset, bit_mask) \ - (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) &= ~(bit_mask)) +#define AM335XGPIO_SET_INPUT(gpio_config) \ + AM335XGPIO_SET_REG_BITS((gpio_config)->chip_num, AM335XGPIO_GPIO_OE_OFFSET, BIT((gpio_config)->gpio_num)) +#define AM335XGPIO_SET_OUTPUT(gpio_config) \ + AM335XGPIO_CLEAR_REG_BITS((gpio_config)->chip_num, AM335XGPIO_GPIO_OE_OFFSET, BIT((gpio_config)->gpio_num)) +#define AM335XGPIO_SET_HIGH(gpio_config) \ + AM335XGPIO_WRITE_REG((gpio_config)->chip_num, AM335XGPIO_GPIO_SETDATAOUT_OFFSET, BIT((gpio_config)->gpio_num)) +#define AM335XGPIO_SET_LOW(gpio_config) \ + AM335XGPIO_WRITE_REG((gpio_config)->chip_num, AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET, BIT((gpio_config)->gpio_num)) -enum amx335gpio_gpio_mode { +enum amx335gpio_initial_gpio_mode { AM335XGPIO_GPIO_MODE_INPUT, - AM335XGPIO_GPIO_MODE_OUTPUT, /* To set output mode but not state */ AM335XGPIO_GPIO_MODE_OUTPUT_LOW, AM335XGPIO_GPIO_MODE_OUTPUT_HIGH, }; -static const uint32_t am335xgpio_gpio_port_hw_addr[AM335XGPIO_NUM_GPIO_PORTS] = { +static const uint32_t am335xgpio_gpio_chip_hw_addr[AM335XGPIO_NUM_GPIO_CHIPS] = { AM335XGPIO_GPIO0_HW_ADDR, AM335XGPIO_GPIO1_HW_ADDR, AM335XGPIO_GPIO2_HW_ADDR, @@ -71,117 +72,151 @@ static const uint32_t am335xgpio_gpio_port_hw_addr[AM335XGPIO_NUM_GPIO_PORTS] = }; /* Memory-mapped address pointers */ -static volatile uint32_t *am335xgpio_gpio_port_mmap_addr[AM335XGPIO_NUM_GPIO_PORTS]; +static volatile uint32_t *am335xgpio_gpio_chip_mmap_addr[AM335XGPIO_NUM_GPIO_CHIPS]; static int dev_mem_fd; - -/* GPIO numbers for each signal. Negative values are invalid */ -static int tck_gpio = -1; -static enum amx335gpio_gpio_mode tck_gpio_mode; -static int tms_gpio = -1; -static enum amx335gpio_gpio_mode tms_gpio_mode; -static int tdi_gpio = -1; -static enum amx335gpio_gpio_mode tdi_gpio_mode; -static int tdo_gpio = -1; -static enum amx335gpio_gpio_mode tdo_gpio_mode; -static int trst_gpio = -1; -static enum amx335gpio_gpio_mode trst_gpio_mode; -static int srst_gpio = -1; -static enum amx335gpio_gpio_mode srst_gpio_mode; -static int swclk_gpio = -1; -static enum amx335gpio_gpio_mode swclk_gpio_mode; -static int swdio_gpio = -1; -static enum amx335gpio_gpio_mode swdio_gpio_mode; -static int swdio_dir_gpio = -1; -static enum amx335gpio_gpio_mode swdio_dir_gpio_mode; -static int led_gpio = -1; -static enum amx335gpio_gpio_mode led_gpio_mode = -1; - -static bool swdio_dir_is_active_high = true; /* Active state means output */ -static bool led_is_active_high = true; +static enum amx335gpio_initial_gpio_mode initial_gpio_mode[ADAPTER_GPIO_IDX_NUM]; /* Transition delay coefficients */ static int speed_coeff = 600000; static int speed_offset = 575; static unsigned int jtag_delay; -static int is_gpio_valid(int gpio_num) -{ - return gpio_num >= 0 && gpio_num < (32 * AM335XGPIO_NUM_GPIO_PORTS); -} +static const struct adapter_gpio_config *adapter_gpio_config; -static int get_gpio_value(int gpio_num) +static bool is_gpio_config_valid(const struct adapter_gpio_config *gpio_config) { - unsigned int shift = AM335XGPIO_BIT_NUM(gpio_num); - return (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_DATAIN_OFFSET) >> shift) & 1; + return gpio_config->chip_num >= 0 + && gpio_config->chip_num < AM335XGPIO_NUM_GPIO_CHIPS + && gpio_config->gpio_num >= 0 + && gpio_config->gpio_num < AM335XGPIO_NUM_GPIO_PER_CHIP; } -static void set_gpio_value(int gpio_num, int value) +static int get_gpio_value(const struct adapter_gpio_config *gpio_config) { - if (value) - AM335XGPIO_WRITE_REG(gpio_num, AM335XGPIO_GPIO_SETDATAOUT_OFFSET, AM335XGPIO_BIT_MASK(gpio_num)); - else - AM335XGPIO_WRITE_REG(gpio_num, AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET, AM335XGPIO_BIT_MASK(gpio_num)); + unsigned int shift = gpio_config->gpio_num; + uint32_t value = AM335XGPIO_READ_REG(gpio_config->chip_num, AM335XGPIO_GPIO_DATAIN_OFFSET); + value = (value >> shift) & 1; + return value ^ (gpio_config->active_low ? 1 : 0); } -static enum amx335gpio_gpio_mode get_gpio_mode(int gpio_num) +static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value) { - if (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_OE_OFFSET) & AM335XGPIO_BIT_MASK(gpio_num)) { - return AM335XGPIO_GPIO_MODE_INPUT; - } else { - /* Return output level too so that pin mode can be fully restored */ - if (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_DATAOUT_OFFSET) & AM335XGPIO_BIT_MASK(gpio_num)) - return AM335XGPIO_GPIO_MODE_OUTPUT_HIGH; + value = value ^ (gpio_config->active_low ? 1 : 0); + switch (gpio_config->drive) { + case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL: + if (value) + AM335XGPIO_SET_HIGH(gpio_config); else - return AM335XGPIO_GPIO_MODE_OUTPUT_LOW; + AM335XGPIO_SET_LOW(gpio_config); + /* For performance reasons assume the GPIO is already set as an output + * and therefore the call can be omitted here. + */ + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN: + if (value) { + AM335XGPIO_SET_INPUT(gpio_config); + } else { + AM335XGPIO_SET_LOW(gpio_config); + AM335XGPIO_SET_OUTPUT(gpio_config); + } + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE: + if (value) { + AM335XGPIO_SET_HIGH(gpio_config); + AM335XGPIO_SET_OUTPUT(gpio_config); + } else { + AM335XGPIO_SET_INPUT(gpio_config); + } + break; } } -static void set_gpio_mode(int gpio_num, enum amx335gpio_gpio_mode gpio_mode) +static enum amx335gpio_initial_gpio_mode get_gpio_mode(const struct adapter_gpio_config *gpio_config) { - if (gpio_mode == AM335XGPIO_GPIO_MODE_INPUT) { - AM335XGPIO_SET_REG_BITS(gpio_num, AM335XGPIO_GPIO_OE_OFFSET, AM335XGPIO_BIT_MASK(gpio_num)); - return; - } - - if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_LOW) - set_gpio_value(gpio_num, 0); - if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_HIGH) - set_gpio_value(gpio_num, 1); + if (AM335XGPIO_READ_REG(gpio_config->chip_num, AM335XGPIO_GPIO_OE_OFFSET) & BIT(gpio_config->gpio_num)) + return AM335XGPIO_GPIO_MODE_INPUT; - if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT || - gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_LOW || - gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_HIGH) { - AM335XGPIO_CLEAR_REG_BITS(gpio_num, AM335XGPIO_GPIO_OE_OFFSET, AM335XGPIO_BIT_MASK(gpio_num)); - } + /* Return output level too so that pin mode can be fully restored */ + if (AM335XGPIO_READ_REG(gpio_config->chip_num, AM335XGPIO_GPIO_DATAOUT_OFFSET) & BIT(gpio_config->gpio_num)) + return AM335XGPIO_GPIO_MODE_OUTPUT_HIGH; + return AM335XGPIO_GPIO_MODE_OUTPUT_LOW; } -static const char *get_gpio_mode_name(enum amx335gpio_gpio_mode gpio_mode) +static const char *get_gpio_mode_name(enum amx335gpio_initial_gpio_mode gpio_mode) { switch (gpio_mode) { case AM335XGPIO_GPIO_MODE_INPUT: return "input"; - case AM335XGPIO_GPIO_MODE_OUTPUT: - return "output"; case AM335XGPIO_GPIO_MODE_OUTPUT_LOW: return "output (low)"; case AM335XGPIO_GPIO_MODE_OUTPUT_HIGH: return "output (high)"; - default: - return "unknown"; + } + return "unknown"; +} + +static void initialize_gpio(enum adapter_gpio_config_index idx) +{ + if (!is_gpio_config_valid(&adapter_gpio_config[idx])) + return; + + initial_gpio_mode[idx] = get_gpio_mode(&adapter_gpio_config[idx]); + LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %s", + adapter_gpio_get_name(idx), adapter_gpio_config[idx].chip_num, adapter_gpio_config[idx].gpio_num, + get_gpio_mode_name(initial_gpio_mode[idx])); + + if (adapter_gpio_config[idx].pull != ADAPTER_GPIO_PULL_NONE) { + LOG_WARNING("am335xgpio does not support pull-up or pull-down settings (signal %s)", + adapter_gpio_get_name(idx)); + } + + switch (adapter_gpio_config[idx].init_state) { + case ADAPTER_GPIO_INIT_STATE_INACTIVE: + set_gpio_value(&adapter_gpio_config[idx], 0); + break; + case ADAPTER_GPIO_INIT_STATE_ACTIVE: + set_gpio_value(&adapter_gpio_config[idx], 1); + break; + case ADAPTER_GPIO_INIT_STATE_INPUT: + AM335XGPIO_SET_INPUT(&adapter_gpio_config[idx]); + break; + } + + /* Direction for non push-pull is already set by set_gpio_value() */ + if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) + AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[idx]); +} + +static void restore_gpio(enum adapter_gpio_config_index idx) +{ + if (is_gpio_config_valid(&adapter_gpio_config[idx])) { + switch (initial_gpio_mode[idx]) { + case AM335XGPIO_GPIO_MODE_INPUT: + AM335XGPIO_SET_INPUT(&adapter_gpio_config[idx]); + break; + case AM335XGPIO_GPIO_MODE_OUTPUT_LOW: + AM335XGPIO_SET_LOW(&adapter_gpio_config[idx]); + AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[idx]); + break; + case AM335XGPIO_GPIO_MODE_OUTPUT_HIGH: + AM335XGPIO_SET_HIGH(&adapter_gpio_config[idx]); + AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[idx]); + break; + } } } static bb_value_t am335xgpio_read(void) { - return get_gpio_value(tdo_gpio) ? BB_HIGH : BB_LOW; + return get_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TDO]) ? BB_HIGH : BB_LOW; } static int am335xgpio_write(int tck, int tms, int tdi) { - set_gpio_value(tdi_gpio, tdi); - set_gpio_value(tms_gpio, tms); - set_gpio_value(tck_gpio, tck); /* Write clock last */ + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TDI], tdi); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TMS], tms); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TCK], tck); /* Write clock last */ for (unsigned int i = 0; i < jtag_delay; ++i) asm volatile (""); @@ -191,8 +226,8 @@ static int am335xgpio_write(int tck, int tms, int tdi) static int am335xgpio_swd_write(int swclk, int swdio) { - set_gpio_value(swdio_gpio, swdio); - set_gpio_value(swclk_gpio, swclk); /* Write clock last */ + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO], swdio); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK], swclk); /* Write clock last */ for (unsigned int i = 0; i < jtag_delay; ++i) asm volatile (""); @@ -203,49 +238,45 @@ static int am335xgpio_swd_write(int swclk, int swdio) /* (1) assert or (0) deassert reset lines */ static int am335xgpio_reset(int trst, int srst) { - /* assume active low */ - if (is_gpio_valid(srst_gpio)) { - if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL) - set_gpio_mode(srst_gpio, srst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH); - else - set_gpio_mode(srst_gpio, srst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_INPUT); - } + /* As the "adapter reset_config" command keeps the srst and trst gpio drive + * mode settings in sync we can use our standard set_gpio_value() function + * that honours drive mode and active low. + */ + if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_SRST])) + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SRST], srst); - /* assume active low */ - if (is_gpio_valid(trst_gpio)) { - if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN) - set_gpio_mode(trst_gpio, trst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_INPUT); - else - set_gpio_mode(trst_gpio, trst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH); - } + if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST])) + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST], trst); - LOG_DEBUG("am335xgpio_reset(%d, %d), trst_gpio: %d (%s), srst_gpio: %d (%s)", + LOG_DEBUG("am335xgpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d", trst, srst, - trst_gpio, get_gpio_mode_name(get_gpio_mode(trst_gpio)), - srst_gpio, get_gpio_mode_name(get_gpio_mode(srst_gpio))); + adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num, + adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num); return ERROR_OK; } static void am335xgpio_swdio_drive(bool is_output) { if (is_output) { - set_gpio_value(swdio_dir_gpio, swdio_dir_is_active_high ? 1 : 0); - set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_OUTPUT); + if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO_DIR])) + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO_DIR], 1); + AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO]); } else { - set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_INPUT); - set_gpio_value(swdio_dir_gpio, swdio_dir_is_active_high ? 0 : 1); + AM335XGPIO_SET_INPUT(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO]); + if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO_DIR])) + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO_DIR], 0); } } static int am335xgpio_swdio_read(void) { - return get_gpio_value(swdio_gpio); + return get_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO]); } static int am335xgpio_blink(int on) { - if (is_gpio_valid(led_gpio)) - set_gpio_value(led_gpio, (!on ^ led_is_active_high) ? 1 : 0); + if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED])) + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on); return ERROR_OK; } @@ -283,144 +314,6 @@ static int am335xgpio_speed(int speed) return ERROR_OK; } -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionums) -{ - if (CMD_ARGC == 4) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); - } else if (CMD_ARGC != 0) { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - command_print(CMD, "AM335x GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d", - tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tck) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); - - command_print(CMD, "AM335x GPIO config: tck = %d", tck_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tms) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio); - - command_print(CMD, "AM335x GPIO config: tms = %d", tms_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tdo) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio); - - command_print(CMD, "AM335x GPIO config: tdo = %d", tdo_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tdi) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio); - - command_print(CMD, "AM335x GPIO config: tdi = %d", tdi_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_srst) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio); - - command_print(CMD, "AM335x GPIO config: srst = %d", srst_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_trst) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio); - - command_print(CMD, "AM335x GPIO config: trst = %d", trst_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_swd_gpionums) -{ - if (CMD_ARGC == 2) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio); - } else if (CMD_ARGC != 0) { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - command_print(CMD, "AM335x GPIO config: swclk = %d, swdio = %d", swclk_gpio, swdio_gpio); - - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swclk) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); - - command_print(CMD, "AM335x GPIO config: swclk = %d", swclk_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swdio) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio); - - command_print(CMD, "AM335x GPIO config: swdio = %d", swdio_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swdio_dir) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_dir_gpio); - - command_print(CMD, "AM335x GPIO config: swdio_dir = %d", swdio_dir_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_swd_dir_output_state) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_BOOL(CMD_ARGV[0], swdio_dir_is_active_high, "high", "low"); - - command_print(CMD, "AM335x GPIO config: swdio_dir_output_state = %s", swdio_dir_is_active_high ? "high" : "low"); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_gpionum_led) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], led_gpio); - - command_print(CMD, "AM335x GPIO config: led = %d", led_gpio); - return ERROR_OK; -} - -COMMAND_HANDLER(am335xgpio_handle_led_on_state) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_BOOL(CMD_ARGV[0], led_is_active_high, "high", "low"); - - command_print(CMD, "AM335x GPIO config: led_on_state = %s", led_is_active_high ? "high" : "low"); - return ERROR_OK; -} - COMMAND_HANDLER(am335xgpio_handle_speed_coeffs) { if (CMD_ARGC == 2) { @@ -434,104 +327,6 @@ COMMAND_HANDLER(am335xgpio_handle_speed_coeffs) } static const struct command_registration am335xgpio_subcommand_handlers[] = { - { - .name = "jtag_nums", - .handler = am335xgpio_handle_jtag_gpionums, - .mode = COMMAND_CONFIG, - .help = "gpio numbers for tck, tms, tdi, tdo (in that order).", - .usage = "[tck tms tdi tdo]", - }, - { - .name = "tck_num", - .handler = am335xgpio_handle_jtag_gpionum_tck, - .mode = COMMAND_CONFIG, - .help = "gpio number for tck.", - .usage = "[tck]", - }, - { - .name = "tms_num", - .handler = am335xgpio_handle_jtag_gpionum_tms, - .mode = COMMAND_CONFIG, - .help = "gpio number for tms.", - .usage = "[tms]", - }, - { - .name = "tdo_num", - .handler = am335xgpio_handle_jtag_gpionum_tdo, - .mode = COMMAND_CONFIG, - .help = "gpio number for tdo.", - .usage = "[tdo]", - }, - { - .name = "tdi_num", - .handler = am335xgpio_handle_jtag_gpionum_tdi, - .mode = COMMAND_CONFIG, - .help = "gpio number for tdi.", - .usage = "[tdi]", - }, - { - .name = "swd_nums", - .handler = am335xgpio_handle_swd_gpionums, - .mode = COMMAND_CONFIG, - .help = "gpio numbers for swclk, swdio (in that order).", - .usage = "[swclk swdio]", - }, - { - .name = "swclk_num", - .handler = am335xgpio_handle_swd_gpionum_swclk, - .mode = COMMAND_CONFIG, - .help = "gpio number for swclk.", - .usage = "[swclk]", - }, - { - .name = "swdio_num", - .handler = am335xgpio_handle_swd_gpionum_swdio, - .mode = COMMAND_CONFIG, - .help = "gpio number for swdio.", - .usage = "[swdio]", - }, - { - .name = "swdio_dir_num", - .handler = am335xgpio_handle_swd_gpionum_swdio_dir, - .mode = COMMAND_CONFIG, - .help = "gpio number for swdio direction control pin.", - .usage = "[swdio_dir]", - }, - { - .name = "swdio_dir_output_state", - .handler = am335xgpio_handle_swd_dir_output_state, - .mode = COMMAND_CONFIG, - .help = "required state for swdio_dir pin to select SWDIO buffer to be output.", - .usage = "['off'|'on']", - }, - { - .name = "srst_num", - .handler = am335xgpio_handle_jtag_gpionum_srst, - .mode = COMMAND_CONFIG, - .help = "gpio number for srst.", - .usage = "[srst]", - }, - { - .name = "trst_num", - .handler = am335xgpio_handle_jtag_gpionum_trst, - .mode = COMMAND_CONFIG, - .help = "gpio number for trst.", - .usage = "[trst]", - }, - { - .name = "led_num", - .handler = am335xgpio_handle_gpionum_led, - .mode = COMMAND_CONFIG, - .help = "gpio number for led.", - .usage = "[led]", - }, - { - .name = "led_on_state", - .handler = am335xgpio_handle_led_on_state, - .mode = COMMAND_CONFIG, - .help = "required state for led pin to turn on LED.", - .usage = "['off'|'on']", - }, { .name = "speed_coeffs", .handler = am335xgpio_handle_speed_coeffs, @@ -562,32 +357,33 @@ static struct jtag_interface am335xgpio_interface = { static bool am335xgpio_jtag_mode_possible(void) { - if (!is_gpio_valid(tck_gpio)) + if (!is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_TCK])) return false; - if (!is_gpio_valid(tms_gpio)) + if (!is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_TMS])) return false; - if (!is_gpio_valid(tdi_gpio)) + if (!is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_TDI])) return false; - if (!is_gpio_valid(tdo_gpio)) + if (!is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_TDO])) return false; return true; } static bool am335xgpio_swd_mode_possible(void) { - if (!is_gpio_valid(swclk_gpio)) + if (!is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK])) return false; - if (!is_gpio_valid(swdio_gpio)) + if (!is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO])) return false; return true; } static int am335xgpio_init(void) { - bitbang_interface = &am335xgpio_bitbang; - LOG_INFO("AM335x GPIO JTAG/SWD bitbang driver"); + bitbang_interface = &am335xgpio_bitbang; + adapter_gpio_config = adapter_gpio_get_config(); + if (transport_is_jtag() && !am335xgpio_jtag_mode_possible()) { LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode"); return ERROR_JTAG_INIT_FAILED; @@ -608,99 +404,77 @@ static int am335xgpio_init(void) return ERROR_JTAG_INIT_FAILED; } - for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_PORTS; ++i) { - am335xgpio_gpio_port_mmap_addr[i] = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, - MAP_SHARED, dev_mem_fd, am335xgpio_gpio_port_hw_addr[i]); + for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_CHIPS; ++i) { + am335xgpio_gpio_chip_mmap_addr[i] = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, + MAP_SHARED, dev_mem_fd, am335xgpio_gpio_chip_hw_addr[i]); - if (am335xgpio_gpio_port_mmap_addr[i] == MAP_FAILED) { + if (am335xgpio_gpio_chip_mmap_addr[i] == MAP_FAILED) { LOG_ERROR("mmap: %s", strerror(errno)); close(dev_mem_fd); return ERROR_JTAG_INIT_FAILED; } } - /* - * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST as outputs. - * Drive TDI and TCK low, and TMS high. + /* Configure JTAG/SWD signals. Default directions and initial states are handled + * by adapter.c and "adapter gpio" command. */ if (transport_is_jtag()) { - tdo_gpio_mode = get_gpio_mode(tdo_gpio); - tdi_gpio_mode = get_gpio_mode(tdi_gpio); - tck_gpio_mode = get_gpio_mode(tck_gpio); - tms_gpio_mode = get_gpio_mode(tms_gpio); - LOG_DEBUG("saved GPIO mode for tdo (GPIO #%d): %s", tdo_gpio, get_gpio_mode_name(tdo_gpio_mode)); - LOG_DEBUG("saved GPIO mode for tdi (GPIO #%d): %s", tdi_gpio, get_gpio_mode_name(tdi_gpio_mode)); - LOG_DEBUG("saved GPIO mode for tck (GPIO #%d): %s", tck_gpio, get_gpio_mode_name(tck_gpio_mode)); - LOG_DEBUG("saved GPIO mode for tms (GPIO #%d): %s", tms_gpio, get_gpio_mode_name(tms_gpio_mode)); - - set_gpio_mode(tdo_gpio, AM335XGPIO_GPIO_MODE_INPUT); - set_gpio_mode(tdi_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW); - set_gpio_mode(tms_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_HIGH); - set_gpio_mode(tck_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW); - - if (is_gpio_valid(trst_gpio)) { - trst_gpio_mode = get_gpio_mode(trst_gpio); - LOG_DEBUG("saved GPIO mode for trst (GPIO #%d): %s", trst_gpio, get_gpio_mode_name(trst_gpio_mode)); - } + initialize_gpio(ADAPTER_GPIO_IDX_TDO); + initialize_gpio(ADAPTER_GPIO_IDX_TDI); + initialize_gpio(ADAPTER_GPIO_IDX_TMS); + initialize_gpio(ADAPTER_GPIO_IDX_TCK); + initialize_gpio(ADAPTER_GPIO_IDX_TRST); } if (transport_is_swd()) { - swclk_gpio_mode = get_gpio_mode(swclk_gpio); - swdio_gpio_mode = get_gpio_mode(swdio_gpio); - LOG_DEBUG("saved GPIO mode for swclk (GPIO #%d): %s", swclk_gpio, get_gpio_mode_name(swclk_gpio_mode)); - LOG_DEBUG("saved GPIO mode for swdio (GPIO #%d): %s", swdio_gpio, get_gpio_mode_name(swdio_gpio_mode)); - if (is_gpio_valid(swdio_dir_gpio)) { - swdio_dir_gpio_mode = get_gpio_mode(swdio_dir_gpio); - LOG_DEBUG("saved GPIO mode for swdio_dir (GPIO #%d): %s", - swdio_dir_gpio, get_gpio_mode_name(swdio_dir_gpio_mode)); - set_gpio_mode(swdio_dir_gpio, - swdio_dir_is_active_high ? AM335XGPIO_GPIO_MODE_OUTPUT_HIGH : AM335XGPIO_GPIO_MODE_OUTPUT_LOW); - + /* swdio and its buffer should be initialized in the order that prevents + * two outputs from being connected together. This will occur if the + * swdio GPIO of the AM335x is configured as an output while its + * external buffer is configured to send the swdio signal from the + * target to the AM335x. + */ + if (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].init_state == ADAPTER_GPIO_INIT_STATE_INPUT) { + initialize_gpio(ADAPTER_GPIO_IDX_SWDIO); + initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR); + } else { + initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR); + initialize_gpio(ADAPTER_GPIO_IDX_SWDIO); } - set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW); - set_gpio_mode(swclk_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW); - } - if (is_gpio_valid(srst_gpio)) { - srst_gpio_mode = get_gpio_mode(srst_gpio); - LOG_DEBUG("saved GPIO mode for srst (GPIO #%d): %s", srst_gpio, get_gpio_mode_name(srst_gpio_mode)); + initialize_gpio(ADAPTER_GPIO_IDX_SWCLK); } - if (is_gpio_valid(led_gpio)) { - led_gpio_mode = get_gpio_mode(led_gpio); - LOG_DEBUG("saved GPIO mode for led (GPIO #%d): %s", led_gpio, get_gpio_mode_name(led_gpio_mode)); - set_gpio_mode(led_gpio, - led_is_active_high ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH); - } + initialize_gpio(ADAPTER_GPIO_IDX_SRST); + initialize_gpio(ADAPTER_GPIO_IDX_LED); - /* Set GPIO modes for TRST and SRST and make both inactive */ - am335xgpio_reset(0, 0); return ERROR_OK; } static int am335xgpio_quit(void) { if (transport_is_jtag()) { - set_gpio_mode(tdo_gpio, tdo_gpio_mode); - set_gpio_mode(tdi_gpio, tdi_gpio_mode); - set_gpio_mode(tck_gpio, tck_gpio_mode); - set_gpio_mode(tms_gpio, tms_gpio_mode); - if (is_gpio_valid(trst_gpio)) - set_gpio_mode(trst_gpio, trst_gpio_mode); + restore_gpio(ADAPTER_GPIO_IDX_TDO); + restore_gpio(ADAPTER_GPIO_IDX_TDI); + restore_gpio(ADAPTER_GPIO_IDX_TMS); + restore_gpio(ADAPTER_GPIO_IDX_TCK); + restore_gpio(ADAPTER_GPIO_IDX_TRST); } if (transport_is_swd()) { - set_gpio_mode(swclk_gpio, swclk_gpio_mode); - set_gpio_mode(swdio_gpio, swdio_gpio_mode); - if (is_gpio_valid(swdio_dir_gpio)) - set_gpio_mode(swdio_dir_gpio, swdio_dir_gpio_mode); + /* Restore swdio/swdio_dir to their initial modes, even if that means + * connecting two outputs. Begin by making swdio an input so that the + * current and final states of swdio and swdio_dir do not have to be + * considered to calculate the safe restoration order. + */ + AM335XGPIO_SET_INPUT(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO]); + restore_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR); + restore_gpio(ADAPTER_GPIO_IDX_SWDIO); + + restore_gpio(ADAPTER_GPIO_IDX_SWCLK); } - if (is_gpio_valid(srst_gpio)) - set_gpio_mode(srst_gpio, srst_gpio_mode); - - if (is_gpio_valid(led_gpio)) - set_gpio_mode(led_gpio, led_gpio_mode); + restore_gpio(ADAPTER_GPIO_IDX_SRST); + restore_gpio(ADAPTER_GPIO_IDX_LED); return ERROR_OK; } diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 8791611e08..a72775e666 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -863,4 +863,106 @@ proc "xds110 serial" {args} { eval adapter serial $args } +lappend _telnet_autocomplete_skip "am335xgpio jtag_nums" +proc "am335xgpio jtag_nums" {tck_num tms_num tdi_num tdo_num} { + echo "DEPRECATED! use 'adapter gpio tck; adapter gpio tms; adapter gpio tdi; adapter gpio tdo' not 'am335xgpio jtag_nums'" + eval adapter gpio tck [expr {$tck_num % 32}] -chip [expr {$tck_num / 32}] + eval adapter gpio tms [expr {$tms_num % 32}] -chip [expr {$tms_num / 32}] + eval adapter gpio tdi [expr {$tdi_num % 32}] -chip [expr {$tdi_num / 32}] + eval adapter gpio tdo [expr {$tdo_num % 32}] -chip [expr {$tdo_num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio tck_num" +proc "am335xgpio tck_num" {num} { + echo "DEPRECATED! use 'adapter gpio tck' not 'am335xgpio tck_num'" + eval adapter gpio tck [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio tms_num" +proc "am335xgpio tms_num" {num} { + echo "DEPRECATED! use 'adapter gpio tms' not 'am335xgpio tms_num'" + eval adapter gpio tms [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio tdi_num" +proc "am335xgpio tdi_num" {num} { + echo "DEPRECATED! use 'adapter gpio tdi' not 'am335xgpio tdi_num'" + eval adapter gpio tdi [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio tdo_num" +proc "am335xgpio tdo_num" {num} { + echo "DEPRECATED! use 'adapter gpio tdo' not 'am335xgpio tdo_num'" + eval adapter gpio tdo [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio swd_nums" +proc "am335xgpio swd_nums" {swclk swdio} { + echo "DEPRECATED! use 'adapter gpio swclk; adapter gpio swdio' not 'am335xgpio jtag_nums'" + eval adapter gpio swclk [expr {$swclk % 32}] -chip [expr {$swclk / 32}] + eval adapter gpio swdio [expr {$swdio % 32}] -chip [expr {$swdio / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio swclk_num" +proc "am335xgpio swclk_num" {num} { + echo "DEPRECATED! use 'adapter gpio swclk' not 'am335xgpio swclk_num'" + eval adapter gpio swclk [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio swdio_num" +proc "am335xgpio swdio_num" {num} { + echo "DEPRECATED! use 'adapter gpio swdio' not 'am335xgpio swdio_num'" + eval adapter gpio swdio [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio swdio_dir_num" +proc "am335xgpio swdio_dir_num" {num} { + echo "DEPRECATED! use 'adapter gpio swdio_dir' not 'am335xgpio swdio_dir_num'" + eval adapter gpio swdio_dir [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio swdio_dir_output_state" +proc "am335xgpio swdio_dir_output_state" {state} { + echo "DEPRECATED! use 'adapter gpio swdio_dir -active-high' or 'adapter gpio swdio_dir -active-low', not 'am335xgpio swdio_dir_output_state'" + switch $state { + "high" + {eval adapter gpio swdio_dir -active-high} + "low" + {eval adapter gpio swdio_dir -active-low} + default + {return -code 1 -level 1 "am335xgpio swdio_dir_output_state: syntax error"} + } +} + +lappend _telnet_autocomplete_skip "am335xgpio srst_num" +proc "am335xgpio srst_num" {num} { + echo "DEPRECATED! use 'adapter gpio srst' not 'am335xgpio srst_num'" + eval adapter gpio srst [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio trst_num" +proc "am335xgpio trst_num" {num} { + echo "DEPRECATED! use 'adapter gpio trst' not 'am335xgpio trst_num'" + eval adapter gpio trst [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio led_num" +proc "am335xgpio led_num" {num} { + echo "DEPRECATED! use 'adapter gpio led' not 'am335xgpio led_num'" + eval adapter gpio led [expr {$num % 32}] -chip [expr {$num / 32}] +} + +lappend _telnet_autocomplete_skip "am335xgpio led_on_state" +proc "am335xgpio led_on_state" {state} { + echo "DEPRECATED! use 'adapter gpio led -active-high' or 'adapter gpio led -active-low', not 'am335xgpio led_on_state'" + switch $state { + "high" + {eval adapter gpio led -active-high} + "low" + {eval adapter gpio led -active-low} + default + {return -code 1 -level 1 "am335xgpio led_on_state: syntax error"} + } +} + # END MIGRATION AIDS diff --git a/tcl/interface/beaglebone-jtag-native.cfg b/tcl/interface/beaglebone-jtag-native.cfg index cd32ca49b5..0240e5d8b8 100644 --- a/tcl/interface/beaglebone-jtag-native.cfg +++ b/tcl/interface/beaglebone-jtag-native.cfg @@ -16,13 +16,21 @@ adapter driver am335xgpio # am335xgpio speed SPEED_COEFF SPEED_OFFSET am335xgpio speed_coeffs 600000 575 -am335xgpio tdo_num 20 -am335xgpio tdi_num 60 -am335xgpio tms_num 4 -am335xgpio tck_num 2 +# BeagleBone pin P9_41 +adapter gpio tdo 20 -chip 0 -am335xgpio led_num 51 -am335xgpio led_on_state on +# BeagleBone pin P9_12 +adapter gpio tdi 28 -chip 1 -am335xgpio srst_num 65 +# BeagleBone pin P9_18 +adapter gpio tms 4 -chip 0 + +# BeagleBone pin P9_22 +adapter gpio tck 2 -chip 0 + +# BeagleBone pin P9_16 +adapter gpio led 19 -chip 1 + +# BeagleBone pin P8_18 +adapter gpio srst 1 -chip 2 reset_config srst_only srst_push_pull diff --git a/tcl/interface/beaglebone-swd-native.cfg b/tcl/interface/beaglebone-swd-native.cfg index f7bff6e57b..6c40849798 100644 --- a/tcl/interface/beaglebone-swd-native.cfg +++ b/tcl/interface/beaglebone-swd-native.cfg @@ -16,14 +16,18 @@ adapter driver am335xgpio # am335xgpio speed SPEED_COEFF SPEED_OFFSET am335xgpio speed_coeffs 600000 575 -am335xgpio swclk_num 2 -am335xgpio swdio_num 4 -am335xgpio swdio_dir_num 60 -am335xgpio swdio_dir_output_state on +# BeagleBone pin P9_22 +adapter gpio swclk 2 -chip 0 + +# BeagleBone pin P9_18 +adapter gpio swdio 4 -chip 0 + +# BeagleBone pin P9_12 +adapter gpio swdio_dir 28 -chip 1 # USR0 LED -am335xgpio led_num 53 -am335xgpio led_on_state on +adapter gpio led 21 -chip 1 -am335xgpio srst_num 65 +# BeagleBone pin P8_18 +adapter gpio srst 1 -chip 2 reset_config srst_only srst_push_pull diff --git a/testing/test-am335xgpio-deprecated-commands.cfg b/testing/test-am335xgpio-deprecated-commands.cfg new file mode 100644 index 0000000000..09b2040161 --- /dev/null +++ b/testing/test-am335xgpio-deprecated-commands.cfg @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# OpenOCD script to test that the deprecated "am335xgpio *" commands produce the +# expected results. Run this command as: +# +# openocd -f /test-linuxgpiod-deprecated-commands.cfg + +# Raise an error if the "actual" value does not match the "expected" value. Trim +# whitespace (including newlines) from strings before comparing. +proc expected_value {expected actual} { + if {[string trim $expected] ne [string trim $actual]} { + error [puts "ERROR: '${actual}' != '${expected}'"] + } +} + +adapter driver am335xgpio + +am335xgpio jtag_nums 1 2 3 4 +expected_value "adapter gpio tck (output): num 1, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tck] +expected_value "adapter gpio tms (output): num 2, chip 0, active-high, push-pull, pull-none, init-state active" [eval adapter gpio tms] +expected_value "adapter gpio tdi (output): num 3, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tdi] +expected_value "adapter gpio tdo (input): num 4, chip 0, active-high, pull-none, init-state input" [eval adapter gpio tdo] + +am335xgpio tck_num 5 +expected_value "adapter gpio tck (output): num 5, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tck] + +am335xgpio tms_num 6 +expected_value "adapter gpio tms (output): num 6, chip 0, active-high, push-pull, pull-none, init-state active" [eval adapter gpio tms] + +am335xgpio tdi_num 7 +expected_value "adapter gpio tdi (output): num 7, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tdi] + +am335xgpio tdo_num 8 +expected_value "adapter gpio tdo (input): num 8, chip 0, active-high, pull-none, init-state input" [eval adapter gpio tdo] + +am335xgpio swd_nums 9 10 +expected_value "adapter gpio swclk (output): num 9, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swclk] +expected_value "adapter gpio swdio (bidirectional): num 10, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swdio] + +am335xgpio swclk_num 11 +expected_value "adapter gpio swclk (output): num 11, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swclk] + +am335xgpio swdio_num 12 +expected_value "adapter gpio swdio (bidirectional): num 12, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swdio] + +am335xgpio swdio_dir_num 13 +expected_value "adapter gpio swdio_dir (output): num 13, chip 0, active-high, push-pull, pull-none" [eval adapter gpio swdio_dir] + +am335xgpio swdio_dir_output_state low +expected_value "adapter gpio swdio_dir (output): num 13, chip 0, active-low, push-pull, pull-none" [eval adapter gpio swdio_dir] + +am335xgpio swdio_dir_output_state high +expected_value "adapter gpio swdio_dir (output): num 13, chip 0, active-high, push-pull, pull-none" [eval adapter gpio swdio_dir] + +am335xgpio srst_num 14 +expected_value "adapter gpio srst (output): num 14, chip 0, active-low, pull-none, init-state inactive" [eval adapter gpio srst] + +am335xgpio trst_num 15 +expected_value "adapter gpio trst (output): num 15, chip 0, active-low, pull-none, init-state inactive" [eval adapter gpio trst] + +am335xgpio led_num 16 +expected_value "adapter gpio led (output): num 16, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio led] + +am335xgpio led_on_state low +expected_value "adapter gpio led (output): num 16, chip 0, active-low, push-pull, pull-none, init-state inactive" [eval adapter gpio led] + +am335xgpio led_on_state high +expected_value "adapter gpio led (output): num 16, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio led] + +puts "SUCCESS" From 903f2e92a143acf66fcaa82e628c1672fdd0da9f Mon Sep 17 00:00:00 2001 From: Steve Marple Date: Wed, 22 Jun 2022 15:43:51 +0100 Subject: [PATCH 0030/1312] drivers/am335xgpio: Release resources on error and when quitting The /dev/mem file descriptor can be closed without invalidating the mappings so close as soon as possible. munmap() all memory, either on error or from quit. Change-Id: I9466edd2f43791e64f2dce719957c67728f3ec06 Signed-off-by: Steve Marple Reviewed-on: https://review.openocd.org/c/openocd/+/7047 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/am335xgpio.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index 5b68b6d6f1..ae58b16402 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -377,6 +377,13 @@ static bool am335xgpio_swd_mode_possible(void) return true; } +static void am335xgpio_munmap(void) +{ + for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_CHIPS && am335xgpio_gpio_chip_mmap_addr[i] != MAP_FAILED; ++i) + if (munmap((void *)am335xgpio_gpio_chip_mmap_addr[i], sysconf(_SC_PAGE_SIZE)) < 0) + LOG_ERROR("Cannot unmap GPIO memory for chip %d: %s", i, strerror(errno)); +} + static int am335xgpio_init(void) { LOG_INFO("AM335x GPIO JTAG/SWD bitbang driver"); @@ -410,10 +417,12 @@ static int am335xgpio_init(void) if (am335xgpio_gpio_chip_mmap_addr[i] == MAP_FAILED) { LOG_ERROR("mmap: %s", strerror(errno)); + am335xgpio_munmap(); close(dev_mem_fd); return ERROR_JTAG_INIT_FAILED; } } + close(dev_mem_fd); /* Configure JTAG/SWD signals. Default directions and initial states are handled * by adapter.c and "adapter gpio" command. @@ -476,6 +485,8 @@ static int am335xgpio_quit(void) restore_gpio(ADAPTER_GPIO_IDX_SRST); restore_gpio(ADAPTER_GPIO_IDX_LED); + am335xgpio_munmap(); + return ERROR_OK; } From 290eac04b93cd2f98e0a921e9dbf73b0822ae33b Mon Sep 17 00:00:00 2001 From: Steve Marple Date: Tue, 21 Jun 2022 23:06:25 +0100 Subject: [PATCH 0031/1312] drivers/linuxgpiod: Migrate to adapter gpio commands Use the new "adapter gpio" commands to configure the GPIOs used by the linuxgpiod driver. Adds support for drive mode and resistor pull options on all signals. Change-Id: Ic90cb4f06db82435294228b6793330107a9f3606 Signed-off-by: Steve Marple Reviewed-on: https://review.openocd.org/c/openocd/+/7048 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 89 +-- src/jtag/drivers/linuxgpiod.c | 636 +++++------------- src/jtag/startup.tcl | 127 +++- tcl/interface/dln-2-gpiod.cfg | 15 +- .../test-linuxgpiod-deprecated-commands.cfg | 105 +++ 5 files changed, 383 insertions(+), 589 deletions(-) create mode 100644 testing/test-linuxgpiod-deprecated-commands.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 27a552286f..9a5ab9a186 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3401,87 +3401,14 @@ See @file{interface/beaglebone-swd-native.cfg} for a sample configuration file. @deffn {Interface Driver} {linuxgpiod} -Linux provides userspace access to GPIO through libgpiod since Linux kernel version v4.6. -The driver emulates either JTAG or SWD transport through bitbanging. - -See @file{interface/dln-2-gpiod.cfg} for a sample config. - -@deffn {Config Command} {linuxgpiod gpiochip} @var{chip} -Set the GPIO chip number for all GPIOs used by linuxgpiod. If GPIOs use -different GPIO chips then the individual GPIO configuration commands (i.e., not -@command{linuxgpiod jtag_nums} or @command{linuxgpiod swd_nums}) can be used to -set chip numbers independently for each GPIO. -@end deffn - -@deffn {Config Command} {linuxgpiod jtag_nums} @var{tck} @var{tms} @var{tdi} @var{tdo} -Set JTAG transport GPIO numbers for TCK, TMS, TDI, and TDO (in that order). Must -be specified to enable JTAG transport. These pins can also be specified -individually. -@end deffn - -@deffn {Config Command} {linuxgpiod tck_num} [@var{chip}] @var{tck} -Set TCK GPIO number, and optionally TCK chip number. Must be specified to enable -JTAG transport. Can also be specified using the configuration command -@command{linuxgpiod jtag_nums}. -@end deffn - -@deffn {Config Command} {linuxgpiod tms_num} [@var{chip}] @var{tms} -Set TMS GPIO number, and optionally TMS chip number. Must be specified to enable -JTAG transport. Can also be specified using the configuration command -@command{linuxgpiod jtag_nums}. -@end deffn - -@deffn {Config Command} {linuxgpiod tdo_num} [@var{chip}] @var{tdo} -Set TDO GPIO number, and optionally TDO chip number. Must be specified to enable -JTAG transport. Can also be specified using the configuration command -@command{linuxgpiod jtag_nums}. -@end deffn - -@deffn {Config Command} {linuxgpiod tdi_num} [@var{chip}] @var{tdi} -Set TDI GPIO number, and optionally TDI chip number. Must be specified to enable -JTAG transport. Can also be specified using the configuration command -@command{linuxgpiod jtag_nums}. -@end deffn - -@deffn {Config Command} {linuxgpiod trst_num} [@var{chip}] @var{trst} -Set TRST GPIO number, and optionally TRST chip number. Must be specified to -enable TRST. -@end deffn - -@deffn {Config Command} {linuxgpiod swd_nums} @var{swclk} @var{swdio} -Set SWD transport GPIO numbers for SWCLK and SWDIO (in that order). Must be -specified to enable SWD transport. These pins can also be specified -individually. -@end deffn - -@deffn {Config Command} {linuxgpiod swclk_num} [@var{chip}] @var{swclk} -Set SWCLK GPIO number, and optionally SWCLK chip number. Must be specified to -enable SWD transport. Can also be specified using the configuration command -@command{linuxgpiod swd_nums}. -@end deffn - -@deffn {Config Command} {linuxgpiod swdio_num} [@var{chip}] @var{swdio} -Set SWDIO GPIO number, and optionally SWDIO chip number. Must be specified to -enable SWD transport. Can also be specified using the configuration command -@command{linuxgpiod swd_nums}. -@end deffn - -@deffn {Config Command} {linuxgpiod swdio_dir_num} [@var{chip}] @var{swdio_dir} -Set SWDIO direction control GPIO number, and optionally SWDIO direction control -chip number. If specified, this GPIO can be used to control the direction of an -external buffer connected to the SWDIO GPIO (set=output mode, clear=input mode). -@end deffn - -@deffn {Config Command} {linuxgpiod srst_num} [@var{chip}] @var{srst} -Set SRST GPIO number, and optionally SRST chip number. Must be specified to -enable SRST. -@end deffn - -@deffn {Config Command} {linuxgpiod led_num} [@var{chip}] @var{led} -Set activity LED GPIO number, and optionally activity LED chip number. If not -specified an activity LED is not enabled. -@end deffn - +Linux provides userspace access to GPIO through libgpiod since Linux kernel +version v4.6. The driver emulates either JTAG or SWD transport through +bitbanging. There are no driver-specific commands, all GPIO configuration is +handled by the generic command @ref{adapter gpio, @command{adapter gpio}}. This +driver supports the resistor pull options provided by the @command{adapter gpio} +command but the underlying hardware may not be able to support them. + +See @file{interface/dln-2-gpiod.cfg} for a sample configuration file. @end deffn diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 0e96d82e54..e8e93a55b3 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -14,67 +14,41 @@ #endif #include +#include #include #include #include "bitbang.h" -/* gpio numbers for each gpio. Negative values are invalid */ -static int tck_gpio = -1; -static int tms_gpio = -1; -static int tdi_gpio = -1; -static int tdo_gpio = -1; -static int trst_gpio = -1; -static int srst_gpio = -1; -static int swclk_gpio = -1; -static int swdio_gpio = -1; -static int swdio_dir_gpio = -1; -static int led_gpio = -1; -static int gpiochip = -1; -static int tck_gpiochip = -1; -static int tms_gpiochip = -1; -static int tdi_gpiochip = -1; -static int tdo_gpiochip = -1; -static int trst_gpiochip = -1; -static int srst_gpiochip = -1; -static int swclk_gpiochip = -1; -static int swdio_gpiochip = -1; -static int swdio_dir_gpiochip = -1; -static int led_gpiochip = -1; - -static struct gpiod_chip *gpiod_chip_tck; -static struct gpiod_chip *gpiod_chip_tms; -static struct gpiod_chip *gpiod_chip_tdi; -static struct gpiod_chip *gpiod_chip_tdo; -static struct gpiod_chip *gpiod_chip_trst; -static struct gpiod_chip *gpiod_chip_srst; -static struct gpiod_chip *gpiod_chip_swclk; -static struct gpiod_chip *gpiod_chip_swdio; -static struct gpiod_chip *gpiod_chip_swdio_dir; -static struct gpiod_chip *gpiod_chip_led; - -static struct gpiod_line *gpiod_tck; -static struct gpiod_line *gpiod_tms; -static struct gpiod_line *gpiod_tdi; -static struct gpiod_line *gpiod_tdo; -static struct gpiod_line *gpiod_trst; -static struct gpiod_line *gpiod_swclk; -static struct gpiod_line *gpiod_swdio; -static struct gpiod_line *gpiod_swdio_dir; -static struct gpiod_line *gpiod_srst; -static struct gpiod_line *gpiod_led; +static struct gpiod_chip *gpiod_chip[ADAPTER_GPIO_IDX_NUM] = {}; +static struct gpiod_line *gpiod_line[ADAPTER_GPIO_IDX_NUM] = {}; static int last_swclk; static int last_swdio; static bool last_stored; static bool swdio_input; -static bool swdio_dir_is_active_high = true; + +static const struct adapter_gpio_config *adapter_gpio_config; + +/* + * Helper function to determine if gpio config is valid + * + * Assume here that there will be less than 10000 gpios per gpiochip, and less + * than 1000 gpiochips. + */ +static bool is_gpio_config_valid(enum adapter_gpio_config_index idx) +{ + return adapter_gpio_config[idx].chip_num >= 0 + && adapter_gpio_config[idx].chip_num < 1000 + && adapter_gpio_config[idx].gpio_num >= 0 + && adapter_gpio_config[idx].gpio_num < 10000; +} /* Bitbang interface read of TDO */ static bb_value_t linuxgpiod_read(void) { int retval; - retval = gpiod_line_get_value(gpiod_tdo); + retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_TDO]); if (retval < 0) { LOG_WARNING("reading tdo failed"); return 0; @@ -107,20 +81,20 @@ static int linuxgpiod_write(int tck, int tms, int tdi) } if (tdi != last_tdi) { - retval = gpiod_line_set_value(gpiod_tdi, tdi); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TDI], tdi); if (retval < 0) LOG_WARNING("writing tdi failed"); } if (tms != last_tms) { - retval = gpiod_line_set_value(gpiod_tms, tms); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TMS], tms); if (retval < 0) LOG_WARNING("writing tms failed"); } /* write clk last */ if (tck != last_tck) { - retval = gpiod_line_set_value(gpiod_tck, tck); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TCK], tck); if (retval < 0) LOG_WARNING("writing tck failed"); } @@ -136,7 +110,7 @@ static int linuxgpiod_swdio_read(void) { int retval; - retval = gpiod_line_get_value(gpiod_swdio); + retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]); if (retval < 0) { LOG_WARNING("Fail read swdio"); return 0; @@ -154,23 +128,23 @@ static void linuxgpiod_swdio_drive(bool is_output) * https://stackoverflow.com/questions/58735140/ * this would change in future libgpiod */ - gpiod_line_release(gpiod_swdio); + gpiod_line_release(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]); if (is_output) { - if (gpiod_swdio_dir) { - retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 1 : 0); + if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) { + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 1); if (retval < 0) LOG_WARNING("Fail set swdio_dir"); } - retval = gpiod_line_request_output(gpiod_swdio, "OpenOCD", 1); + retval = gpiod_line_request_output(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD", 1); if (retval < 0) LOG_WARNING("Fail request_output line swdio"); } else { - retval = gpiod_line_request_input(gpiod_swdio, "OpenOCD"); + retval = gpiod_line_request_input(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD"); if (retval < 0) LOG_WARNING("Fail request_input line swdio"); - if (gpiod_swdio_dir) { - retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 0 : 1); + if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) { + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 0); if (retval < 0) LOG_WARNING("Fail set swdio_dir"); } @@ -186,7 +160,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio) if (!swdio_input) { if (!last_stored || (swdio != last_swdio)) { - retval = gpiod_line_set_value(gpiod_swdio, swdio); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], swdio); if (retval < 0) LOG_WARNING("Fail set swdio"); } @@ -194,7 +168,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio) /* write swclk last */ if (!last_stored || (swclk != last_swclk)) { - retval = gpiod_line_set_value(gpiod_swclk, swclk); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWCLK], swclk); if (retval < 0) LOG_WARNING("Fail set swclk"); } @@ -210,10 +184,10 @@ static int linuxgpiod_blink(int on) { int retval; - if (!gpiod_led) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) return ERROR_OK; - retval = gpiod_line_set_value(gpiod_led, on); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on); if (retval < 0) LOG_WARNING("Fail set led"); return retval; @@ -239,16 +213,18 @@ static int linuxgpiod_reset(int trst, int srst) LOG_DEBUG("linuxgpiod_reset"); - /* assume active low */ - if (gpiod_srst) { - retval1 = gpiod_line_set_value(gpiod_srst, srst ? 0 : 1); + /* + * active low behaviour handled by "adaptor gpio" command and + * GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW flag when requesting the line. + */ + if (gpiod_line[ADAPTER_GPIO_IDX_SRST]) { + retval1 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SRST], srst); if (retval1 < 0) LOG_WARNING("set srst value failed"); } - /* assume active low */ - if (gpiod_trst) { - retval2 = gpiod_line_set_value(gpiod_trst, trst ? 0 : 1); + if (gpiod_line[ADAPTER_GPIO_IDX_TRST]) { + retval2 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TRST], trst); if (retval2 < 0) LOG_WARNING("set trst value failed"); } @@ -256,109 +232,134 @@ static int linuxgpiod_reset(int trst, int srst) return ((retval1 < 0) || (retval2 < 0)) ? ERROR_FAIL : ERROR_OK; } -/* - * Helper function to determine if gpio number is valid - * - * Assume here that there will be less than 10000 gpios per gpiochip - */ -static bool is_gpio_valid(int gpio) -{ - return gpio >= 0 && gpio < 10000; -} - static bool linuxgpiod_jtag_mode_possible(void) { - if (!is_gpio_valid(tck_gpio)) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TCK)) return false; - if (!is_gpio_valid(tms_gpio)) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TMS)) return false; - if (!is_gpio_valid(tdi_gpio)) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDI)) return false; - if (!is_gpio_valid(tdo_gpio)) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDO)) return false; return true; } static bool linuxgpiod_swd_mode_possible(void) { - if (!is_gpio_valid(swclk_gpio)) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWCLK)) return false; - if (!is_gpio_valid(swdio_gpio)) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO)) return false; return true; } -static inline void helper_release(struct gpiod_line *line, struct gpiod_chip *chip) +static inline void helper_release(enum adapter_gpio_config_index idx) { - if (line) - gpiod_line_release(line); - if (chip) - gpiod_chip_close(chip); + if (gpiod_line[idx]) { + gpiod_line_release(gpiod_line[idx]); + gpiod_line[idx] = NULL; + } + if (gpiod_chip[idx]) { + gpiod_chip_close(gpiod_chip[idx]); + gpiod_chip[idx] = NULL; + } } static int linuxgpiod_quit(void) { - helper_release(gpiod_led, gpiod_chip_led); - helper_release(gpiod_srst, gpiod_chip_srst); - helper_release(gpiod_swdio, gpiod_chip_swdio); - helper_release(gpiod_swdio_dir, gpiod_chip_swdio_dir); - helper_release(gpiod_swclk, gpiod_chip_swclk); - helper_release(gpiod_trst, gpiod_chip_trst); - helper_release(gpiod_tms, gpiod_chip_tms); - helper_release(gpiod_tck, gpiod_chip_tck); - helper_release(gpiod_tdi, gpiod_chip_tdi); - helper_release(gpiod_tdo, gpiod_chip_tdo); + LOG_DEBUG("linuxgpiod_quit"); + for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) + helper_release(i); return ERROR_OK; } -static struct gpiod_line *helper_get_line(const char *label, - struct gpiod_chip *gpiod_chip, unsigned int offset, - int val, int dir, int flags) +int helper_get_line(enum adapter_gpio_config_index idx) { - struct gpiod_line *line; - int retval; + if (!is_gpio_config_valid(idx)) + return ERROR_OK; + + int dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT, flags = 0, val = 0, retval; + + gpiod_chip[idx] = gpiod_chip_open_by_number(adapter_gpio_config[idx].chip_num); + if (!gpiod_chip[idx]) { + LOG_ERROR("Cannot open LinuxGPIOD chip %d for %s", adapter_gpio_config[idx].chip_num, + adapter_gpio_get_name(idx)); + return ERROR_JTAG_INIT_FAILED; + } + + gpiod_line[idx] = gpiod_chip_get_line(gpiod_chip[idx], adapter_gpio_config[idx].gpio_num); + if (!gpiod_line[idx]) { + LOG_ERROR("Error get line %s", adapter_gpio_get_name(idx)); + return ERROR_JTAG_INIT_FAILED; + } + + switch (adapter_gpio_config[idx].init_state) { + case ADAPTER_GPIO_INIT_STATE_INPUT: + dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT; + break; + case ADAPTER_GPIO_INIT_STATE_INACTIVE: + dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT; + val = 0; + break; + case ADAPTER_GPIO_INIT_STATE_ACTIVE: + dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT; + val = 1; + break; + } + + switch (adapter_gpio_config[idx].drive) { + case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL: + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN: + flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE: + flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE; + break; + } - line = gpiod_chip_get_line(gpiod_chip, offset); - if (!line) { - LOG_ERROR("Error get line %s", label); - return NULL; + switch (adapter_gpio_config[idx].pull) { + case ADAPTER_GPIO_PULL_NONE: +#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE + flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE; +#endif + break; + case ADAPTER_GPIO_PULL_UP: +#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP + flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP; +#else + LOG_WARNING("linuxgpiod: ignoring request for pull-up on %s: not supported by gpiod v%s", + adapter_gpio_get_name(idx), gpiod_version_string()); +#endif + break; + case ADAPTER_GPIO_PULL_DOWN: +#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN + flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN; +#else + LOG_WARNING("linuxgpiod: ignoring request for pull-down on %s: not supported by gpiod v%s", + adapter_gpio_get_name(idx), gpiod_version_string()); +#endif + break; } + if (adapter_gpio_config[idx].active_low) + flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW; + struct gpiod_line_request_config config = { .consumer = "OpenOCD", .request_type = dir, .flags = flags, }; - retval = gpiod_line_request(line, &config, val); + retval = gpiod_line_request(gpiod_line[idx], &config, val); if (retval < 0) { - LOG_ERROR("Error requesting gpio line %s", label); - return NULL; + LOG_ERROR("Error requesting gpio line %s", adapter_gpio_get_name(idx)); + return ERROR_JTAG_INIT_FAILED; } - return line; -} - -static struct gpiod_line *helper_get_input_line(const char *label, - struct gpiod_chip *gpiod_chip, unsigned int offset) -{ - return helper_get_line(label, gpiod_chip, offset, 0, - GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0); -} - -static struct gpiod_line *helper_get_output_line(const char *label, - struct gpiod_chip *gpiod_chip, unsigned int offset, int val) -{ - return helper_get_line(label, gpiod_chip, offset, val, - GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0); -} - -static struct gpiod_line *helper_get_open_drain_output_line(const char *label, - struct gpiod_chip *gpiod_chip, unsigned int offset, int val) -{ - return helper_get_line(label, gpiod_chip, offset, val, - GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN); + return ERROR_OK; } static int linuxgpiod_init(void) @@ -366,11 +367,11 @@ static int linuxgpiod_init(void) LOG_INFO("Linux GPIOD JTAG/SWD bitbang driver"); bitbang_interface = &linuxgpiod_bitbang; + adapter_gpio_config = adapter_gpio_get_config(); /* - * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST - * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. - * For SWD, SWCLK and SWDIO are configures as output high. + * Configure JTAG/SWD signals. Default directions and initial states are handled + * by adapter.c and "adapter gpio" command. */ if (transport_is_jtag()) { @@ -379,129 +380,44 @@ static int linuxgpiod_init(void) goto out_error; } - gpiod_chip_tdo = gpiod_chip_open_by_number(tdo_gpiochip); - if (!gpiod_chip_tdo) { - LOG_ERROR("Cannot open LinuxGPIOD tdo_gpiochip %d", tdo_gpiochip); - goto out_error; - } - gpiod_chip_tdi = gpiod_chip_open_by_number(tdi_gpiochip); - if (!gpiod_chip_tdi) { - LOG_ERROR("Cannot open LinuxGPIOD tdi_gpiochip %d", tdi_gpiochip); - goto out_error; - } - gpiod_chip_tck = gpiod_chip_open_by_number(tck_gpiochip); - if (!gpiod_chip_tck) { - LOG_ERROR("Cannot open LinuxGPIOD tck_gpiochip %d", tck_gpiochip); - goto out_error; - } - gpiod_chip_tms = gpiod_chip_open_by_number(tms_gpiochip); - if (!gpiod_chip_tms) { - LOG_ERROR("Cannot open LinuxGPIOD tms_gpiochip %d", tms_gpiochip); - goto out_error; - } - - gpiod_tdo = helper_get_input_line("tdo", gpiod_chip_tdo, tdo_gpio); - if (!gpiod_tdo) - goto out_error; - - gpiod_tdi = helper_get_output_line("tdi", gpiod_chip_tdi, tdi_gpio, 0); - if (!gpiod_tdi) - goto out_error; - - gpiod_tck = helper_get_output_line("tck", gpiod_chip_tck, tck_gpio, 0); - if (!gpiod_tck) - goto out_error; - - gpiod_tms = helper_get_output_line("tms", gpiod_chip_tms, tms_gpio, 1); - if (!gpiod_tms) - goto out_error; - - if (is_gpio_valid(trst_gpio)) { - gpiod_chip_trst = gpiod_chip_open_by_number(trst_gpiochip); - if (!gpiod_chip_trst) { - LOG_ERROR("Cannot open LinuxGPIOD trst_gpiochip %d", trst_gpiochip); + if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK || + helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK || + helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK || + helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK || + helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) goto out_error; - } - - if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN) - gpiod_trst = helper_get_open_drain_output_line("trst", gpiod_chip_trst, trst_gpio, 1); - else - gpiod_trst = helper_get_output_line("trst", gpiod_chip_trst, trst_gpio, 1); - - if (!gpiod_trst) - goto out_error; - } } if (transport_is_swd()) { + int retval1, retval2; if (!linuxgpiod_swd_mode_possible()) { LOG_ERROR("Require swclk and swdio gpio for SWD mode"); goto out_error; } - gpiod_chip_swclk = gpiod_chip_open_by_number(swclk_gpiochip); - if (!gpiod_chip_swclk) { - LOG_ERROR("Cannot open LinuxGPIOD swclk_gpiochip %d", swclk_gpiochip); - goto out_error; + /* + * swdio and its buffer should be initialized in the order that prevents + * two outputs from being connected together. This will occur if the + * swdio GPIO is configured as an output while the external buffer is + * configured to send the swdio signal from the target to the GPIO. + */ + if (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].init_state == ADAPTER_GPIO_INIT_STATE_INPUT) { + retval1 = helper_get_line(ADAPTER_GPIO_IDX_SWDIO); + retval2 = helper_get_line(ADAPTER_GPIO_IDX_SWDIO_DIR); + } else { + retval1 = helper_get_line(ADAPTER_GPIO_IDX_SWDIO_DIR); + retval2 = helper_get_line(ADAPTER_GPIO_IDX_SWDIO); } - gpiod_chip_swdio = gpiod_chip_open_by_number(swdio_gpiochip); - if (!gpiod_chip_swdio) { - LOG_ERROR("Cannot open LinuxGPIOD swdio_gpiochip %d", swdio_gpiochip); + if (retval1 != ERROR_OK || retval2 != ERROR_OK) goto out_error; - } - - if (is_gpio_valid(swdio_dir_gpio)) { - gpiod_chip_swdio_dir = gpiod_chip_open_by_number(swdio_dir_gpiochip); - if (!gpiod_chip_swdio_dir) { - LOG_ERROR("Cannot open LinuxGPIOD swdio_dir_gpiochip %d", swdio_dir_gpiochip); - goto out_error; - } - } - gpiod_swclk = helper_get_output_line("swclk", gpiod_chip_swclk, swclk_gpio, 1); - if (!gpiod_swclk) - goto out_error; - - /* Set buffer direction before making SWDIO an output */ - if (is_gpio_valid(swdio_dir_gpio)) { - gpiod_swdio_dir = helper_get_output_line("swdio_dir", gpiod_chip_swdio_dir, swdio_dir_gpio, - swdio_dir_is_active_high ? 1 : 0); - if (!gpiod_swdio_dir) - goto out_error; - } - - gpiod_swdio = helper_get_output_line("swdio", gpiod_chip_swdio, swdio_gpio, 1); - if (!gpiod_swdio) + if (helper_get_line(ADAPTER_GPIO_IDX_SWCLK) != ERROR_OK) goto out_error; } - if (is_gpio_valid(srst_gpio)) { - gpiod_chip_srst = gpiod_chip_open_by_number(srst_gpiochip); - if (!gpiod_chip_srst) { - LOG_ERROR("Cannot open LinuxGPIOD srst_gpiochip %d", srst_gpiochip); - goto out_error; - } - - if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL) - gpiod_srst = helper_get_output_line("srst", gpiod_chip_srst, srst_gpio, 1); - else - gpiod_srst = helper_get_open_drain_output_line("srst", gpiod_chip_srst, srst_gpio, 1); - - if (!gpiod_srst) - goto out_error; - } - - if (is_gpio_valid(led_gpio)) { - gpiod_chip_led = gpiod_chip_open_by_number(led_gpiochip); - if (!gpiod_chip_led) { - LOG_ERROR("Cannot open LinuxGPIOD led_gpiochip %d", led_gpiochip); - goto out_error; - } - - gpiod_led = helper_get_output_line("led", gpiod_chip_led, led_gpio, 0); - if (!gpiod_led) + if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK || + helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) goto out_error; - } return ERROR_OK; @@ -511,241 +427,6 @@ static int linuxgpiod_init(void) return ERROR_JTAG_INIT_FAILED; } -COMMAND_HELPER(linuxgpiod_helper_gpionum, const char *name, int *chip, int *line) -{ - int i = 0; - if (CMD_ARGC > 2) - return ERROR_COMMAND_SYNTAX_ERROR; - if (CMD_ARGC == 2) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], *chip); - i = 1; - } - if (CMD_ARGC > 0) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[i], *line); - command_print(CMD, "LinuxGPIOD %s: chip = %d, num = %d", name, *chip, *line); - return ERROR_OK; -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionums) -{ - if (CMD_ARGC == 4) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); - } else if (CMD_ARGC != 0) { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - command_print(CMD, - "LinuxGPIOD nums: tck = %d, tms = %d, tdi = %d, tdo = %d", - tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); - - return ERROR_OK; -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tck) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tck", &tck_gpiochip, - &tck_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tms) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tms", &tms_gpiochip, - &tms_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tdo) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tdo", &tdo_gpiochip, - &tdo_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tdi) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tdi", &tdi_gpiochip, - &tdi_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_srst) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "srst", &srst_gpiochip, - &srst_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_trst) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "trst", &trst_gpiochip, - &trst_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_swd_gpionums) -{ - if (CMD_ARGC == 2) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio); - } else if (CMD_ARGC != 0) { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - command_print(CMD, - "LinuxGPIOD nums: swclk = %d, swdio = %d", - swclk_gpio, swdio_gpio); - - return ERROR_OK; -} - -COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swclk) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swclk", &swclk_gpiochip, - &swclk_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swdio", &swdio_gpiochip, - &swdio_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio_dir) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swdio_dir", &swdio_dir_gpiochip, - &swdio_dir_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_gpionum_led) -{ - return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "led", &led_gpiochip, - &led_gpio); -} - -COMMAND_HANDLER(linuxgpiod_handle_gpiochip) -{ - if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], gpiochip); - tck_gpiochip = gpiochip; - tms_gpiochip = gpiochip; - tdi_gpiochip = gpiochip; - tdo_gpiochip = gpiochip; - trst_gpiochip = gpiochip; - srst_gpiochip = gpiochip; - swclk_gpiochip = gpiochip; - swdio_gpiochip = gpiochip; - swdio_dir_gpiochip = gpiochip; - led_gpiochip = gpiochip; - } - - command_print(CMD, "LinuxGPIOD gpiochip = %d", gpiochip); - return ERROR_OK; -} - -static const struct command_registration linuxgpiod_subcommand_handlers[] = { - { - .name = "jtag_nums", - .handler = linuxgpiod_handle_jtag_gpionums, - .mode = COMMAND_CONFIG, - .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)", - .usage = "tck tms tdi tdo", - }, - { - .name = "tck_num", - .handler = linuxgpiod_handle_jtag_gpionum_tck, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for tck.", - .usage = "[chip] tck", - }, - { - .name = "tms_num", - .handler = linuxgpiod_handle_jtag_gpionum_tms, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for tms.", - .usage = "[chip] tms", - }, - { - .name = "tdo_num", - .handler = linuxgpiod_handle_jtag_gpionum_tdo, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for tdo.", - .usage = "[chip] tdo", - }, - { - .name = "tdi_num", - .handler = linuxgpiod_handle_jtag_gpionum_tdi, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for tdi.", - .usage = "[chip] tdi", - }, - { - .name = "srst_num", - .handler = linuxgpiod_handle_jtag_gpionum_srst, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for srst.", - .usage = "[chip] srst", - }, - { - .name = "trst_num", - .handler = linuxgpiod_handle_jtag_gpionum_trst, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for trst.", - .usage = "[chip] trst", - }, - { - .name = "swd_nums", - .handler = linuxgpiod_handle_swd_gpionums, - .mode = COMMAND_CONFIG, - .help = "gpio numbers for swclk, swdio. (in that order)", - .usage = "swclk swdio", - }, - { - .name = "swclk_num", - .handler = linuxgpiod_handle_swd_gpionum_swclk, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for swclk.", - .usage = "[chip] swclk", - }, - { - .name = "swdio_num", - .handler = linuxgpiod_handle_swd_gpionum_swdio, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for swdio.", - .usage = "[chip] swdio", - }, - { - .name = "swdio_dir_num", - .handler = linuxgpiod_handle_swd_gpionum_swdio_dir, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for swdio_dir.", - .usage = "[chip] swdio_dir", - }, - { - .name = "led_num", - .handler = linuxgpiod_handle_gpionum_led, - .mode = COMMAND_CONFIG, - .help = "gpio chip number (optional) and gpio number for LED.", - .usage = "[chip] led", - }, - { - .name = "gpiochip", - .handler = linuxgpiod_handle_gpiochip, - .mode = COMMAND_CONFIG, - .help = "number of the gpiochip.", - .usage = "gpiochip", - }, - COMMAND_REGISTRATION_DONE -}; - -static const struct command_registration linuxgpiod_command_handlers[] = { - { - .name = "linuxgpiod", - .mode = COMMAND_ANY, - .help = "perform linuxgpiod management", - .chain = linuxgpiod_subcommand_handlers, - .usage = "", - }, - COMMAND_REGISTRATION_DONE -}; - static const char *const linuxgpiod_transport[] = { "swd", "jtag", NULL }; static struct jtag_interface linuxgpiod_interface = { @@ -756,7 +437,6 @@ static struct jtag_interface linuxgpiod_interface = { struct adapter_driver linuxgpiod_adapter_driver = { .name = "linuxgpiod", .transports = linuxgpiod_transport, - .commands = linuxgpiod_command_handlers, .init = linuxgpiod_init, .quit = linuxgpiod_quit, diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index a72775e666..1a638a30f8 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -535,74 +535,72 @@ proc bcm2835gpio_peripheral_base args { lappend _telnet_autocomplete_skip linuxgpiod_jtag_nums proc linuxgpiod_jtag_nums args { - echo "DEPRECATED! use 'linuxgpiod jtag_nums' not 'linuxgpiod_jtag_nums'" - eval linuxgpiod jtag_nums $args + eval adapter_gpio_jtag_nums $args } lappend _telnet_autocomplete_skip linuxgpiod_tck_num proc linuxgpiod_tck_num args { - echo "DEPRECATED! use 'linuxgpiod tck_num' not 'linuxgpiod_tck_num'" - eval linuxgpiod tck_num $args + eval adapter_gpio_helper tck $args } lappend _telnet_autocomplete_skip linuxgpiod_tms_num proc linuxgpiod_tms_num args { - echo "DEPRECATED! use 'linuxgpiod tms_num' not 'linuxgpiod_tms_num'" - eval linuxgpiod tms_num $args + eval adapter_gpio_helper tms $args } lappend _telnet_autocomplete_skip linuxgpiod_tdo_num proc linuxgpiod_tdo_num args { - echo "DEPRECATED! use 'linuxgpiod tdo_num' not 'linuxgpiod_tdo_num'" - eval linuxgpiod tdo_num $args + eval adapter_gpio_helper tdo $args } lappend _telnet_autocomplete_skip linuxgpiod_tdi_num proc linuxgpiod_tdi_num args { - echo "DEPRECATED! use 'linuxgpiod tdi_num' not 'linuxgpiod_tdi_num'" - eval linuxgpiod tdi_num $args + eval adapter_gpio_helper tdi $args } lappend _telnet_autocomplete_skip linuxgpiod_srst_num proc linuxgpiod_srst_num args { - echo "DEPRECATED! use 'linuxgpiod srst_num' not 'linuxgpiod_srst_num'" - eval linuxgpiod srst_num $args + eval adapter_gpio_helper srst $args } lappend _telnet_autocomplete_skip linuxgpiod_trst_num proc linuxgpiod_trst_num args { - echo "DEPRECATED! use 'linuxgpiod trst_num' not 'linuxgpiod_trst_num'" - eval linuxgpiod trst_num $args + eval adapter_gpio_helper trst $args } lappend _telnet_autocomplete_skip linuxgpiod_swd_nums proc linuxgpiod_swd_nums args { - echo "DEPRECATED! use 'linuxgpiod swd_nums' not 'linuxgpiod_swd_nums'" - eval linuxgpiod swd_nums $args + eval adapter_gpio_swd_nums $args } lappend _telnet_autocomplete_skip linuxgpiod_swclk_num proc linuxgpiod_swclk_num args { - echo "DEPRECATED! use 'linuxgpiod swclk_num' not 'linuxgpiod_swclk_num'" - eval linuxgpiod swclk_num $args + eval adapter_gpio_helper swclk $args } lappend _telnet_autocomplete_skip linuxgpiod_swdio_num proc linuxgpiod_swdio_num args { - echo "DEPRECATED! use 'linuxgpiod swdio_num' not 'linuxgpiod_swdio_num'" - eval linuxgpiod swdio_num $args + eval adapter_gpio_helper swdio $args } lappend _telnet_autocomplete_skip linuxgpiod_led_num proc linuxgpiod_led_num args { - echo "DEPRECATED! use 'linuxgpiod led_num' not 'linuxgpiod_led_num'" - eval linuxgpiod led_num $args + eval adapter_gpio_helper led $args } lappend _telnet_autocomplete_skip linuxgpiod_gpiochip proc linuxgpiod_gpiochip args { - echo "DEPRECATED! use 'linuxgpiod gpiochip' not 'linuxgpiod_gpiochip'" - eval linuxgpiod gpiochip $args + echo "DEPRECATED! use 'adapter -chip' not 'linuxgpiod_gpiochip'" + switch [llength $args] { + 0 { } + 1 { + foreach sig_name {tck tms tdi tdo trst srst swclk swdio swdio_dir led} { + eval adapter gpio $sig_name -chip $args + } + } + default {return -code 1 -level 1 "linuxgpiod_gpiochip: syntax error"} + } + eval adapter gpio } lappend _telnet_autocomplete_skip sysfsgpio_jtag_nums @@ -863,6 +861,87 @@ proc "xds110 serial" {args} { eval adapter serial $args } +lappend _telnet_autocomplete_skip linuxgpiod +# linuxgpiod command completely removed, this is required for the sub-commands to work +proc linuxgpiod {subcommand args} { + eval {"linuxgpiod $subcommand"} $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod tck_num" +proc "linuxgpiod tck_num" {args} { + eval adapter_gpio_helper tck $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod tms_num" +proc "linuxgpiod tms_num" {args} { + eval adapter_gpio_helper tms $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod tdi_num" +proc "linuxgpiod tdi_num" {args} { + eval adapter_gpio_helper tdi $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod tdo_num" +proc "linuxgpiod tdo_num" {args} { + eval adapter_gpio_helper tdo $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod trst_num" +proc "linuxgpiod trst_num" {args} { + eval adapter_gpio_helper trst $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod srst_num" +proc "linuxgpiod srst_num" {args} { + eval adapter_gpio_helper srst $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod swclk_num" +proc "linuxgpiod swclk_num" {args} { + eval adapter_gpio_helper swclk $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod swdio_num" +proc "linuxgpiod swdio_num" {args} { + eval adapter_gpio_helper swdio $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod swdio_dir_num" +proc "linuxgpiod swdio_dir_num" {args} { + eval adapter_gpio_helper swdio_dir $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod led_num" +proc "linuxgpiod led_num" {args} { + eval adapter_gpio_helper led $args +} + +lappend _telnet_autocomplete_skip "linuxgpiod gpiochip" +proc "linuxgpiod gpiochip" {num} { + echo "DEPRECATED! use 'adapter -chip' not 'linuxgpiod gpiochip'" + foreach sig_name {tck tms tdi tdo trst srst swclk swdio swdio_dir led} { + eval adapter gpio $sig_name -chip $num + } + eval adapter gpio +} + +lappend _telnet_autocomplete_skip "linuxgpiod jtag_nums" +proc "linuxgpiod jtag_nums" {tck_num tms_num tdi_num tdo_num} { + echo "DEPRECATED! use 'adapter gpio tck; adapter gpio tms; adapter gpio tdi; adapter gpio tdo' not 'linuxgpiod jtag_nums'" + eval adapter gpio tck $tck_num + eval adapter gpio tms $tms_num + eval adapter gpio tdi $tdi_num + eval adapter gpio tdo $tdo_num +} + +lappend _telnet_autocomplete_skip "linuxgpiod swd_nums" +proc "linuxgpiod swd_nums" {swclk swdio} { + echo "DEPRECATED! use 'adapter gpio swclk; adapter gpio swdio' not 'linuxgpiod jtag_nums'" + eval adapter gpio swclk $swclk + eval adapter gpio swdio $swdio +} + lappend _telnet_autocomplete_skip "am335xgpio jtag_nums" proc "am335xgpio jtag_nums" {tck_num tms_num tdi_num tdo_num} { echo "DEPRECATED! use 'adapter gpio tck; adapter gpio tms; adapter gpio tdi; adapter gpio tdo' not 'am335xgpio jtag_nums'" diff --git a/tcl/interface/dln-2-gpiod.cfg b/tcl/interface/dln-2-gpiod.cfg index cd6061fd98..c9e33881f7 100644 --- a/tcl/interface/dln-2-gpiod.cfg +++ b/tcl/interface/dln-2-gpiod.cfg @@ -17,11 +17,14 @@ adapter driver linuxgpiod -linuxgpiod gpiochip 0 -linuxgpiod jtag_nums 2 3 4 1 -linuxgpiod trst_num 5 -linuxgpiod swd_nums 2 3 -linuxgpiod srst_num 0 -linuxgpiod led_num 6 +adapter gpio srst 0 -chip 0 +adapter gpio tdo 1 -chip 0 +adapter gpio tck 2 -chip 0 +adapter gpio swclk 2 -chip 0 +adapter gpio tms 3 -chip 0 +adapter gpio swdio 3 -chip 0 +adapter gpio tdi 4 -chip 0 +adapter gpio trst 5 -chip 0 +adapter gpio led 6 -chip 0 reset_config trst_and_srst separate srst_push_pull diff --git a/testing/test-linuxgpiod-deprecated-commands.cfg b/testing/test-linuxgpiod-deprecated-commands.cfg new file mode 100644 index 0000000000..3d4f5cb4c4 --- /dev/null +++ b/testing/test-linuxgpiod-deprecated-commands.cfg @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# OpenOCD script to test that the deprecated "linuxgpiod *" and "linuxgpiod_*" +# commands produce the expected results. Run this command as: +# openocd -f /test-linuxgpiod-deprecated-commands.cfg + +# Raise an error if the "actual" value does not match the "expected" value. Trim +# whitespace (including newlines) from strings before comparing. +proc expected_value {expected actual} { + if {[string trim $expected] ne [string trim $actual]} { + error [puts "ERROR: '${actual}' != '${expected}'"] + } +} + +adapter driver linuxgpiod +puts "Driver is '[adapter name]'" +expected_value "linuxgpiod" [adapter name] +echo [adapter gpio] + +##################################### +# Test the "linuxgpiod *" commands + +# Change the GPIO chip for all signals. Don't check directly here, do so when +# each signal command is tested. +linuxgpiod gpiochip 0 + +linuxgpiod jtag_nums 1 2 3 4 +expected_value "adapter gpio tck (output): num 1, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tck] +expected_value "adapter gpio tms (output): num 2, chip 0, active-high, push-pull, pull-none, init-state active" [eval adapter gpio tms] +expected_value "adapter gpio tdi (output): num 3, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tdi] +expected_value "adapter gpio tdo (input): num 4, chip 0, active-high, pull-none, init-state input" [eval adapter gpio tdo] + +linuxgpiod tck_num 5 +expected_value "adapter gpio tck (output): num 5, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tck] + +linuxgpiod tms_num 6 +expected_value "adapter gpio tms (output): num 6, chip 0, active-high, push-pull, pull-none, init-state active" [eval adapter gpio tms] + +linuxgpiod tdi_num 7 +expected_value "adapter gpio tdi (output): num 7, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tdi] + +linuxgpiod tdo_num 8 +expected_value "adapter gpio tdo (input): num 8, chip 0, active-high, pull-none, init-state input" [eval adapter gpio tdo] + +linuxgpiod swd_nums 9 10 +expected_value "adapter gpio swclk (output): num 9, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swclk] +expected_value "adapter gpio swdio (bidirectional): num 10, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swdio] + +linuxgpiod swclk_num 11 +expected_value "adapter gpio swclk (output): num 11, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swclk] + +linuxgpiod swdio_num 12 +expected_value "adapter gpio swdio (bidirectional): num 12, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swdio] + +linuxgpiod swdio_dir_num 13 +expected_value "adapter gpio swdio_dir (output): num 13, chip 0, active-high, push-pull, pull-none" [eval adapter gpio swdio_dir] + +linuxgpiod srst_num 14 +expected_value "adapter gpio srst (output): num 14, chip 0, active-low, pull-none, init-state inactive" [eval adapter gpio srst] + +linuxgpiod trst_num 15 +expected_value "adapter gpio trst (output): num 15, chip 0, active-low, pull-none, init-state inactive" [eval adapter gpio trst] + +linuxgpiod led_num 16 +expected_value "adapter gpio led (output): num 16, chip 0, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio led] + +##################################### +# Test the old linuxgpiod_* commands + +# Change the GPIO chip for all signals. Don't check directly here, do so when +# each signal command is tested. +linuxgpiod_gpiochip 1 + +linuxgpiod_jtag_nums 17 18 19 20 +expected_value "adapter gpio tck (output): num 17, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tck] +expected_value "adapter gpio tms (output): num 18, chip 1, active-high, push-pull, pull-none, init-state active" [eval adapter gpio tms] +expected_value "adapter gpio tdi (output): num 19, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tdi] +expected_value "adapter gpio tdo (input): num 20, chip 1, active-high, pull-none, init-state input" [eval adapter gpio tdo] + +linuxgpiod_tck_num 21 +expected_value "adapter gpio tck (output): num 21, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tck] + +linuxgpiod_tms_num 22 +expected_value "adapter gpio tms (output): num 22, chip 1, active-high, push-pull, pull-none, init-state active" [eval adapter gpio tms] + +linuxgpiod_tdi_num 23 +expected_value "adapter gpio tdi (output): num 23, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio tdi] + +linuxgpiod_tdo_num 24 +expected_value "adapter gpio tdo (input): num 24, chip 1, active-high, pull-none, init-state input" [eval adapter gpio tdo] + +linuxgpiod_swd_nums 25 26 +expected_value "adapter gpio swclk (output): num 25, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swclk] +expected_value "adapter gpio swdio (bidirectional): num 26, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swdio] + +linuxgpiod_swclk_num 27 +expected_value "adapter gpio swclk (output): num 27, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swclk] + +linuxgpiod_swdio_num 28 +expected_value "adapter gpio swdio (bidirectional): num 28, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio swdio] + +linuxgpiod_led_num 29 +expected_value "adapter gpio led (output): num 29, chip 1, active-high, push-pull, pull-none, init-state inactive" [eval adapter gpio led] + +puts "SUCCESS" From 9cd714cd145a73a4f43bdfc37554f4d5ab05f92b Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Tue, 2 Aug 2022 01:15:12 +0200 Subject: [PATCH 0032/1312] target/espressif: remove author lines from esp32xx and xtensa files Some files have author info some doesn't. For the consistency we removed all. Signed-off-by: Erhan Kurubas Change-Id: Ie6f1ec012302e3a954c75c5106f12820722cb715 Reviewed-on: https://review.openocd.org/c/openocd/+/7104 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/esp_usb_jtag.c | 16 ++-------------- src/target/espressif/esp32.c | 2 -- src/target/espressif/esp32s2.c | 1 - src/target/espressif/esp32s2.h | 1 - src/target/espressif/esp_xtensa.c | 1 - src/target/espressif/esp_xtensa.h | 1 - src/target/espressif/esp_xtensa_smp.c | 1 - src/target/xtensa/xtensa.c | 3 --- src/target/xtensa/xtensa.h | 1 - src/target/xtensa/xtensa_debug_module.h | 5 +---- src/target/xtensa/xtensa_regs.h | 2 +- 11 files changed, 4 insertions(+), 30 deletions(-) diff --git a/src/jtag/drivers/esp_usb_jtag.c b/src/jtag/drivers/esp_usb_jtag.c index a73984a3a1..d280c6ad87 100644 --- a/src/jtag/drivers/esp_usb_jtag.c +++ b/src/jtag/drivers/esp_usb_jtag.c @@ -1,20 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /*************************************************************************** * Espressif USB to Jtag adapter * * Copyright (C) 2020 Espressif Systems (Shanghai) Co. Ltd. * - * Author: Jeroen Domburg * - * * - * 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 . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 29d94a272b..de8f1aacf7 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -3,8 +3,6 @@ /*************************************************************************** * ESP32 target API for OpenOCD * * Copyright (C) 2016-2019 Espressif Systems Ltd. * - * Author: Dmitry Yakovlev * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index 4251e84c98..bbf7ff5afa 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -3,7 +3,6 @@ /*************************************************************************** * ESP32-S2 target for OpenOCD * * Copyright (C) 2019 Espressif Systems Ltd. * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/espressif/esp32s2.h b/src/target/espressif/esp32s2.h index adaabbf852..26fc7a198c 100644 --- a/src/target/espressif/esp32s2.h +++ b/src/target/espressif/esp32s2.h @@ -3,7 +3,6 @@ /*************************************************************************** * ESP32-S2 target for OpenOCD * * Copyright (C) 2019 Espressif Systems Ltd. * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifndef OPENOCD_TARGET_ESP32S2_H diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index cc2888b0de..ce1601289c 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -3,7 +3,6 @@ /*************************************************************************** * Espressif Xtensa target API for OpenOCD * * Copyright (C) 2019 Espressif Systems Ltd. * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h index e3507e31e0..4bbbd756ca 100644 --- a/src/target/espressif/esp_xtensa.h +++ b/src/target/espressif/esp_xtensa.h @@ -3,7 +3,6 @@ /*************************************************************************** * Generic ESP xtensa target implementation for OpenOCD * * Copyright (C) 2019 Espressif Systems Ltd. * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifndef OPENOCD_TARGET_ESP_XTENSA_H diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c index 7c2c72331a..6060662475 100644 --- a/src/target/espressif/esp_xtensa_smp.c +++ b/src/target/espressif/esp_xtensa_smp.c @@ -3,7 +3,6 @@ /*************************************************************************** * ESP Xtensa SMP target API for OpenOCD * * Copyright (C) 2020 Espressif Systems Ltd. Co * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index f04132e68c..6f9d77e6cc 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -5,9 +5,6 @@ * Copyright (C) 2016-2019 Espressif Systems Ltd. * * Derived from esp108.c * * Author: Angus Gratton gus@projectgus.com * - * Author: Jeroen Domburg * - * Author: Alexey Gerenkov * - * Author: Andrey Gramakov * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 86b6a9c9b3..d6000d80e7 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -3,7 +3,6 @@ /*************************************************************************** * Generic Xtensa target * * Copyright (C) 2019 Espressif Systems Ltd. * - * Author: Alexey Gerenkov * ***************************************************************************/ #ifndef OPENOCD_TARGET_XTENSA_H diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h index 88f9eb2a7b..189a6c97a8 100644 --- a/src/target/xtensa/xtensa_debug_module.h +++ b/src/target/xtensa/xtensa_debug_module.h @@ -3,11 +3,8 @@ /*************************************************************************** * Xtensa debug module API * * Copyright (C) 2019 Espressif Systems Ltd. * - * * - * * * Derived from original ESP8266 target. * - * Copyright (C) 2015 by Angus Gratton * - * gus@projectgus.com * + * Author: Angus Gratton gus@projectgus.com * ***************************************************************************/ #ifndef OPENOCD_TARGET_XTENSA_DEBUG_MODULE_H diff --git a/src/target/xtensa/xtensa_regs.h b/src/target/xtensa/xtensa_regs.h index 632400abf9..7009a2a5fc 100644 --- a/src/target/xtensa/xtensa_regs.h +++ b/src/target/xtensa/xtensa_regs.h @@ -4,8 +4,8 @@ * Generic Xtensa target API for OpenOCD * * Copyright (C) 2016-2019 Espressif Systems Ltd. * * Author: Angus Gratton gus@projectgus.com * - * Author: Jeroen Domburg * ***************************************************************************/ + #ifndef OPENOCD_TARGET_XTENSA_REGS_H #define OPENOCD_TARGET_XTENSA_REGS_H From c271958850e27de62557ce75fae658b2abd1f3ba Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 11 Aug 2022 01:32:25 +0200 Subject: [PATCH 0033/1312] target/semihosting: drop type casting from semihosting->result Also used type helper (PRId64) to specify format of int64_t Signed-off-by: Erhan Kurubas Change-Id: I594863eab594aff621c26fefcc69a1872e9730ee Reviewed-on: https://review.openocd.org/c/openocd/+/7111 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/semihosting_common.c | 47 +++++++++++++-------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index e31ff6fd4a..c449b05396 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -406,7 +406,7 @@ int semihosting_common(struct target *target) } else { semihosting->result = close(fd); semihosting->sys_errno = errno; - LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result); + LOG_DEBUG("close(%d)=%" PRId64, fd, semihosting->result); } } break; @@ -631,10 +631,10 @@ int semihosting_common(struct target *target) semihosting->result = fstat(fd, &buf); if (semihosting->result == -1) { semihosting->sys_errno = errno; - LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result); + LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result); break; } - LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result); + LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result); semihosting->result = buf.st_size; } break; @@ -691,8 +691,7 @@ int semihosting_common(struct target *target) if (retval != ERROR_OK) return retval; } - LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg, - (int)semihosting->result); + LOG_DEBUG("SYS_GET_CMDLINE=[%s], %" PRId64, arg, semihosting->result); } break; @@ -784,7 +783,7 @@ int semihosting_common(struct target *target) int fd = semihosting_get_field(target, 0, fields); semihosting->result = isatty(fd); semihosting->sys_errno = errno; - LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result); + LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result); } break; @@ -902,22 +901,19 @@ int semihosting_common(struct target *target) semihosting->result = fd; semihosting->stdin_fd = fd; semihosting->sys_errno = errno; - LOG_DEBUG("dup(STDIN)=%d", - (int)semihosting->result); + LOG_DEBUG("dup(STDIN)=%" PRId64, semihosting->result); } else if (mode < 8) { int fd = dup(STDOUT_FILENO); semihosting->result = fd; semihosting->stdout_fd = fd; semihosting->sys_errno = errno; - LOG_DEBUG("dup(STDOUT)=%d", - (int)semihosting->result); + LOG_DEBUG("dup(STDOUT)=%" PRId64, semihosting->result); } else { int fd = dup(STDERR_FILENO); semihosting->result = fd; semihosting->stderr_fd = fd; semihosting->sys_errno = errno; - LOG_DEBUG("dup(STDERR)=%d", - (int)semihosting->result); + LOG_DEBUG("dup(STDERR)=%" PRId64, semihosting->result); } } else { /* cygwin requires the permission setting @@ -927,8 +923,7 @@ int semihosting_common(struct target *target) open_host_modeflags[mode], 0644); semihosting->sys_errno = errno; - LOG_DEBUG("open('%s')=%d", fn, - (int)semihosting->result); + LOG_DEBUG("open('%s')=%" PRId64, fn, semihosting->result); } } free(fn); @@ -991,11 +986,11 @@ int semihosting_common(struct target *target) semihosting->sys_errno = ENOMEM; } else { semihosting->result = semihosting_read(semihosting, fd, buf, len); - LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d", + LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%" PRId64, fd, addr, len, - (int)semihosting->result); + semihosting->result); if (semihosting->result >= 0) { retval = target_write_buffer(target, addr, semihosting->result, @@ -1031,7 +1026,7 @@ int semihosting_common(struct target *target) return ERROR_FAIL; } semihosting->result = semihosting_getchar(semihosting, semihosting->stdin_fd); - LOG_DEBUG("getchar()=%d", (int)semihosting->result); + LOG_DEBUG("getchar()=%" PRId64, semihosting->result); break; case SEMIHOSTING_SYS_REMOVE: /* 0x0E */ @@ -1077,8 +1072,7 @@ int semihosting_common(struct target *target) fn[len] = 0; semihosting->result = remove((char *)fn); semihosting->sys_errno = errno; - LOG_DEBUG("remove('%s')=%d", fn, - (int)semihosting->result); + LOG_DEBUG("remove('%s')=%" PRId64, fn, semihosting->result); free(fn); } @@ -1147,9 +1141,7 @@ int semihosting_common(struct target *target) semihosting->result = rename((char *)fn1, (char *)fn2); semihosting->sys_errno = errno; - LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2, - (int)semihosting->result); - + LOG_DEBUG("rename('%s', '%s')=%" PRId64 " %d", fn1, fn2, semihosting->result, errno); free(fn1); free(fn2); } @@ -1194,8 +1186,7 @@ int semihosting_common(struct target *target) } else { semihosting->result = lseek(fd, pos, SEEK_SET); semihosting->sys_errno = errno; - LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos, - (int)semihosting->result); + LOG_DEBUG("lseek(%d, %d)=%" PRId64, fd, (int)pos, semihosting->result); if (semihosting->result == pos) semihosting->result = 0; } @@ -1254,9 +1245,7 @@ int semihosting_common(struct target *target) cmd[len] = 0; semihosting->result = system( (const char *)cmd); - LOG_DEBUG("system('%s')=%d", - cmd, - (int)semihosting->result); + LOG_DEBUG("system('%s')=%" PRId64, cmd, semihosting->result); } free(cmd); @@ -1335,11 +1324,11 @@ int semihosting_common(struct target *target) } semihosting->result = semihosting_write(semihosting, fd, buf, len); semihosting->sys_errno = errno; - LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d", + LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%" PRId64, fd, addr, len, - (int)semihosting->result); + semihosting->result); if (semihosting->result >= 0) { /* The number of bytes that are NOT written. * */ From 5f46de2e79db6377410107961ed81fae7e61c39f Mon Sep 17 00:00:00 2001 From: MadSquirrel Date: Sat, 4 Jun 2022 22:01:11 +0200 Subject: [PATCH 0034/1312] server/gdb_server: Add support for default thread, use by IDA debugger Signed-off-by: Benoit Forgette Change-Id: Ia3a29a3377be650f0ccad11a0ae4fe4da78b3ab4 Reviewed-on: https://review.openocd.org/c/openocd/+/7017 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 185 ++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 93 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 1e50b43f3f..5cffa23d11 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3030,128 +3030,127 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p gdb_running_type = 's'; bool fake_step = false; - if (strncmp(parse, "s:", 2) == 0) { - struct target *ct = target; - int current_pc = 1; - int64_t thread_id; + struct target *ct = target; + int current_pc = 1; + int64_t thread_id; + parse++; + packet_size--; + if (parse[0] == ':') { char *endp; - - parse += 2; - packet_size -= 2; - + parse++; + packet_size--; thread_id = strtoll(parse, &endp, 16); if (endp) { packet_size -= endp - parse; parse = endp; } + } else { + thread_id = 0; + } + + if (target->rtos) { + /* FIXME: why is this necessary? rtos state should be up-to-date here already! */ + rtos_update_threads(target); - if (target->rtos) { - /* FIXME: why is this necessary? rtos state should be up-to-date here already! */ - rtos_update_threads(target); + target->rtos->gdb_target_for_threadid(connection, thread_id, &ct); - target->rtos->gdb_target_for_threadid(connection, thread_id, &ct); + /* + * check if the thread to be stepped is the current rtos thread + * if not, we must fake the step + */ + if (target->rtos->current_thread != thread_id) + fake_step = true; + } - /* - * check if the thread to be stepped is the current rtos thread - * if not, we must fake the step - */ - if (target->rtos->current_thread != thread_id) - fake_step = true; - } + if (parse[0] == ';') { + ++parse; + --packet_size; - if (parse[0] == ';') { - ++parse; - --packet_size; + if (parse[0] == 'c') { + parse += 1; - if (parse[0] == 'c') { + /* check if thread-id follows */ + if (parse[0] == ':') { + int64_t tid; parse += 1; - /* check if thread-id follows */ - if (parse[0] == ':') { - int64_t tid; - parse += 1; - - tid = strtoll(parse, &endp, 16); - if (tid == thread_id) { - /* - * Special case: only step a single thread (core), - * keep the other threads halted. Currently, only - * aarch64 target understands it. Other target types don't - * care (nobody checks the actual value of 'current') - * and it doesn't really matter. This deserves - * a symbolic constant and a formal interface documentation - * at a later time. - */ - LOG_DEBUG("request to step current core only"); - /* uncomment after checking that indeed other targets are safe */ - /*current_pc = 2;*/ - } + tid = strtoll(parse, NULL, 16); + if (tid == thread_id) { + /* + * Special case: only step a single thread (core), + * keep the other threads halted. Currently, only + * aarch64 target understands it. Other target types don't + * care (nobody checks the actual value of 'current') + * and it doesn't really matter. This deserves + * a symbolic constant and a formal interface documentation + * at a later time. + */ + LOG_DEBUG("request to step current core only"); + /* uncomment after checking that indeed other targets are safe */ + /*current_pc = 2;*/ } } } + } - LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id); - gdb_connection->output_flag = GDB_OUTPUT_ALL; - target_call_event_callbacks(ct, TARGET_EVENT_GDB_START); - - /* - * work around an annoying gdb behaviour: when the current thread - * is changed in gdb, it assumes that the target can follow and also - * make the thread current. This is an assumption that cannot hold - * for a real target running a multi-threading OS. We just fake - * the step to not trigger an internal error in gdb. See - * https://sourceware.org/bugzilla/show_bug.cgi?id=22925 for details - */ - if (fake_step) { - int sig_reply_len; - char sig_reply[128]; - - LOG_DEBUG("fake step thread %"PRIx64, thread_id); + LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id); + gdb_connection->output_flag = GDB_OUTPUT_ALL; + target_call_event_callbacks(ct, TARGET_EVENT_GDB_START); - sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), - "T05thread:%016"PRIx64";", thread_id); + /* + * work around an annoying gdb behaviour: when the current thread + * is changed in gdb, it assumes that the target can follow and also + * make the thread current. This is an assumption that cannot hold + * for a real target running a multi-threading OS. We just fake + * the step to not trigger an internal error in gdb. See + * https://sourceware.org/bugzilla/show_bug.cgi?id=22925 for details + */ + if (fake_step) { + int sig_reply_len; + char sig_reply[128]; - gdb_put_packet(connection, sig_reply, sig_reply_len); - gdb_connection->output_flag = GDB_OUTPUT_NO; + LOG_DEBUG("fake step thread %"PRIx64, thread_id); - return true; - } + sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), + "T05thread:%016"PRIx64";", thread_id); - /* support for gdb_sync command */ - if (gdb_connection->sync) { - gdb_connection->sync = false; - if (ct->state == TARGET_HALTED) { - LOG_DEBUG("stepi ignored. GDB will now fetch the register state " - "from the target."); - gdb_sig_halted(connection); - gdb_connection->output_flag = GDB_OUTPUT_NO; - } else - gdb_connection->frontend_state = TARGET_RUNNING; - return true; - } + gdb_put_packet(connection, sig_reply, sig_reply_len); + gdb_connection->output_flag = GDB_OUTPUT_NO; - retval = target_step(ct, current_pc, 0, 0); - if (retval == ERROR_TARGET_NOT_HALTED) - LOG_INFO("target %s was not halted when step was requested", target_name(ct)); + return true; + } - /* if step was successful send a reply back to gdb */ - if (retval == ERROR_OK) { - retval = target_poll(ct); - if (retval != ERROR_OK) - LOG_DEBUG("error polling target %s after successful step", target_name(ct)); - /* send back signal information */ - gdb_signal_reply(ct, connection); - /* stop forwarding log packets! */ + /* support for gdb_sync command */ + if (gdb_connection->sync) { + gdb_connection->sync = false; + if (ct->state == TARGET_HALTED) { + LOG_DEBUG("stepi ignored. GDB will now fetch the register state " + "from the target."); + gdb_sig_halted(connection); gdb_connection->output_flag = GDB_OUTPUT_NO; } else gdb_connection->frontend_state = TARGET_RUNNING; - } else { - LOG_ERROR("Unknown vCont packet"); - return false; + return true; } + + retval = target_step(ct, current_pc, 0, 0); + if (retval == ERROR_TARGET_NOT_HALTED) + LOG_INFO("target %s was not halted when step was requested", target_name(ct)); + + /* if step was successful send a reply back to gdb */ + if (retval == ERROR_OK) { + retval = target_poll(ct); + if (retval != ERROR_OK) + LOG_DEBUG("error polling target %s after successful step", target_name(ct)); + /* send back signal information */ + gdb_signal_reply(ct, connection); + /* stop forwarding log packets! */ + gdb_connection->output_flag = GDB_OUTPUT_NO; + } else + gdb_connection->frontend_state = TARGET_RUNNING; return true; } - + LOG_ERROR("Unknown vCont packet"); return false; } From 9ffeedb5794e5ebe7b3a7d7fd63fde4d7124c0dd Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo Date: Thu, 20 Jan 2022 12:31:18 -0800 Subject: [PATCH 0035/1312] tcl/fpga: add Lattice MachXO3 family support Add support for Lattice MachXO3 FPGA family. Signed-off-by: Jae Hyun Yoo Change-Id: I01fcec0ee458e809246e4505019d15047655dd47 Reviewed-on: https://review.openocd.org/c/openocd/+/7113 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/fpga/lattice_machxo3.cfg | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tcl/fpga/lattice_machxo3.cfg diff --git a/tcl/fpga/lattice_machxo3.cfg b/tcl/fpga/lattice_machxo3.cfg new file mode 100644 index 0000000000..37fa054300 --- /dev/null +++ b/tcl/fpga/lattice_machxo3.cfg @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME machxo3 +} + +# Lattice MachXO3 family +# TAP IDs are extracted from BSDL files found on this page: +# https://www.latticesemi.com/Products/FPGAandCPLD/MachXO3 +# +# 0x412b2043 - LCMXO3L_1300E_XXUWG36/XXMG121 +# 0x412b3043 - LCMXO3L_2100E_XXMG121/XXMG256/XXUWG49 +# 0x412b4043 - LCMXO3L_4300E_XXMG121/XXMG324/XXUWG81 +# 0x412b5043 - LCMXO3L_6900E_XXMG256/XXMG324 +# 0x412b6043 - LCMXO3L_9400E_XXBG256/XXMG256 +# 0x412bb043 - LCMXO3L_2100C_XXBG256 +# 0x412bc043 - LCMXO3L_4300C_XXBG256/XXBG324 +# 0x412bd043 - LCMXO3L_6900C_XXBG256/XXBG324/XXBG400 +# 0x412be043 - LCMXO3L_9400C_XXBG256/XXBG400/XXBG484 +# 0x612b2043 - LCMXO3LF_1300E_XXMG121/XXUWG36 +# 0x612b3043 - LCMXO3LF_2100E_XXMG121/XXMG256/XXUWG49 +# 0x612b4043 - LCMXO3LF_4300E_XXMG121/XXMG256/XXMG324/XXUWG81 +# 0x612b5043 - LCMXO3LF_6900E_XXMG256/XXMG324 +# 0x612b6043 - LCMXO3LF_9400E_XXBG256/XXMG256 +# 0x612bb043 - LCMXO3LF_2100C_XXBG256 +# 0x612bc043 - LCMXO3LF_4300C_XXBG256/XXBG324 +# 0x612bd043 - LCMXO3LF_6900C_XXBG256/XXBG324/XXBG400 +# 0x612be043 - LCMXO3LF_9400C_XXBG256/XXBG400/XXBG484 +# 0xc12b2043 - LCMXO3L_640E_XXMG121 +# 0xc12b4043 - LCMXO3L_2100E_XXMG324 +# 0xc12bb043 - LCMXO3L_1300C_XXBG256/XXMG256 +# 0xc12bc043 - LCMXO3L_2100C_XXBG324 +# 0xc12bd043 - LCMXO3L_4300C_XXBG400 +# 0xe12b2043 - LCMXO3LF_640E_XXMG121 +# 0xe12b3043 - LCMXO3LF_1300E_XXMG256 +# 0xe12b4043 - LCMXO3LF_2100E_XXMG324 +# 0xe12bb043 - LCMXO3LF_1300C_XXBG256 +# 0xe12bc043 - LCMXO3LF_2100C_XXBG324 +# 0xe12bd043 - LCMXO3LF_4300C_XXBG400 + +jtag newtap $_CHIPNAME tap -irlen 8 -irmask 0x83 -ircapture 0x1 \ + -expected-id 0x412b2043 -expected-id 0x412b3043 -expected-id 0x412b4043 \ + -expected-id 0x412b5043 -expected-id 0x412b6043 -expected-id 0x412bb043 \ + -expected-id 0x412bc043 -expected-id 0x412bd043 -expected-id 0x412be043 \ + -expected-id 0x612b2043 -expected-id 0x612b3043 -expected-id 0x612b4043 \ + -expected-id 0x612b5043 -expected-id 0x612b6043 -expected-id 0x612bb043 \ + -expected-id 0x612bc043 -expected-id 0x612bd043 -expected-id 0x612be043 \ + -expected-id 0xc12b2043 -expected-id 0xc12b4043 -expected-id 0xc12bb043 \ + -expected-id 0xc12bc043 -expected-id 0xc12bd043 -expected-id 0xe12b2043 \ + -expected-id 0xe12b3043 -expected-id 0xe12b4043 -expected-id 0xe12bb043 \ + -expected-id 0xe12bc043 -expected-id 0xe12bd043 From be2e5c6c35f77fecb4df2a19cec05cceac500ca9 Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo Date: Thu, 20 Jan 2022 12:07:58 -0800 Subject: [PATCH 0036/1312] tcl/interface: add linuxgpiod cfg for Aspeed AST2600 Add linuxgpiod cfg for Aspeed AST2600 for a case if JTAG master needs to be implemented using linuxgpiod intead of hardware JTAG master mode. These AST2600 GPIOs will be mapped to JTAG/SWD signals. +-----------+-------------+-------------+ | signal | GPIO name | gpio offset | +-----------+-------------+-------------+ | TCK/SWCLK | GPIOI2 | 66 | | TMS/SWDIO | GPIOI3 | 67 | | TDI | GPIOI1 | 65 | | TDO | GPIOI4 | 68 | | nTRST | GPIOI0 | 64 | +-----------+-------------+-------------+ Signed-off-by: Jae Hyun Yoo Change-Id: I19278402b0895be12d38c0ecea8fdbc56fd491b8 Reviewed-on: https://review.openocd.org/c/openocd/+/7112 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/interface/ast2600-gpiod.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/interface/ast2600-gpiod.cfg diff --git a/tcl/interface/ast2600-gpiod.cfg b/tcl/interface/ast2600-gpiod.cfg new file mode 100644 index 0000000000..5cad02fbdf --- /dev/null +++ b/tcl/interface/ast2600-gpiod.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Use AST2600 GPIO through linuxgpiod +# +# +-----------+-------------+-------------+ +# | signal | GPIO name | gpio offset | +# +-----------+-------------+-------------+ +# | TCK/SWCLK | GPIOI2 | 66 | +# | TMS/SWDIO | GPIOI3 | 67 | +# | TDI | GPIOI1 | 65 | +# | TDO | GPIOI4 | 68 | +# | nTRST | GPIOI0 | 64 | +# +-----------+-------------+-------------+ + +adapter driver linuxgpiod + +adapter gpio trst 64 -chip 0 +adapter gpio tdi 65 -chip 0 +adapter gpio tck 66 -chip 0 +adapter gpio swclk 66 -chip 0 +adapter gpio tms 67 -chip 0 +adapter gpio swdio 67 -chip 0 +adapter gpio tdo 68 -chip 0 + +reset_config trst_only separate trst_push_pull From ce5ca9f7ba782ea9fba8ecd5fc1cb9407fd27949 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Fri, 24 Jun 2022 22:27:32 -0700 Subject: [PATCH 0037/1312] target: add generic Xtensa LX support Generic Xtensa LX support extends the original Espressif/Xtensa patch-set to support arbitrary Xtensa configurations, as defined in a core-specific .cfg file. Not yet fully-featured. Additional functionality to be added: - Xtensa NX support - DAP/SWD support - File-IO support - Generic Xtensa multi-core support Valgrind-clean, no new Clang analyzer warnings Signed-off-by: Ian Thompson Change-Id: I08e7bf8fa57c25b5d0cb75a1aa7a2ac13a380c52 Reviewed-on: https://review.openocd.org/c/openocd/+/7055 Tested-by: jenkins Reviewed-by: Erhan Kurubas Reviewed-by: Antonio Borneo --- doc/openocd.texi | 161 +- src/target/espressif/Makefile.am | 5 +- src/target/espressif/esp32.c | 205 +- src/target/espressif/esp32.h | 31 - src/target/espressif/esp32s2.c | 196 +- src/target/espressif/esp32s2.h | 28 - src/target/espressif/esp32s3.c | 239 --- src/target/espressif/esp32s3.h | 54 - src/target/espressif/esp_xtensa.c | 3 +- src/target/espressif/esp_xtensa.h | 1 - src/target/espressif/esp_xtensa_smp.c | 192 +- src/target/espressif/esp_xtensa_smp.h | 1 - src/target/target.c | 2 + src/target/xtensa/Makefile.am | 2 + src/target/xtensa/xtensa.c | 2854 ++++++++++++++++++------- src/target/xtensa/xtensa.h | 211 +- src/target/xtensa/xtensa_chip.c | 170 ++ src/target/xtensa/xtensa_chip.h | 34 + src/target/xtensa/xtensa_regs.h | 224 +- tcl/target/esp32.cfg | 2 + tcl/target/esp32s2.cfg | 2 + tcl/target/esp32s3.cfg | 2 + tcl/target/xtensa-core-esp32.cfg | 260 +++ tcl/target/xtensa-core-esp32s2.cfg | 223 ++ tcl/target/xtensa-core-esp32s3.cfg | 297 +++ 25 files changed, 3594 insertions(+), 1805 deletions(-) delete mode 100644 src/target/espressif/esp32.h delete mode 100644 src/target/espressif/esp32s2.h delete mode 100644 src/target/espressif/esp32s3.h create mode 100644 src/target/xtensa/xtensa_chip.c create mode 100644 src/target/xtensa/xtensa_chip.h create mode 100644 tcl/target/xtensa-core-esp32.cfg create mode 100644 tcl/target/xtensa-core-esp32s2.cfg create mode 100644 tcl/target/xtensa-core-esp32s3.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 9a5ab9a186..0df25406ff 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4906,6 +4906,7 @@ And two debug interfaces cores: @item @code{testee} -- a dummy target for cases without a real CPU, e.g. CPLD. @item @code{xscale} -- this is actually an architecture, not a CPU type. It is based on the ARMv5 architecture. +@item @code{xtensa} -- this is a generic Cadence/Tensilica Xtensa core. @end itemize @end deffn @@ -10935,33 +10936,150 @@ 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 is a highly-customizable, user-extensible microprocessor and DSP +architecture for complex embedded systems provided by Cadence Design +Systems, Inc. See the +@uref{https://www.cadence.com/en_US/home/tools/ip/tensilica-ip.html, Tensilica IP} +website for additional information and documentation. + +OpenOCD supports generic Xtensa processor implementations which can be customized by +providing a core-specific configuration file which describes every enabled 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 +size instructions support, memory banks configuration etc. OpenOCD also supports SMP +configurations for Xtensa processors with any number of cores and allows configuring +their debug interconnect (termed "break/stall networks"), which control how debug +signals are distributed among cores. Xtensa "break networks" are compatible with +ARM's Cross Trigger Interface (CTI). OpenOCD implements both generic Xtensa targets +as well as several Espressif Xtensa-based chips from the @uref{https://www.espressif.com/en/products/socs, ESP32 family}. -@subsection General Xtensa Commands +OCD sessions for Xtensa processor and DSP targets are accessed via the Xtensa +Debug Module (XDM), which provides external connectivity either through a +traditional JTAG interface or an ARM DAP interface. If used, the DAP interface +can control Xtensa targets through JTAG or SWD probes. + +@subsection Xtensa Core Configuration + +Due to the high level of configurability in Xtensa cores, the Xtensa target +configuration comprises two categories: + +@enumerate +@item Base Xtensa support common to all core configurations, and +@item Core-specific support as configured for individual cores. +@end enumerate + +All common Xtensa support is built into the OpenOCD Xtensa target layer and +is enabled through a combination of TCL scripts: the target-specific +@file{target/xtensa.cfg} and a board-specific @file{board/xtensa-*.cfg}, +similar to other target architectures. + +Importantly, core-specific configuration information must be provided by +the user, and takes the form of an @file{xtensa-core-XXX.cfg} TCL script that +defines the core's configurable features through a series of Xtensa +configuration commands (detailed below). + +This core-specific @file{xtensa-core-XXX.cfg} file is typically either: + +@itemize @bullet +@item Located within the Xtensa core configuration build as +@file{src/config/xtensa-core-openocd.cfg}, or +@item Generated by running the command @code{xt-gdb --dump-oocd-config} +from the Xtensa processor tool-chain's command-line tools. +@end itemize + +NOTE: @file{xtensa-core-XXX.cfg} must match the target Xtensa hardware +connected to OpenOCD. + +Some example Xtensa configurations are bundled with OpenOCD for reference: +@itemize @bullet +@item Cadence Palladium VDebug emulation target. The user can combine their +@file{xtensa-core-XXX.cfg} with the provided +@file{board/xtensa-palladium-vdebug.cfg} to debug an emulated Xtensa RTL design. +@item NXP MIMXRT685-EVK evaluation kit. The relevant configuration files are +@file{board/xtensa-rt685-jlink.cfg} and @file{board/xtensa-core-nxp_rt600.cfg}. +Additional information is provided by +@uref{https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/i-mx-rt600-evaluation-kit:MIMXRT685-EVK, +NXP}. +@end itemize + +@subsection Xtensa Configuration Commands + +@deffn {Command} {xtensa xtdef} (@option{LX}|@option{NX}) +Configure the Xtensa target architecture. Currently, Xtensa support is limited +to LX6, LX7, and NX cores. +@end deffn + +@deffn {Command} {xtensa xtopt} option value +Configure Xtensa target options that are relevant to the debug subsystem. +@var{option} is one of: @option{arnum}, @option{windowed}, +@option{cpenable}, @option{exceptions}, @option{intnum}, @option{hipriints}, +@option{excmlevel}, @option{intlevels}, @option{debuglevel}, +@option{ibreaknum}, or @option{dbreaknum}. @var{value} is an integer with +the exact range determined by each particular option. + +NOTE: Some options are specific to Xtensa LX or Xtensa NX architecture, while +others may be common to both but have different valid ranges. +@end deffn + +@deffn {Command} {xtensa xtmem} (@option{iram}|@option{dram}|@option{sram}|@option{irom}|@option{drom}|@option{srom}) baseaddr bytes +Configure Xtensa target memory. Memory type determines access rights, +where RAMs are read/write while ROMs are read-only. @var{baseaddr} and +@var{bytes} are both integers, typically hexadecimal and decimal, respectively. +@end deffn + +@deffn {Command} {xtensa xtmem} (@option{icache}|@option{dcache}) linebytes cachebytes ways [writeback] +Configure Xtensa processor cache. All parameters are required except for +the optional @option{writeback} parameter; all are integers. +@end deffn + +@deffn {Command} {xtensa xtmpu} numfgseg minsegsz lockable execonly +Configure an Xtensa Memory Protection Unit (MPU). MPUs can restrict access +and/or control cacheability of specific address ranges, but are lighter-weight +than a full traditional MMU. All parameters are required; all are integers. +@end deffn + +@deffn {Command} {xtensa xtmmu} numirefillentries numdrefillentries +(Xtensa-LX only) Configure an Xtensa Memory Management Unit (MMU). Both +parameters are required; both are integers. +@end deffn + +@deffn {Command} {xtensa xtregs} numregs +Configure the total number of registers for the Xtensa core. Configuration +logic expects to subsequently process this number of @code{xtensa xtreg} +definitions. @var{numregs} is an integer. +@end deffn + +@deffn {Command} {xtensa xtregfmt} (@option{sparse}|@option{contiguous}) [general] +Configure the type of register map used by GDB to access the Xtensa core. +Generic Xtensa tools (e.g. xt-gdb) require @option{sparse} mapping (default) while +Espressif tools expect @option{contiguous} mapping. Contiguous mapping takes an +additional, optional integer parameter @option{numgregs}, which specifies the number +of general registers used in handling g/G packets. +@end deffn + +@deffn {Command} {xtensa xtreg} name offset +Configure an Xtensa core register. All core registers are 32 bits wide, +while TIE and user registers may have variable widths. @var{name} is a +character string identifier while @var{offset} is a hexadecimal integer. +@end deffn + +@subsection Xtensa Operation Commands + +@deffn {Command} {xtensa maskisr} (@option{on}|@option{off}) +(Xtensa-LX only) Mask or unmask Xtensa interrupts during instruction step. +When masked, an interrupt that occurs during a step operation is handled and +its ISR is executed, with the user's debug session returning after potentially +executing many instructions. When unmasked, a triggered interrupt will result +in execution progressing the requested number of instructions into the relevant +vector/ISR code. +@end deffn @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 @@ -10985,6 +11103,13 @@ This feature is not well implemented and tested yet. @end itemize @end deffn +@deffn {Command} {xtensa exe} +Execute arbitrary instruction(s) provided as an ascii string. The string represents an integer +number of instruction bytes, thus its length must be even. +@end deffn + +@subsection Xtensa Performance Monitor Configuration + @deffn {Command} {xtensa perfmon_enable} [mask] [kernelcnt] [tracelevel] diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index c575b534e0..2aacc3620a 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3978,6 +3978,38 @@ COMMAND_HANDLER(xtensa_cmd_smpbreak) get_current_target(CMD_CTX)); } +COMMAND_HELPER(xtensa_cmd_dm_rw_do, struct xtensa *xtensa) +{ + if (CMD_ARGC == 1) { + // read: xtensa dm addr + uint32_t addr = strtoul(CMD_ARGV[0], NULL, 0); + uint32_t val; + int res = xtensa_dm_read(&xtensa->dbg_mod, addr, &val); + if (res == ERROR_OK) + command_print(CMD, "xtensa DM(0x%08" PRIx32 ") -> 0x%08" PRIx32, addr, val); + else + command_print(CMD, "xtensa DM(0x%08" PRIx32 ") : read ERROR %" PRId32, addr, res); + return res; + } else if (CMD_ARGC == 2) { + // write: xtensa dm addr value + uint32_t addr = strtoul(CMD_ARGV[0], NULL, 0); + uint32_t val = strtoul(CMD_ARGV[1], NULL, 0); + int res = xtensa_dm_write(&xtensa->dbg_mod, addr, val); + if (res == ERROR_OK) + command_print(CMD, "xtensa DM(0x%08" PRIx32 ") <- 0x%08" PRIx32, addr, val); + else + command_print(CMD, "xtensa DM(0x%08" PRIx32 ") : write ERROR %" PRId32, addr, res); + return res; + } + return ERROR_COMMAND_SYNTAX_ERROR; +} + +COMMAND_HANDLER(xtensa_cmd_dm_rw) +{ + return CALL_COMMAND_HANDLER(xtensa_cmd_dm_rw_do, + target_to_xtensa(get_current_target(CMD_CTX))); +} + COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa) { struct xtensa_trace_status trace_status; @@ -4234,6 +4266,13 @@ static const struct command_registration xtensa_any_command_handlers[] = { .help = "Set the way the CPU chains OCD breaks", .usage = "[none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut]", }, + { + .name = "dm", + .handler = xtensa_cmd_dm_rw, + .mode = COMMAND_ANY, + .help = "Xtensa DM read/write", + .usage = "addr [value]" + }, { .name = "perfmon_enable", .handler = xtensa_cmd_perfmon_enable, diff --git a/src/target/xtensa/xtensa_debug_module.c b/src/target/xtensa/xtensa_debug_module.c index 31d7a9435c..8045779b81 100644 --- a/src/target/xtensa/xtensa_debug_module.c +++ b/src/target/xtensa/xtensa_debug_module.c @@ -34,6 +34,16 @@ static const struct xtensa_dm_pwr_reg_offsets xdm_pwr_regs[XDMREG_PWRNUM] = static const struct xtensa_dm_reg_offsets xdm_regs[XDMREG_NUM] = XTENSA_DM_REG_OFFSETS; +static enum xtensa_dm_reg xtensa_dm_regaddr_to_id(uint32_t addr) +{ + enum xtensa_dm_reg id; + uint32_t addr_masked = (addr & (XTENSA_DM_APB_ALIGN - 1)); + for (id = XDMREG_TRAXID; id < XDMREG_NUM; id++) + if (xdm_regs[id].apb == addr_masked) + break; + return id; +} + static void xtensa_dm_add_set_ir(struct xtensa_debug_module *dm, uint8_t value) { struct scan_field field; @@ -285,6 +295,34 @@ int xtensa_dm_core_status_clear(struct xtensa_debug_module *dm, xtensa_dsr_t bit return xtensa_dm_queue_execute(dm); } +int xtensa_dm_read(struct xtensa_debug_module *dm, uint32_t addr, uint32_t *val) +{ + enum xtensa_dm_reg reg = xtensa_dm_regaddr_to_id(addr); + uint8_t buf[sizeof(uint32_t)]; + if (reg < XDMREG_NUM) { + xtensa_dm_queue_enable(dm); + dm->dbg_ops->queue_reg_read(dm, reg, buf); + xtensa_dm_queue_tdi_idle(dm); + int res = xtensa_dm_queue_execute(dm); + if (res == ERROR_OK && val) + *val = buf_get_u32(buf, 0, 32); + return res; + } + return ERROR_FAIL; +} + +int xtensa_dm_write(struct xtensa_debug_module *dm, uint32_t addr, uint32_t val) +{ + enum xtensa_dm_reg reg = xtensa_dm_regaddr_to_id(addr); + if (reg < XDMREG_NUM) { + xtensa_dm_queue_enable(dm); + dm->dbg_ops->queue_reg_write(dm, reg, val); + xtensa_dm_queue_tdi_idle(dm); + return xtensa_dm_queue_execute(dm); + } + return ERROR_FAIL; +} + int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg) { /*Turn off trace unit so we can start a new trace. */ diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h index 46b29354cd..495da2a646 100644 --- a/src/target/xtensa/xtensa_debug_module.h +++ b/src/target/xtensa/xtensa_debug_module.h @@ -75,6 +75,22 @@ enum xtensa_dm_reg { XDMREG_DELAYCNT, XDMREG_MEMADDRSTART, XDMREG_MEMADDREND, + XDMREG_EXTTIMELO, + XDMREG_EXTTIMEHI, + XDMREG_TRAXRSVD48, + XDMREG_TRAXRSVD4C, + XDMREG_TRAXRSVD50, + XDMREG_TRAXRSVD54, + XDMREG_TRAXRSVD58, + XDMREG_TRAXRSVD5C, + XDMREG_TRAXRSVD60, + XDMREG_TRAXRSVD64, + XDMREG_TRAXRSVD68, + XDMREG_TRAXRSVD6C, + XDMREG_TRAXRSVD70, + XDMREG_TRAXRSVD74, + XDMREG_CONFIGID0, + XDMREG_CONFIGID1, /* Performance Monitor Registers */ XDMREG_PMG, @@ -168,6 +184,22 @@ struct xtensa_dm_reg_offsets { { .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \ { .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \ { .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \ + { .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \ + { .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \ + { .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \ + { .nar = 0x13, .apb = 0x004c }, /* XDMREG_TRAXRSVD4C */ \ + { .nar = 0x14, .apb = 0x0050 }, /* XDMREG_TRAXRSVD50 */ \ + { .nar = 0x15, .apb = 0x0054 }, /* XDMREG_TRAXRSVD54 */ \ + { .nar = 0x16, .apb = 0x0058 }, /* XDMREG_TRAXRSVD58 */ \ + { .nar = 0x17, .apb = 0x005c }, /* XDMREG_TRAXRSVD5C */ \ + { .nar = 0x18, .apb = 0x0060 }, /* XDMREG_TRAXRSVD60 */ \ + { .nar = 0x19, .apb = 0x0064 }, /* XDMREG_TRAXRSVD64 */ \ + { .nar = 0x1a, .apb = 0x0068 }, /* XDMREG_TRAXRSVD68 */ \ + { .nar = 0x1b, .apb = 0x006c }, /* XDMREG_TRAXRSVD6C */ \ + { .nar = 0x1c, .apb = 0x0070 }, /* XDMREG_TRAXRSVD70 */ \ + { .nar = 0x1d, .apb = 0x0074 }, /* XDMREG_TRAXRSVD74 */ \ + { .nar = 0x1e, .apb = 0x0078 }, /* XDMREG_CONFIGID0 */ \ + { .nar = 0x1f, .apb = 0x007c }, /* XDMREG_CONFIGID1 */ \ \ /* Performance Monitor Registers */ \ { .nar = 0x20, .apb = 0x1000 }, /* XDMREG_PMG */ \ @@ -297,6 +329,11 @@ struct xtensa_dm_reg_offsets { #define DEBUGCAUSE_DI BIT(5) /* Debug Interrupt */ #define DEBUGCAUSE_VALID BIT(31) /* Pseudo-value to trigger reread (NX only) */ +/* TRAXID */ +#define TRAXID_PRODNO_TRAX 0 /* TRAXID.PRODNO value for TRAX module */ +#define TRAXID_PRODNO_SHIFT 28 +#define TRAXID_PRODNO_MASK 0xf + #define TRAXCTRL_TREN BIT(0) /* Trace enable. Tracing starts on 0->1 */ #define TRAXCTRL_TRSTP BIT(1) /* Trace Stop. Make 1 to stop trace. */ #define TRAXCTRL_PCMEN BIT(2) /* PC match enable */ @@ -512,6 +549,9 @@ static inline xtensa_dsr_t xtensa_dm_core_status_get(struct xtensa_debug_module return dm->core_status.dsr; } +int xtensa_dm_read(struct xtensa_debug_module *dm, uint32_t addr, uint32_t *val); +int xtensa_dm_write(struct xtensa_debug_module *dm, uint32_t addr, uint32_t val); + int xtensa_dm_device_id_read(struct xtensa_debug_module *dm); static inline xtensa_ocdid_t xtensa_dm_device_id_get(struct xtensa_debug_module *dm) { From 7c60f6593edd692cff90b8486412a9b8adba28d2 Mon Sep 17 00:00:00 2001 From: Kirill Radkin Date: Wed, 18 Oct 2023 19:13:25 +0300 Subject: [PATCH 0622/1312] breakpoints: Fix endless loop in bp/wp_clear_target If we can't remove bp/wp, we will stuck in endless loop Change-Id: I44c0a164db1d15c0a0637d33c75087a49cf5c0f4 Signed-off-by: Kirill Radkin Reviewed-on: https://review.openocd.org/c/openocd/+/7940 Tested-by: jenkins Reviewed-by: Anatoly P Reviewed-by: Tim Newsome Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo --- src/target/breakpoints.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index d9c12f523d..d4662c4de8 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -326,6 +326,8 @@ static int breakpoint_remove_internal(struct target *target, target_addr_t addre static int breakpoint_remove_all_internal(struct target *target) { + LOG_TARGET_DEBUG(target, "Delete all breakpoints"); + struct breakpoint *breakpoint = target->breakpoints; int retval = ERROR_OK; @@ -464,22 +466,6 @@ int watchpoint_remove_all(struct target *target) return breakpoint_watchpoint_remove_all(target, WATCHPOINT); } -static int breakpoint_clear_target_internal(struct target *target) -{ - LOG_DEBUG("Delete all breakpoints for target: %s", - target_name(target)); - - int retval = ERROR_OK; - - while (target->breakpoints) { - int status = breakpoint_free(target, target->breakpoints); - if (status != ERROR_OK) - retval = status; - } - - return retval; -} - int breakpoint_clear_target(struct target *target) { int retval = ERROR_OK; @@ -489,13 +475,13 @@ int breakpoint_clear_target(struct target *target) foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - int status = breakpoint_clear_target_internal(curr); + int status = breakpoint_remove_all_internal(curr); if (status != ERROR_OK) retval = status; } } else { - retval = breakpoint_clear_target_internal(target); + retval = breakpoint_remove_all_internal(target); } return retval; @@ -659,16 +645,19 @@ int watchpoint_remove(struct target *target, target_addr_t address) int watchpoint_clear_target(struct target *target) { - int retval = ERROR_OK; - LOG_DEBUG("Delete all watchpoints for target: %s", target_name(target)); - while (target->watchpoints) { - int status = watchpoint_free(target, target->watchpoints); + + struct watchpoint *watchpoint = target->watchpoints; + int retval = ERROR_OK; + + while (watchpoint) { + struct watchpoint *tmp = watchpoint; + watchpoint = watchpoint->next; + int status = watchpoint_free(target, tmp); if (status != ERROR_OK) retval = status; } - return retval; } From 851d1ad87a6e9f1ae1b44b8ac395138031290488 Mon Sep 17 00:00:00 2001 From: Marek Vrbka Date: Fri, 29 Sep 2023 13:14:10 +0200 Subject: [PATCH 0623/1312] breakpoints: Add target logging to breakpoints and watchpoints This patch adds target logging to breakpoint handling code. This makes it easier to debug multicore/multithread systems. Change-Id: I6bea8079a457070a8f63d0ce381a4ece6f5a190a Signed-off-by: Marek Vrbka Reviewed-on: https://review.openocd.org/c/openocd/+/7922 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- src/target/breakpoints.c | 32 +++++++++++++++----------------- src/target/target.c | 8 ++++---- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index d4662c4de8..c39a980570 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -52,7 +52,7 @@ static int breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_ERROR("Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", + LOG_TARGET_ERROR(target, "Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); return ERROR_TARGET_DUPLICATE_BREAKPOINT; } @@ -83,16 +83,15 @@ static int breakpoint_add_internal(struct target *target, default: reason = "unknown reason"; fail: - LOG_ERROR("can't add breakpoint: %s", reason); + LOG_TARGET_ERROR(target, "can't add breakpoint: %s", reason); free((*breakpoint_p)->orig_instr); free(*breakpoint_p); *breakpoint_p = NULL; return retval; } - LOG_DEBUG("[%d] added %s breakpoint at " TARGET_ADDR_FMT + LOG_TARGET_DEBUG(target, "added %s breakpoint at " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", - target->coreid, breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); @@ -134,14 +133,14 @@ static int context_breakpoint_add_internal(struct target *target, (*breakpoint_p)->unique_id = bpwp_unique_id++; retval = target_add_context_breakpoint(target, *breakpoint_p); if (retval != ERROR_OK) { - LOG_ERROR("could not add breakpoint"); + LOG_TARGET_ERROR(target, "could not add breakpoint"); free((*breakpoint_p)->orig_instr); free(*breakpoint_p); *breakpoint_p = NULL; return retval; } - LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", + LOG_TARGET_DEBUG(target, "added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->asid, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); @@ -165,11 +164,11 @@ static int hybrid_breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_TARGET_ERROR(target, "Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); return ERROR_TARGET_DUPLICATE_BREAKPOINT; } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) { - LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", + LOG_TARGET_ERROR(target, "Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); return ERROR_TARGET_DUPLICATE_BREAKPOINT; @@ -190,13 +189,13 @@ static int hybrid_breakpoint_add_internal(struct target *target, retval = target_add_hybrid_breakpoint(target, *breakpoint_p); if (retval != ERROR_OK) { - LOG_ERROR("could not add breakpoint"); + LOG_TARGET_ERROR(target, "could not add breakpoint"); free((*breakpoint_p)->orig_instr); free(*breakpoint_p); *breakpoint_p = NULL; return retval; } - LOG_DEBUG( + LOG_TARGET_DEBUG(target, "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, @@ -298,7 +297,7 @@ static int breakpoint_free(struct target *target, struct breakpoint *breakpoint_ return retval; } - LOG_DEBUG("free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval); + LOG_TARGET_DEBUG(target, "free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval); (*breakpoint_p) = breakpoint->next; free(breakpoint->orig_instr); free(breakpoint); @@ -404,7 +403,7 @@ static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_ return retval; } - LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval); + LOG_TARGET_DEBUG(target, "free WPID: %d --> %d", watchpoint->unique_id, retval); (*watchpoint_p) = watchpoint->next; free(watchpoint); @@ -514,7 +513,7 @@ static int watchpoint_add_internal(struct target *target, target_addr_t address, || watchpoint->value != value || watchpoint->mask != mask || watchpoint->rw != rw) { - LOG_ERROR("address " TARGET_ADDR_FMT + LOG_TARGET_ERROR(target, "address " TARGET_ADDR_FMT " already has watchpoint %d", address, watchpoint->unique_id); return ERROR_FAIL; @@ -548,7 +547,7 @@ static int watchpoint_add_internal(struct target *target, target_addr_t address, default: reason = "unrecognized error"; bye: - LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT ", %s", + LOG_TARGET_ERROR(target, "can't add %s watchpoint at " TARGET_ADDR_FMT ", %s", watchpoint_rw_strings[(*watchpoint_p)->rw], address, reason); free(*watchpoint_p); @@ -556,9 +555,8 @@ static int watchpoint_add_internal(struct target *target, target_addr_t address, return retval; } - LOG_DEBUG("[%d] added %s watchpoint at " TARGET_ADDR_FMT + LOG_TARGET_DEBUG(target, "added %s watchpoint at " TARGET_ADDR_FMT " of length 0x%8.8" PRIx32 " (WPID: %d)", - target->coreid, watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, (*watchpoint_p)->length, @@ -674,7 +672,7 @@ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, *rw = hit_watchpoint->rw; *address = hit_watchpoint->address; - LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT " (WPID: %d)", + LOG_TARGET_DEBUG(target, "Found hit watchpoint at " TARGET_ADDR_FMT " (WPID: %d)", hit_watchpoint->address, hit_watchpoint->unique_id); diff --git a/src/target/target.c b/src/target/target.c index 30f7029a5d..9f43e2f911 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3974,7 +3974,7 @@ static int handle_bp_command_set(struct command_invocation *cmd, } else if (addr == 0) { if (!target->type->add_context_breakpoint) { - LOG_ERROR("Context breakpoint not available"); + LOG_TARGET_ERROR(target, "Context breakpoint not available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = context_breakpoint_add(target, asid, length, hw); @@ -3984,7 +3984,7 @@ static int handle_bp_command_set(struct command_invocation *cmd, } else { if (!target->type->add_hybrid_breakpoint) { - LOG_ERROR("Hybrid breakpoint not available"); + LOG_TARGET_ERROR(target, "Hybrid breakpoint not available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = hybrid_breakpoint_add(target, addr, asid, length, hw); @@ -4121,7 +4121,7 @@ COMMAND_HANDLER(handle_wp_command) type = WPT_ACCESS; break; default: - LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); + LOG_TARGET_ERROR(target, "invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); return ERROR_COMMAND_SYNTAX_ERROR; } /* fall through */ @@ -4137,7 +4137,7 @@ COMMAND_HANDLER(handle_wp_command) int retval = watchpoint_add(target, addr, length, type, data_value, data_mask); if (retval != ERROR_OK) - LOG_ERROR("Failure setting watchpoints"); + LOG_TARGET_ERROR(target, "Failure setting watchpoints"); return retval; } From ee96a95d44322aa109847e35b86aed5ad3066cf8 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 27 Sep 2023 17:02:03 -0700 Subject: [PATCH 0624/1312] openocd: src/target: Correctly handle CCSIDR_EL1.Associativity=0 Associativity=0 means that only one CMO is needed for all ways. It could also mean that the cache is 1-way, but this is less likely. Currently Associativity=0 causes us to hang in the while loop in decode_cache_reg. Fix it by skipping the loop in this case. We can let way_shift be set to the arbitrary value of 0 because in the case where Associativity=0 we only ever shift 0 by it before ORing it into the CMO operand. Change-Id: I7c1de68d33f6b3ed627cbb1e2401d43185e4c1e3 Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/7916 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv8_cache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index cf7111950d..98f4b3f04c 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -286,8 +286,9 @@ static struct armv8_cachesize decode_cache_reg(uint32_t cache_reg) size.index = (cache_reg >> 13) & 0x7fff; size.way = ((cache_reg >> 3) & 0x3ff); - while (((size.way << i) & 0x80000000) == 0) - i++; + if (size.way != 0) + while (((size.way << i) & 0x80000000) == 0) + i++; size.way_shift = i; return size; From 393da819b14c62d267cf5ec86bc511c187e1af18 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 17 Oct 2023 19:04:00 -0700 Subject: [PATCH 0625/1312] aarch64: Use 64-bit reads/writes to access SCTLR_EL1 We were previously inadvertently clearing the top 32 bits of SCTLR_EL1 during read_memory/write_memory as a result of using 32-bit operations to access the register and because the fields used to temporarily store the register were 32-bit. Fix it. Change-Id: I657d7f949e1f7ab6bf90609e3f91cae09cade31a Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/7939 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/aarch64.c | 8 ++++---- src/target/aarch64.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index db602435cf..1c056a015e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -105,7 +105,7 @@ static int aarch64_restore_system_control_reg(struct target *target) if (target_mode != ARM_MODE_ANY) armv8_dpm_modeswitch(&armv8->dpm, target_mode); - retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, aarch64->system_control_reg); + retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr, aarch64->system_control_reg); if (retval != ERROR_OK) return retval; @@ -182,7 +182,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) if (target_mode != ARM_MODE_ANY) armv8_dpm_modeswitch(&armv8->dpm, target_mode); - retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, + retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr, aarch64->system_control_reg_curr); if (target_mode != ARM_MODE_ANY) @@ -1055,14 +1055,14 @@ static int aarch64_post_debug_entry(struct target *target) if (target_mode != ARM_MODE_ANY) armv8_dpm_modeswitch(&armv8->dpm, target_mode); - retval = armv8->dpm.instr_read_data_r0(&armv8->dpm, instr, &aarch64->system_control_reg); + retval = armv8->dpm.instr_read_data_r0_64(&armv8->dpm, instr, &aarch64->system_control_reg); if (retval != ERROR_OK) return retval; if (target_mode != ARM_MODE_ANY) armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); - LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); + LOG_DEBUG("System_register: %8.8" PRIx64, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; if (armv8->armv8_mmu.armv8_cache.info == -1) { diff --git a/src/target/aarch64.h b/src/target/aarch64.h index 2721fe747d..b265e82498 100644 --- a/src/target/aarch64.h +++ b/src/target/aarch64.h @@ -43,8 +43,8 @@ struct aarch64_common { struct armv8_common armv8_common; /* Context information */ - uint32_t system_control_reg; - uint32_t system_control_reg_curr; + uint64_t system_control_reg; + uint64_t system_control_reg_curr; /* Breakpoint register pairs */ int brp_num_context; From 8bf7f603ae8c441c7734c9dcdc5ee2805a620fb4 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Mon, 16 Oct 2023 11:00:28 +0200 Subject: [PATCH 0626/1312] contrib/firmware: remove unnecessary delay commands in the i2c bit-banging implementation Change-Id: I741244be7a1bf186cfcb66a5b93e2a1a2ab0fde5 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7809 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/src/usb.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index 747fef1246..e284efdf58 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -773,8 +773,6 @@ void i2c_recieve(void) /* ack: */ uint8_t ack = get_ack(); - delay_us(10); - /* send data */ if (reg_adr_check) { //if there is a byte reg send_byte(reg_adr); @@ -782,8 +780,6 @@ void i2c_recieve(void) ack = get_ack(); } - delay_us(10); - /* repeated start: */ repeated_start(); /* address: */ @@ -791,8 +787,6 @@ void i2c_recieve(void) /* get ack: */ ack = get_ack(); - delay_us(10); - /* receive data */ for (uint8_t i = 0; i < count; i++) { EP8FIFOBUF[i] = receive_byte(); @@ -801,13 +795,9 @@ void i2c_recieve(void) send_ack(); } - delay_ms(1); - /* stop */ stop_cd(); - delay_us(10); - EP8BCH = 0; //EP8 syncdelay(3); EP8BCL = count; //EP8 From a69a4e23f4630fb21daea6f8264881c0546e340b Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Mon, 16 Oct 2023 11:04:16 +0200 Subject: [PATCH 0627/1312] contrib/firmware: extend the number of bytes to be sent in the i2c bit-banging read operation Change-Id: Iaeb3d5ba37da1bd77d36ad0ebbc6b45c46860dec Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7810 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/src/usb.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index e284efdf58..0a43ff9f65 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -757,14 +757,13 @@ void i2c_recieve(void) PIN_SDA_DIR = 0; if (EP6FIFOBUF[0] == 1) { uint8_t rdwr = EP6FIFOBUF[0]; //read - uint8_t reg_adr_check = EP6FIFOBUF[1]; - uint8_t count = EP6FIFOBUF[2]; //request data count + uint8_t data_count = EP6FIFOBUF[1]; //data sent count + uint8_t count = EP6FIFOBUF[2]; //requested data count uint8_t adr = EP6FIFOBUF[3]; //address - uint8_t reg_adr = EP6FIFOBUF[4]; uint8_t address = get_address(adr, rdwr); //address byte (read command) uint8_t address_2 = get_address(adr, 0); //address byte 2 (write command) - printf("%d\n", address); + printf("%d\n", address - 1); /* start: */ start_cd(); @@ -774,10 +773,12 @@ void i2c_recieve(void) uint8_t ack = get_ack(); /* send data */ - if (reg_adr_check) { //if there is a byte reg - send_byte(reg_adr); - /* ack(): */ - ack = get_ack(); + if (data_count) { //if there is a byte reg + for (uint8_t i = 0; i < data_count; i++) { + send_byte(EP6FIFOBUF[i + 4]); + /* ack(): */ + ack = get_ack(); + } } /* repeated start: */ @@ -788,13 +789,15 @@ void i2c_recieve(void) ack = get_ack(); /* receive data */ - for (uint8_t i = 0; i < count; i++) { + for (uint8_t i = 0; i < count - 1; i++) { EP8FIFOBUF[i] = receive_byte(); - /* send ack: */ + /* send ack: */ send_ack(); } + EP8FIFOBUF[count - 1] = receive_byte(); + /* stop */ stop_cd(); From bb2767721945fa3496f777aa95eaab0137795137 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Mon, 16 Oct 2023 11:05:59 +0200 Subject: [PATCH 0628/1312] contrib/firmware: add 'send not acknowledged' function to the i2c bit-banging implementation Change-Id: I60597ebc126da4acb00654513b96f52261253e12 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7811 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/include/i2c.h | 1 + contrib/firmware/angie/c/src/i2c.c | 10 ++++++++++ contrib/firmware/angie/c/src/usb.c | 3 +++ 3 files changed, 14 insertions(+) diff --git a/contrib/firmware/angie/c/include/i2c.h b/contrib/firmware/angie/c/include/i2c.h index 06185efb4d..d0404923b3 100644 --- a/contrib/firmware/angie/c/include/i2c.h +++ b/contrib/firmware/angie/c/include/i2c.h @@ -19,6 +19,7 @@ void repeated_start(void); void stop_cd(void); void clock_cd(void); void send_ack(void); +void send_nack(void); bool get_ack(void); uint8_t get_address(uint8_t adr, uint8_t rdwr); diff --git a/contrib/firmware/angie/c/src/i2c.c b/contrib/firmware/angie/c/src/i2c.c index a7004bfac9..53840100b9 100644 --- a/contrib/firmware/angie/c/src/i2c.c +++ b/contrib/firmware/angie/c/src/i2c.c @@ -60,6 +60,16 @@ void send_ack(void) delay_us(1); } +void send_nack(void) +{ + PIN_SDA = 1; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + bool get_ack(void) { PIN_SDA_DIR = 1; diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index 0a43ff9f65..1b7aa47658 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -798,6 +798,9 @@ void i2c_recieve(void) EP8FIFOBUF[count - 1] = receive_byte(); + /* send Nack: */ + send_nack(); + /* stop */ stop_cd(); From b25e5322eea66eb76232da06fa435d2f11097c86 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 6 Nov 2023 15:50:40 +0100 Subject: [PATCH 0629/1312] jtag/drivers/cmsis-dap: Restructure commands Use a command group 'cmsis-dap' with subcommands instead of individual commands with 'cmsis_dap_' prefix. The old commands are still available to ensure backwards compatibility, but are marked as deprecated. Change-Id: I75facb7572a86354c2ce6144aa7fadf3b5a6db4e Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7963 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Bohdan Tymkiv Reviewed-by: Antonio Borneo --- doc/openocd.texi | 10 +++++----- src/jtag/drivers/cmsis_dap.c | 38 ++++++++++++++++++------------------ src/jtag/startup.tcl | 18 +++++++++++++++++ 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index b03da4f832..40b3c5d1dd 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2543,27 +2543,27 @@ and a specific set of GPIOs is used. ARM CMSIS-DAP compliant based adapter v1 (USB HID based) or v2 (USB bulk). -@deffn {Config Command} {cmsis_dap_vid_pid} [vid pid]+ +@deffn {Config Command} {cmsis-dap vid_pid} [vid pid]+ The vendor ID and product ID of the CMSIS-DAP device. If not specified the driver will attempt to auto detect the CMSIS-DAP device. Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g. @example -cmsis_dap_vid_pid 0xc251 0xf001 0x0d28 0x0204 +cmsis-dap vid_pid 0xc251 0xf001 0x0d28 0x0204 @end example @end deffn -@deffn {Config Command} {cmsis_dap_backend} [@option{auto}|@option{usb_bulk}|@option{hid}] +@deffn {Config Command} {cmsis-dap backend} [@option{auto}|@option{usb_bulk}|@option{hid}] Specifies how to communicate with the adapter: @itemize @minus @item @option{hid} Use HID generic reports - CMSIS-DAP v1 @item @option{usb_bulk} Use USB bulk - CMSIS-DAP v2 @item @option{auto} First try USB bulk CMSIS-DAP v2, if not found try HID CMSIS-DAP v1. -This is the default if @command{cmsis_dap_backend} is not specified. +This is the default if @command{cmsis-dap backend} is not specified. @end itemize @end deffn -@deffn {Config Command} {cmsis_dap_usb interface} [number] +@deffn {Config Command} {cmsis-dap usb interface} [number] Specifies the @var{number} of the USB interface to use in v2 mode (USB bulk). In most cases need not to be specified and interfaces are searched by interface string or for user class interface. diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 1e7a851e4b..52e4fadeb9 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -2108,12 +2108,12 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command) COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) { if (CMD_ARGC > MAX_USB_IDS * 2) { - LOG_WARNING("ignoring extra IDs in cmsis_dap_vid_pid " + LOG_WARNING("ignoring extra IDs in cmsis-dap vid_pid " "(maximum is %d pairs)", MAX_USB_IDS); CMD_ARGC = MAX_USB_IDS * 2; } if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { - LOG_WARNING("incomplete cmsis_dap_vid_pid configuration directive"); + LOG_WARNING("incomplete cmsis-dap vid_pid configuration directive"); if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* remove the incomplete trailing id */ @@ -2148,10 +2148,10 @@ COMMAND_HANDLER(cmsis_dap_handle_backend_command) } } - LOG_ERROR("invalid backend argument to cmsis_dap_backend "); + LOG_ERROR("invalid backend argument to cmsis-dap backend "); } } else { - LOG_ERROR("expected exactly one argument to cmsis_dap_backend "); + LOG_ERROR("expected exactly one argument to cmsis-dap backend "); } return ERROR_OK; @@ -2172,27 +2172,15 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = { .usage = "", .help = "issue cmsis-dap command", }, - COMMAND_REGISTRATION_DONE -}; - - -static const struct command_registration cmsis_dap_command_handlers[] = { - { - .name = "cmsis-dap", - .mode = COMMAND_ANY, - .help = "perform CMSIS-DAP management", - .usage = "", - .chain = cmsis_dap_subcommand_handlers, - }, { - .name = "cmsis_dap_vid_pid", + .name = "vid_pid", .handler = &cmsis_dap_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor ID and product ID of the CMSIS-DAP device", .usage = "(vid pid)*", }, { - .name = "cmsis_dap_backend", + .name = "backend", .handler = &cmsis_dap_handle_backend_command, .mode = COMMAND_CONFIG, .help = "set the communication backend to use (USB bulk or HID).", @@ -2200,7 +2188,7 @@ static const struct command_registration cmsis_dap_command_handlers[] = { }, #if BUILD_CMSIS_DAP_USB { - .name = "cmsis_dap_usb", + .name = "usb", .chain = cmsis_dap_usb_subcommand_handlers, .mode = COMMAND_ANY, .help = "USB bulk backend-specific commands", @@ -2210,6 +2198,18 @@ static const struct command_registration cmsis_dap_command_handlers[] = { COMMAND_REGISTRATION_DONE }; + +static const struct command_registration cmsis_dap_command_handlers[] = { + { + .name = "cmsis-dap", + .mode = COMMAND_ANY, + .help = "perform CMSIS-DAP management", + .usage = "", + .chain = cmsis_dap_subcommand_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + static const struct swd_driver cmsis_dap_swd_driver = { .init = cmsis_dap_swd_init, .switch_seq = cmsis_dap_swd_switch_seq, diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 085c89ba17..597a49e958 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -1108,6 +1108,24 @@ proc "am335xgpio led_on_state" {state} { } } +lappend _telnet_autocomplete_skip "cmsis_dap_backend" +proc "cmsis_dap_backend" {backend} { + echo "DEPRECATED! use 'cmsis-dap backend', not 'cmsis_dap_backend'" + eval cmsis-dap backend $backend +} + +lappend _telnet_autocomplete_skip "cmsis_dap_vid_pid" +proc "cmsis_dap_vid_pid" {args} { + echo "DEPRECATED! use 'cmsis-dap vid_pid', not 'cmsis_dap_vid_pid'" + eval cmsis-dap vid_pid $args +} + +lappend _telnet_autocomplete_skip "cmsis_dap_usb" +proc "cmsis_dap_usb" {args} { + echo "DEPRECATED! use 'cmsis-dap usb', not 'cmsis_dap_usb'" + eval cmsis-dap usb $args +} + lappend _telnet_autocomplete_skip "pld device" proc "pld device" {driver tap_name {opt 0}} { echo "DEPRECATED! use 'pld create ...', not 'pld device ...'" From ba79d503bb4f1e92e91a4c300a036819fe91c6d3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 6 Nov 2023 16:22:53 +0100 Subject: [PATCH 0630/1312] jtag/drivers/cmsis-dap: Return error in 'backend' command Change-Id: Ib9bf7ab50cbe193e9e726efb3cb58e53723a6dd1 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7964 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/cmsis_dap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 52e4fadeb9..03832431dd 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -2148,10 +2148,11 @@ COMMAND_HANDLER(cmsis_dap_handle_backend_command) } } - LOG_ERROR("invalid backend argument to cmsis-dap backend "); + command_print(CMD, "invalid backend argument to cmsis-dap backend "); + return ERROR_COMMAND_ARGUMENT_INVALID; } } else { - LOG_ERROR("expected exactly one argument to cmsis-dap backend "); + return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; From 1c9f4ac181f6d5716f392a9e2d9167e797c390c7 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 7 Nov 2023 13:23:14 +0100 Subject: [PATCH 0631/1312] drivers/cmsis_dap: drop unused variable The variable 'mode' was introduced in commit 4dc8cd201c66 ("cmsis-dap: add initial cmsis-dap support") but never has been used (just cleared) Change-Id: Ia741d181ee8006bd0d872f3358a57e045235741a Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7965 Reviewed-by: zapb Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/cmsis_dap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index 16885a51d4..a8554de802 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -52,7 +52,7 @@ struct cmsis_dap { unsigned int pending_fifo_block_count; uint16_t caps; - uint8_t mode; + uint32_t swo_buf_sz; bool trace_enabled; }; From f55b122b42c212fcb3219e372a7361d6573bd6a3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 7 Nov 2023 17:14:09 +0100 Subject: [PATCH 0632/1312] jtag/drivers/kitprog: Restructure commands Use a command group 'kitprog' with subcommands instead of individual commands with 'kitprog_' prefix. The old command is still available to ensure backwards compatibility, but is marked as deprecated. Change-Id: I7f0d447939819ffc488a3d7a8de672b58887127f Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7967 Reviewed-by: Bohdan Tymkiv Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 6 +++--- src/jtag/drivers/kitprog.c | 14 +++++++------- src/jtag/startup.tcl | 6 ++++++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 40b3c5d1dd..5d73fd1744 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2991,7 +2991,7 @@ This driver is for Cypress Semiconductor's KitProg adapters. The KitProg is an SWD-only adapter that is designed to be used with Cypress's PSoC and PRoC device families, but it is possible to use it with some other devices. If you are using this adapter with a PSoC or a PRoC, you may need to add -@command{kitprog_init_acquire_psoc} or @command{kitprog acquire_psoc} to your +@command{kitprog init_acquire_psoc} or @command{kitprog acquire_psoc} to your configuration script. Note that this driver is for the proprietary KitProg protocol, not the CMSIS-DAP @@ -3012,14 +3012,14 @@ versions only implement "SWD line reset". Second, due to a firmware quirk, an SWD sequence must be sent after every target reset in order to re-establish communications with the target. @item Due in part to the limitation above, KitProg devices with firmware below -version 2.14 will need to use @command{kitprog_init_acquire_psoc} in order to +version 2.14 will need to use @command{kitprog init_acquire_psoc} in order to communicate with PSoC 5LP devices. This is because, assuming debug is not disabled on the PSoC, the PSoC 5LP needs its JTAG interface switched to SWD mode before communication can begin, but prior to firmware 2.14, "JTAG to SWD" could only be sent with an acquisition sequence. @end itemize -@deffn {Config Command} {kitprog_init_acquire_psoc} +@deffn {Config Command} {kitprog init_acquire_psoc} Indicate that a PSoC acquisition sequence needs to be run during adapter init. Please be aware that the acquisition sequence hard-resets the target. @end deffn diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c index e126a9c22b..c0d2adc100 100644 --- a/src/jtag/drivers/kitprog.c +++ b/src/jtag/drivers/kitprog.c @@ -879,6 +879,13 @@ static const struct command_registration kitprog_subcommand_handlers[] = { .usage = "", .help = "try to acquire a PSoC", }, + { + .name = "init_acquire_psoc", + .handler = &kitprog_handle_init_acquire_psoc_command, + .mode = COMMAND_CONFIG, + .help = "try to acquire a PSoC during init", + .usage = "", + }, COMMAND_REGISTRATION_DONE }; @@ -890,13 +897,6 @@ static const struct command_registration kitprog_command_handlers[] = { .usage = "", .chain = kitprog_subcommand_handlers, }, - { - .name = "kitprog_init_acquire_psoc", - .handler = &kitprog_handle_init_acquire_psoc_command, - .mode = COMMAND_CONFIG, - .help = "try to acquire a PSoC during init", - .usage = "", - }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 597a49e958..4eca67771d 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -1126,6 +1126,12 @@ proc "cmsis_dap_usb" {args} { eval cmsis-dap usb $args } +lappend _telnet_autocomplete_skip "kitprog_init_acquire_psoc" +proc "kitprog_init_acquire_psoc" {} { + echo "DEPRECATED! use 'kitprog init_acquire_psoc', not 'kitprog_init_acquire_psoc'" + eval kitprog init_acquire_psoc +} + lappend _telnet_autocomplete_skip "pld device" proc "pld device" {driver tap_name {opt 0}} { echo "DEPRECATED! use 'pld create ...', not 'pld device ...'" From 62b526dbbdec073cdcf95bf5cdf622401aa55e78 Mon Sep 17 00:00:00 2001 From: Tobias Diedrich Date: Mon, 1 Aug 2016 20:29:41 +0200 Subject: [PATCH 0633/1312] mips32: MIPS32_OP_SRL was using SRA opcode. The mips opcode macro for the SRL opcode was using the wrong constant value: SRA -- Shift right arithmetic Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0011 SRL -- Shift right logical Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0010 This corrects the opcode constant for SRL and adds the SRA opcode for completeness. There is only one user of MIPS32_OP_SRL in src/flash/nor/cfi.c: Since the mask constant (0x00000080 for the DQ7 mask) shifted in this case would never have the sign bit set, it worked fine even though it was accidentally using the SRA opcode instead of SRL. Change-Id: I0a80746e2075c7df1ce35b9db00d9d0b997a3feb Signed-off-by: Tobias Diedrich Reviewed-on: https://review.openocd.org/c/openocd/+/3613 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- src/target/mips32.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/target/mips32.h b/src/target/mips32.h index d072eb99ac..fc896248b6 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -380,7 +380,8 @@ struct mips32_algorithm { #define MIPS32_OP_XORI 0x0Eu #define MIPS32_OP_XOR 0x26u #define MIPS32_OP_SLTU 0x2Bu -#define MIPS32_OP_SRL 0x03u +#define MIPS32_OP_SRL 0x02u +#define MIPS32_OP_SRA 0x03u #define MIPS32_OP_SYNCI 0x1Fu #define MIPS32_OP_SLL 0x00u #define MIPS32_OP_SLTI 0x0Au @@ -439,7 +440,8 @@ struct mips32_algorithm { #define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) #define MIPS32_ISA_SLTI(tar, src, val) MIPS32_I_INST(MIPS32_OP_SLTI, src, tar, val) #define MIPS32_ISA_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) -#define MIPS32_ISA_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) +#define MIPS32_ISA_SRA(reg, src, off) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, reg, off, MIPS32_OP_SRA) +#define MIPS32_ISA_SRL(reg, src, off) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, reg, off, MIPS32_OP_SRL) #define MIPS32_ISA_SYNC 0xFu #define MIPS32_ISA_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) From a23c69de3dcb4c0934a2bcdf3f7b00541fe139b1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 9 Nov 2023 09:55:27 +0100 Subject: [PATCH 0634/1312] jtag/drivers/jlink: Use correct command errors While at it, remove the syntax error messages as the correct syntax is already suggested due to the return value used. Change-Id: I9310ba96ed3f8a85c37cee9193e481ad3df02e77 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7969 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/jlink.c | 51 +++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 243d1a46b2..5743d8d6eb 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -966,19 +966,17 @@ COMMAND_HANDLER(jlink_usb_command) { int tmp; - if (CMD_ARGC != 1) { - command_print(CMD, "Need exactly one argument for jlink usb"); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_FAIL; + return ERROR_COMMAND_ARGUMENT_INVALID; } if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_FAIL; + return ERROR_COMMAND_ARGUMENT_INVALID; } usb_address = tmp; @@ -1059,7 +1057,7 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) } else if (CMD_ARGC == 1) { if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } switch (tmp) { @@ -1071,10 +1069,9 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) break; default: command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } } else { - command_print(CMD, "Need exactly one argument for jlink jtag"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1086,10 +1083,8 @@ COMMAND_HANDLER(jlink_handle_target_power_command) int ret; int enable; - if (CMD_ARGC != 1) { - command_print(CMD, "Need exactly one argument for jlink targetpower"); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) { command_print(CMD, "Target power supply is not supported by the " @@ -1428,17 +1423,16 @@ COMMAND_HANDLER(jlink_handle_config_usb_address_command) } else if (CMD_ARGC == 1) { if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) { command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_FAIL; + return ERROR_COMMAND_ARGUMENT_INVALID; } if (tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD, "Invalid USB address: %u", tmp); - return ERROR_FAIL; + return ERROR_COMMAND_ARGUMENT_INVALID; } tmp_config.usb_address = tmp; } else { - command_print(CMD, "Need exactly one argument for jlink config usb"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1470,13 +1464,11 @@ COMMAND_HANDLER(jlink_handle_config_target_power_command) enable = false; } else { command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_FAIL; + return ERROR_COMMAND_ARGUMENT_INVALID; } tmp_config.target_power = enable; } else { - command_print(CMD, "Need exactly one argument for jlink config " - "targetpower"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1510,7 +1502,7 @@ COMMAND_HANDLER(jlink_handle_config_mac_address_command) if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || str[8] != ':' || str[11] != ':' || str[14] != ':')) { command_print(CMD, "Invalid MAC address format"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } for (i = 5; i >= 0; i--) { @@ -1520,17 +1512,16 @@ COMMAND_HANDLER(jlink_handle_config_mac_address_command) if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) { command_print(CMD, "Invalid MAC address: zero address"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } if (!(0x01 & addr[0])) { command_print(CMD, "Invalid MAC address: multicast address"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } memcpy(tmp_config.mac_address, addr, sizeof(addr)); } else { - command_print(CMD, "Need exactly one argument for jlink config mac"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1592,20 +1583,26 @@ COMMAND_HANDLER(jlink_handle_config_ip_address_command) if (!CMD_ARGC) { show_config_ip_address(CMD); } else { - if (!string_to_ip(CMD_ARGV[0], ip_address, &i)) - return ERROR_COMMAND_SYNTAX_ERROR; + if (!string_to_ip(CMD_ARGV[0], ip_address, &i)) { + command_print(CMD, "invalid IPv4 address"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } len = strlen(CMD_ARGV[0]); /* Check for format A.B.C.D/E. */ if (i < len) { - if (CMD_ARGV[0][i] != '/') - return ERROR_COMMAND_SYNTAX_ERROR; + if (CMD_ARGV[0][i] != '/') { + command_print(CMD, "missing network mask"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0] + i + 1, subnet_bits); } else if (CMD_ARGC > 1) { - if (!string_to_ip(CMD_ARGV[1], (uint8_t *)&subnet_mask, &i)) - return ERROR_COMMAND_SYNTAX_ERROR; + if (!string_to_ip(CMD_ARGV[1], (uint8_t *)&subnet_mask, &i)) { + command_print(CMD, "invalid subnet mask"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } } if (!subnet_mask) From acc1717970d42344812542f72ab7b17349e71242 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 9 Nov 2023 10:11:34 +0100 Subject: [PATCH 0635/1312] jtag/drivers/ftdi: Use correct command error Change-Id: I625acdd8a226528de86f113582e31755d679e68e Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7970 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/jtag/drivers/ftdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 7175925e42..da5911ac99 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -837,7 +837,7 @@ COMMAND_HANDLER(ftdi_handle_set_signal_command) /* fallthrough */ default: LOG_ERROR("unknown signal level '%s', use 0, 1 or z", CMD_ARGV[1]); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } return mpsse_flush(mpsse_ctx); From dc0f79d45d4ea1fec9f31557478ef0d0cdba1d01 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 9 Nov 2023 10:12:51 +0100 Subject: [PATCH 0636/1312] jtag/drivers/jtag_vpi: Remove redundant error messages The correct syntax is already suggested due to the return value used. Change-Id: I971a579014c1eaf13b1932f7fa87c020a8eba69c Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7971 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/jtag/drivers/jtag_vpi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index f19e9ab44b..c2b3b08083 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -593,10 +593,8 @@ static int jtag_vpi_quit(void) COMMAND_HANDLER(jtag_vpi_set_port) { - if (CMD_ARGC == 0) { - LOG_ERROR("Command \"jtag_vpi set_port\" expects 1 argument (TCP port number)"); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port); LOG_INFO("jtag_vpi: server port set to %u", server_port); @@ -607,10 +605,8 @@ COMMAND_HANDLER(jtag_vpi_set_port) COMMAND_HANDLER(jtag_vpi_set_address) { - if (CMD_ARGC == 0) { - LOG_ERROR("Command \"jtag_vpi set_address\" expects 1 argument (IP address)"); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } free(server_address); server_address = strdup(CMD_ARGV[0]); @@ -621,10 +617,8 @@ COMMAND_HANDLER(jtag_vpi_set_address) COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler) { - if (CMD_ARGC != 1) { - LOG_ERROR("Command \"jtag_vpi stop_sim_on_exit\" expects 1 argument (on|off)"); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit); return ERROR_OK; From 1df35d92fe59eac4603f28a2e1c6e5ee1d56e7da Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 9 Nov 2023 10:13:10 +0100 Subject: [PATCH 0637/1312] jtag/drivers/rshim: Remove redundant error message The correct syntax is already suggested due to the return value used. Change-Id: I0f4a7f93fdf056e7517c754d6d4ecd7928f1d226 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7992 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/jtag/drivers/rshim.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index 6170e86bdb..21fc7fd378 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -434,10 +434,8 @@ static void rshim_disconnect(struct adiv5_dap *dap) COMMAND_HANDLER(rshim_dap_device_command) { - if (CMD_ARGC != 1) { - command_print(CMD, "Too many arguments"); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } free(rshim_dev_path); rshim_dev_path = strdup(CMD_ARGV[0]); From 738f1e1f72f64839462c6da97ea4ab7eba56e337 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Nov 2023 10:17:45 +0100 Subject: [PATCH 0638/1312] flash/nor/stm32f2x: Remove redundant error messages The correct syntax is already suggested due to the return value used. While at it, apply some minor code improvements. Change-Id: I676e2ebf5714c850a436854a32c2e9d2f181d537 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7999 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/flash/nor/stm32f2x.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 2e0d158975..4e0f731827 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -1540,10 +1540,8 @@ static int stm32x_mass_erase(struct flash_bank *bank) COMMAND_HANDLER(stm32x_handle_mass_erase_command) { - if (CMD_ARGC < 1) { - command_print(CMD, "stm32x mass_erase "); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -1566,10 +1564,8 @@ COMMAND_HANDLER(stm32f2x_handle_options_read_command) struct flash_bank *bank; struct stm32x_flash_bank *stm32x_info = NULL; - if (CMD_ARGC != 1) { - command_print(CMD, "stm32f2x options_read "); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (retval != ERROR_OK) @@ -1612,10 +1608,8 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command) struct stm32x_flash_bank *stm32x_info = NULL; uint16_t user_options, boot_addr0, boot_addr1, options_mask; - if (CMD_ARGC < 1) { - command_print(CMD, "stm32f2x options_write ..."); + if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; - } retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (retval != ERROR_OK) @@ -1627,19 +1621,14 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command) stm32x_info = bank->driver_priv; if (stm32x_info->has_boot_addr) { - if (CMD_ARGC != 4) { - command_print(CMD, "stm32f2x options_write " - " "); + if (CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; - } + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], boot_addr0); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], boot_addr1); stm32x_info->option_bytes.boot_addr = boot_addr0 | (((uint32_t) boot_addr1) << 16); - } else { - if (CMD_ARGC != 2) { - command_print(CMD, "stm32f2x options_write "); - return ERROR_COMMAND_SYNTAX_ERROR; - } + } else if (CMD_ARGC != 2) { + return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options); @@ -1674,10 +1663,8 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command) struct stm32x_flash_bank *stm32x_info = NULL; uint32_t optcr2_pcrop; - if (CMD_ARGC != 2) { - command_print(CMD, "stm32f2x optcr2_write "); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); if (retval != ERROR_OK) @@ -1711,10 +1698,8 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command) COMMAND_HANDLER(stm32x_handle_otp_command) { - if (CMD_ARGC < 2) { - command_print(CMD, "stm32x otp (enable|disable|show)"); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -1787,7 +1772,7 @@ static const struct command_registration stm32f2x_exec_command_handlers[] = { .name = "otp", .handler = stm32x_handle_otp_command, .mode = COMMAND_EXEC, - .usage = "bank_id", + .usage = "bank_id (enable|disable|show)", .help = "OTP (One Time Programmable) memory write enable/disable.", }, COMMAND_REGISTRATION_DONE From b310b3ba9d89a059e0edc4f374a31632ec1c58fd Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Nov 2023 10:18:53 +0100 Subject: [PATCH 0639/1312] flash/nor/stm32h7x: Remove redundant error messages The correct syntax is already suggested due to the return value used. While at it, apply some minor code improvements. Change-Id: Idf3d7a46ddecd70823e06bc3997f41fcdb8e501f Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8000 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/stm32h7x.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index 21618b39b8..c02fae992c 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -1080,10 +1080,8 @@ static int stm32x_mass_erase(struct flash_bank *bank) COMMAND_HANDLER(stm32x_handle_mass_erase_command) { - if (CMD_ARGC < 1) { - command_print(CMD, "stm32h7x mass_erase "); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -1101,10 +1099,8 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command) COMMAND_HANDLER(stm32x_handle_option_read_command) { - if (CMD_ARGC < 2) { - command_print(CMD, "stm32h7x option_read "); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -1126,10 +1122,8 @@ COMMAND_HANDLER(stm32x_handle_option_read_command) COMMAND_HANDLER(stm32x_handle_option_write_command) { - if (CMD_ARGC < 3) { - command_print(CMD, "stm32h7x option_write [mask]"); + if (CMD_ARGC != 3 && CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); From ea07b3c53a5538dfd9732bb9a5a70f1b1c7c7308 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Nov 2023 10:19:43 +0100 Subject: [PATCH 0640/1312] flash/nor/stm32l4x: Remove redundant error messages The correct syntax is already suggested due to the return value used. While at it, apply some minor code improvements. Change-Id: Id32440cdd531077008abd679add32246c4249eb2 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8001 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/stm32l4x.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 96757a931d..039938512b 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -2218,10 +2218,8 @@ static int stm32l4_mass_erase(struct flash_bank *bank) COMMAND_HANDLER(stm32l4_handle_mass_erase_command) { - if (CMD_ARGC < 1) { - command_print(CMD, "stm32l4x mass_erase "); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -2239,10 +2237,8 @@ COMMAND_HANDLER(stm32l4_handle_mass_erase_command) COMMAND_HANDLER(stm32l4_handle_option_read_command) { - if (CMD_ARGC < 2) { - command_print(CMD, "stm32l4x option_read "); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -2266,10 +2262,8 @@ COMMAND_HANDLER(stm32l4_handle_option_read_command) COMMAND_HANDLER(stm32l4_handle_option_write_command) { - if (CMD_ARGC < 3) { - command_print(CMD, "stm32l4x option_write [mask]"); + if (CMD_ARGC != 3 && CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -2381,7 +2375,7 @@ COMMAND_HANDLER(stm32l4_handle_lock_command) { struct target *target = NULL; - if (CMD_ARGC < 1) + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; @@ -2416,7 +2410,7 @@ COMMAND_HANDLER(stm32l4_handle_unlock_command) { struct target *target = NULL; - if (CMD_ARGC < 1) + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; @@ -2520,7 +2514,7 @@ COMMAND_HANDLER(stm32l4_handle_wrp_info_command) COMMAND_HANDLER(stm32l4_handle_otp_command) { - if (CMD_ARGC < 2) + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; struct flash_bank *bank; From 4e5b009a723963228509ae65a60af4df4344a68f Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Nov 2023 10:24:51 +0100 Subject: [PATCH 0641/1312] flash/nor/pic32mx: Remove redundant error message The correct syntax is already suggested due to the return value used. While at it, apply some minor code improvements. Change-Id: I990c0f7a0871f4b1a0fcdd13afc190149302443c Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8003 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/pic32mx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index 9a1a634125..0f3937cfc2 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -866,10 +866,8 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) struct mips_ejtag *ejtag_info; int timeout = 10; - if (CMD_ARGC < 1) { - command_print(CMD, "pic32mx unlock "); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct flash_bank *bank; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -932,7 +930,7 @@ static const struct command_registration pic32mx_exec_command_handlers[] = { .name = "unlock", .handler = pic32mx_handle_unlock_command, .mode = COMMAND_EXEC, - .usage = "[bank_id]", + .usage = "bank_id", .help = "Unlock/Erase entire device.", }, COMMAND_REGISTRATION_DONE From 8ccd7827bed2859cd21725a2c857448ab2fcedf6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Nov 2023 10:28:31 +0100 Subject: [PATCH 0642/1312] flash/nor/stmqspi: Use correct command errors Change-Id: I796b4e350653117bf63d18ad274a1d3d3d1337db Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8004 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/stmqspi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c index c9fc1bffa3..a1e1d34116 100644 --- a/src/flash/nor/stmqspi.c +++ b/src/flash/nor/stmqspi.c @@ -646,21 +646,21 @@ COMMAND_HANDLER(stmqspi_handle_set) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], stmqspi_info->dev.size_in_bytes); if (log2u(stmqspi_info->dev.size_in_bytes) < 8) { command_print(CMD, "stmqspi: device size must be 2^n with n >= 8"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], stmqspi_info->dev.pagesize); if (stmqspi_info->dev.pagesize > stmqspi_info->dev.size_in_bytes || (log2u(stmqspi_info->dev.pagesize) < 0)) { command_print(CMD, "stmqspi: page size must be 2^n and <= device size"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], stmqspi_info->dev.read_cmd); if ((stmqspi_info->dev.read_cmd != 0x03) && (stmqspi_info->dev.read_cmd != 0x13)) { command_print(CMD, "stmqspi: only 0x03/0x13 READ cmd allowed"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], stmqspi_info->dev.qread_cmd); @@ -678,7 +678,7 @@ COMMAND_HANDLER(stmqspi_handle_set) (stmqspi_info->dev.qread_cmd != 0xEE)) { command_print(CMD, "stmqspi: only 0x0B/0x0C/0x3B/0x3C/" "0x6B/0x6C/0xBB/0xBC/0xEB/0xEC/0xEE QREAD allowed"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], stmqspi_info->dev.pprog_cmd); @@ -686,7 +686,7 @@ COMMAND_HANDLER(stmqspi_handle_set) (stmqspi_info->dev.pprog_cmd != 0x12) && (stmqspi_info->dev.pprog_cmd != 0x32)) { command_print(CMD, "stmqspi: only 0x02/0x12/0x32 PPRG cmd allowed"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } if (index < CMD_ARGC) @@ -700,7 +700,7 @@ COMMAND_HANDLER(stmqspi_handle_set) (stmqspi_info->dev.sectorsize < stmqspi_info->dev.pagesize) || (log2u(stmqspi_info->dev.sectorsize) < 0)) { command_print(CMD, "stmqspi: sector size must be 2^n and <= device size"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } if (index < CMD_ARGC) @@ -786,7 +786,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) num_write = CMD_ARGC - 2; if (num_write > max) { LOG_ERROR("at most %d bytes may be sent", max); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); @@ -811,7 +811,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) if (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) { if ((num_write & 1) == 0) { LOG_ERROR("number of data bytes to write must be even in dual mode"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } } } else { @@ -819,12 +819,12 @@ COMMAND_HANDLER(stmqspi_handle_cmd) if (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) { if ((num_read & 1) != 0) { LOG_ERROR("number of bytes to read must be even in dual mode"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } } if ((num_write < 1) || (num_write > 5)) { LOG_ERROR("one cmd and up to four addr bytes must be send when reading"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } } From acde409ba07dfd692c2356fabdabab89f6e6a281 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 27 Mar 2022 17:55:53 +0200 Subject: [PATCH 0643/1312] rtt/tcl: Fix line indentation Change-Id: I21f8084ca648cfe35f8f4dba078b2227772578a8 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7993 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtt/tcl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c index f949aa1c94..2b8822fce8 100644 --- a/src/rtt/tcl.c +++ b/src/rtt/tcl.c @@ -17,7 +17,7 @@ COMMAND_HANDLER(handle_rtt_setup_command) { -struct rtt_source source; + struct rtt_source source; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; From 53e67c37abee6506bb06eaf0d50d4d9ce045c0c8 Mon Sep 17 00:00:00 2001 From: Thiemo van Engelen Date: Fri, 23 Jun 2023 09:29:25 +0200 Subject: [PATCH 0644/1312] rtt_server: Add option for a message when client connects This is useful when using the SEGGER RTT tooling, as the SEGGER RTT tool J-Link RTT Viewer version 7.84f requires that it receives a messages immediately after connecting. Otherwise it will give a timeout and it will not connect. Change-Id: I9240a1b6a93cd5c0fbd18292afb33b89013d78bf Signed-off-by: Thiemo van Engelen Reviewed-on: https://review.openocd.org/c/openocd/+/7752 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Antonio Borneo --- doc/openocd.texi | 5 +++-- src/server/rtt_server.c | 24 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 5d73fd1744..e8b207c524 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9448,8 +9448,9 @@ Return a list of all channels and their properties as Tcl list. The list can be manipulated easily from within scripts. @end deffn -@deffn {Command} {rtt server start} port channel -Start a TCP server on @var{port} for the channel @var{channel}. +@deffn {Command} {rtt server start} port channel [message] +Start a TCP server on @var{port} for the channel @var{channel}. When +@var{message} is not empty, it will be sent to a client when it connects. @end deffn @deffn {Command} {rtt server stop} port diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c index df2247bacd..9769153475 100644 --- a/src/server/rtt_server.c +++ b/src/server/rtt_server.c @@ -25,6 +25,7 @@ struct rtt_service { unsigned int channel; + char *hello_message; }; static int read_callback(unsigned int channel, const uint8_t *buffer, @@ -65,6 +66,9 @@ static int rtt_new_connection(struct connection *connection) if (ret != ERROR_OK) return ret; + if (service->hello_message) + connection_write(connection, service->hello_message, strlen(service->hello_message)); + return ERROR_OK; } @@ -117,16 +121,30 @@ COMMAND_HANDLER(handle_rtt_start_command) int ret; struct rtt_service *service; - if (CMD_ARGC != 2) + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; - service = malloc(sizeof(struct rtt_service)); + service = calloc(1, sizeof(struct rtt_service)); if (!service) return ERROR_FAIL; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); + if (CMD_ARGC >= 3) { + const char *hello_message = CMD_ARGV[2]; + size_t hello_length = strlen(hello_message); + + service->hello_message = malloc(hello_length + 2); + if (!service->hello_message) { + LOG_ERROR("Out of memory"); + free(service); + return ERROR_FAIL; + } + strcpy(service->hello_message, hello_message); + service->hello_message[hello_length] = '\n'; + service->hello_message[hello_length + 1] = '\0'; + } ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service); if (ret != ERROR_OK) { @@ -153,7 +171,7 @@ static const struct command_registration rtt_server_subcommand_handlers[] = { .handler = handle_rtt_start_command, .mode = COMMAND_ANY, .help = "Start a RTT server", - .usage = " " + .usage = " [message]" }, { .name = "stop", From be5cfdc86bce09e688aad16134cb36561c85d5eb Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Tue, 31 Oct 2023 16:53:52 +0300 Subject: [PATCH 0645/1312] target: remove `target_number` Change-Id: Id36e5ad2967303483392fd2670630289ecde2553 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/7998 Reviewed-by: Antonio Borneo Reviewed-by: Marek Vrbka Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/target/target.c | 70 ++++++++------------------------------ src/target/target.h | 2 -- src/target/xtensa/xtensa.c | 2 +- 3 files changed, 15 insertions(+), 59 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 9f43e2f911..d8e65863c6 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -298,23 +298,6 @@ const char *target_reset_mode_name(enum target_reset_mode reset_mode) return cp; } -/* determine the number of the new target */ -static int new_target_number(void) -{ - struct target *t; - int x; - - /* number is 0 based */ - x = -1; - t = all_targets; - while (t) { - if (x < t->target_number) - x = t->target_number; - t = t->next; - } - return x + 1; -} - static void append_to_list_all_targets(struct target *target) { struct target **t = &all_targets; @@ -450,7 +433,7 @@ void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_ target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]); } -/* return a pointer to a configured target; id is name or number */ +/* return a pointer to a configured target; id is name or index in all_targets */ struct target *get_target(const char *id) { struct target *target; @@ -463,36 +446,17 @@ struct target *get_target(const char *id) return target; } - /* It's OK to remove this fallback sometime after August 2010 or so */ - - /* no match, try as number */ - unsigned num; - if (parse_uint(id, &num) != ERROR_OK) + /* try as index */ + unsigned int index, counter; + if (parse_uint(id, &index) != ERROR_OK) return NULL; - for (target = all_targets; target; target = target->next) { - if (target->target_number == (int)num) { - LOG_WARNING("use '%s' as target identifier, not '%u'", - target_name(target), num); - return target; - } - } - - return NULL; -} - -/* returns a pointer to the n-th configured target */ -struct target *get_target_by_num(int num) -{ - struct target *target = all_targets; + for (target = all_targets, counter = index; + target && counter; + target = target->next, --counter) + ; - while (target) { - if (target->target_number == num) - return target; - target = target->next; - } - - return NULL; + return target; } struct target *get_current_target(struct command_context *cmd_ctx) @@ -2843,10 +2807,10 @@ COMMAND_HANDLER(handle_targets_command) } } - struct target *target = all_targets; + unsigned int index = 0; command_print(CMD, " TargetName Type Endian TapName State "); command_print(CMD, "-- ------------------ ---------- ------ ------------------ ------------"); - while (target) { + for (struct target *target = all_targets; target; target = target->next, ++index) { const char *state; char marker = ' '; @@ -2861,7 +2825,7 @@ COMMAND_HANDLER(handle_targets_command) /* keep columns lined up to match the headers above */ command_print(CMD, "%2d%c %-18s %-10s %-6s %-18s %s", - target->target_number, + index, marker, target_name(target), target_type_name(target), @@ -2869,7 +2833,6 @@ COMMAND_HANDLER(handle_targets_command) target->endianness)->name, target->tap->dotted_name, state); - target = target->next; } return retval; @@ -5063,8 +5026,7 @@ void target_handle_event(struct target *target, enum target_event e) for (teap = target->event_action; teap; teap = teap->next) { if (teap->event == e) { - LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s", - target->target_number, + LOG_DEBUG("target: %s (%s) event: %d (%s) action: %s", target_name(target), target_type_name(target), e, @@ -5849,8 +5811,7 @@ COMMAND_HANDLER(handle_target_event_list) struct target *target = get_current_target(CMD_CTX); struct target_event_action *teap = target->event_action; - command_print(CMD, "Event actions for target (%d) %s\n", - target->target_number, + command_print(CMD, "Event actions for target %s\n", target_name(target)); command_print(CMD, "%-25s | Body", "Event"); command_print(CMD, "------------------------- | " @@ -6189,9 +6150,6 @@ static int target_create(struct jim_getopt_info *goi) /* set empty smp cluster */ target->smp_targets = &empty_smp_targets; - /* set target number */ - target->target_number = new_target_number(); - /* allocate memory for each unique target type */ target->type = malloc(sizeof(struct target_type)); if (!target->type) { diff --git a/src/target/target.h b/src/target/target.h index abeb8ed511..28a2008074 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -115,7 +115,6 @@ enum target_register_class { struct target { struct target_type *type; /* target type definition (name, access functions) */ char *cmd_name; /* tcl Name of target */ - int target_number; /* DO NOT USE! field to be removed in 2010 */ struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ @@ -412,7 +411,6 @@ int target_call_timer_callbacks_now(void); */ int64_t target_timer_next_event(void); -struct target *get_target_by_num(int num); struct target *get_current_target(struct command_context *cmd_ctx); struct target *get_current_target_or_null(struct command_context *cmd_ctx); struct target *get_target(const char *id); diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 2aacc3620a..e862fe165a 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -1096,7 +1096,7 @@ int xtensa_assert_reset(struct target *target) { struct xtensa *xtensa = target_to_xtensa(target); - LOG_TARGET_DEBUG(target, "target_number=%i, begin", target->target_number); + LOG_TARGET_DEBUG(target, " begin"); xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, PWRCTL_JTAGDEBUGUSE(xtensa) | PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) | From 1b0b07baab2b23318ddc484a58d66214f0c2a0d2 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 12 Nov 2023 11:43:48 +0100 Subject: [PATCH 0646/1312] target: Throw error in 'debug_reason' command Instead of returning an 'error string', throw an error. This makes it much easier to handle errors in Tcl scripts or in tools that use Tcl RPC. Change-Id: I75c48750cfad7430fa5e6bc88fe04ebd59d34cea Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8006 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/target/target.c b/src/target/target.c index d8e65863c6..4a4c62613f 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5845,7 +5845,17 @@ COMMAND_HANDLER(handle_target_debug_reason) struct target *target = get_current_target(CMD_CTX); - command_print(CMD, "%s", debug_reason_name(target)); + + const char *debug_reason = nvp_value2name(nvp_target_debug_reason, + target->debug_reason)->name; + + if (!debug_reason) { + command_print(CMD, "bug: invalid debug reason (%d)", + target->debug_reason); + return ERROR_FAIL; + } + + command_print(CMD, "%s", debug_reason); return ERROR_OK; } From 7ac389cf47463cc35667659804d939015a4815e5 Mon Sep 17 00:00:00 2001 From: Thomas Hebb Date: Fri, 29 Apr 2022 22:17:18 -0700 Subject: [PATCH 0647/1312] tcl/target/gd32vf103: work around broken ndmreset On this chip, the ndmreset bit in the RISC-V debug module doesn't trigger a system reset like it should. To work around this, add a custom "reset-assert" handler in its config file that resets the system by writing to memory-mapped registers. I've tested this workaround on a Sipeed Longan Nano dev board with a GD32VF103CBT6 chip. It works correctly for both "reset run" and "reset halt" (halting at pc=0 for the latter). I originally submitted[1] this workaround to the riscv-openocd fork of OpenOCD. That fork's maintainers accepted it, but have not upstreamed it like they have several other of my changes. [1] https://github.com/riscv/riscv-openocd/pull/538 Change-Id: I7482990755b300fcbe4963c9a599d599bc02684d Signed-off-by: Thomas Hebb Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/6957 Tested-by: jenkins Reviewed-by: zapb --- tcl/target/gd32vf103.cfg | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tcl/target/gd32vf103.cfg b/tcl/target/gd32vf103.cfg index 0681243343..54a74e8cc5 100644 --- a/tcl/target/gd32vf103.cfg +++ b/tcl/target/gd32vf103.cfg @@ -28,6 +28,12 @@ jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME riscv -chain-position $_TARGETNAME +proc default_mem_access {} { + riscv set_mem_access progbuf +} + +default_mem_access + $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash @@ -40,3 +46,74 @@ $_TARGETNAME configure -event reset-init { # DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP mmw 0xE0042004 0x00000300 0 } + +# On this chip, ndmreset (the debug module bit that triggers a software reset) +# doesn't work. So for JTAG connections without an SRST, we need to trigger a +# reset manually. This is an undocumented reset sequence that's used by the +# JTAG flashing script in the vendor-supplied GD32VF103 PlatformIO plugin: +# +# https://github.com/sipeed/platform-gd32v/commit/f9cbb44819bc05dd2010cc815c32be0486800cc2 +# +$_TARGETNAME configure -event reset-assert { + set dmcontrol 0x10 + set dmcontrol_dmactive [expr {1 << 0}] + set dmcontrol_ackhavereset [expr {1 << 28}] + set dmcontrol_haltreq [expr {1 << 31}] + + global _RESETMODE + + # If hardware NRST signal is connected and configured (reset_config srst_only) + # the device has been recently reset in 'jtag arp_init-reset', therefore + # DM_DMSTATUS_ANYHAVERESET reads 1. + # The following 'halt' command checks this status bit + # and shows 'Hart 0 unexpectedly reset!' if set. + # Prevent this message by sending an acknowledge first. + set val [expr {$dmcontrol_dmactive | $dmcontrol_ackhavereset}] + riscv dmi_write $dmcontrol $val + + # Halt the core so that we can write to memory. We do this first so + # that it doesn't clobber our dmcontrol configuration. + halt + + # Set haltreq appropriately for the type of reset we're doing. This + # replicates what the generic RISC-V reset_assert() function would + # do if we weren't overriding it. The $_RESETMODE hack sucks, but + # it's the least invasive way to determine whether we need to halt. + # + # If we didn't override the generic handler, we'd actually still have + # to do this: the default handler sets ndmreset, which prevents memory + # access even though it doesn't actually trigger a reset on this chip. + # So we'd need to unset it here, which involves a write to dmcontrol, + # Since haltreq is write-only and there's no way to leave it unchanged, + # we'd have to figure out its proper value anyway. + set val $dmcontrol_dmactive + if {$_RESETMODE ne "run"} { + set val [expr {$val | $dmcontrol_haltreq}] + } + riscv dmi_write $dmcontrol $val + + # Unlock 0xe0042008 so that the next write triggers a reset + mww 0xe004200c 0x4b5a6978 + + # We need to trigger the reset using abstract memory access, since + # progbuf access tries to read a status code out of a core register + # after the write happens, which fails when the core is in reset. + riscv set_mem_access abstract + + # Go! + mww 0xe0042008 0x1 + + # Put the memory access mode back to what it was. + default_mem_access +} + +# Capture the mode of a given reset so that we can use it later in the +# reset-assert handler. +proc init_reset { mode } { + global _RESETMODE + set _RESETMODE $mode + + if {[using_jtag]} { + jtag arp_init-reset + } +} From 15038ab51a3c5811f7ff95c1f995c6e9dfe7d3d0 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Fri, 17 Nov 2023 11:27:09 +0800 Subject: [PATCH 0648/1312] target/mips32: pracc write cp0 status register first When user requested a change on cp0 status register, it may contain changes on EXL/ERL bits, and changes on these bits could lead to differnt behaviours on writing to other cp0 registers. Change-Id: Ic83039988c29c06ee134226b52de943c46d19da2 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7914 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/mips32_pracc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 9f0d87cd98..db50ef9285 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -842,12 +842,12 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) }; uint32_t cp0_write_data[] = { + /* status */ + c0rs[0], /* lo */ gprs[32], /* hi */ gprs[33], - /* status */ - c0rs[0], /* badvaddr */ c0rs[1], /* cause */ @@ -856,6 +856,9 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) c0rs[3], }; + /* Write CP0 Status Register first, changes on EXL or ERL bits + * may lead to different behaviour on writing to other CP0 registers. + */ for (size_t i = 0; i < ARRAY_SIZE(cp0_write_code); i++) { /* load CP0 value in $1 */ pracc_add_li32(&ctx, 1, cp0_write_data[i], 0); From 73d62f3f0cd4cb3fb6975d4223bf44b35a0e1479 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Tue, 31 Oct 2023 21:13:46 +0300 Subject: [PATCH 0649/1312] target: clarify usage of `coreid` By definition in `target/target.h`, `coreid` is not a unique identifier of a target -- it can be the same for targets on different TAPs. Change-Id: Ifce78da55fffe28dd8b6b06ecae7d8c4e305c0a2 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/7997 Tested-by: jenkins Reviewed-by: Marek Vrbka Reviewed-by: Antonio Borneo --- src/target/armv8_cache.c | 2 +- src/target/cortex_a.c | 19 ++++++++----------- src/target/espressif/esp_xtensa_smp.c | 2 +- src/target/mips_m4k.c | 6 +++--- src/target/smp.c | 3 +++ src/target/xtensa/xtensa.c | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index 98f4b3f04c..66d4e00801 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -243,7 +243,7 @@ static int armv8_flush_all_data(struct target *target) foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; if (curr->state == TARGET_HALTED) { - LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); + LOG_TARGET_INFO(curr, "Wait flushing data l1."); retval = _armv8_flush_all_data(curr); } } diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index ba3349d09a..7fa0c4e8b7 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2989,29 +2989,29 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); if (retval != ERROR_OK) return retval; - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + LOG_TARGET_DEBUG(target, "DBGPRSR 0x%" PRIx32, dbg_osreg); if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) { - LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid); + LOG_TARGET_ERROR(target, "powered down!"); target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ return ERROR_TARGET_INIT_FAILED; } if (dbg_osreg & PRSR_STICKY_RESET_STATUS) - LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid); + LOG_TARGET_DEBUG(target, "was reset!"); /* Read DBGOSLSR and check if OSLK is implemented */ retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); if (retval != ERROR_OK) return retval; - LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg); + LOG_TARGET_DEBUG(target, "DBGOSLSR 0x%" PRIx32, dbg_osreg); /* check if OS Lock is implemented */ if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) { /* check if OS Lock is set */ if (dbg_osreg & OSLSR_OSLK) { - LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid); + LOG_TARGET_DEBUG(target, "OSLock set! Trying to unlock"); retval = mem_ap_write_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_OSLAR, @@ -3022,8 +3022,7 @@ static int cortex_a_examine_first(struct target *target) /* if we fail to access the register or cannot reset the OSLK bit, bail out */ if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) { - LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?", - target->coreid); + LOG_TARGET_ERROR(target, "OSLock sticky, core not powered?"); target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ return ERROR_TARGET_INIT_FAILED; } @@ -3036,13 +3035,11 @@ static int cortex_a_examine_first(struct target *target) return retval; if (dbg_idpfr1 & 0x000000f0) { - LOG_DEBUG("target->coreid %" PRId32 " has security extensions", - target->coreid); + LOG_TARGET_DEBUG(target, "has security extensions"); armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT; } if (dbg_idpfr1 & 0x0000f000) { - LOG_DEBUG("target->coreid %" PRId32 " has virtualization extensions", - target->coreid); + LOG_TARGET_DEBUG(target, "has virtualization extensions"); /* * overwrite and simplify the checks. * virtualization extensions require implementation of security extension diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c index 1d70be9e3c..bc4d8a21ad 100644 --- a/src/target/espressif/esp_xtensa_smp.c +++ b/src/target/espressif/esp_xtensa_smp.c @@ -746,7 +746,7 @@ COMMAND_HANDLER(esp_xtensa_smp_cmd_perfmon_dump) struct target *curr; foreach_smp_target(head, target->smp_targets) { curr = head->target; - LOG_INFO("CPU%d:", curr->coreid); + LOG_TARGET_INFO(curr, ":"); int ret = CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do, target_to_xtensa(curr)); if (ret != ERROR_OK) diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 0a06bb1604..ad98089614 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -142,7 +142,7 @@ static int mips_m4k_halt_smp(struct target *target) ret = mips_m4k_halt(curr); if (ret != ERROR_OK) { - LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid); + LOG_TARGET_ERROR(curr, "halt failed."); retval = ret; } } @@ -412,8 +412,8 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han handle_breakpoints, 0); if (ret != ERROR_OK) { - LOG_ERROR("target->coreid :%" PRId32 " failed to resume at address :0x%" PRIx32, - curr->coreid, address); + LOG_TARGET_ERROR(curr, "failed to resume at address: 0x%" PRIx32, + address); retval = ret; } } diff --git a/src/target/smp.c b/src/target/smp.c index effc63f521..50b19d01a0 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -132,6 +132,9 @@ COMMAND_HANDLER(handle_smp_gdb_command) { struct target *target = get_current_target(CMD_CTX); int retval = ERROR_OK; + + LOG_WARNING(DEPRECATED_MSG); + if (!list_empty(target->smp_targets)) { if (CMD_ARGC == 1) { int coreid = 0; diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index e862fe165a..85dce0614c 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -822,7 +822,7 @@ int xtensa_examine(struct target *target) struct xtensa *xtensa = target_to_xtensa(target); unsigned int cmd = PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) | PWRCTL_COREWAKEUP(xtensa); - LOG_DEBUG("coreid = %d", target->coreid); + LOG_TARGET_DEBUG(target, ""); if (xtensa->core_config->core_type == XT_UNDEF) { LOG_ERROR("XTensa core not configured; is xtensa-core-openocd.cfg missing?"); From 119a5338623d77bbdbc37b6ecb5e93df3368af30 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 20 Nov 2023 11:33:00 +0100 Subject: [PATCH 0650/1312] target/target: Fix 'wp' command usage While at it, fix the 'wp' command documentation. Change-Id: I70f3110e8ce286051f8f810260f1857b2285e634 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8022 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Jan Matyas --- doc/openocd.texi | 2 +- src/target/target.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index e8b207c524..c14ee9cb6a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9374,7 +9374,7 @@ Remove the breakpoint at @var{address} or all breakpoints. Remove data watchpoint on @var{address} or all watchpoints. @end deffn -@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]] +@deffn {Command} {wp} [address length [(@option{r}|@option{w}|@option{a}) [value [mask]]]] With no parameters, lists all active watchpoints. Else sets a data watchpoint on data from @var{address} for @var{length} bytes. The watch point is an "access" watchpoint unless diff --git a/src/target/target.c b/src/target/target.c index 4a4c62613f..f847894d69 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -7064,7 +7064,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_wp_command, .mode = COMMAND_EXEC, .help = "list (no params) or create watchpoints", - .usage = "[address length [('r'|'w'|'a') value [mask]]]", + .usage = "[address length [('r'|'w'|'a') [value [mask]]]]", }, { .name = "rwp", From 0f70c6c325785517f35bbbb9316801bef7a79d8b Mon Sep 17 00:00:00 2001 From: Manuel Wick Date: Sat, 30 Jan 2021 22:46:50 +0100 Subject: [PATCH 0651/1312] remote_bitbang: Add SWD support This adds new command characters to make SWD work with the new split jtag and swd operations of bitbang. The command characters are as follows: O - SWDIO drive 1 o - SWDIO drive 0 c - SWDIO read request d - SWD write 0 0 e - SWD write 0 1 f - SWD write 1 0 g - SWD write 1 1 Documentation has been updated accordingly. The new commands will be used by an adapted version of the jtag-openocd applet of the "Glasgow Debug Tool" (https://github.com/glasgowEmbedded/Glasgow). It has been tested against an stm32f103 and an at91samd21 target. contrib/remote/bitbang/remote_bitbang_sysfsgpio.c has also been adapted to support SWD via the new command set. Some limited testing has been done using a Raspberry Pi 2 with an stm32f103 and an at91samd21 target attached. Change-Id: I8e998a2cb36905142cb16e534483094cd99e8fa7 Signed-off-by: Manuel Wick Signed-off-by: David Ryskalczyk Reviewed-on: https://review.openocd.org/c/openocd/+/6044 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- configure.ac | 6 +- .../remote_bitbang/remote_bitbang_sysfsgpio.c | 211 ++++++++++++++---- doc/manual/jtag/drivers/remote_bitbang.txt | 36 ++- doc/openocd.texi | 6 +- src/jtag/drivers/remote_bitbang.c | 31 ++- 5 files changed, 230 insertions(+), 60 deletions(-) diff --git a/configure.ac b/configure.ac index a2442d40b5..c9cf0214e3 100644 --- a/configure.ac +++ b/configure.ac @@ -382,7 +382,7 @@ AC_ARG_ENABLE([internal-libjaylink], [use_internal_libjaylink=$enableval], [use_internal_libjaylink=no]) AC_ARG_ENABLE([remote-bitbang], - AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]), + AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang driver]), [build_remote_bitbang=$enableval], [build_remote_bitbang=no]) AS_CASE(["${host_cpu}"], @@ -598,9 +598,9 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ AS_IF([test "x$build_remote_bitbang" = "xyes"], [ build_bitbang=yes - AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang JTAG driver.]) + AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang driver.]) ], [ - AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang JTAG driver.]) + AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang driver.]) ]) AS_IF([test "x$build_sysfsgpio" = "xyes"], [ diff --git a/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c b/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c index 9294837e3c..1588eb9a3c 100644 --- a/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c +++ b/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c @@ -1,30 +1,31 @@ // SPDX-License-Identifier: GPL-2.0-or-later /*************************************************************************** + * Copyright (C) 2021 by Manuel Wick * * Copyright (C) 2013 Paul Fertser * * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au * ***************************************************************************/ /* - This is a test application to be used as a remote bitbang server for - the OpenOCD remote_bitbang interface driver. - - To compile run: - gcc -Wall -ansi -pedantic -std=c99 -o remote_bitbang_sysfsgpio remote_bitbang_sysfsgpio.c - - - Usage example: - - On Raspberry Pi run: - socat TCP6-LISTEN:7777,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" - - On host run: - openocd -c "interface remote_bitbang; remote_bitbang host raspberrypi; remote_bitbang port 7777" \ - -f target/stm32f1x.cfg - - Or if you want to test UNIX sockets, run both on Raspberry Pi: - socat UNIX-LISTEN:/tmp/remotebitbang-socket,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" - openocd -c "interface remote_bitbang; remote_bitbang host /tmp/remotebitbang-socket" -f target/stm32f1x.cfg + * This is a test application to be used as a remote bitbang server for + * the OpenOCD remote_bitbang interface driver. + * + * To compile run: + * gcc -Wall -ansi -pedantic -std=c99 -o remote_bitbang_sysfsgpio remote_bitbang_sysfsgpio.c + * + * + * Usage example: + * + * On Raspberry Pi run: + * socat TCP6-LISTEN:7777,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" + * + * On host run: + * openocd -c "adapter driver remote_bitbang; remote_bitbang host raspberrypi; remote_bitbang port 7777" \ + * -f target/stm32f1x.cfg + * + * Or if you want to test UNIX sockets, run both on Raspberry Pi: + * socat UNIX-LISTEN:/tmp/remotebitbang-socket,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" + * openocd -c "adapter driver remote_bitbang; remote_bitbang host /tmp/remotebitbang-socket" -f target/stm32f1x.cfg */ #include @@ -97,11 +98,14 @@ static void unexport_sysfs_gpio(int gpio) * If the gpio is an output, it is initialized according to init_high, * otherwise it is ignored. * + * When open_rw is set, the file descriptor will be open as read and write, + * e.g. for SWDIO (TMS) that is used as input and output. + * * If the gpio is already exported we just show a warning and continue; if * openocd happened to crash (or was killed by user) then the gpios will not * have been cleaned up. */ -static int setup_sysfs_gpio(int gpio, int is_output, int init_high) +static int setup_sysfs_gpio(int gpio, int is_output, int init_high, int open_rw) { char buf[40]; char gpiostr[4]; @@ -132,7 +136,9 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high) } snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio); - if (is_output) + if (open_rw) + ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC); + else if (is_output) ret = open(buf, O_WRONLY | O_NONBLOCK | O_SYNC); else ret = open(buf, O_RDONLY | O_NONBLOCK | O_SYNC); @@ -143,6 +149,37 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high) return ret; } +/* + * Change direction for gpio. + */ +static int change_dir_sysfs_gpio(int gpio, int is_output, int init_high) +{ + char buf[40]; + int ret; + + if (!is_gpio_valid(gpio)) + return ERROR_OK; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio); + ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in"); + if (ret < 0) { + LOG_ERROR("Couldn't set direction for gpio %d", gpio); + perror("sysfsgpio: "); + unexport_sysfs_gpio(gpio); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +/* gpio numbers for each gpio. Negative values are invalid */ +static int tck_gpio = -1; +static int tms_gpio = -1; +static int tdi_gpio = -1; +static int tdo_gpio = -1; +static int trst_gpio = -1; +static int srst_gpio = -1; + /* * file descriptors for /sys/class/gpio/gpioXX/value * Set up during init. @@ -154,6 +191,15 @@ static int tdo_fd = -1; static int trst_fd = -1; static int srst_fd = -1; +/* + * GPIO state of /sys/class/gpio/gpioXX/value + */ +static int last_tck = -1; +static int last_tms = -1; +static int last_tms_drive = -1; +static int last_tdi = -1; +static int last_initialized = -1; + /* * Bitbang interface read of TDO * @@ -179,26 +225,22 @@ static int sysfsgpio_read(void) /* * Bitbang interface write of TCK, TMS, TDI * - * Seeing as this is the only function where the outputs are changed, - * we can cache the old value to avoid needlessly writing it. + * Output states are changed here and in sysfsgpio_write_swd, + * which are not used simultaneously, so we can cache the old + * value to avoid needlessly writing it. */ static void sysfsgpio_write(int tck, int tms, int tdi) { const char one[] = "1"; const char zero[] = "0"; - static int last_tck; - static int last_tms; - static int last_tdi; - - static int first_time; size_t bytes_written; - if (!first_time) { + if (!last_initialized) { last_tck = !tck; last_tms = !tms; last_tdi = !tdi; - first_time = 1; + last_initialized = 1; } if (tdi != last_tdi) { @@ -251,13 +293,81 @@ static void sysfsgpio_reset(int trst, int srst) } } -/* gpio numbers for each gpio. Negative values are invalid */ -static int tck_gpio = -1; -static int tms_gpio = -1; -static int tdi_gpio = -1; -static int tdo_gpio = -1; -static int trst_gpio = -1; -static int srst_gpio = -1; +/* + * Bitbang interface set direction of SWDIO (TMS) + */ +static void sysfsgpio_swdio_drive(int is_output) +{ + int ret; + + if (is_output != 0 && last_tms == -1) + last_tms = 0; + + ret = change_dir_sysfs_gpio(tms_gpio, (is_output != 0) ? 1 : 0, last_tms); + if (ret != ERROR_OK) + LOG_WARNING("Failed to change SWDIO (TMS) direction to output"); + else + last_tms_drive = (is_output != 0) ? 1 : 0; +} + +/* + * Bitbang interface read of SWDIO (TMS) + * + * The sysfs value will read back either '0' or '1'. The trick here is to call + * lseek to bypass buffering in the sysfs kernel driver. + */ +static int sysfsgpio_swdio_read(void) +{ + char buf[1]; + + /* important to seek to signal sysfs of new read */ + lseek(tms_fd, 0, SEEK_SET); + int ret = read(tms_fd, &buf, sizeof(buf)); + + if (ret < 0) { + LOG_WARNING("reading swdio (tms) failed"); + return 0; + } + + return buf[0]; +} + +/* + * Bitbang interface write of SWCLK (TCK) and SWDIO (TMS) + * + * Output states are changed here and in sysfsgpio_write, which + * are not used simultaneously, so we can cache the old value + * to avoid needlessly writing it. + */ +static void sysfsgpio_swd_write(int swclk, int swdio) +{ + static const char one[] = "1"; + static const char zero[] = "0"; + + size_t bytes_written; + + if (!last_initialized) { + last_tck = !swclk; + last_tms = !swdio; + last_initialized = 1; + } + + if (last_tms_drive == 1 && swdio != last_tms) { + bytes_written = write(tms_fd, swdio ? &one : &zero, 1); + if (bytes_written != 1) + LOG_WARNING("writing swdio (tms) failed"); + } + + /* write clk last */ + if (swclk != last_tck) { + bytes_written = write(tck_fd, swclk ? &one : &zero, 1); + if (bytes_written != 1) + LOG_WARNING("writing swclk (tck) failed"); + } + + last_tms = swdio; + last_tck = swclk; +} /* helper func to close and cleanup files only if they were valid/ used */ static void cleanup_fd(int fd, int gpio) @@ -293,13 +403,21 @@ static void process_remote_protocol(void) char d = c - 'r'; sysfsgpio_reset(!!(d & 2), (d & 1)); - } else if (c >= '0' && c <= '0' + 7) {/* Write */ + } else if (c >= '0' && c <= '0' + 7) { /* Write */ char d = c - '0'; sysfsgpio_write(!!(d & 4), !!(d & 2), (d & 1)); } else if (c == 'R') putchar(sysfsgpio_read()); + else if (c == 'c') /* SWDIO read */ + putchar(sysfsgpio_swdio_read()); + else if (c == 'o' || c == 'O') /* SWDIO drive */ + sysfsgpio_swdio_drive(c == 'o' ? 0 : 1); + else if (c >= 'd' && c <= 'g') { /* SWD write */ + char d = c - 'd'; + sysfsgpio_swd_write((d & 2), (d & 1)); + } else LOG_ERROR("Unknown command '%c' received", c); } @@ -307,7 +425,7 @@ static void process_remote_protocol(void) int main(int argc, char *argv[]) { - LOG_WARNING("SysfsGPIO remote_bitbang JTAG driver\n"); + LOG_WARNING("SysfsGPIO remote_bitbang JTAG+SWD driver\n"); for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "tck")) @@ -349,36 +467,39 @@ int main(int argc, char *argv[]) * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. */ - tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0); + tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0, 0); if (tck_fd < 0) goto out_error; - tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1); + tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1, 1); if (tms_fd < 0) goto out_error; + last_tms_drive = 0; - tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0); + tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0, 0); if (tdi_fd < 0) goto out_error; - tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0); + tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0, 0); if (tdo_fd < 0) goto out_error; /* assume active low */ if (trst_gpio > 0) { - trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1); + trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1, 0); if (trst_fd < 0) goto out_error; } /* assume active low */ if (srst_gpio > 0) { - srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1); + srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1, 0); if (srst_fd < 0) goto out_error; } + last_initialized = 0; + LOG_WARNING("SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d", tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); LOG_WARNING("SysfsGPIO num: srst = %d", srst_gpio); diff --git a/doc/manual/jtag/drivers/remote_bitbang.txt b/doc/manual/jtag/drivers/remote_bitbang.txt index f394d736af..7c8eee289e 100644 --- a/doc/manual/jtag/drivers/remote_bitbang.txt +++ b/doc/manual/jtag/drivers/remote_bitbang.txt @@ -1,15 +1,19 @@ /** @remote_bitbangpage OpenOCD Developer's Guide -The remote_bitbang JTAG driver is used to drive JTAG from a remote process. The -remote_bitbang driver communicates via TCP or UNIX sockets with some remote -process using an ASCII encoding of the bitbang interface. The remote process -presumably then drives the JTAG however it pleases. The remote process should -act as a server, listening for connections from the openocd remote_bitbang -driver. +The remote_bitbang JTAG+SWD driver is used to drive JTAG and/or SWD from a +remote process. The remote_bitbang driver communicates via TCP or UNIX +sockets with some remote process using an ASCII encoding of the bitbang +interface. The remote process presumably then drives the JTAG/SWD however +it pleases. The remote process should act as a server, listening for +connections from the openocd remote_bitbang driver. The remote bitbang driver is useful for debugging software running on processors which are being simulated. +There also is an implementation of the server-side protocol for the +Glasgow Debug Tool (https://github.com/glasgowEmbedded/Glasgow) through +the jtag-openocd applet. + The bitbang interface consists of the following functions. blink on @@ -24,11 +28,20 @@ write tck tms tdi reset trst srst Set the value of trst, srst. +swdio_drive + Set the output enable of the bidirectional swdio (tms) pin + +swdio_read + Sample the value of swdio (tms). + +swd_write + Set the value of swclk (tck) and swdio (tms). + An additional function, quit, is added to the remote_bitbang interface to indicate there will be no more requests and the connection with the remote driver should be closed. -These five functions are encoded in ASCII by assigning a single character to +These eight functions are encoded in ASCII by assigning a single character to each possible request. The assignments are: B - Blink on @@ -47,7 +60,14 @@ each possible request. The assignments are: s - Reset 0 1 t - Reset 1 0 u - Reset 1 1 + O - SWDIO drive 1 + o - SWDIO drive 0 + c - SWDIO read request + d - SWD write 0 0 + e - SWD write 0 1 + f - SWD write 1 0 + g - SWD write 1 1 -The read response is encoded in ASCII as either digit 0 or 1. +The read responses are encoded in ASCII as either digit 0 or 1. */ diff --git a/doc/openocd.texi b/doc/openocd.texi index c14ee9cb6a..de990c5381 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2810,9 +2810,9 @@ If not specified, default 0xFFFF is used. @end deffn @deffn {Interface Driver} {remote_bitbang} -Drive JTAG from a remote process. This sets up a UNIX or TCP socket connection -with a remote process and sends ASCII encoded bitbang requests to that process -instead of directly driving JTAG. +Drive JTAG and SWD from a remote process. This sets up a UNIX or TCP socket +connection with a remote process and sends ASCII encoded bitbang requests to +that process instead of directly driving JTAG and SWD. The remote_bitbang driver is useful for debugging software running on processors which are being simulated. diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 36bcbe19ca..261c30df2d 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -3,6 +3,8 @@ /*************************************************************************** * Copyright (C) 2011 by Richard Uhler * * ruhler@mit.edu * + * * + * Copyright (C) 2021 by Manuel Wick * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -220,11 +222,35 @@ static int remote_bitbang_blink(int on) return remote_bitbang_queue(c, FLUSH_SEND_BUF); } +static void remote_bitbang_swdio_drive(bool is_output) +{ + char c = is_output ? 'O' : 'o'; + if (remote_bitbang_queue(c, FLUSH_SEND_BUF) == ERROR_FAIL) + LOG_ERROR("Error setting direction for swdio"); +} + +static int remote_bitbang_swdio_read(void) +{ + if (remote_bitbang_queue('c', FLUSH_SEND_BUF) != ERROR_FAIL) + return remote_bitbang_read_sample(); + else + return BB_ERROR; +} + +static int remote_bitbang_swd_write(int swclk, int swdio) +{ + char c = 'd' + ((swclk ? 0x2 : 0x0) | (swdio ? 0x1 : 0x0)); + return remote_bitbang_queue(c, NO_FLUSH); +} + static struct bitbang_interface remote_bitbang_bitbang = { .buf_size = sizeof(remote_bitbang_recv_buf) - 1, .sample = &remote_bitbang_sample, .read_sample = &remote_bitbang_read_sample, .write = &remote_bitbang_write, + .swdio_read = &remote_bitbang_swdio_read, + .swdio_drive = &remote_bitbang_swdio_drive, + .swd_write = &remote_bitbang_swd_write, .blink = &remote_bitbang_blink, }; @@ -349,6 +375,8 @@ COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command) return ERROR_COMMAND_SYNTAX_ERROR; } +static const char * const remote_bitbang_transports[] = { "jtag", "swd", NULL }; + static const struct command_registration remote_bitbang_subcommand_handlers[] = { { .name = "port", @@ -401,7 +429,7 @@ static struct jtag_interface remote_bitbang_interface = { struct adapter_driver remote_bitbang_adapter_driver = { .name = "remote_bitbang", - .transports = jtag_only, + .transports = remote_bitbang_transports, .commands = remote_bitbang_command_handlers, .init = &remote_bitbang_init, @@ -409,4 +437,5 @@ struct adapter_driver remote_bitbang_adapter_driver = { .reset = &remote_bitbang_reset, .jtag_ops = &remote_bitbang_interface, + .swd_ops = &bitbang_swd, }; From fd75e9e542700e40f11d79532d19e311cf437de1 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 19 Nov 2022 07:26:37 +0100 Subject: [PATCH 0652/1312] jtag/drivers/cmsis_dap_bulk: use asynchronous libusb transfer The synchronous libusb_bulk_transfer() always waits for the transfer to complete. Therefore it does not allow issuing multiple USB requests as used on HID backend. Switch to asynchrounous libusb_submit_transfer(). With this patch a good USB FS based CMSIS-DAPv2 adapter almost doubles the throughput: adapter speed: 20000 kHz poll off > load_image /run/user/1000/ram256k.bin 0x20000000 262144 bytes written at address 0x20000000 downloaded 262144 bytes in 0.428576s (597.327 KiB/s) > dump_image /dev/null 0x20000000 0x40000 dumped 262144 bytes in 0.572875s (446.869 KiB/s) Signed-off-by: Tomas Vanek Change-Id: Ic6168ea4eca4f6bd1d8ad541a07a8d70427cc509 Reviewed-on: https://review.openocd.org/c/openocd/+/7365 Reviewed-by: zapb Tested-by: jenkins --- src/jtag/drivers/cmsis_dap.c | 114 ++++++++---- src/jtag/drivers/cmsis_dap.h | 4 +- src/jtag/drivers/cmsis_dap_usb_bulk.c | 239 +++++++++++++++++++++++--- src/jtag/drivers/cmsis_dap_usb_hid.c | 25 ++- 4 files changed, 319 insertions(+), 63 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 03832431dd..bc86eb46af 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -225,6 +225,12 @@ struct pending_scan_result { unsigned int buffer_offset; }; +/* Read mode */ +enum cmsis_dap_blocking { + CMSIS_DAP_NON_BLOCKING, + CMSIS_DAP_BLOCKING +}; + /* Each block in FIFO can contain up to pending_queue_len transfers */ static unsigned int pending_queue_len; static unsigned int tfer_max_command_size; @@ -315,7 +321,7 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap) * USB close/open so we need to flush up to 64 old packets * to be sure all buffers are empty */ for (i = 0; i < 64; i++) { - int retval = dap->backend->read(dap, 10); + int retval = dap->backend->read(dap, 10, NULL); if (retval == ERROR_TIMEOUT_REACHED) break; } @@ -326,10 +332,13 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap) /* Send a message and receive the reply */ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) { + if (dap->write_count + dap->read_count) { + LOG_ERROR("internal: queue not empty before xfer"); + } if (dap->pending_fifo_block_count) { LOG_ERROR("pending %u blocks, flushing", dap->pending_fifo_block_count); while (dap->pending_fifo_block_count) { - dap->backend->read(dap, 10); + dap->backend->read(dap, 10, NULL); dap->pending_fifo_block_count--; } dap->pending_fifo_put_idx = 0; @@ -342,7 +351,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) return retval; /* get reply */ - retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS); + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, NULL); if (retval < 0) return retval; @@ -750,6 +759,16 @@ static int cmsis_dap_cmd_dap_swo_data( } +static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap) +{ + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) + dap->pending_fifo[i].transfer_count = 0; + + dap->pending_fifo_put_idx = 0; + dap->pending_fifo_get_idx = 0; + dap->pending_fifo_block_count = 0; +} + static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) { uint8_t *command = dap->command; @@ -770,8 +789,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) goto skip; } - if (block->transfer_count == 0) + if (block->transfer_count == 0) { + LOG_ERROR("internal: write an empty queue?!"); goto skip; + } bool block_cmd = !cmsis_dap_handle->swd_cmds_differ && block->transfer_count >= CMD_DAP_TFER_BLOCK_MIN_OPS; @@ -831,14 +852,12 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) if (retval < 0) { queued_retval = retval; goto skip; - } else { - queued_retval = ERROR_OK; } dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % dap->packet_count; dap->pending_fifo_block_count++; if (dap->pending_fifo_block_count > dap->packet_count) - LOG_ERROR("too much pending writes %u", dap->pending_fifo_block_count); + LOG_ERROR("internal: too much pending writes %u", dap->pending_fifo_block_count); return; @@ -846,21 +865,47 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) block->transfer_count = 0; } -static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) +static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blocking blocking) { + int retval; struct pending_request_block *block = &dap->pending_fifo[dap->pending_fifo_get_idx]; - if (dap->pending_fifo_block_count == 0) - LOG_ERROR("no pending write"); + if (dap->pending_fifo_block_count == 0) { + LOG_ERROR("internal: no pending write when reading?!"); + return; + } + + if (queued_retval != ERROR_OK) { + /* keep reading blocks until the pipeline is empty */ + retval = dap->backend->read(dap, 10, NULL); + if (retval == ERROR_TIMEOUT_REACHED || retval == 0) { + /* timeout means that we flushed the pipeline, + * we can safely discard remaining pending requests */ + cmsis_dap_swd_discard_all_pending(dap); + return; + } + goto skip; + } /* get reply */ - int retval = dap->backend->read(dap, timeout_ms); - if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < LIBUSB_TIMEOUT_MS) + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 0 + }; + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking ? NULL : &tv); + bool timeout = (retval == ERROR_TIMEOUT_REACHED || retval == 0); + if (timeout && blocking == CMSIS_DAP_NON_BLOCKING) return; if (retval <= 0) { - LOG_DEBUG("error reading data"); + LOG_DEBUG("error reading adapter response"); queued_retval = ERROR_FAIL; + if (timeout) { + /* timeout means that we flushed the pipeline, + * we can safely discard remaining pending requests */ + cmsis_dap_swd_discard_all_pending(dap); + return; + } goto skip; } @@ -899,8 +944,9 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d", block->transfer_count, transfer_count); - LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u timeout %i", - transfer_count, dap->pending_fifo_get_idx, timeout_ms); + LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u, %s mode", + transfer_count, dap->pending_fifo_get_idx, + blocking ? "blocking" : "nonblocking"); for (unsigned int i = 0; i < transfer_count; i++) { struct pending_transfer_result *transfer = &(block->transfers[i]); @@ -932,13 +978,15 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) static int cmsis_dap_swd_run_queue(void) { - if (cmsis_dap_handle->pending_fifo_block_count) - cmsis_dap_swd_read_process(cmsis_dap_handle, 0); + if (cmsis_dap_handle->write_count + cmsis_dap_handle->read_count) { + if (cmsis_dap_handle->pending_fifo_block_count) + cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_NON_BLOCKING); - cmsis_dap_swd_write_from_queue(cmsis_dap_handle); + cmsis_dap_swd_write_from_queue(cmsis_dap_handle); + } while (cmsis_dap_handle->pending_fifo_block_count) - cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS); + cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING); cmsis_dap_handle->pending_fifo_put_idx = 0; cmsis_dap_handle->pending_fifo_get_idx = 0; @@ -979,10 +1027,16 @@ static unsigned int cmsis_dap_tfer_resp_size(unsigned int write_count, static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) { + /* TARGETSEL register write cannot be queued */ + if (swd_cmd(false, false, DP_TARGETSEL) == cmd) { + queued_retval = cmsis_dap_swd_run_queue(); + + cmsis_dap_metacmd_targetsel(data); + return; + } + /* Compute sizes of the DAP Transfer command and the expected response * for all queued and this operation */ - bool targetsel_cmd = swd_cmd(false, false, DP_TARGETSEL) == cmd; - unsigned int write_count = cmsis_dap_handle->write_count; unsigned int read_count = cmsis_dap_handle->read_count; bool block_cmd; @@ -1003,20 +1057,18 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) block_cmd); unsigned int max_transfer_count = block_cmd ? 65535 : 255; - /* Does the DAP Transfer command and the expected response fit into one packet? - * Run the queue also before a targetsel - it cannot be queued */ + /* Does the DAP Transfer command and also its expected response fit into one packet? */ if (cmd_size > tfer_max_command_size || resp_size > tfer_max_response_size - || targetsel_cmd || write_count + read_count > max_transfer_count) { if (cmsis_dap_handle->pending_fifo_block_count) - cmsis_dap_swd_read_process(cmsis_dap_handle, 0); + cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_NON_BLOCKING); /* Not enough room in the queue. Run the queue. */ cmsis_dap_swd_write_from_queue(cmsis_dap_handle); if (cmsis_dap_handle->pending_fifo_block_count >= cmsis_dap_handle->packet_count) - cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS); + cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING); } assert(cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx].transfer_count < pending_queue_len); @@ -1024,11 +1076,6 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) if (queued_retval != ERROR_OK) return; - if (targetsel_cmd) { - cmsis_dap_metacmd_targetsel(data); - return; - } - struct pending_request_block *block = &cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx]; struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]); transfer->data = data; @@ -1160,6 +1207,9 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) unsigned int s_len; int retval; + if (swd_mode) + queued_retval = cmsis_dap_swd_run_queue(); + if (seq != LINE_RESET && (output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST)) == (SWJ_PIN_SRST | SWJ_PIN_TRST)) { @@ -1296,7 +1346,7 @@ static int cmsis_dap_init(void) if (data[0] == 2) { /* short */ uint16_t pkt_sz = data[1] + (data[2] << 8); if (pkt_sz != cmsis_dap_handle->packet_size) { - free(cmsis_dap_handle->packet_buffer); + cmsis_dap_handle->backend->packet_buffer_free(cmsis_dap_handle); retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz); if (retval != ERROR_OK) goto init_err; diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index a8554de802..187aeb54d8 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -61,9 +61,11 @@ struct cmsis_dap_backend { const char *name; int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial); void (*close)(struct cmsis_dap *dap); - int (*read)(struct cmsis_dap *dap, int timeout_ms); + int (*read)(struct cmsis_dap *dap, int transfer_timeout_ms, + struct timeval *wait_timeout); int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz); + void (*packet_buffer_free)(struct cmsis_dap *dap); }; extern const struct cmsis_dap_backend cmsis_dap_hid_backend; diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 6599c414ce..aaab5804d1 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -28,8 +28,29 @@ #include #include #include +#include /* ERROR_JTAG_DEVICE_ERROR only */ #include "cmsis_dap.h" +#include "libusb_helper.h" + +#if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000105) \ + || defined(_WIN32) || defined(__CYGWIN__) + #define libusb_dev_mem_alloc(dev, sz) malloc(sz) + #define libusb_dev_mem_free(dev, buffer, sz) free(buffer) +#endif + +enum { + CMSIS_DAP_TRANSFER_PENDING = 0, /* must be 0, used in libusb_handle_events_completed */ + CMSIS_DAP_TRANSFER_IDLE, + CMSIS_DAP_TRANSFER_COMPLETED +}; + +struct cmsis_dap_bulk_transfer { + struct libusb_transfer *transfer; + uint8_t *buffer; + int status; /* either CMSIS_DAP_TRANSFER_ enum or error code */ + int transferred; +}; struct cmsis_dap_backend_data { struct libusb_context *usb_ctx; @@ -37,12 +58,16 @@ struct cmsis_dap_backend_data { unsigned int ep_out; unsigned int ep_in; int interface; + + struct cmsis_dap_bulk_transfer command_transfers[MAX_PENDING_REQUESTS]; + struct cmsis_dap_bulk_transfer response_transfers[MAX_PENDING_REQUESTS]; }; static int cmsis_dap_usb_interface = -1; static void cmsis_dap_usb_close(struct cmsis_dap *dap); static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz); +static void cmsis_dap_usb_free(struct cmsis_dap *dap); static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial) { @@ -358,6 +383,24 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p dap->bdata->ep_in = ep_in; dap->bdata->interface = interface_num; + for (unsigned int idx = 0; idx < MAX_PENDING_REQUESTS; idx++) { + dap->bdata->command_transfers[idx].status = CMSIS_DAP_TRANSFER_IDLE; + dap->bdata->command_transfers[idx].transfer = libusb_alloc_transfer(0); + if (!dap->bdata->command_transfers[idx].transfer) { + LOG_ERROR("unable to allocate USB transfer"); + cmsis_dap_usb_close(dap); + return ERROR_FAIL; + } + + dap->bdata->response_transfers[idx].status = CMSIS_DAP_TRANSFER_IDLE; + dap->bdata->response_transfers[idx].transfer = libusb_alloc_transfer(0); + if (!dap->bdata->response_transfers[idx].transfer) { + LOG_ERROR("unable to allocate USB transfer"); + cmsis_dap_usb_close(dap); + return ERROR_FAIL; + } + } + err = cmsis_dap_usb_alloc(dap, packet_size); if (err != ERROR_OK) cmsis_dap_usb_close(dap); @@ -376,65 +419,178 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p static void cmsis_dap_usb_close(struct cmsis_dap *dap) { + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { + libusb_free_transfer(dap->bdata->command_transfers[i].transfer); + libusb_free_transfer(dap->bdata->response_transfers[i].transfer); + } + cmsis_dap_usb_free(dap); libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface); libusb_close(dap->bdata->dev_handle); libusb_exit(dap->bdata->usb_ctx); free(dap->bdata); dap->bdata = NULL; - free(dap->packet_buffer); - dap->packet_buffer = NULL; } -static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms) +static void LIBUSB_CALL cmsis_dap_usb_callback(struct libusb_transfer *transfer) +{ + struct cmsis_dap_bulk_transfer *tr; + + tr = (struct cmsis_dap_bulk_transfer *)transfer->user_data; + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { + tr->status = CMSIS_DAP_TRANSFER_COMPLETED; + tr->transferred = transfer->actual_length; + } else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { + tr->status = ERROR_TIMEOUT_REACHED; + } else { + tr->status = ERROR_JTAG_DEVICE_ERROR; + } +} + +static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms, + struct timeval *wait_timeout) { int transferred = 0; int err; + struct cmsis_dap_bulk_transfer *tr; + tr = &dap->bdata->response_transfers[dap->pending_fifo_get_idx]; + + if (tr->status == CMSIS_DAP_TRANSFER_IDLE) { + libusb_fill_bulk_transfer(tr->transfer, + dap->bdata->dev_handle, dap->bdata->ep_in, + tr->buffer, dap->packet_size, + &cmsis_dap_usb_callback, tr, + transfer_timeout_ms); + LOG_DEBUG_IO("submit read @ %u", dap->pending_fifo_get_idx); + tr->status = CMSIS_DAP_TRANSFER_PENDING; + err = libusb_submit_transfer(tr->transfer); + if (err) { + tr->status = CMSIS_DAP_TRANSFER_IDLE; + LOG_ERROR("error submitting USB read: %s", libusb_strerror(err)); + return ERROR_FAIL; + } + } - err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_in, - dap->packet_buffer, dap->packet_size, &transferred, timeout_ms); - if (err) { - if (err == LIBUSB_ERROR_TIMEOUT) { - return ERROR_TIMEOUT_REACHED; - } else { - LOG_ERROR("error reading data: %s", libusb_strerror(err)); + struct timeval tv = { + .tv_sec = transfer_timeout_ms / 1000, + .tv_usec = transfer_timeout_ms % 1000 * 1000 + }; + + while (tr->status == CMSIS_DAP_TRANSFER_PENDING) { + err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, + wait_timeout ? wait_timeout : &tv, + &tr->status); + if (err) { + LOG_ERROR("error handling USB events: %s", libusb_strerror(err)); return ERROR_FAIL; } + if (wait_timeout) + break; } - memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred); + if (tr->status < 0 || tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { + /* Check related command request for an error */ + struct cmsis_dap_bulk_transfer *tr_cmd; + tr_cmd = &dap->bdata->command_transfers[dap->pending_fifo_get_idx]; + if (tr_cmd->status < 0) { + err = tr_cmd->status; + tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE; + if (err != ERROR_TIMEOUT_REACHED) + LOG_ERROR("error writing USB data"); + else + LOG_DEBUG("command write USB timeout @ %u", dap->pending_fifo_get_idx); + + return err; + } + if (tr_cmd->status == CMSIS_DAP_TRANSFER_COMPLETED) + tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE; + } + + if (tr->status < 0) { + err = tr->status; + tr->status = CMSIS_DAP_TRANSFER_IDLE; + if (err != ERROR_TIMEOUT_REACHED) + LOG_ERROR("error reading USB data"); + else + LOG_DEBUG("USB timeout @ %u", dap->pending_fifo_get_idx); + + return err; + } + + if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { + transferred = tr->transferred; + LOG_DEBUG_IO("completed read @ %u, transferred %i", + dap->pending_fifo_get_idx, transferred); + memcpy(dap->packet_buffer, tr->buffer, transferred); + memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred); + tr->status = CMSIS_DAP_TRANSFER_IDLE; + } return transferred; } static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) { - int transferred = 0; int err; + struct cmsis_dap_bulk_transfer *tr; + tr = &dap->bdata->command_transfers[dap->pending_fifo_put_idx]; + + if (tr->status == CMSIS_DAP_TRANSFER_PENDING) { + LOG_ERROR("busy command USB transfer at %u", dap->pending_fifo_put_idx); + struct timeval tv = { + .tv_sec = timeout_ms / 1000, + .tv_usec = timeout_ms % 1000 * 1000 + }; + libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, &tr->status); + } + if (tr->status < 0) { + if (tr->status != ERROR_TIMEOUT_REACHED) + LOG_ERROR("error writing USB data, late detect"); + else + LOG_DEBUG("USB write timeout @ %u, late detect", dap->pending_fifo_get_idx); + tr->status = CMSIS_DAP_TRANSFER_IDLE; + } + if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { + LOG_ERROR("USB write: late transfer competed"); + tr->status = CMSIS_DAP_TRANSFER_IDLE; + } + if (tr->status != CMSIS_DAP_TRANSFER_IDLE) { + libusb_cancel_transfer(tr->transfer); + /* TODO: switch to less verbose errors and wait for USB working again */ + return ERROR_JTAG_DEVICE_ERROR; + } + + memcpy(tr->buffer, dap->packet_buffer, txlen); + + libusb_fill_bulk_transfer(tr->transfer, + dap->bdata->dev_handle, dap->bdata->ep_out, + tr->buffer, txlen, + &cmsis_dap_usb_callback, tr, + timeout_ms); - /* skip the first byte that is only used by the HID backend */ - err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out, - dap->packet_buffer, txlen, &transferred, timeout_ms); + LOG_DEBUG_IO("submit write @ %u", dap->pending_fifo_put_idx); + tr->status = CMSIS_DAP_TRANSFER_PENDING; + err = libusb_submit_transfer(tr->transfer); if (err) { - if (err == LIBUSB_ERROR_TIMEOUT) { - return ERROR_TIMEOUT_REACHED; - } else { - LOG_ERROR("error writing data: %s", libusb_strerror(err)); - return ERROR_FAIL; - } + if (err == LIBUSB_ERROR_BUSY) + libusb_cancel_transfer(tr->transfer); + else + tr->status = CMSIS_DAP_TRANSFER_IDLE; + + LOG_ERROR("error submitting USB write: %s", libusb_strerror(err)); + return ERROR_FAIL; } - return transferred; + return ERROR_OK; } static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz) { - uint8_t *buf = malloc(pkt_sz); - if (!buf) { + dap->packet_buffer = malloc(pkt_sz); + if (!dap->packet_buffer) { LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); return ERROR_FAIL; } - dap->packet_buffer = buf; dap->packet_size = pkt_sz; dap->packet_buffer_size = pkt_sz; /* Prevent sending zero size USB packets */ @@ -443,9 +599,41 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz) dap->command = dap->packet_buffer; dap->response = dap->packet_buffer; + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { + dap->bdata->command_transfers[i].buffer = + libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz); + if (!dap->bdata->command_transfers[i].buffer) { + LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); + return ERROR_FAIL; + } + dap->bdata->response_transfers[i].buffer = + libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz); + if (!dap->bdata->response_transfers[i].buffer) { + LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); + return ERROR_FAIL; + } + } + return ERROR_OK; } +static void cmsis_dap_usb_free(struct cmsis_dap *dap) +{ + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { + libusb_dev_mem_free(dap->bdata->dev_handle, + dap->bdata->command_transfers[i].buffer, dap->packet_size); + dap->bdata->command_transfers[i].buffer = NULL; + libusb_dev_mem_free(dap->bdata->dev_handle, + dap->bdata->response_transfers[i].buffer, dap->packet_size); + dap->bdata->response_transfers[i].buffer = NULL; + } + + free(dap->packet_buffer); + dap->packet_buffer = NULL; + dap->command = NULL; + dap->response = NULL; +} + COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command) { if (CMD_ARGC == 1) @@ -474,4 +662,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = { .read = cmsis_dap_usb_read, .write = cmsis_dap_usb_write, .packet_buffer_alloc = cmsis_dap_usb_alloc, + .packet_buffer_free = cmsis_dap_usb_free, }; diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 52dfd76165..6338886c84 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -36,6 +36,7 @@ struct cmsis_dap_backend_data { static void cmsis_dap_hid_close(struct cmsis_dap *dap); static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz); +static void cmsis_dap_hid_free(struct cmsis_dap *dap); static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial) { @@ -165,14 +166,21 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap) hid_exit(); free(dap->bdata); dap->bdata = NULL; - free(dap->packet_buffer); - dap->packet_buffer = NULL; + cmsis_dap_hid_free(dap); } -static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms) +static int cmsis_dap_hid_read(struct cmsis_dap *dap, int transfer_timeout_ms, + struct timeval *wait_timeout) { - int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, timeout_ms); - + int timeout_ms; + if (wait_timeout) + timeout_ms = wait_timeout->tv_usec / 1000 + wait_timeout->tv_sec * 1000; + else + timeout_ms = transfer_timeout_ms; + + int retval = hid_read_timeout(dap->bdata->dev_handle, + dap->packet_buffer, dap->packet_buffer_size, + timeout_ms); if (retval == 0) { return ERROR_TIMEOUT_REACHED; } else if (retval == -1) { @@ -222,6 +230,12 @@ static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz) return ERROR_OK; } +static void cmsis_dap_hid_free(struct cmsis_dap *dap) +{ + free(dap->packet_buffer); + dap->packet_buffer = NULL; +} + const struct cmsis_dap_backend cmsis_dap_hid_backend = { .name = "hid", .open = cmsis_dap_hid_open, @@ -229,4 +243,5 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = { .read = cmsis_dap_hid_read, .write = cmsis_dap_hid_write, .packet_buffer_alloc = cmsis_dap_hid_alloc, + .packet_buffer_free = cmsis_dap_hid_free, }; From 66391d28373fef090999b253b193d19dbdc11217 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 20 Nov 2022 21:01:17 +0100 Subject: [PATCH 0653/1312] jtag/drivers/cmsis_dap: implement canceling of pending USB requests Use it whenever an out-of-sync response is detected to clean USB bulk transfer state. USB hidapi does not offer any means to cancel a pending request, therefore cmsis_dap_hid_cancel_all() does nothing. Signed-off-by: Tomas Vanek Change-Id: Ie36fa760c1643ae10be0e87fc633068965a72242 Reviewed-on: https://review.openocd.org/c/openocd/+/7366 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/drivers/cmsis_dap.c | 18 +++++++++++++++--- src/jtag/drivers/cmsis_dap.h | 1 + src/jtag/drivers/cmsis_dap_usb_bulk.c | 14 ++++++++++++++ src/jtag/drivers/cmsis_dap_usb_hid.c | 5 +++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index bc86eb46af..5d060bdadd 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -365,6 +365,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) LOG_ERROR("CMSIS-DAP command mismatch. Sent 0x%" PRIx8 " received 0x%" PRIx8, current_cmd, resp[0]); + dap->backend->cancel_all(dap); cmsis_dap_flush_read(dap); return ERROR_FAIL; } @@ -758,7 +759,6 @@ static int cmsis_dap_cmd_dap_swo_data( return ERROR_OK; } - static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap) { for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) @@ -769,6 +769,13 @@ static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap) dap->pending_fifo_block_count = 0; } +static void cmsis_dap_swd_cancel_transfers(struct cmsis_dap *dap) +{ + dap->backend->cancel_all(dap); + cmsis_dap_flush_read(dap); + cmsis_dap_swd_discard_all_pending(dap); +} + static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) { uint8_t *command = dap->command; @@ -913,8 +920,9 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo if (resp[0] != block->command) { LOG_ERROR("CMSIS-DAP command mismatch. Expected 0x%x received 0x%" PRIx8, block->command, resp[0]); + cmsis_dap_swd_cancel_transfers(dap); queued_retval = ERROR_FAIL; - goto skip; + return; } unsigned int transfer_count; @@ -940,9 +948,13 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo goto skip; } - if (block->transfer_count != transfer_count) + if (block->transfer_count != transfer_count) { LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d", block->transfer_count, transfer_count); + cmsis_dap_swd_cancel_transfers(dap); + queued_retval = ERROR_FAIL; + return; + } LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u, %s mode", transfer_count, dap->pending_fifo_get_idx, diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index 187aeb54d8..817636f346 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -66,6 +66,7 @@ struct cmsis_dap_backend { int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz); void (*packet_buffer_free)(struct cmsis_dap *dap); + void (*cancel_all)(struct cmsis_dap *dap); }; extern const struct cmsis_dap_backend cmsis_dap_hid_backend; diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index aaab5804d1..17e490f05a 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -634,6 +634,19 @@ static void cmsis_dap_usb_free(struct cmsis_dap *dap) dap->response = NULL; } +static void cmsis_dap_usb_cancel_all(struct cmsis_dap *dap) +{ + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { + if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) + libusb_cancel_transfer(dap->bdata->command_transfers[i].transfer); + if (dap->bdata->response_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) + libusb_cancel_transfer(dap->bdata->response_transfers[i].transfer); + + dap->bdata->command_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE; + dap->bdata->response_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE; + } +} + COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command) { if (CMD_ARGC == 1) @@ -663,4 +676,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = { .write = cmsis_dap_usb_write, .packet_buffer_alloc = cmsis_dap_usb_alloc, .packet_buffer_free = cmsis_dap_usb_free, + .cancel_all = cmsis_dap_usb_cancel_all, }; diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 6338886c84..1decc7156d 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -236,6 +236,10 @@ static void cmsis_dap_hid_free(struct cmsis_dap *dap) dap->packet_buffer = NULL; } +static void cmsis_dap_hid_cancel_all(struct cmsis_dap *dap) +{ +} + const struct cmsis_dap_backend cmsis_dap_hid_backend = { .name = "hid", .open = cmsis_dap_hid_open, @@ -244,4 +248,5 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = { .write = cmsis_dap_hid_write, .packet_buffer_alloc = cmsis_dap_hid_alloc, .packet_buffer_free = cmsis_dap_hid_free, + .cancel_all = cmsis_dap_hid_cancel_all, }; From ba16fdc1c645bda82adb5a06b4403e7501e150c4 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 7 Nov 2023 14:45:45 +0100 Subject: [PATCH 0654/1312] drivers/cmsis_dap: use quirk workarounds optionally Introduce 'cmsis-dap quirk' command to enable and disable quirk mode. If enabled, disconnect and connect before a switch sequence and do not use multiple packets pipelining. Change-Id: I6576f7de9f6c98a25c3cf9eec9a456a23610d00d Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7966 Tested-by: jenkins --- doc/openocd.texi | 12 ++++++++++++ src/jtag/drivers/cmsis_dap.c | 33 ++++++++++++++++++++++++++++----- src/jtag/drivers/cmsis_dap.h | 1 + 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index de990c5381..db7315fe44 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2569,6 +2569,18 @@ In most cases need not to be specified and interfaces are searched by interface string or for user class interface. @end deffn +@deffn {Command} {cmsis-dap quirk} [@option{enable}|@option{disable}] +Enables or disables the following workarounds of known CMSIS-DAP adapter +quirks: +@itemize @minus +@item disconnect and re-connect before sending a switch sequence +@item packets pipelining is suppressed, only one packet at a time is +submitted to the adapter +@end itemize +The quirk workarounds are disabled by default. +The command without a parameter displays current setting. +@end deffn + @deffn {Command} {cmsis-dap info} Display various device information, like hardware version, firmware version, current bus status. @end deffn diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 5d060bdadd..caacc9b916 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -861,9 +861,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) goto skip; } - dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % dap->packet_count; + unsigned int packet_count = dap->quirk_mode ? 1 : dap->packet_count; + dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % packet_count; dap->pending_fifo_block_count++; - if (dap->pending_fifo_block_count > dap->packet_count) + if (dap->pending_fifo_block_count > packet_count) LOG_ERROR("internal: too much pending writes %u", dap->pending_fifo_block_count); return; @@ -984,7 +985,8 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo skip: block->transfer_count = 0; - dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count; + if (!dap->quirk_mode && dap->packet_count > 1) + dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count; dap->pending_fifo_block_count--; } @@ -1079,7 +1081,8 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) /* Not enough room in the queue. Run the queue. */ cmsis_dap_swd_write_from_queue(cmsis_dap_handle); - if (cmsis_dap_handle->pending_fifo_block_count >= cmsis_dap_handle->packet_count) + unsigned int packet_count = cmsis_dap_handle->quirk_mode ? 1 : cmsis_dap_handle->packet_count; + if (cmsis_dap_handle->pending_fifo_block_count >= packet_count) cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING); } @@ -1222,7 +1225,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) if (swd_mode) queued_retval = cmsis_dap_swd_run_queue(); - if (seq != LINE_RESET && + if (cmsis_dap_handle->quirk_mode && seq != LINE_RESET && (output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST)) == (SWJ_PIN_SRST | SWJ_PIN_TRST)) { /* Following workaround deasserts reset on most adapters. @@ -2220,6 +2223,19 @@ COMMAND_HANDLER(cmsis_dap_handle_backend_command) return ERROR_OK; } +COMMAND_HANDLER(cmsis_dap_handle_quirk_command) +{ + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 1) + COMMAND_PARSE_ENABLE(CMD_ARGV[0], cmsis_dap_handle->quirk_mode); + + command_print(CMD, "CMSIS-DAP quirk workarounds %s", + cmsis_dap_handle->quirk_mode ? "enabled" : "disabled"); + return ERROR_OK; +} + static const struct command_registration cmsis_dap_subcommand_handlers[] = { { .name = "info", @@ -2249,6 +2265,13 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = { .help = "set the communication backend to use (USB bulk or HID).", .usage = "(auto | usb_bulk | hid)", }, + { + .name = "quirk", + .handler = &cmsis_dap_handle_quirk_command, + .mode = COMMAND_ANY, + .help = "allow expensive workarounds of known adapter quirks.", + .usage = "[enable | disable]", + }, #if BUILD_CMSIS_DAP_USB { .name = "usb", diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index 817636f346..e47697d1f9 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -52,6 +52,7 @@ struct cmsis_dap { unsigned int pending_fifo_block_count; uint16_t caps; + bool quirk_mode; /* enable expensive workarounds */ uint32_t swo_buf_sz; bool trace_enabled; From d3ffcc784dac76ffb5d5d29ca73cb56f38154c1a Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Mon, 3 Jul 2023 11:02:13 +0200 Subject: [PATCH 0655/1312] target/espressif: add algorithm support to execute code on target This functionality can be useful for; 1-ESP flashing code to load flasher stub on target and write/read/erase flash. 2-ESP GCOV command uses some of these functions to run onboard routines to dump coverage info. This is high level api for the Espressif xtensa and riscv targets Signed-off-by: Erhan Kurubas Change-Id: I5e618b960bb6566ee618d4ba261f51af97a7cb0e Reviewed-on: https://review.openocd.org/c/openocd/+/7759 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/espressif/Makefile.am | 4 +- src/target/espressif/esp_algorithm.c | 595 ++++++++++++++++++++++++++ src/target/espressif/esp_algorithm.h | 420 ++++++++++++++++++ src/target/espressif/esp_xtensa_smp.c | 78 ++++ src/target/espressif/esp_xtensa_smp.h | 8 +- 5 files changed, 1103 insertions(+), 2 deletions(-) create mode 100644 src/target/espressif/esp_algorithm.c create mode 100644 src/target/espressif/esp_algorithm.h diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am index 776818ff4d..1fbd926d9d 100644 --- a/src/target/espressif/Makefile.am +++ b/src/target/espressif/Makefile.am @@ -21,4 +21,6 @@ noinst_LTLIBRARIES += %D%/libespressif.la %D%/esp32_sysview.h \ %D%/segger_sysview.h \ %D%/esp_semihosting.c \ - %D%/esp_semihosting.h + %D%/esp_semihosting.h \ + %D%/esp_algorithm.c \ + %D%/esp_algorithm.h diff --git a/src/target/espressif/esp_algorithm.c b/src/target/espressif/esp_algorithm.c new file mode 100644 index 0000000000..79f610b922 --- /dev/null +++ b/src/target/espressif/esp_algorithm.c @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/*************************************************************************** + * Espressif chips common algorithm API for OpenOCD * + * Copyright (C) 2022 Espressif Systems Ltd. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "esp_algorithm.h" + +#define DEFAULT_ALGORITHM_TIMEOUT_MS 40000 /* ms */ + +static int esp_algorithm_read_stub_logs(struct target *target, struct esp_algorithm_stub *stub) +{ + if (!stub || stub->log_buff_addr == 0 || stub->log_buff_size == 0) + return ERROR_FAIL; + + uint32_t len = 0; + int retval = target_read_u32(target, stub->log_buff_addr, &len); + if (retval != ERROR_OK) + return retval; + + /* sanity check. log_buff_size = sizeof(len) + sizeof(log_buff) */ + if (len == 0 || len > stub->log_buff_size - 4) + return ERROR_FAIL; + + uint8_t *log_buff = calloc(1, len); + if (!log_buff) { + LOG_ERROR("Failed to allocate memory for the stub log!"); + return ERROR_FAIL; + } + retval = target_read_memory(target, stub->log_buff_addr + 4, 1, len, log_buff); + if (retval == ERROR_OK) + LOG_OUTPUT("%*.*s", len, len, log_buff); + free(log_buff); + return retval; +} + +static int esp_algorithm_run_image(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap) +{ + struct working_area **mem_handles = NULL; + + if (!run || !run->hw) + return ERROR_FAIL; + + int retval = run->hw->algo_init(target, run, num_args, ap); + if (retval != ERROR_OK) + return retval; + + /* allocate memory arguments and fill respective reg params */ + if (run->mem_args.count > 0) { + mem_handles = calloc(run->mem_args.count, sizeof(*mem_handles)); + if (!mem_handles) { + LOG_ERROR("Failed to alloc target mem handles!"); + retval = ERROR_FAIL; + goto _cleanup; + } + /* alloc memory args target buffers */ + for (uint32_t i = 0; i < run->mem_args.count; i++) { + /* small hack: if we need to update some reg param this field holds + * appropriate user argument number, */ + /* otherwise should hold UINT_MAX */ + uint32_t usr_param_num = run->mem_args.params[i].address; + static struct working_area *area; + retval = target_alloc_working_area(target, run->mem_args.params[i].size, &area); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to alloc target buffer!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _cleanup; + } + mem_handles[i] = area; + run->mem_args.params[i].address = area->address; + if (usr_param_num != UINT_MAX) /* if we need update some register param with mem param value */ + esp_algorithm_user_arg_set_uint(run, usr_param_num, run->mem_args.params[i].address); + } + } + + if (run->usr_func_init) { + retval = run->usr_func_init(target, run, run->usr_func_arg); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to prepare algorithm host side args stub (%d)!", retval); + goto _cleanup; + } + } + + LOG_DEBUG("Algorithm start @ " TARGET_ADDR_FMT ", stack %d bytes @ " TARGET_ADDR_FMT, + run->stub.tramp_mapped_addr, run->stack_size, run->stub.stack_addr); + retval = target_start_algorithm(target, + run->mem_args.count, run->mem_args.params, + run->reg_args.count, run->reg_args.params, + run->stub.tramp_mapped_addr, 0, + run->stub.ainfo); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to start algorithm (%d)!", retval); + goto _cleanup; + } + + if (run->usr_func) { + /* give target algorithm stub time to init itself, then user func can communicate to it safely */ + alive_sleep(100); + retval = run->usr_func(target, run->usr_func_arg); + if (retval != ERROR_OK) + LOG_ERROR("Failed to exec algorithm user func (%d)!", retval); + } + uint32_t timeout_ms = 0; /* do not wait if 'usr_func' returned error */ + if (retval == ERROR_OK) + timeout_ms = run->timeout_ms ? run->timeout_ms : DEFAULT_ALGORITHM_TIMEOUT_MS; + LOG_DEBUG("Wait algorithm completion"); + retval = target_wait_algorithm(target, + run->mem_args.count, run->mem_args.params, + run->reg_args.count, run->reg_args.params, + 0, timeout_ms, + run->stub.ainfo); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to wait algorithm (%d)!", retval); + /* target has been forced to stop in target_wait_algorithm() */ + } + esp_algorithm_read_stub_logs(target, &run->stub); + + if (run->usr_func_done) + run->usr_func_done(target, run, run->usr_func_arg); + + if (retval != ERROR_OK) { + LOG_ERROR("Algorithm run failed (%d)!", retval); + } else { + run->ret_code = esp_algorithm_user_arg_get_uint(run, 0); + LOG_DEBUG("Got algorithm RC 0x%" PRIx32, run->ret_code); + } + +_cleanup: + /* free memory arguments */ + if (mem_handles) { + for (uint32_t i = 0; i < run->mem_args.count; i++) { + if (mem_handles[i]) + target_free_working_area(target, mem_handles[i]); + } + free(mem_handles); + } + run->hw->algo_cleanup(target, run); + + return retval; +} + +static int esp_algorithm_run_debug_stub(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap) +{ + if (!run || !run->hw) + return ERROR_FAIL; + + int retval = run->hw->algo_init(target, run, num_args, ap); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("Algorithm start @ " TARGET_ADDR_FMT ", stack %d bytes @ " TARGET_ADDR_FMT, + run->stub.tramp_mapped_addr, run->stack_size, run->stub.stack_addr); + retval = target_start_algorithm(target, + run->mem_args.count, run->mem_args.params, + run->reg_args.count, run->reg_args.params, + run->stub.tramp_mapped_addr, 0, + run->stub.ainfo); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to start algorithm (%d)!", retval); + goto _cleanup; + } + + uint32_t timeout_ms = 0; /* do not wait if 'usr_func' returned error */ + if (retval == ERROR_OK) + timeout_ms = run->timeout_ms ? run->timeout_ms : DEFAULT_ALGORITHM_TIMEOUT_MS; + LOG_DEBUG("Wait algorithm completion"); + retval = target_wait_algorithm(target, + run->mem_args.count, run->mem_args.params, + run->reg_args.count, run->reg_args.params, + 0, timeout_ms, + run->stub.ainfo); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to wait algorithm (%d)!", retval); + /* target has been forced to stop in target_wait_algorithm() */ + } + + if (retval != ERROR_OK) { + LOG_ERROR("Algorithm run failed (%d)!", retval); + } else { + run->ret_code = esp_algorithm_user_arg_get_uint(run, 0); + LOG_DEBUG("Got algorithm RC 0x%" PRIx32, run->ret_code); + } + +_cleanup: + run->hw->algo_cleanup(target, run); + + return retval; +} + +static void reverse_binary(const uint8_t *src, uint8_t *dest, size_t length) +{ + size_t remaining = length % 4; + size_t offset = 0; + size_t aligned_len = ALIGN_UP(length, 4); + + if (remaining > 0) { + /* Put extra bytes to the beginning with padding */ + memset(dest + remaining, 0xFF, 4 - remaining); + for (size_t i = 0; i < remaining; i++) + dest[i] = src[length - remaining + i]; + length -= remaining; /* reverse the others */ + offset = 4; + } + + for (size_t i = offset; i < aligned_len; i += 4) { + dest[i + 0] = src[length - i + offset - 4]; + dest[i + 1] = src[length - i + offset - 3]; + dest[i + 2] = src[length - i + offset - 2]; + dest[i + 3] = src[length - i + offset - 1]; + } +} + +static int load_section_from_image(struct target *target, + struct esp_algorithm_run_data *run, + int section_num, + bool reverse) +{ + if (!run) + return ERROR_FAIL; + + struct imagesection *section = &run->image.image.sections[section_num]; + uint32_t sec_wr = 0; + uint8_t buf[1024]; + + assert(sizeof(buf) % 4 == 0); + + while (sec_wr < section->size) { + uint32_t nb = section->size - sec_wr > sizeof(buf) ? sizeof(buf) : section->size - sec_wr; + size_t size_read = 0; + int retval = image_read_section(&run->image.image, section_num, sec_wr, nb, buf, &size_read); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read stub section (%d)!", retval); + return retval; + } + + if (reverse) { + size_t aligned_len = ALIGN_UP(size_read, 4); + uint8_t reversed_buf[aligned_len]; + + /* Send original size to allow padding */ + reverse_binary(buf, reversed_buf, size_read); + + /* + The address range accessed via the instruction bus is in reverse order (word-wise) compared to access + via the data bus. That is to say, address + 0x3FFE_0000 and 0x400B_FFFC access the same word + 0x3FFE_0004 and 0x400B_FFF8 access the same word + 0x3FFE_0008 and 0x400B_FFF4 access the same word + ... + The data bus and instruction bus of the CPU are still both little-endian, + so the byte order of individual words is not reversed between address spaces. + For example, address + 0x3FFE_0000 accesses the least significant byte in the word accessed by 0x400B_FFFC. + 0x3FFE_0001 accesses the second least significant byte in the word accessed by 0x400B_FFFC. + 0x3FFE_0002 accesses the second most significant byte in the word accessed by 0x400B_FFFC. + For more details, please refer to ESP32 TRM, Internal SRAM1 section. + */ + retval = target_write_buffer(target, run->image.dram_org - sec_wr - aligned_len, aligned_len, reversed_buf); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to write stub section!"); + return retval; + } + } else { + retval = target_write_buffer(target, section->base_address + sec_wr, size_read, buf); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to write stub section!"); + return retval; + } + } + + sec_wr += size_read; + } + + return ERROR_OK; +} + +/* + * Configuration: + * ---------------------------- + * The linker scripts defines the memory layout for the stub code. + * The OpenOCD script specifies the workarea address and it's size + * Sections defined in the linker are organized to share the same addresses with the workarea. + * code and data sections are located in Internal SRAM1 and OpenOCD fills these sections using the data bus. + */ +int esp_algorithm_load_func_image(struct target *target, struct esp_algorithm_run_data *run) +{ + int retval; + size_t tramp_sz = 0; + const uint8_t *tramp = NULL; + struct duration algo_time; + bool alloc_code_working_area = true; + + if (!run || !run->hw) + return ERROR_FAIL; + + if (duration_start(&algo_time) != 0) { + LOG_ERROR("Failed to start algo time measurement!"); + return ERROR_FAIL; + } + + if (run->hw->stub_tramp_get) { + tramp = run->hw->stub_tramp_get(target, &tramp_sz); + if (!tramp) + return ERROR_FAIL; + } + + LOG_DEBUG("stub: base 0x%x, start 0x%" PRIx32 ", %d sections", + run->image.image.base_address_set ? (unsigned int)run->image.image.base_address : 0, + run->image.image.start_address, + run->image.image.num_sections); + run->stub.entry = run->image.image.start_address; + + /* [code + trampoline] + + [data] */ + + /* ESP32 has reversed memory region. It will use the last part of DRAM, the others will use the first part. + * To avoid complexity for the backup/restore process, we will allocate a workarea for all IRAM region from + * the beginning. In that case no need to have a padding area. + */ + if (run->image.reverse) { + if (target_alloc_working_area(target, run->image.iram_len, &run->stub.code) != ERROR_OK) { + LOG_ERROR("no working area available, can't alloc space for stub code!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _on_error; + } + alloc_code_working_area = false; + } + + uint32_t code_size = 0; + + /* Load code section */ + for (unsigned int i = 0; i < run->image.image.num_sections; i++) { + struct imagesection *section = &run->image.image.sections[i]; + + if (section->size == 0) + continue; + + if (section->flags & ESP_IMAGE_ELF_PHF_EXEC) { + LOG_DEBUG("addr " TARGET_ADDR_FMT ", sz %d, flags %" PRIx64, + section->base_address, section->size, section->flags); + + if (alloc_code_working_area) { + retval = target_alloc_working_area(target, section->size, &run->stub.code); + if (retval != ERROR_OK) { + LOG_ERROR("no working area available, can't alloc space for stub code!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _on_error; + } + } + + if (section->base_address == 0) { + section->base_address = run->stub.code->address; + /* sanity check, stub is compiled to be run from working area */ + } else if (run->stub.code->address != section->base_address) { + LOG_ERROR("working area " TARGET_ADDR_FMT " and stub code section " TARGET_ADDR_FMT + " address mismatch!", + section->base_address, + run->stub.code->address); + retval = ERROR_FAIL; + goto _on_error; + } + + retval = load_section_from_image(target, run, i, run->image.reverse); + if (retval != ERROR_OK) + goto _on_error; + + code_size += ALIGN_UP(section->size, 4); + break; /* Stub has one executable text section */ + } + } + + /* If exists, load trampoline to the code area */ + if (tramp) { + if (run->stub.tramp_addr == 0) { + if (alloc_code_working_area) { + /* alloc trampoline in code working area */ + if (target_alloc_working_area(target, tramp_sz, &run->stub.tramp) != ERROR_OK) { + LOG_ERROR("no working area available, can't alloc space for stub jumper!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _on_error; + } + run->stub.tramp_addr = run->stub.tramp->address; + } + } + + size_t al_tramp_size = ALIGN_UP(tramp_sz, 4); + + if (run->image.reverse) { + target_addr_t reversed_tramp_addr = run->image.dram_org - code_size; + uint8_t reversed_tramp[al_tramp_size]; + + /* Send original size to allow padding */ + reverse_binary(tramp, reversed_tramp, tramp_sz); + run->stub.tramp_addr = reversed_tramp_addr - al_tramp_size; + LOG_DEBUG("Write reversed tramp to addr " TARGET_ADDR_FMT ", sz %zu", run->stub.tramp_addr, al_tramp_size); + retval = target_write_buffer(target, run->stub.tramp_addr, al_tramp_size, reversed_tramp); + } else { + LOG_DEBUG("Write tramp to addr " TARGET_ADDR_FMT ", sz %zu", run->stub.tramp_addr, tramp_sz); + retval = target_write_buffer(target, run->stub.tramp_addr, tramp_sz, tramp); + } + + if (retval != ERROR_OK) { + LOG_ERROR("Failed to write stub jumper!"); + goto _on_error; + } + + run->stub.tramp_mapped_addr = run->image.iram_org + code_size; + code_size += al_tramp_size; + LOG_DEBUG("Tramp mapped to addr " TARGET_ADDR_FMT, run->stub.tramp_mapped_addr); + } + + /* allocate dummy space until the data address */ + if (alloc_code_working_area) { + /* we dont need to restore padding area. */ + uint32_t backup_working_area_prev = target->backup_working_area; + target->backup_working_area = 0; + if (target_alloc_working_area(target, run->image.iram_len - code_size, &run->stub.padding) != ERROR_OK) { + LOG_ERROR("no working area available, can't alloc space for stub code!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _on_error; + } + target->backup_working_area = backup_working_area_prev; + } + + /* Load the data section */ + for (unsigned int i = 0; i < run->image.image.num_sections; i++) { + struct imagesection *section = &run->image.image.sections[i]; + + if (section->size == 0) + continue; + + if (!(section->flags & ESP_IMAGE_ELF_PHF_EXEC)) { + LOG_DEBUG("addr " TARGET_ADDR_FMT ", sz %d, flags %" PRIx64, section->base_address, section->size, + section->flags); + /* target_alloc_working_area() aligns the whole working area size to 4-byte boundary. + We alloc one area for both DATA and BSS, so align each of them ourselves. */ + uint32_t data_sec_sz = ALIGN_UP(section->size, 4); + LOG_DEBUG("DATA sec size %" PRIu32 " -> %" PRIu32, section->size, data_sec_sz); + uint32_t bss_sec_sz = ALIGN_UP(run->image.bss_size, 4); + LOG_DEBUG("BSS sec size %" PRIu32 " -> %" PRIu32, run->image.bss_size, bss_sec_sz); + if (target_alloc_working_area(target, data_sec_sz + bss_sec_sz, &run->stub.data) != ERROR_OK) { + LOG_ERROR("no working area available, can't alloc space for stub data!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _on_error; + } + if (section->base_address == 0) { + section->base_address = run->stub.data->address; + /* sanity check, stub is compiled to be run from working area */ + } else if (run->stub.data->address != section->base_address) { + LOG_ERROR("working area " TARGET_ADDR_FMT + " and stub data section " TARGET_ADDR_FMT + " address mismatch!", + section->base_address, + run->stub.data->address); + retval = ERROR_FAIL; + goto _on_error; + } + + retval = load_section_from_image(target, run, i, false); + if (retval != ERROR_OK) + goto _on_error; + } + } + + /* stack */ + if (run->stub.stack_addr == 0 && run->stack_size > 0) { + /* allocate stack in data working area */ + if (target_alloc_working_area(target, run->stack_size, &run->stub.stack) != ERROR_OK) { + LOG_ERROR("no working area available, can't alloc stub stack!"); + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto _on_error; + } + run->stub.stack_addr = run->stub.stack->address + run->stack_size; + } + + if (duration_measure(&algo_time) != 0) { + LOG_ERROR("Failed to stop algo run measurement!"); + retval = ERROR_FAIL; + goto _on_error; + } + LOG_DEBUG("Stub loaded in %g ms", duration_elapsed(&algo_time) * 1000); + return ERROR_OK; + +_on_error: + esp_algorithm_unload_func_image(target, run); + return retval; +} + +int esp_algorithm_unload_func_image(struct target *target, struct esp_algorithm_run_data *run) +{ + if (!run) + return ERROR_FAIL; + + target_free_all_working_areas(target); + + run->stub.tramp = NULL; + run->stub.stack = NULL; + run->stub.code = NULL; + run->stub.data = NULL; + run->stub.padding = NULL; + + return ERROR_OK; +} + +int esp_algorithm_exec_func_image_va(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap) +{ + if (!run || !run->image.image.start_address_set || run->image.image.start_address == 0) + return ERROR_FAIL; + + return esp_algorithm_run_image(target, run, num_args, ap); +} + +int esp_algorithm_load_onboard_func(struct target *target, target_addr_t func_addr, struct esp_algorithm_run_data *run) +{ + int res; + const uint8_t *tramp = NULL; + size_t tramp_sz = 0; + struct duration algo_time; + + if (!run || !run->hw) + return ERROR_FAIL; + + if (duration_start(&algo_time) != 0) { + LOG_ERROR("Failed to start algo time measurement!"); + return ERROR_FAIL; + } + + if (run->hw->stub_tramp_get) { + tramp = run->hw->stub_tramp_get(target, &tramp_sz); + if (!tramp) + return ERROR_FAIL; + } + + if (tramp_sz > run->on_board.code_buf_size) { + LOG_ERROR("Stub tramp size %zu bytes exceeds target buf size %d bytes!", + tramp_sz, run->on_board.code_buf_size); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + if (run->stack_size > run->on_board.min_stack_size) { + LOG_ERROR("Algorithm stack size not fit into the allocated target stack!"); + return ERROR_FAIL; + } + + run->stub.stack_addr = run->on_board.min_stack_addr + run->stack_size; + run->stub.tramp_addr = run->on_board.code_buf_addr; + run->stub.tramp_mapped_addr = run->stub.tramp_addr; + run->stub.entry = func_addr; + + if (tramp) { + res = target_write_buffer(target, run->stub.tramp_addr, tramp_sz, tramp); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write stub jumper!"); + esp_algorithm_unload_onboard_func(target, run); + return res; + } + } + + if (duration_measure(&algo_time) != 0) { + LOG_ERROR("Failed to stop algo run measurement!"); + return ERROR_FAIL; + } + LOG_DEBUG("Stub loaded in %g ms", duration_elapsed(&algo_time) * 1000); + + return ERROR_OK; +} + +int esp_algorithm_unload_onboard_func(struct target *target, struct esp_algorithm_run_data *run) +{ + return ERROR_OK; +} + +int esp_algorithm_exec_onboard_func_va(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap) +{ + return esp_algorithm_run_debug_stub(target, run, num_args, ap); +} diff --git a/src/target/espressif/esp_algorithm.h b/src/target/espressif/esp_algorithm.h new file mode 100644 index 0000000000..11d2757776 --- /dev/null +++ b/src/target/espressif/esp_algorithm.h @@ -0,0 +1,420 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/*************************************************************************** + * Espressif chips common algorithm API for OpenOCD * + * Copyright (C) 2022 Espressif Systems Ltd. * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ESP_ALGORITHM_H +#define OPENOCD_TARGET_ESP_ALGORITHM_H + +#include "helper/log.h" +#include "helper/binarybuffer.h" +#include +#include +#include + +/** + * API defined below allows executing pieces of code on target without breaking the execution of the running program. + * This functionality can be useful for various debugging and maintenance procedures. + * @note ESP flashing code to load flasher stub on target and write/read/erase flash. + * Also ESP GCOV command uses some of these functions to run onboard routines to dump coverage info. + * Stub entry function can take up to 5 arguments and should be of the following form: + * + * int stub_entry([uint32_t a1 [, uint32_t a2 [, uint32_t a3 [, uint32_t a4 [, uint32_t a5]]]]]); + * + * The general scheme of stub code execution is shown below. + * + * ------- ----------- (initial frame) ---- + * | | -------(registers, stub entry, stub args)------> |trampoline | ---(stub args)---> | | + * | | | | | | + * |OpenOCD| <----------(stub-specific communications)---------------------------------------> |stub| + * | | | | | | + * | | <---------(target halted event, ret code)------- |tramp break| <---(ret code)---- | | + * ------- ----------- ---- + * + * Procedure of executing stub on target includes: + * 1) User prepares struct esp_algorithm_run_data and calls one of algorithm_run_xxx() functions. + * 2) Routine allocates all necessary stub code and data sections. + * 3) If a user specifies an initializer func esp_algorithm_usr_func_init_t it is called just before the stub starts. + * 4) If user specifies stub communication func esp_algorithm_usr_func_t (@see esp_flash_write/read in ESP flash driver) + * it is called just after the stub starts. When communication with stub is finished this function must return. + * 5) OpenOCD waits for the stub to finish (hit exit breakpoint). + * 6) If the user specified arguments cleanup func esp_algorithm_usr_func_done_t, + * it is called just after the stub finishes. + * + * There are two options to run code on target under OpenOCD control: + * - Run externally compiled stub code. + * - Run onboard pre-compiled code. @note For ESP chips debug stubs must be enabled in target code @see ESP IDF docs. + * The main difference between the execution of external stub code and target built-in functions is that + * in the latter case working areas can not be used to allocate target memory for code and data because they can overlap + * with code and data involved in onboard function execution. For example, if memory allocated in the working area + * for the stub stack will overlap with some on-board data used by the stub the stack will get overwritten. + * The same stands for allocations in target code space. + * + * External Code Execution + * ----------------------- + * To run external code on the target user should use esp_algorithm_run_func_image(). + * In this case all necessary memory (code/data) is allocated in working areas that have fixed configuration + * defined in target TCL file. Stub code is actually a standalone program, so all its segments must have known + * addresses due to position-dependent code nature. So stub must be linked in such a way that its code segment + * starts at the beginning of the working area for code space defined in TCL. The same restriction must be applied + * to stub's data segment and base addresses of working area for data space. @see ESP stub flasher LD scripts. + * Also in order to simplify memory allocation BSS section must follow the DATA section in the stub image. + * The size of the BSS section must be specified in the bss_size field of struct algorithm_image. + * Sample stub memory map is shown below. + * ___________________________________________ + * | data space working area start | + * | | + * | | + * |___________________________________________| + * | stub .bss start | + * | | + * | | + * |___________________________________________| + * | stub stack base | + * | | + * | | + * |___________________________________________| + * | | + * | | + * |___________________________________________| + * | | + * | | + * |___________________________________________| + * ___________________________________________ + * | code space working area start | + * | | + * | | + * |___________________________________________| + * | | + * | | + * |___________________________________________| + * + * For example on how to execute external code with memory arguments @see esp_algo_flash_blank_check in + * ESP flash driver. + * + * On-Board Code Execution + * ----------------------- + * To run on-board code on the target user should use esp_algorithm_run_onboard_func(). + * On-board code execution process does not need to allocate target memory for stub code and data, + * Because the stub is pre-compiled to the code running on the target. + * But it still needs memory for stub trampoline, stack, and memory arguments. + * Working areas can not be used due to possible memory layout conflicts with on-board stub code and data. + * Debug stubs functionality provided by ESP IDF allows OpenOCD to overcome the above problem. + * It provides a special descriptor which provides info necessary to safely allocate memory on target. + * @see struct esp_dbg_stubs_desc. + * That info is also used to locate memory for stub trampoline code. + * User can execute target function at any address, but @see ESP IDF debug stubs also provide a way to pass to the host + * an entry address of pre-defined registered stub functions. + * For example of an on-board code execution @see esp32_cmd_gcov() in ESP32 apptrace module. +*/ + +/** + * Algorithm image data. + * Helper struct to work with algorithms consisting of code and data segments. + */ +struct esp_algorithm_image { + /** Image. */ + struct image image; + /** BSS section size. */ + uint32_t bss_size; + /** IRAM start address in the linker script */ + uint32_t iram_org; + /** Total reserved IRAM size */ + uint32_t iram_len; + /** DRAM start address in the linker script */ + uint32_t dram_org; + /** Total reserved DRAM size */ + uint32_t dram_len; + /** IRAM DRAM address range reversed or not */ + bool reverse; +}; + +#define ESP_IMAGE_ELF_PHF_EXEC 0x1 + +/** + * Algorithm stub data. + */ +struct esp_algorithm_stub { + /** Entry addr. */ + target_addr_t entry; + /** Working area for code segment. */ + struct working_area *code; + /** Working area for data segment. */ + struct working_area *data; + /** Working area for trampoline. */ + struct working_area *tramp; + /** Working area for padding between code and data area. */ + struct working_area *padding; + /** Address of the target buffer for stub trampoline. If zero tramp->address will be used. */ + target_addr_t tramp_addr; + /** Tramp code area will be filled from dbus. + * We need to map it to the ibus to be able to initialize PC register to start algorithm execution from. + */ + target_addr_t tramp_mapped_addr; + /** Working area for stack. */ + struct working_area *stack; + /** Address of the target buffer for stack. If zero tramp->address will be used. */ + target_addr_t stack_addr; + /** Address of the log buffer */ + target_addr_t log_buff_addr; + /** Size of the log buffer */ + uint32_t log_buff_size; + /** Algorithm's arch-specific info. */ + void *ainfo; +}; + +/** + * Algorithm stub in-memory arguments. + */ +struct esp_algorithm_mem_args { + /** Memory params. */ + struct mem_param *params; + /** Number of memory params. */ + uint32_t count; +}; + +/** + * Algorithm stub register arguments. + */ +struct esp_algorithm_reg_args { + /** Algorithm register params. User args start from user_first_reg_param */ + struct reg_param *params; + /** Number of register params. */ + uint32_t count; + /** The first several reg_params can be used by stub itself (e.g. for trampoline). + * This is the index of the first reg_param available for user to pass args to algorithm stub. */ + uint32_t first_user_param; +}; + +struct esp_algorithm_run_data; + +/** + * @brief Algorithm run function. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param arg Function specific argument. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ +typedef int (*esp_algorithm_func_t)(struct target *target, struct esp_algorithm_run_data *run, void *arg); + +/** + * @brief Host part of algorithm. + * This function will be called while stub is running on target. + * It can be used for communication with stub. + * + * @param target Pointer to target. + * @param usr_arg Function specific argument. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ +typedef int (*esp_algorithm_usr_func_t)(struct target *target, void *usr_arg); + +/** + * @brief Algorithm's arguments setup function. + * This function will be called just before stub start. + * It must return when all operations with running stub are completed. + * It can be used to prepare stub memory parameters. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ +typedef int (*esp_algorithm_usr_func_init_t)(struct target *target, + struct esp_algorithm_run_data *run, + void *usr_arg); + +/** + * @brief Algorithm's arguments cleanup function. + * This function will be called just after stub exit. + * It can be used to cleanup stub memory parameters. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ +typedef void (*esp_algorithm_usr_func_done_t)(struct target *target, + struct esp_algorithm_run_data *run, + void *usr_arg); + +struct esp_algorithm_hw { + int (*algo_init)(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, va_list ap); + int (*algo_cleanup)(struct target *target, struct esp_algorithm_run_data *run); + const uint8_t *(*stub_tramp_get)(struct target *target, size_t *size); +}; + +/** + * Algorithm run data. + */ +struct esp_algorithm_run_data { + /** Algorithm completion timeout in ms. If 0, default value will be used */ + uint32_t timeout_ms; + /** Algorithm stack size. */ + uint32_t stack_size; + /** Algorithm register arguments. */ + struct esp_algorithm_reg_args reg_args; + /** Algorithm memory arguments. */ + struct esp_algorithm_mem_args mem_args; + /** Algorithm arch-specific info. For Xtensa this should point to struct xtensa_algorithm. */ + void *arch_info; + /** Algorithm return code. */ + int32_t ret_code; + /** Stub. */ + struct esp_algorithm_stub stub; + union { + struct { + /** Size of the pre-alocated on-board buffer for stub's code. */ + uint32_t code_buf_size; + /** Address of pre-compiled target buffer for stub trampoline. */ + target_addr_t code_buf_addr; + /** Size of the pre-alocated on-board buffer for stub's stack. */ + uint32_t min_stack_size; + /** Pre-compiled target buffer's addr for stack. */ + target_addr_t min_stack_addr; + } on_board; + struct esp_algorithm_image image; + }; + /** Host side algorithm function argument. */ + void *usr_func_arg; + /** Host side algorithm function. */ + esp_algorithm_usr_func_t usr_func; + /** Host side algorithm function setup routine. */ + esp_algorithm_usr_func_init_t usr_func_init; + /** Host side algorithm function cleanup routine. */ + esp_algorithm_usr_func_done_t usr_func_done; + /** Algorithm run function: see algorithm_run_xxx for example. */ + esp_algorithm_func_t algo_func; + /** HW specific API */ + const struct esp_algorithm_hw *hw; +}; + +int esp_algorithm_load_func_image(struct target *target, struct esp_algorithm_run_data *run); +int esp_algorithm_unload_func_image(struct target *target, struct esp_algorithm_run_data *run); + +int esp_algorithm_exec_func_image_va(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap); + +/** + * @brief Loads and runs stub from specified image. + * This function should be used to run external stub code on target. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param num_args Number of stub arguments that follow. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. Stub return code is in run->ret_code. + */ +static inline int esp_algorithm_run_func_image_va(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap) +{ + int ret = esp_algorithm_load_func_image(target, run); + if (ret != ERROR_OK) + return ret; + ret = esp_algorithm_exec_func_image_va(target, run, num_args, ap); + int rc = esp_algorithm_unload_func_image(target, run); + return ret != ERROR_OK ? ret : rc; +} + +static inline int esp_algorithm_run_func_image(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + ...) +{ + va_list ap; + va_start(ap, num_args); + int retval = esp_algorithm_run_func_image_va(target, run, num_args, ap); + va_end(ap); + return retval; +} + +int esp_algorithm_load_onboard_func(struct target *target, + target_addr_t func_addr, + struct esp_algorithm_run_data *run); +int esp_algorithm_unload_onboard_func(struct target *target, struct esp_algorithm_run_data *run); +int esp_algorithm_exec_onboard_func_va(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t num_args, + va_list ap); + +/** + * @brief Runs pre-compiled on-board function. + * This function should be used to run on-board stub code. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param func_entry Address of the function to run. + * @param num_args Number of function arguments that follow. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. Stub return code is in run->ret_code. + */ +static inline int esp_algorithm_run_onboard_func_va(struct target *target, + struct esp_algorithm_run_data *run, + target_addr_t func_addr, + uint32_t num_args, + va_list ap) +{ + int ret = esp_algorithm_load_onboard_func(target, func_addr, run); + if (ret != ERROR_OK) + return ret; + ret = esp_algorithm_exec_onboard_func_va(target, run, num_args, ap); + if (ret != ERROR_OK) + return ret; + return esp_algorithm_unload_onboard_func(target, run); +} + +static inline int esp_algorithm_run_onboard_func(struct target *target, + struct esp_algorithm_run_data *run, + target_addr_t func_addr, + uint32_t num_args, + ...) +{ + va_list ap; + va_start(ap, num_args); + int retval = esp_algorithm_run_onboard_func_va(target, run, func_addr, num_args, ap); + va_end(ap); + return retval; +} + +/** + * @brief Set the value of an argument passed via registers to the stub main function. + */ +static inline void esp_algorithm_user_arg_set_uint(struct esp_algorithm_run_data *run, + int arg_num, + uint64_t val) +{ + struct reg_param *param = &run->reg_args.params[run->reg_args.first_user_param + arg_num]; + + assert(param->size <= 64); + + if (param->size <= 32) + buf_set_u32(param->value, 0, param->size, val); + else + buf_set_u64(param->value, 0, param->size, val); +} + +/** + * @brief Get the value of an argument passed via registers from the stub main function. + */ +static inline uint64_t esp_algorithm_user_arg_get_uint(struct esp_algorithm_run_data *run, int arg_num) +{ + struct reg_param *param = &run->reg_args.params[run->reg_args.first_user_param + arg_num]; + + assert(param->size <= 64); + + if (param->size <= 32) + return buf_get_u32(param->value, 0, param->size); + return buf_get_u64(param->value, 0, param->size); +} + +#endif /* OPENOCD_TARGET_ESP_ALGORITHM_H */ diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c index bc4d8a21ad..f883b1ce76 100644 --- a/src/target/espressif/esp_xtensa_smp.c +++ b/src/target/espressif/esp_xtensa_smp.c @@ -16,6 +16,7 @@ #include #include "esp_xtensa_smp.h" #include "esp_xtensa_semihosting.h" +#include "esp_algorithm.h" /* Multiprocessor stuff common: @@ -495,6 +496,83 @@ int esp_xtensa_smp_watchpoint_remove(struct target *target, struct watchpoint *w return ERROR_OK; } +int esp_xtensa_smp_run_func_image(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, ...) +{ + struct target *run_target = target; + struct target_list *head; + va_list ap; + uint32_t smp_break = 0; + int res; + + if (target->smp) { + /* find first HALTED and examined core */ + foreach_smp_target(head, target->smp_targets) { + run_target = head->target; + if (target_was_examined(run_target) && run_target->state == TARGET_HALTED) + break; + } + if (!head) { + LOG_ERROR("Failed to find HALTED core!"); + return ERROR_FAIL; + } + + res = esp_xtensa_smp_smpbreak_disable(run_target, &smp_break); + if (res != ERROR_OK) + return res; + } + + va_start(ap, num_args); + int algo_res = esp_algorithm_run_func_image_va(run_target, run, num_args, ap); + va_end(ap); + + if (target->smp) { + res = esp_xtensa_smp_smpbreak_restore(run_target, smp_break); + if (res != ERROR_OK) + return res; + } + return algo_res; +} + +int esp_xtensa_smp_run_onboard_func(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t func_addr, + uint32_t num_args, + ...) +{ + struct target *run_target = target; + struct target_list *head; + va_list ap; + uint32_t smp_break = 0; + int res; + + if (target->smp) { + /* find first HALTED and examined core */ + foreach_smp_target(head, target->smp_targets) { + run_target = head->target; + if (target_was_examined(run_target) && run_target->state == TARGET_HALTED) + break; + } + if (!head) { + LOG_ERROR("Failed to find HALTED core!"); + return ERROR_FAIL; + } + res = esp_xtensa_smp_smpbreak_disable(run_target, &smp_break); + if (res != ERROR_OK) + return res; + } + + va_start(ap, num_args); + int algo_res = esp_algorithm_run_onboard_func_va(run_target, run, func_addr, num_args, ap); + va_end(ap); + + if (target->smp) { + res = esp_xtensa_smp_smpbreak_restore(run_target, smp_break); + if (res != ERROR_OK) + return res; + } + return algo_res; +} + int esp_xtensa_smp_init_arch_info(struct target *target, struct esp_xtensa_smp_common *esp_xtensa_smp, struct xtensa_debug_module_config *dm_cfg, diff --git a/src/target/espressif/esp_xtensa_smp.h b/src/target/espressif/esp_xtensa_smp.h index 4e4f3b3321..39afd8af10 100644 --- a/src/target/espressif/esp_xtensa_smp.h +++ b/src/target/espressif/esp_xtensa_smp.h @@ -9,6 +9,7 @@ #define OPENOCD_TARGET_XTENSA_ESP_SMP_H #include "esp_xtensa.h" +#include "esp_algorithm.h" struct esp_xtensa_smp_chip_ops { int (*poll)(struct target *target); @@ -47,7 +48,12 @@ int esp_xtensa_smp_init_arch_info(struct target *target, struct xtensa_debug_module_config *dm_cfg, const struct esp_xtensa_smp_chip_ops *chip_ops, const struct esp_semihost_ops *semihost_ops); - +int esp_xtensa_smp_run_func_image(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, ...); +int esp_xtensa_smp_run_onboard_func(struct target *target, + struct esp_algorithm_run_data *run, + uint32_t func_addr, + uint32_t num_args, + ...); extern const struct command_registration esp_xtensa_smp_command_handlers[]; extern const struct command_registration esp_xtensa_smp_xtensa_command_handlers[]; extern const struct command_registration esp_xtensa_smp_esp_command_handlers[]; From d06d8ea3e4d0057dd13a6dac792b1ad7c246aebb Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Mon, 10 Jul 2023 23:56:56 +0200 Subject: [PATCH 0656/1312] target/xtensa: add algorithm support Add arch level functions to execute code on the target Signed-off-by: Erhan Kurubas Change-Id: I089095de6fcb9906ad8c84232fa52a77db5e6185 Reviewed-on: https://review.openocd.org/c/openocd/+/7771 Tested-by: jenkins Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo --- src/target/xtensa/xtensa.c | 209 +++++++++++++++++++++++++++++++++++++ src/target/xtensa/xtensa.h | 25 +++++ 2 files changed, 234 insertions(+) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 85dce0614c..d2ca32c1d1 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "xtensa_chip.h" #include "xtensa.h" @@ -2635,6 +2636,214 @@ int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoin return ERROR_OK; } +int xtensa_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + void *arch_info) +{ + struct xtensa *xtensa = target_to_xtensa(target); + struct xtensa_algorithm *algorithm_info = arch_info; + int retval = ERROR_OK; + bool usr_ps = false; + + /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + + if (target->state != TARGET_HALTED) { + LOG_WARNING("Target not halted!"); + return ERROR_TARGET_NOT_HALTED; + } + + for (unsigned int i = 0; i < xtensa->core_cache->num_regs; i++) { + struct reg *reg = &xtensa->core_cache->reg_list[i]; + buf_cpy(reg->value, xtensa->algo_context_backup[i], reg->size); + } + /* save debug reason, it will be changed */ + algorithm_info->ctx_debug_reason = target->debug_reason; + /* write mem params */ + for (int i = 0; i < num_mem_params; i++) { + if (mem_params[i].direction != PARAM_IN) { + retval = target_write_buffer(target, mem_params[i].address, + mem_params[i].size, + mem_params[i].value); + if (retval != ERROR_OK) + return retval; + } + } + /* write reg params */ + for (int i = 0; i < num_reg_params; i++) { + if (reg_params[i].size > 32) { + LOG_ERROR("BUG: not supported register size (%d)", reg_params[i].size); + return ERROR_FAIL; + } + struct reg *reg = register_get_by_name(xtensa->core_cache, reg_params[i].reg_name, 0); + if (!reg) { + LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + return ERROR_FAIL; + } + if (reg->size != reg_params[i].size) { + LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); + return ERROR_FAIL; + } + if (memcmp(reg_params[i].reg_name, "ps", 3)) { + usr_ps = true; + } else { + unsigned int reg_id = xtensa->eps_dbglevel_idx; + assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!"); + reg = &xtensa->core_cache->reg_list[reg_id]; + } + xtensa_reg_set_value(reg, buf_get_u32(reg_params[i].value, 0, reg->size)); + reg->valid = 1; + } + /* ignore custom core mode if custom PS value is specified */ + if (!usr_ps) { + unsigned int eps_reg_idx = xtensa->eps_dbglevel_idx; + xtensa_reg_val_t ps = xtensa_reg_get(target, eps_reg_idx); + enum xtensa_mode core_mode = XT_PS_RING_GET(ps); + if (algorithm_info->core_mode != XT_MODE_ANY && algorithm_info->core_mode != core_mode) { + LOG_DEBUG("setting core_mode: 0x%x", algorithm_info->core_mode); + xtensa_reg_val_t new_ps = (ps & ~XT_PS_RING_MSK) | XT_PS_RING(algorithm_info->core_mode); + /* save previous core mode */ + /* TODO: core_mode is not restored for now. Can be added to the end of wait_algorithm */ + algorithm_info->core_mode = core_mode; + xtensa_reg_set(target, eps_reg_idx, new_ps); + xtensa->core_cache->reg_list[eps_reg_idx].valid = 1; + } + } + + return xtensa_resume(target, 0, entry_point, 1, 1); +} + +/** Waits for an algorithm in the target. */ +int xtensa_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t exit_point, unsigned int timeout_ms, + void *arch_info) +{ + struct xtensa *xtensa = target_to_xtensa(target); + struct xtensa_algorithm *algorithm_info = arch_info; + int retval = ERROR_OK; + xtensa_reg_val_t pc; + + /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + + retval = target_wait_state(target, TARGET_HALTED, timeout_ms); + /* If the target fails to halt due to the breakpoint, force a halt */ + if (retval != ERROR_OK || target->state != TARGET_HALTED) { + retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + retval = target_wait_state(target, TARGET_HALTED, 500); + if (retval != ERROR_OK) + return retval; + LOG_TARGET_ERROR(target, "not halted %d, pc 0x%" PRIx32 ", ps 0x%" PRIx32, retval, + xtensa_reg_get(target, XT_REG_IDX_PC), + xtensa_reg_get(target, xtensa->eps_dbglevel_idx)); + return ERROR_TARGET_TIMEOUT; + } + pc = xtensa_reg_get(target, XT_REG_IDX_PC); + if (exit_point && pc != exit_point) { + LOG_ERROR("failed algorithm halted at 0x%" PRIx32 ", expected " TARGET_ADDR_FMT, pc, exit_point); + return ERROR_TARGET_TIMEOUT; + } + /* Copy core register values to reg_params[] */ + for (int i = 0; i < num_reg_params; i++) { + if (reg_params[i].direction != PARAM_OUT) { + struct reg *reg = register_get_by_name(xtensa->core_cache, reg_params[i].reg_name, 0); + if (!reg) { + LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + return ERROR_FAIL; + } + if (reg->size != reg_params[i].size) { + LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); + return ERROR_FAIL; + } + buf_set_u32(reg_params[i].value, 0, 32, xtensa_reg_get_value(reg)); + } + } + /* Read memory values to mem_params */ + LOG_DEBUG("Read mem params"); + for (int i = 0; i < num_mem_params; i++) { + LOG_DEBUG("Check mem param @ " TARGET_ADDR_FMT, mem_params[i].address); + if (mem_params[i].direction != PARAM_OUT) { + LOG_DEBUG("Read mem param @ " TARGET_ADDR_FMT, mem_params[i].address); + retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); + if (retval != ERROR_OK) + return retval; + } + } + + /* avoid gdb keep_alive warning */ + keep_alive(); + + for (int i = xtensa->core_cache->num_regs - 1; i >= 0; i--) { + struct reg *reg = &xtensa->core_cache->reg_list[i]; + if (i == XT_REG_IDX_PS) { + continue; /* restore mapped reg number of PS depends on NDEBUGLEVEL */ + } else if (i == XT_REG_IDX_DEBUGCAUSE) { + /*FIXME: restoring DEBUGCAUSE causes exception when executing corresponding + * instruction in DIR */ + LOG_DEBUG("Skip restoring register %s: 0x%8.8" PRIx32 " -> 0x%8.8" PRIx32, + xtensa->core_cache->reg_list[i].name, + buf_get_u32(reg->value, 0, 32), + buf_get_u32(xtensa->algo_context_backup[i], 0, 32)); + buf_cpy(xtensa->algo_context_backup[i], reg->value, reg->size); + xtensa->core_cache->reg_list[i].dirty = 0; + xtensa->core_cache->reg_list[i].valid = 0; + } else if (memcmp(xtensa->algo_context_backup[i], reg->value, reg->size / 8)) { + if (reg->size <= 32) { + LOG_DEBUG("restoring register %s: 0x%8.8" PRIx32 " -> 0x%8.8" PRIx32, + xtensa->core_cache->reg_list[i].name, + buf_get_u32(reg->value, 0, reg->size), + buf_get_u32(xtensa->algo_context_backup[i], 0, reg->size)); + } else if (reg->size <= 64) { + LOG_DEBUG("restoring register %s: 0x%8.8" PRIx64 " -> 0x%8.8" PRIx64, + xtensa->core_cache->reg_list[i].name, + buf_get_u64(reg->value, 0, reg->size), + buf_get_u64(xtensa->algo_context_backup[i], 0, reg->size)); + } else { + LOG_DEBUG("restoring register %s %u-bits", xtensa->core_cache->reg_list[i].name, reg->size); + } + buf_cpy(xtensa->algo_context_backup[i], reg->value, reg->size); + xtensa->core_cache->reg_list[i].dirty = 1; + xtensa->core_cache->reg_list[i].valid = 1; + } + } + target->debug_reason = algorithm_info->ctx_debug_reason; + + retval = xtensa_write_dirty_registers(target); + if (retval != ERROR_OK) + LOG_ERROR("Failed to write dirty regs (%d)!", retval); + + return retval; +} + +int xtensa_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + unsigned int timeout_ms, void *arch_info) +{ + int retval = xtensa_start_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, exit_point, + arch_info); + + if (retval == ERROR_OK) { + retval = xtensa_wait_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, timeout_ms, + arch_info); + } + + return retval; +} + static int xtensa_build_reg_cache(struct target *target) { struct xtensa *xtensa = target_to_xtensa(target); diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 4216ae24f6..3b37122d6b 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -222,6 +222,16 @@ struct xtensa_sw_breakpoint { uint8_t insn_sz; /* 2 or 3 bytes */ }; +/** + * Xtensa algorithm data. + */ +struct xtensa_algorithm { + /** User can set this to specify which core mode algorithm should be run in. */ + enum xtensa_mode core_mode; + /** Used internally to backup and restore debug_reason. */ + enum target_debug_reason ctx_debug_reason; +}; + #define XTENSA_COMMON_MAGIC 0x54E4E555U /** @@ -395,6 +405,21 @@ int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint); int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint); int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint); int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint); +int xtensa_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + void *arch_info); +int xtensa_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t exit_point, unsigned int timeout_ms, + void *arch_info); +int xtensa_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + unsigned int timeout_ms, void *arch_info); void xtensa_set_permissive_mode(struct target *target, bool state); const char *xtensa_get_gdb_arch(struct target *target); int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p); From 4003762177b1aec2ab27eaa6946b47f13c457bbc Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Mon, 10 Jul 2023 23:47:06 +0200 Subject: [PATCH 0657/1312] target/espressif: add algorithm support to xtensa chips Also includes esp_xtensa flasher stub jumper binary. Signed-off-by: Erhan Kurubas Change-Id: I054ce31033ca6a87afe9b5325b545338a7d8fe8f Reviewed-on: https://review.openocd.org/c/openocd/+/7772 Tested-by: jenkins Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo --- .../trampoline/espressif/xtensa/Makefile | 38 +++++ .../xtensa/esp_xtensa_stub_tramp_win.S | 41 +++++ .../xtensa/esp_xtensa_stub_tramp_win.inc | 3 + src/target/espressif/Makefile.am | 2 + src/target/espressif/esp.c | 10 ++ src/target/espressif/esp.h | 2 + src/target/espressif/esp32.c | 4 + src/target/espressif/esp32s2.c | 4 + src/target/espressif/esp32s3.c | 4 + src/target/espressif/esp_xtensa.c | 8 +- src/target/espressif/esp_xtensa_algorithm.c | 140 ++++++++++++++++++ src/target/espressif/esp_xtensa_algorithm.h | 19 +++ 12 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 contrib/loaders/trampoline/espressif/xtensa/Makefile create mode 100644 contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S create mode 100644 contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc create mode 100644 src/target/espressif/esp_xtensa_algorithm.c create mode 100644 src/target/espressif/esp_xtensa_algorithm.h diff --git a/contrib/loaders/trampoline/espressif/xtensa/Makefile b/contrib/loaders/trampoline/espressif/xtensa/Makefile new file mode 100644 index 0000000000..bd1f630449 --- /dev/null +++ b/contrib/loaders/trampoline/espressif/xtensa/Makefile @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Espressif Xtensa Makefile to compile flasher stub wrapper +# Copyright (C) 2023 Espressif Systems Ltd. + +# Prefix for Espressif xtensa cross compilers (can include a directory path) +CROSS ?= xtensa-esp32-elf- + +APP_ARCH := xtensa +APP_CHIP_PATH := $(shell pwd) +SRCS := $(APP_CHIP_PATH)/esp_xtensa_stub_tramp_win.S + +BIN2C = ../../../../../src/helper/bin2char.sh +BUILD_DIR = build + +APP = esp_xtensa_stub_tramp_win +APP_OBJ = $(BUILD_DIR)/$(APP).o +APP_BIN = $(BUILD_DIR)/$(APP).bin +APP_CODE = $(APP).inc + +.PHONY: all clean + +all: $(BUILD_DIR) $(APP_OBJ) $(APP_CODE) + +$(BUILD_DIR): + $(Q) mkdir $@ + +$(APP_OBJ): $(SRCS) + @echo " CC $^ -> $@" + $(Q) $(CROSS)gcc -c $(CFLAGS) -o $@ $^ + +$(APP_CODE): $(APP_OBJ) + @echo " CC $^ -> $@" + $(Q) $(CROSS)objcopy -O binary -j.text $^ $(APP_BIN) + $(Q) $(BIN2C) < $(APP_BIN) > $@ + +clean: + $(Q) rm -rf $(BUILD_DIR) diff --git a/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S new file mode 100644 index 0000000000..e0c827d9f3 --- /dev/null +++ b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/*************************************************************************** + * Xtensa flasher stub wrapper * + * Copyright (C) 2017 Espressif Systems Ltd. * + ***************************************************************************/ + +/* + * Expects : + * a0 = zero + * a1 = stack_base + stack_size - 16, 16 bytes aligned + * a8 = address of the function to call + * Params : + * a2 = command arg0, result (out) + * a3 = command arg1 + * a4 = command arg2 + * a5 = command arg3 + * a6 = command arg4 + * Maximum 5 user args + */ + .text + + .align 4 +_stub_enter: + /* initialize initial stack frame for callx8 */ + addi a9, sp, 32 /* point 16 past extra save area */ + s32e a9, sp, -12 /* access to extra save area */ + /* prepare args */ + mov a10, a2 + mov a11, a3 + mov a12, a4 + mov a13, a5 + mov a14, a6 + /* call stub */ + callx8 a8 + /* prepare return value */ + mov a2, a10 + break 0,0 + +_idle_loop: + j _idle_loop diff --git a/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc new file mode 100644 index 0000000000..1657223e1b --- /dev/null +++ b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc @@ -0,0 +1,3 @@ +/* Autogenerated with ../../../../../src/helper/bin2char.sh */ +0x92,0xc1,0x20,0x90,0xd1,0x49,0xad,0x02,0xbd,0x03,0xcd,0x04,0xdd,0x05,0x60,0xe6, +0x20,0xe0,0x08,0x00,0x2d,0x0a,0x00,0x40,0x00,0x06,0xff,0xff, diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am index 1fbd926d9d..cf82ee995e 100644 --- a/src/target/espressif/Makefile.am +++ b/src/target/espressif/Makefile.am @@ -10,6 +10,8 @@ noinst_LTLIBRARIES += %D%/libespressif.la %D%/esp_xtensa_semihosting.h \ %D%/esp_xtensa_apptrace.c \ %D%/esp_xtensa_apptrace.h \ + %D%/esp_xtensa_algorithm.c \ + %D%/esp_xtensa_algorithm.h \ %D%/esp32_apptrace.c \ %D%/esp32_apptrace.h \ %D%/esp32.c \ diff --git a/src/target/espressif/esp.c b/src/target/espressif/esp.c index 9583d6493e..600f6d7e99 100644 --- a/src/target/espressif/esp.c +++ b/src/target/espressif/esp.c @@ -14,6 +14,16 @@ #include "target/target.h" #include "esp.h" +int esp_common_init(struct esp_common *esp, const struct esp_algorithm_hw *algo_hw) +{ + if (!esp) + return ERROR_FAIL; + + esp->algo_hw = algo_hw; + + return ERROR_OK; +} + int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs) { uint32_t table_size, table_start_id, desc_entry_id, gcov_entry_id; diff --git a/src/target/espressif/esp.h b/src/target/espressif/esp.h index 3ba2b8bcfa..6e0a2d2d35 100644 --- a/src/target/espressif/esp.h +++ b/src/target/espressif/esp.h @@ -77,9 +77,11 @@ struct esp_dbg_stubs { }; struct esp_common { + const struct esp_algorithm_hw *algo_hw; struct esp_dbg_stubs dbg_stubs; }; +int esp_common_init(struct esp_common *esp, const struct esp_algorithm_hw *algo_hw); int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs); #endif /* OPENOCD_TARGET_ESP_H */ diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index b510f287c3..324aa3993b 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -484,6 +484,10 @@ struct target_type esp32_target = { .get_gdb_arch = xtensa_get_gdb_arch, .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = esp_xtensa_breakpoint_add, .remove_breakpoint = esp_xtensa_breakpoint_remove, diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index dadc130c1a..2abde479ea 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -521,6 +521,10 @@ struct target_type esp32s2_target = { .get_gdb_arch = xtensa_get_gdb_arch, .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = esp_xtensa_breakpoint_add, .remove_breakpoint = esp_xtensa_breakpoint_remove, diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 5036956ee8..22e1630e16 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -405,6 +405,10 @@ struct target_type esp32s3_target = { .get_gdb_arch = xtensa_get_gdb_arch, .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = esp_xtensa_breakpoint_add, .remove_breakpoint = esp_xtensa_breakpoint_remove, diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index 0bd2cdd9dd..11895d23bb 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -12,10 +12,12 @@ #include #include #include -#include "esp_xtensa_apptrace.h" #include +#include "esp.h" #include "esp_xtensa.h" +#include "esp_xtensa_apptrace.h" #include "esp_semihosting.h" +#include "esp_xtensa_algorithm.h" #define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_) \ do { \ @@ -68,6 +70,10 @@ int esp_xtensa_init_arch_info(struct target *target, int ret = xtensa_init_arch_info(target, &esp_xtensa->xtensa, dm_cfg); if (ret != ERROR_OK) return ret; + ret = esp_common_init(&esp_xtensa->esp, &xtensa_algo_hw); + if (ret != ERROR_OK) + return ret; + esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops; esp_xtensa->apptrace.hw = &esp_xtensa_apptrace_hw; return ERROR_OK; diff --git a/src/target/espressif/esp_xtensa_algorithm.c b/src/target/espressif/esp_xtensa_algorithm.c new file mode 100644 index 0000000000..68005cbf2c --- /dev/null +++ b/src/target/espressif/esp_xtensa_algorithm.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/*************************************************************************** + * Module to run arbitrary code on Xtensa using OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "esp_xtensa_algorithm.h" + +static int esp_xtensa_algo_init(struct target *target, struct esp_algorithm_run_data *run, + uint32_t num_args, va_list ap); +static int esp_xtensa_algo_cleanup(struct target *target, struct esp_algorithm_run_data *run); +static const uint8_t *esp_xtensa_stub_tramp_get(struct target *target, size_t *size); + +const struct esp_algorithm_hw xtensa_algo_hw = { + .algo_init = esp_xtensa_algo_init, + .algo_cleanup = esp_xtensa_algo_cleanup, + .stub_tramp_get = esp_xtensa_stub_tramp_get, +}; + +/* Generated from contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S */ +static const uint8_t esp_xtensa_stub_tramp_win[] = { +#include "../../../contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc" +}; + +static const uint8_t *esp_xtensa_stub_tramp_get(struct target *target, size_t *size) +{ + struct xtensa *xtensa = target_to_xtensa(target); + + if (!xtensa->core_config->windowed) { + LOG_ERROR("Running stubs is not supported for cores without windowed registers option!"); + return NULL; + } + *size = sizeof(esp_xtensa_stub_tramp_win); + return esp_xtensa_stub_tramp_win; +} + +static int esp_xtensa_algo_regs_init_start(struct target *target, struct esp_algorithm_run_data *run) +{ + uint32_t stack_addr = run->stub.stack_addr; + + LOG_TARGET_DEBUG(target, "Check stack addr 0x%x", stack_addr); + if (stack_addr & 0xFUL) { + stack_addr &= ~0xFUL; + LOG_TARGET_DEBUG(target, "Adjust stack addr to 0x%x", stack_addr); + } + stack_addr -= 16; + struct reg_param *params = run->reg_args.params; + init_reg_param(¶ms[0], "a0", 32, PARAM_OUT); /*TODO: move to tramp */ + init_reg_param(¶ms[1], "a1", 32, PARAM_OUT); + init_reg_param(¶ms[2], "a8", 32, PARAM_OUT); + init_reg_param(¶ms[3], "windowbase", 32, PARAM_OUT); /*TODO: move to tramp */ + init_reg_param(¶ms[4], "windowstart", 32, PARAM_OUT); /*TODO: move to tramp */ + init_reg_param(¶ms[5], "ps", 32, PARAM_OUT); + buf_set_u32(params[0].value, 0, 32, 0); /* a0 TODO: move to tramp */ + buf_set_u32(params[1].value, 0, 32, stack_addr); /* a1 */ + buf_set_u32(params[2].value, 0, 32, run->stub.entry); /* a8 */ + buf_set_u32(params[3].value, 0, 32, 0x0); /* initial window base TODO: move to tramp */ + buf_set_u32(params[4].value, 0, 32, 0x1); /* initial window start TODO: move to tramp */ + buf_set_u32(params[5].value, 0, 32, 0x60025); /* enable WOE, UM and debug interrupts level (6) */ + return ERROR_OK; +} + +static int esp_xtensa_algo_init(struct target *target, struct esp_algorithm_run_data *run, + uint32_t num_args, va_list ap) +{ + enum xtensa_mode core_mode = XT_MODE_ANY; + static const char *const arg_regs[] = { "a2", "a3", "a4", "a5", "a6" }; + + if (!run) + return ERROR_FAIL; + + if (num_args > ARRAY_SIZE(arg_regs)) { + LOG_ERROR("Too many algo user args %u! Max %zu args are supported.", num_args, ARRAY_SIZE(arg_regs)); + return ERROR_FAIL; + } + + struct xtensa_algorithm *ainfo = calloc(1, sizeof(struct xtensa_algorithm)); + if (!ainfo) { + LOG_ERROR("Unable to allocate memory"); + return ERROR_FAIL; + } + + if (run->arch_info) { + struct xtensa_algorithm *xtensa_algo = run->arch_info; + core_mode = xtensa_algo->core_mode; + } + + run->reg_args.first_user_param = ESP_XTENSA_STUB_ARGS_FUNC_START; + run->reg_args.count = run->reg_args.first_user_param + num_args; + if (num_args == 0) + run->reg_args.count++; /* a2 reg is used as the 1st arg and return code */ + LOG_DEBUG("reg params count %d (%d/%d).", + run->reg_args.count, + run->reg_args.first_user_param, + num_args); + run->reg_args.params = calloc(run->reg_args.count, sizeof(struct reg_param)); + if (!run->reg_args.params) { + free(ainfo); + LOG_ERROR("Unable to allocate memory"); + return ERROR_FAIL; + } + + esp_xtensa_algo_regs_init_start(target, run); + + init_reg_param(&run->reg_args.params[run->reg_args.first_user_param + 0], "a2", 32, PARAM_IN_OUT); + + if (num_args > 0) { + uint32_t arg = va_arg(ap, uint32_t); + esp_algorithm_user_arg_set_uint(run, 0, arg); + LOG_DEBUG("Set arg[0] = %d (%s)", arg, run->reg_args.params[run->reg_args.first_user_param + 0].reg_name); + } else { + esp_algorithm_user_arg_set_uint(run, 0, 0); + } + + for (unsigned int i = 1; i < num_args; i++) { + uint32_t arg = va_arg(ap, uint32_t); + init_reg_param(&run->reg_args.params[run->reg_args.first_user_param + i], (char *)arg_regs[i], 32, PARAM_OUT); + esp_algorithm_user_arg_set_uint(run, i, arg); + LOG_DEBUG("Set arg[%d] = %d (%s)", i, arg, run->reg_args.params[run->reg_args.first_user_param + i].reg_name); + } + + ainfo->core_mode = core_mode; + run->stub.ainfo = ainfo; + return ERROR_OK; +} + +static int esp_xtensa_algo_cleanup(struct target *target, struct esp_algorithm_run_data *run) +{ + free(run->stub.ainfo); + for (uint32_t i = 0; i < run->reg_args.count; i++) + destroy_reg_param(&run->reg_args.params[i]); + free(run->reg_args.params); + return ERROR_OK; +} diff --git a/src/target/espressif/esp_xtensa_algorithm.h b/src/target/espressif/esp_xtensa_algorithm.h new file mode 100644 index 0000000000..36fa1a331b --- /dev/null +++ b/src/target/espressif/esp_xtensa_algorithm.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/*************************************************************************** + * Module to run arbitrary code on Xtensa using OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ESP_XTENSA_ALGO_H +#define OPENOCD_TARGET_ESP_XTENSA_ALGO_H + +#include +#include + +/** Index of the first user-defined algo arg. @see algorithm_stub */ +#define ESP_XTENSA_STUB_ARGS_FUNC_START 6 + +extern const struct esp_algorithm_hw xtensa_algo_hw; + +#endif /* OPENOCD_TARGET_XTENSA_ALGO_H */ From 0ce08ec858add3e26ba04536b87fad680561fe50 Mon Sep 17 00:00:00 2001 From: Kirill Radkin Date: Tue, 31 Oct 2023 18:24:35 +0300 Subject: [PATCH 0658/1312] target: Add some info messages about examination process. These messages helps to clarify current status of examination process Change-Id: I5d93903c4680deed2c1bf707d8f7ef0b48ffdc9a Signed-off-by: Kirill Radkin Reviewed-on: https://review.openocd.org/c/openocd/+/8013 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/target/target.c b/src/target/target.c index f847894d69..2703f7b00a 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -675,10 +675,14 @@ static int default_check_reset(struct target *target) * Keep in sync */ int target_examine_one(struct target *target) { + LOG_TARGET_DEBUG(target, "Examination started"); + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); int retval = target->type->examine(target); if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "Examination failed"); + LOG_TARGET_DEBUG(target, "examine() returned error code %d", retval); target_reset_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_FAIL); return retval; @@ -687,6 +691,7 @@ int target_examine_one(struct target *target) target_set_examined(target); target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); + LOG_TARGET_INFO(target, "Examination succeed"); return ERROR_OK; } From 2bd40b0bf930459f0fc3dbcbde3ac2f40ff56e4e Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Wed, 22 Nov 2023 09:57:06 +0000 Subject: [PATCH 0659/1312] target: Increase maximum profile sample count to 1000000 Change-Id: I38276dd1af011ce5781b0264b7cbb08c31a0a2ad Signed-off-by: Paul Reimer Signed-off-by: Karl Palsson Reviewed-on: https://review.openocd.org/c/openocd/+/6099 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 2 +- src/target/target.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index db7315fe44..6c6519d625 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9492,7 +9492,7 @@ TCP/IP port 9090. @deffn {Command} {profile} seconds filename [start end] Profiling samples the CPU's program counter as quickly as possible, which is useful for non-intrusive stochastic profiling. -Saves up to 10000 samples in @file{filename} using ``gmon.out'' +Saves up to 1000000 samples in @file{filename} using ``gmon.out'' format. Optional @option{start} and @option{end} parameters allow to limit the address range. @end deffn diff --git a/src/target/target.c b/src/target/target.c index 2703f7b00a..d7283324ff 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4298,7 +4298,7 @@ COMMAND_HANDLER(handle_profile_command) if ((CMD_ARGC != 2) && (CMD_ARGC != 4)) return ERROR_COMMAND_SYNTAX_ERROR; - const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000; + const uint32_t MAX_PROFILE_SAMPLE_NUM = 1000000; uint32_t offset; uint32_t num_of_samples; int retval = ERROR_OK; From 5f6b25aa91eb81903aed128ee304ffc69e0492f3 Mon Sep 17 00:00:00 2001 From: Peter Lawrence Date: Wed, 15 Nov 2023 09:58:24 -0600 Subject: [PATCH 0660/1312] tcl/target/at91sama5d2.cfg: allow choice of SWD instead of JTAG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The target supports both SWD and JTAG, but the existing cfg file only supports JTAG. Using the standard [using_jtag] mechanism, the user would now have a choice. Change-Id: Ic6adb68090422812d591f6bf5b945ac10f323c74 Signed-off-by: Peter Lawrence Reviewed-on: https://review.openocd.org/c/openocd/+/8020 Reviewed-by: Jörg Wunsch Reviewed-by: Paul Fertser Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/at91sama5d2.cfg | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tcl/target/at91sama5d2.cfg b/tcl/target/at91sama5d2.cfg index 65e5217e1e..30ddc92a9d 100644 --- a/tcl/target/at91sama5d2.cfg +++ b/tcl/target/at91sama5d2.cfg @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later # +# SAMA5D2 devices support both JTAG and SWD transports. +# # The JTAG connection is disabled at reset, and during the ROM Code execution. # It is re-enabled when the ROM code jumps in the boot file copied from an # external Flash memory into the internalSRAM, or when the ROM code launches @@ -12,14 +14,28 @@ # - if enabled, boundary Scan mode is activated. JTAG ID Code value is 0x05B3F03F. # - if disabled, ICE mode is activated. Debug Port JTAG IDCODE value is 0x5BA00477 # + +source [find target/swj-dp.tcl] + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + set _CPUTAPID 0x5ba00477 + } else { + # SWD IDCODE (single drop, arm) + set _CPUTAPID 0x5ba02477 + } +} + if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME at91sama5d2 } -jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x0f \ - -expected-id 0x5ba00477 +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID # Cortex-A5 target set _TARGETNAME $_CHIPNAME.cpu_a5 From c1ae95f6f55168a15a7cf359c1d4c5f1d4b04c01 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 1 Dec 2023 23:49:35 +0100 Subject: [PATCH 0661/1312] HACKING: fix how to retrieve hooks/commit-msg Probably due to new version of gerrit, the download of the gerrit hooks via scp is not working anymore. Also the instructions available, after login, in https://review.openocd.org/admin/repos/openocd,general report that the hook file has to be downloaded via https also when the user want to use ssh for gerrit access. Drop scp in the suggestions to download the hook file and keep https download only. Change-Id: I0c8e5bb61ed8c7423a42a0d5d92866e071a814bb Signed-off-by: Antonio Borneo Reported-by: Rolf Nooteboom Reviewed-on: https://review.openocd.org/c/openocd/+/8034 Tested-by: jenkins Reviewed-by: Paul Fertser --- HACKING | 4 ---- 1 file changed, 4 deletions(-) diff --git a/HACKING b/HACKING index fbc0eae939..74cbe02e74 100644 --- a/HACKING +++ b/HACKING @@ -155,10 +155,6 @@ topics. It is possible because @c for/master is not a traditional Git branch. -# You will need to install this hook, we will look into a better solution: @code -scp -p -P 29418 USERNAME@review.openocd.org:hooks/commit-msg .git/hooks/ -@endcode - Or with http only: -@code wget https://review.openocd.org/tools/hooks/commit-msg mv commit-msg .git/hooks chmod +x .git/hooks/commit-msg From 3413ae67ae4b886f240c57af8bf562fb0ba8ce76 Mon Sep 17 00:00:00 2001 From: Samuel Dewan Date: Fri, 1 Dec 2023 14:16:22 -0500 Subject: [PATCH 0662/1312] cmsis_dap_usb_hid: improve detection of probes with unusual report sizes Currently all Atmel CMSIS-DAP interfaces are assumed to have 512 byte reports except for the mEDBG (found on Xplained Mini boards) and the nEDBG (found on Curiosity Nano boards). This check is far from exaustive and it results in some Microchip programmers (like the MPLAB Snap and PICkit 4) not working correctly with OpenOCD. Instead of assuming that Atmel programmers have 512 byte reports unless we know otherwise, this commit flips the logic around. Only the older "third generation" EDBG based programmers have 512 byte report sizes, and that 64 bytes will be more common in Microchip tools going forward. The list of PIDs for 3rd generation Microchip programmers comes from toolinfo.py from Microchip's pyedbglib. This commit adds a more generic "quirks" list that will allow programmers with unusual report sizes to be added easily in the future. Change-Id: Ic39a4bdcd67c4c93d5707657c6ee5d216bc4437a Signed-off-by: Samuel Dewan Reviewed-on: https://review.openocd.org/c/openocd/+/8033 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/cmsis_dap_usb_hid.c | 44 ++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 1decc7156d..98ccc3e381 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -34,6 +34,36 @@ struct cmsis_dap_backend_data { hid_device *dev_handle; }; +struct cmsis_dap_report_size { + unsigned short vid; + unsigned short pid; + unsigned int report_size; +}; + +static const struct cmsis_dap_report_size report_size_quirks[] = { + /* Third gen Atmel tools use a report size of 512 */ + /* This list of PIDs comes from toolinfo.py in Microchip's pyedbglib. */ + // Atmel JTAG-ICE 3 + { .vid = 0x03eb, .pid = 0x2140, .report_size = 512 }, + // Atmel-ICE + { .vid = 0x03eb, .pid = 0x2141, .report_size = 512 }, + // Atmel Power Debugger + { .vid = 0x03eb, .pid = 0x2144, .report_size = 512 }, + // EDBG (found on Xplained Pro boards) + { .vid = 0x03eb, .pid = 0x2111, .report_size = 512 }, + // Zero (???) + { .vid = 0x03eb, .pid = 0x2157, .report_size = 512 }, + // EDBG with Mass Storage (found on Xplained Pro boards) + { .vid = 0x03eb, .pid = 0x2169, .report_size = 512 }, + // Commercially available EDBG (for third-party use) + { .vid = 0x03eb, .pid = 0x216a, .report_size = 512 }, + // Kraken (???) + { .vid = 0x03eb, .pid = 0x2170, .report_size = 512 }, + + { .vid = 0, .pid = 0, .report_size = 0 } +}; + + static void cmsis_dap_hid_close(struct cmsis_dap *dap); static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz); static void cmsis_dap_hid_free(struct cmsis_dap *dap); @@ -139,13 +169,15 @@ static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p unsigned int packet_size = 64; - /* atmel cmsis-dap uses 512 byte reports */ - /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained - * board */ + /* Check for adapters that are known to have unusual report lengths. */ + for (i = 0; report_size_quirks[i].vid != 0; i++) { + if (report_size_quirks[i].vid == target_vid && + report_size_quirks[i].pid == target_pid) { + packet_size = report_size_quirks[i].report_size; + } + } /* TODO: HID report descriptor should be parsed instead of - * hardcoding a match by VID */ - if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175) - packet_size = 512; + * hardcoding a match by VID/PID */ dap->bdata->dev_handle = dev; From 49348f1ce10049c3102bf23b2af9d4965423faa1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Dec 2023 11:34:03 +0100 Subject: [PATCH 0663/1312] target: use bool for backup_working_area The field backup_working_area is always used as a boolean value. Use bool type for backup_working_area. Change-Id: I55c68d717dbbe9e5caf60fd1db368527c6d1b995 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8036 Tested-by: jenkins Reviewed-by: zapb --- src/target/target.c | 8 ++++---- src/target/target.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index d7283324ff..bb773f6a5c 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5450,13 +5450,13 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; - /* make this exactly 1 or 0 */ - target->backup_working_area = (!!w); + /* make this boolean */ + target->backup_working_area = (w != 0); } else { if (goi->argc != 0) goto no_params; } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area ? 1 : 0)); /* loop for more e*/ break; @@ -6181,7 +6181,7 @@ static int target_create(struct jim_getopt_info *goi) target->working_area = 0x0; target->working_area_size = 0x0; target->working_areas = NULL; - target->backup_working_area = 0; + target->backup_working_area = false; target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED; diff --git a/src/target/target.h b/src/target/target.h index 28a2008074..6caf598874 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -148,7 +148,7 @@ struct target { bool working_area_phys_spec; /* physical address specified? */ target_addr_t working_area_phys; /* physical address */ uint32_t working_area_size; /* size in bytes */ - uint32_t backup_working_area; /* whether the content of the working area has to be preserved */ + bool backup_working_area; /* whether the content of the working area has to be preserved */ struct working_area *working_areas;/* list of allocated working areas */ enum target_debug_reason debug_reason;/* reason why the target entered debug state */ enum target_endianness endianness; /* target endianness */ From d3d287bf676573fcbb6d6df3becfb4b3392df3db Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 4 Dec 2023 00:29:56 +0100 Subject: [PATCH 0664/1312] helper: nvp: minor fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix incorrect reference for original file. Fix copy-paste example. Change-Id: I1ea7909ca241611122f93ca11a4c94c97674b430 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8037 Tested-by: jenkins Reviewed-by: Henrik Nordström --- src/helper/nvp.c | 2 +- src/helper/nvp.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/helper/nvp.c b/src/helper/nvp.c index 7a8abc2e23..a938716ae9 100644 --- a/src/helper/nvp.c +++ b/src/helper/nvp.c @@ -14,7 +14,7 @@ * Copyright 2009 David Brownell * Copyright (c) 2005-2011 Jim Tcl Project. All rights reserved. * - * This file is extracted from jim_nvp.c, originally part of jim TCL code. + * This file is extracted from jim-nvp.c, originally part of jim TCL code. */ #ifdef HAVE_CONFIG_H diff --git a/src/helper/nvp.h b/src/helper/nvp.h index 14bd9b028c..1f4e3d1b43 100644 --- a/src/helper/nvp.h +++ b/src/helper/nvp.h @@ -14,7 +14,7 @@ * Copyright 2009 David Brownell * Copyright (c) 2005-2011 Jim Tcl Project. All rights reserved. * - * This file is extracted from jim_nvp.h, originally part of jim TCL code. + * This file is extracted from jim-nvp.h, originally part of jim TCL code. */ #ifndef OPENOCD_HELPER_NVP_H @@ -51,7 +51,7 @@ * returns &yn[0]; * result = nvp_name2value(yn, "no"); * returns &yn[1]; - * result = jim_nvp_name2value(yn, "Blah"); + * result = nvp_name2value(yn, "Blah"); * returns &yn[4]; * \endcode * From f018cd7d90243ab29c3cad25caf6932d1f1b83ea Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 6 Dec 2023 18:08:50 +0100 Subject: [PATCH 0665/1312] jtag: Rename 'hasidcode' to 'has_idcode' While at it, fix some coding style issues. Change-Id: I8196045f46ce043ed0d28cb95470132b3a7de1bb Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8039 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/xcf.c | 2 +- src/jtag/core.c | 6 +++--- src/jtag/hla/hla_interface.c | 2 +- src/jtag/jtag.h | 2 +- src/pld/intel.c | 2 +- src/pld/lattice.c | 4 ++-- src/target/dsp563xx.c | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/flash/nor/xcf.c b/src/flash/nor/xcf.c index 2870725514..c253b2264b 100644 --- a/src/flash/nor/xcf.c +++ b/src/flash/nor/xcf.c @@ -597,7 +597,7 @@ static int xcf_probe(struct flash_bank *bank) } /* check idcode and alloc memory for sector table */ - if (!bank->target->tap->hasidcode) + if (!bank->target->tap->has_idcode) return ERROR_FLASH_OPERATION_FAILED; /* guess number of blocks using chip ID */ diff --git a/src/jtag/core.c b/src/jtag/core.c index 5748011875..665a932190 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1177,7 +1177,7 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) { - if (tap->expected_ids_cnt == 0 || !tap->hasidcode) + if (tap->expected_ids_cnt == 0 || !tap->has_idcode) return true; /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */ @@ -1283,13 +1283,13 @@ static int jtag_examine_chain(void) /* Zero for LSB indicates a device in bypass */ LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")", tap->dotted_name, idcode); - tap->hasidcode = false; + tap->has_idcode = false; tap->idcode = 0; bit_count += 1; } else { /* Friendly devices support IDCODE */ - tap->hasidcode = true; + tap->has_idcode = true; tap->idcode = idcode; jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode); diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index f4bfeb1a14..9c8d0fadea 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -100,7 +100,7 @@ int hl_interface_init_target(struct target *t) } t->tap->priv = &hl_if; - t->tap->hasidcode = 1; + t->tap->has_idcode = true; return ERROR_OK; } diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 04d1b4a2b5..7353104f0a 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -115,7 +115,7 @@ struct jtag_tap { uint32_t idcode; /**< device identification code */ /** not all devices have idcode, * we'll discover this during chain examination */ - bool hasidcode; + bool has_idcode; /** Array of expected identification codes */ uint32_t *expected_ids; diff --git a/src/pld/intel.c b/src/pld/intel.c index 8422c94c4b..a39e16c212 100644 --- a/src/pld/intel.c +++ b/src/pld/intel.c @@ -157,7 +157,7 @@ static int intel_check_for_unique_id(struct intel_pld_device *intel_info) static int intel_check_config(struct intel_pld_device *intel_info) { - if (!intel_info->tap->hasidcode) { + if (!intel_info->tap->has_idcode) { LOG_ERROR("no IDCODE"); return ERROR_FAIL; } diff --git a/src/pld/lattice.c b/src/pld/lattice.c index cd72d3cb59..2997cdc39f 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -81,7 +81,7 @@ static int lattice_check_device_family(struct lattice_pld_device *lattice_device if (lattice_device->family != LATTICE_UNKNOWN && lattice_device->preload_length != 0) return ERROR_OK; - if (!lattice_device->tap || !lattice_device->tap->hasidcode) + if (!lattice_device->tap || !lattice_device->tap->has_idcode) return ERROR_FAIL; for (size_t i = 0; i < ARRAY_SIZE(lattice_devices); ++i) { @@ -280,7 +280,7 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen return ERROR_FAIL; struct jtag_tap *tap = lattice_device->tap; - if (!tap || !tap->hasidcode) + if (!tap || !tap->has_idcode) return ERROR_FAIL; int retval = lattice_check_device_family(lattice_device); diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 5789201547..80cca1ed50 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -912,7 +912,7 @@ static int dsp563xx_examine(struct target *target) { uint32_t chip; - if (target->tap->hasidcode == false) { + if (!target->tap->has_idcode) { LOG_ERROR("no IDCODE present on device"); return ERROR_COMMAND_SYNTAX_ERROR; } From d2b34b474024926811989d75b6a8faf04c1810d6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 6 Dec 2023 18:11:11 +0100 Subject: [PATCH 0666/1312] jtag/core: Use 'bool' data type for 'bypass' Change-Id: I918fd5ce674e808ad6a96634a11046d2b3f6a05c Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8040 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/core.c | 4 ++-- src/jtag/drivers/driver.c | 4 ++-- src/jtag/jtag.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index 665a932190..e2af6c53d9 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1049,7 +1049,7 @@ static int jtag_reset_callback(enum jtag_event event, void *priv) /* current instruction is either BYPASS or IDCODE */ buf_set_ones(tap->cur_instr, tap->ir_length); - tap->bypass = 1; + tap->bypass = true; } return ERROR_OK; @@ -1464,7 +1464,7 @@ void jtag_tap_init(struct jtag_tap *tap) buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask); /* TAP will be in bypass mode after jtag_validate_ircapture() */ - tap->bypass = 1; + tap->bypass = true; buf_set_ones(tap->cur_instr, tap->ir_length); /* register the reset callback for the TAP */ diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index 409b800874..7732315003 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -76,13 +76,13 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active, if (tap == active) { /* if TAP is listed in input fields, copy the value */ - tap->bypass = 0; + tap->bypass = false; jtag_scan_field_clone(field, in_fields); } else { /* if a TAP isn't listed in input fields, set it to BYPASS */ - tap->bypass = 1; + tap->bypass = true; field->num_bits = tap->ir_length; field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length); diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 7353104f0a..1d1c495cf1 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -131,7 +131,7 @@ struct jtag_tap { /** current instruction */ uint8_t *cur_instr; /** Bypass register selected */ - int bypass; + bool bypass; struct jtag_tap_event_action *event_action; From 16e9b9c44fa62ea6eec99d1fb7bc43a8f1cc2f7e Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 6 Dec 2023 15:05:03 +0100 Subject: [PATCH 0667/1312] doc/usb_adapters: add dumps of two versions of Atmel EDBG USB HS based CMSIS-DAP v1 (HID) adapters found on Atmel/Microchip Xplained Pro development boards. Signed-off-by: Tomas Vanek Change-Id: I62a4b656dc6dce27da386e906d87088befc2bcbf Reviewed-on: https://review.openocd.org/c/openocd/+/8038 Reviewed-by: Antonio Borneo Tested-by: jenkins --- .../cmsis_dap/03eb_2111_atmel_edbg.txt | 211 ++++++++++++++++++ .../cmsis_dap/03eb_2169_atmel_edbg.txt | 211 ++++++++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 doc/usb_adapters/cmsis_dap/03eb_2111_atmel_edbg.txt create mode 100644 doc/usb_adapters/cmsis_dap/03eb_2169_atmel_edbg.txt diff --git a/doc/usb_adapters/cmsis_dap/03eb_2111_atmel_edbg.txt b/doc/usb_adapters/cmsis_dap/03eb_2111_atmel_edbg.txt new file mode 100644 index 0000000000..e4dd6cee0d --- /dev/null +++ b/doc/usb_adapters/cmsis_dap/03eb_2111_atmel_edbg.txt @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later + +# Optional comment + +Bus 001 Device 006: ID 03eb:2111 Atmel Corp. Xplained Pro board debugger and programmer +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x03eb Atmel Corp. + idProduct 0x2111 Xplained Pro board debugger and programmer + bcdDevice 1.01 + iManufacturer 1 Atmel Corp. + iProduct 2 EDBG CMSIS-DAP + iSerial 3 ATMLxxxxxxxxxxxxxxxx + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0082 + bNumInterfaces 4 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 3 Human Interface Device + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 4 EDBG CMSIS-DAP + HID Device Descriptor: + bLength 9 + bDescriptorType 33 + bcdHID 1.11 + bCountryCode 0 Not supported + bNumDescriptors 1 + bDescriptorType 34 Report + wDescriptorLength 35 + Report Descriptor: (length is 35) + Item(Global): Usage Page, data= [ 0x00 0xff ] 65280 + (null) + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Global): Logical Minimum, data= [ 0x00 ] 0 + Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x00 0x02 ] 512 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x00 0x02 ] 512 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x04 ] 4 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Feature, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 1 + bInterfaceCount 2 + bFunctionClass 2 Communications + bFunctionSubClass 2 Abstract (modem) + bFunctionProtocol 1 AT-commands (v.25ter) + iFunction 6 EDBG Virtual COM Port + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 0 + CDC Header: + bcdCDC 1.10 + CDC ACM: + bmCapabilities 0x06 + sends break + line coding and serial state + CDC Union: + bMasterInterface 1 + bSlaveInterface 2 + CDC Call Management: + bmCapabilities 0x03 + call management + use DataInterface + bDataInterface 2 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 8 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x84 EP 4 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x05 EP 5 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 255 Vendor Specific Subclass + bInterfaceProtocol 255 Vendor Specific Protocol + iInterface 5 EDBG Data Gateway + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x87 EP 7 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x06 EP 6 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 255 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/doc/usb_adapters/cmsis_dap/03eb_2169_atmel_edbg.txt b/doc/usb_adapters/cmsis_dap/03eb_2169_atmel_edbg.txt new file mode 100644 index 0000000000..1f7f26efd9 --- /dev/null +++ b/doc/usb_adapters/cmsis_dap/03eb_2169_atmel_edbg.txt @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later + +# Optional comment + +Bus 001 Device 005: ID 03eb:2169 Atmel Corp. EDBG CMSIS-DAP +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x03eb Atmel Corp. + idProduct 0x2169 + bcdDevice 1.01 + iManufacturer 1 Atmel Corp. + iProduct 2 EDBG CMSIS-DAP + iSerial 3 ATMLxxxxxxxxxxxxxxxx + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0082 + bNumInterfaces 4 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 3 Human Interface Device + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 4 EDBG CMSIS-DAP + HID Device Descriptor: + bLength 9 + bDescriptorType 33 + bcdHID 1.11 + bCountryCode 0 Not supported + bNumDescriptors 1 + bDescriptorType 34 Report + wDescriptorLength 35 + Report Descriptor: (length is 35) + Item(Global): Usage Page, data= [ 0x00 0xff ] 65280 + (null) + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Global): Logical Minimum, data= [ 0x00 ] 0 + Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x00 0x02 ] 512 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x00 0x02 ] 512 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x04 ] 4 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Feature, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 1 + bInterfaceCount 2 + bFunctionClass 2 Communications + bFunctionSubClass 2 Abstract (modem) + bFunctionProtocol 1 AT-commands (v.25ter) + iFunction 6 EDBG Virtual COM Port + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 0 + CDC Header: + bcdCDC 1.10 + CDC ACM: + bmCapabilities 0x06 + sends break + line coding and serial state + CDC Union: + bMasterInterface 1 + bSlaveInterface 2 + CDC Call Management: + bmCapabilities 0x03 + call management + use DataInterface + bDataInterface 2 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 8 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x84 EP 4 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x05 EP 5 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 8 Mass Storage + bInterfaceSubClass 6 SCSI + bInterfaceProtocol 80 Bulk-Only + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x87 EP 7 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x06 EP 6 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) From e8e09b1b5513f0decf31aaa25151858fae126e1e Mon Sep 17 00:00:00 2001 From: Jeremy Herbert Date: Tue, 7 Feb 2023 12:02:31 +1000 Subject: [PATCH 0668/1312] remote_bitbang: add use_remote_sleep option to send delays to remote If the remote_bitbang host does not execute requests immediately, delays performed inside OpenOCD can be lost. This option allows the delays to be sent to the remote host so that they can be queued and executed in order. Signed-off-by: Jeremy Herbert Signed-off-by: David Ryskalczyk Change-Id: Ie1b09e09ea132dd528139618e4305154819cbc9e Reviewed-on: https://review.openocd.org/c/openocd/+/7472 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/manual/jtag/drivers/remote_bitbang.txt | 14 ++++++- doc/openocd.texi | 18 ++++++++ src/jtag/drivers/bitbang.c | 11 ++++- src/jtag/drivers/bitbang.h | 3 ++ src/jtag/drivers/remote_bitbang.c | 49 +++++++++++++++++++++- 5 files changed, 91 insertions(+), 4 deletions(-) diff --git a/doc/manual/jtag/drivers/remote_bitbang.txt b/doc/manual/jtag/drivers/remote_bitbang.txt index 7c8eee289e..94d6038163 100644 --- a/doc/manual/jtag/drivers/remote_bitbang.txt +++ b/doc/manual/jtag/drivers/remote_bitbang.txt @@ -37,12 +37,16 @@ swdio_read swd_write Set the value of swclk (tck) and swdio (tms). +(optional) sleep + Instructs the remote host to sleep/idle for some period of time before + executing the next request + An additional function, quit, is added to the remote_bitbang interface to indicate there will be no more requests and the connection with the remote driver should be closed. -These eight functions are encoded in ASCII by assigning a single character to -each possible request. The assignments are: +The eight mandatory functions are encoded in ASCII by assigning a single +character to each possible request. The assignments are: B - Blink on b - Blink off @@ -70,4 +74,10 @@ each possible request. The assignments are: The read responses are encoded in ASCII as either digit 0 or 1. +If the use_remote_sleep option is set to 'yes', two additional requests may +be sent: + + D - Sleep for 1 millisecond + d - Sleep for 1 microsecond + */ diff --git a/doc/openocd.texi b/doc/openocd.texi index 6c6519d625..ec7c9964a8 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2839,6 +2839,15 @@ Specifies the hostname of the remote process to connect to using TCP, or the name of the UNIX socket to use if remote_bitbang port is 0. @end deffn +@deffn {Config Command} {remote_bitbang use_remote_sleep} (on|off) +If this option is enabled, delays will not be executed locally but instead +forwarded to the remote host. This is useful if the remote host performs its +own request queuing rather than executing requests immediately. + +This is disabled by default. This option must only be enabled if the given +remote_bitbang host supports receiving the delay information. +@end deffn + For example, to connect remotely via TCP to the host foobar you might have something like: @@ -2848,6 +2857,15 @@ remote_bitbang port 3335 remote_bitbang host foobar @end example +And if you also wished to enable remote sleeping: + +@example +adapter driver remote_bitbang +remote_bitbang port 3335 +remote_bitbang host foobar +remote_bitbang use_remote_sleep on +@end example + To connect to another process running locally via UNIX sockets with socket named mysocket: diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 665dbf329e..6e97d15840 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -278,6 +278,15 @@ static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, return ERROR_OK; } +static void bitbang_sleep(unsigned int microseconds) +{ + if (bitbang_interface->sleep) { + bitbang_interface->sleep(microseconds); + } else { + jtag_sleep(microseconds); + } +} + int bitbang_execute_queue(void) { struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ @@ -351,7 +360,7 @@ int bitbang_execute_queue(void) break; case JTAG_SLEEP: LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us); - jtag_sleep(cmd->cmd.sleep->us); + bitbang_sleep(cmd->cmd.sleep->us); break; case JTAG_TMS: retval = bitbang_execute_tms(cmd); diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 4ea1cc0454..e3714df9c8 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -54,6 +54,9 @@ struct bitbang_interface { /** Set SWCLK and SWDIO to the given value. */ int (*swd_write)(int swclk, int swdio); + + /** Sleep for some number of microseconds. **/ + int (*sleep)(unsigned int microseconds); }; extern const struct swd_driver bitbang_swd; diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 261c30df2d..c488f83340 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -31,6 +31,8 @@ static int remote_bitbang_fd; static uint8_t remote_bitbang_send_buf[512]; static unsigned int remote_bitbang_send_buf_used; +static bool use_remote_sleep; + /* Circular buffer. When start == end, the buffer is empty. */ static char remote_bitbang_recv_buf[256]; static unsigned int remote_bitbang_recv_buf_start; @@ -216,6 +218,32 @@ static int remote_bitbang_reset(int trst, int srst) return remote_bitbang_queue(c, FLUSH_SEND_BUF); } +static int remote_bitbang_sleep(unsigned int microseconds) +{ + if (!use_remote_sleep) { + jtag_sleep(microseconds); + return ERROR_OK; + } + + int tmp; + unsigned int ms = microseconds / 1000; + unsigned int us = microseconds % 1000; + + for (unsigned int i = 0; i < ms; i++) { + tmp = remote_bitbang_queue('D', NO_FLUSH); + if (tmp != ERROR_OK) + return tmp; + } + + for (unsigned int i = 0; i < us; i++) { + tmp = remote_bitbang_queue('d', NO_FLUSH); + if (tmp != ERROR_OK) + return tmp; + } + + return remote_bitbang_flush(); +} + static int remote_bitbang_blink(int on) { char c = on ? 'B' : 'b'; @@ -252,6 +280,7 @@ static struct bitbang_interface remote_bitbang_bitbang = { .swdio_drive = &remote_bitbang_swdio_drive, .swd_write = &remote_bitbang_swd_write, .blink = &remote_bitbang_blink, + .sleep = &remote_bitbang_sleep, }; static int remote_bitbang_init_tcp(void) @@ -377,6 +406,16 @@ COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command) static const char * const remote_bitbang_transports[] = { "jtag", "swd", NULL }; +COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_use_remote_sleep_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], use_remote_sleep); + + return ERROR_OK; +} + static const struct command_registration remote_bitbang_subcommand_handlers[] = { { .name = "port", @@ -394,7 +433,15 @@ static const struct command_registration remote_bitbang_subcommand_handlers[] = " if port is 0 or unset, this is the name of the unix socket to use.", .usage = "host_name", }, - COMMAND_REGISTRATION_DONE, + { + .name = "use_remote_sleep", + .handler = remote_bitbang_handle_remote_bitbang_use_remote_sleep_command, + .mode = COMMAND_CONFIG, + .help = "Rather than executing sleep locally, include delays in the " + "instruction stream for the remote host.", + .usage = "(on|off)", + }, + COMMAND_REGISTRATION_DONE }; static const struct command_registration remote_bitbang_command_handlers[] = { From 2e920a212fbe2de705811d547c169c1ae1611a02 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Wed, 22 Nov 2023 18:10:27 +0300 Subject: [PATCH 0669/1312] break from long loops on shutdown request In loops that typically take longer time to complete, check if there is a pending shutdown request. If so, terminate the loop. This allows to respond to a signal requesting a shutdown during some loops which do not return control to main OpenOCD loop. Change-Id: Iace0b58eddde1237832d0f9333a7c7b930565674 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8032 Reviewed-by: Jan Matyas Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/server.h | 1 + src/target/image.c | 3 +++ src/target/target.c | 20 +++++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/server/server.h b/src/server/server.h index c9d4698af8..ea1e94ec5f 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -118,5 +118,6 @@ COMMAND_HELPER(server_port_command, unsigned short *out); #define ERROR_SERVER_REMOTE_CLOSED (-400) #define ERROR_CONNECTION_REJECTED (-401) +#define ERROR_SERVER_INTERRUPTED (-402) #endif /* OPENOCD_SERVER_SERVER_H */ diff --git a/src/target/image.c b/src/target/image.c index 9175c200af..440fe17d18 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -24,6 +24,7 @@ #include "image.h" #include "target.h" #include +#include /* convert ELF header field to host endianness */ #define field16(elf, field) \ @@ -1295,6 +1296,8 @@ int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes, uint32_t *c crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buffer++) & 255]; } keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; } LOG_DEBUG("Calculating checksum done; checksum=0x%" PRIx32, crc); diff --git a/src/target/target.c b/src/target/target.c index bb773f6a5c..5605d29202 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1204,6 +1204,10 @@ int target_run_read_async_algorithm(struct target *target, /* Avoid GDB timeouts */ keep_alive(); + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + break; + } } if (retval != ERROR_OK) { @@ -3224,8 +3228,11 @@ int target_wait_state(struct target *target, enum target_state state, unsigned i nvp_value2name(nvp_target_state, state)->name); } - if (cur-then > 500) + if (cur - then > 500) { keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + } if ((cur-then) > ms) { LOG_ERROR("timed out while waiting for target %s", @@ -3507,6 +3514,11 @@ static int target_fill_mem(struct target *target, break; /* avoid GDB timeouts */ keep_alive(); + + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + break; + } } free(target_buf); @@ -3849,6 +3861,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver } } keep_alive(); + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + free(data); + free(buffer); + goto done; + } } } free(data); From 33749a7fbeb5e6054ea5b9c6a15578302fe512e0 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 29 Nov 2023 06:32:53 -0600 Subject: [PATCH 0670/1312] tcl/target/ti_k3: Add J722S SoC Add support for the TI K3 family J722S SoC. This SoC is a variant of AM62P chassis with a different JTAG ID, additional R5 added in (along with C7x and few other peripheral changes). Reuse existing definition. For further details, see https://www.ti.com/lit/zip/sprujb3 Change-Id: I754e6be8df3a26212437ea955f6a791d7c99b0c8 Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8049 Reviewed-by: Bryan Brattlof Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/ti_k3.cfg | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 23825b86b4..ebea821793 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -24,6 +24,8 @@ # Has 2 ARMV8 Cores and 6 R5 Cores and an M3 # * J721S2: https://www.ti.com/lit/pdf/spruj28 # Has 2 ARMV8 Cores and 6 R5 Cores and an M4F +# * J722S: https://www.ti.com/lit/zip/sprujb3 +# Has 4 ARMV8 Cores and 3 R5 Cores # * J784S4/AM69: http://www.ti.com/lit/zip/spruj52 # Has 8 ARMV8 Cores and 8 R5 Cores # @@ -185,6 +187,7 @@ switch $_soc { set _dmem_emu_base_address_map_to 0x1d500000 set _dmem_emu_ap_list 1 } + j722s - am62p - am62a7 { set _K3_DAP_TAPID 0x0bb8d02f @@ -211,6 +214,14 @@ switch $_soc { set _K3_DAP_TAPID 0x0bb9d02f set R5_NAMES {wkup0_r5.0 mcu0_r5.0} } + # Overrides for j722s + if { "$_soc" == "j722s" } { + set _K3_DAP_TAPID 0x0bba002f + set _r5_cores 3 + set R5_NAMES {wkup0_r5.0 main0_r5.0 mcu0_r5.0} + set R5_DBGBASE {0x9d410000 0x9d510000 0x9d810000} + set R5_CTIBASE {0x9d418000 0x9d518000 0x9d818000} + } } j721e { set _K3_DAP_TAPID 0x0bb6402f From b8422b076daab0797a24a6aec50104bb739aa949 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 29 Nov 2023 06:37:14 -0600 Subject: [PATCH 0671/1312] tcl/board: Add TI j722sevm config Add basic connection details with j722s EVM For further details, see: https://www.ti.com/lit/zip/sprr495 Change-Id: Ic69d85d69c773c7fad2184561267391fef7a98bc Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8050 Reviewed-by: Bryan Brattlof Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/ti_j722sevm.cfg | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tcl/board/ti_j722sevm.cfg diff --git a/tcl/board/ti_j722sevm.cfg b/tcl/board/ti_j722sevm.cfg new file mode 100644 index 0000000000..6a5c2d9cd9 --- /dev/null +++ b/tcl/board/ti_j722sevm.cfg @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ +# +# Texas Instruments EVM-J722S: https://www.ti.com/lit/zip/sprr495 +# + +# J722S EVM has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC j722s +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 From 49489747d26d4dcd679fb16afec61d90d7ca3586 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 10 Dec 2023 22:26:44 +0100 Subject: [PATCH 0672/1312] doc: usb_adapters: fix HID report in lsusb dump of few adapters Real dumps from adapters I have access to. Serial numbers have been manually edited but are still consistent. While there, rename a file to correct the USB PID. Change-Id: I4fd0b6661d55294c2ce0ecbead765def1143880c Signed-off-by: Antonio Borneo Fixes: e0059dfffae4 ("doc: usb_adapters: add lsusb dump of few adapters") Reviewed-on: https://review.openocd.org/c/openocd/+/8047 Tested-by: jenkins --- .../cmsis_dap/0d28_0204_nxp_daplink.txt | 31 ++++++++++++++-- .../cmsis_dap/c251_2722_keil_ulink2.txt | 31 ++++++++++++++-- .../nulink/0416_511d_nuvoton_nulink.txt | 28 +++++++++++++-- .../nulink/0416_5200_nuvoton_nulink.txt | 35 ++++++++++++++++--- ..._ti_xds110.txt => 0451_bef3_ti_xds110.txt} | 24 +++++++++++-- 5 files changed, 137 insertions(+), 12 deletions(-) rename doc/usb_adapters/xds110/{0451_0451_ti_xds110.txt => 0451_bef3_ti_xds110.txt} (89%) diff --git a/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt b/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt index 2ec0d58e2d..5141a1b6b8 100644 --- a/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt +++ b/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt @@ -76,8 +76,35 @@ Device Descriptor: bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 33 - Report Descriptors: - ** UNAVAILABLE ** + Report Descriptor: (length is 33) + Item(Global): Usage Page, data= [ 0x00 0xff ] 65280 + (null) + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Global): Logical Minimum, data= [ 0x00 ] 0 + Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x01 ] 1 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Feature, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 diff --git a/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt b/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt index 520f7c5531..65903b3533 100644 --- a/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt +++ b/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt @@ -46,8 +46,35 @@ Device Descriptor: bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 33 - Report Descriptors: - ** UNAVAILABLE ** + Report Descriptor: (length is 33) + Item(Global): Usage Page, data= [ 0x00 0xff ] 65280 + (null) + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Global): Logical Minimum, data= [ 0x00 ] 0 + Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x01 ] 1 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Feature, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 diff --git a/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt b/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt index fb43923514..2ac9a44a0d 100644 --- a/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt +++ b/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt @@ -47,8 +47,32 @@ Device Descriptor: bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 28 - Report Descriptors: - ** UNAVAILABLE ** + Report Descriptor: (length is 28) + Item(Global): Usage Page, data= [ 0x01 ] 1 + Generic Desktop Controls + Item(Local ): Usage, data= [ 0x00 ] 0 + Undefined + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Global): Logical Minimum, data= [ 0x00 ] 0 + Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 + Item(Local ): Usage Minimum, data= [ 0x00 ] 0 + Undefined + Item(Local ): Usage Maximum, data= [ 0x00 ] 0 + Undefined + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Local ): Usage Minimum, data= [ 0x00 ] 0 + Undefined + Item(Local ): Usage Maximum, data= [ 0x00 ] 0 + Undefined + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 diff --git a/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt b/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt index 1d8661f18d..5735d3bd2f 100644 --- a/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt +++ b/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt @@ -16,7 +16,7 @@ Device Descriptor: idProduct 0x5200 Nuvoton Nu-Link2-ME ICE/MSC/VCOM bcdDevice 0.00 iManufacturer 1 Nuvoton - iProduct 2 Nu-Link2 Bulk + iProduct 9 Nu-Link2 iSerial 6 13010000AAAAAAAAAAAAAAAAAAAAAAAA bNumConfigurations 1 Configuration Descriptor: @@ -38,7 +38,7 @@ Device Descriptor: bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass 0 bInterfaceProtocol 0 - iInterface 0 + iInterface 2 Nu-Link2 Bulk Endpoint Descriptor: bLength 7 bDescriptorType 5 @@ -146,8 +146,35 @@ Device Descriptor: bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 35 - Report Descriptors: - ** UNAVAILABLE ** + Report Descriptor: (length is 35) + Item(Global): Usage Page, data= [ 0x06 0xff ] 65286 + (null) + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Global): Logical Minimum, data= [ 0x00 ] 0 + Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x00 0x04 ] 1024 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x00 0x04 ] 1024 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Global): Report Count, data= [ 0x08 ] 8 + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Feature, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 diff --git a/doc/usb_adapters/xds110/0451_0451_ti_xds110.txt b/doc/usb_adapters/xds110/0451_bef3_ti_xds110.txt similarity index 89% rename from doc/usb_adapters/xds110/0451_0451_ti_xds110.txt rename to doc/usb_adapters/xds110/0451_bef3_ti_xds110.txt index 9ad9b7dbf2..628b529e2a 100644 --- a/doc/usb_adapters/xds110/0451_0451_ti_xds110.txt +++ b/doc/usb_adapters/xds110/0451_bef3_ti_xds110.txt @@ -220,8 +220,28 @@ Device Descriptor: bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 24 - Report Descriptors: - ** UNAVAILABLE ** + Report Descriptor: (length is 24) + Item(Global): Usage Page, data= [ 0x00 0xff ] 65280 + (null) + Item(Local ): Usage, data= [ 0x01 ] 1 + (null) + Item(Main ): Collection, data= [ 0x01 ] 1 + Application + Item(Local ): Usage, data= [ 0x03 ] 3 + (null) + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Main ): Input, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Local ): Usage, data= [ 0x04 ] 4 + (null) + Item(Global): Report Size, data= [ 0x08 ] 8 + Item(Global): Report Count, data= [ 0x40 ] 64 + Item(Main ): Output, data= [ 0x02 ] 2 + Data Variable Absolute No_Wrap Linear + Preferred_State No_Null_Position Non_Volatile Bitfield + Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 From 492dc7c537d5685e5e6d41757b73eea2365b96ee Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 14 Dec 2023 22:05:52 +0100 Subject: [PATCH 0673/1312] helper/bin2char: drop trailing empty line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For unknown reasons, the coreutils tool 'od' on MacOS outputs an extra empty line, which appears in the new auto-generated files. Modify the script bin2char.sh to drop every empty line. Change-Id: Id835fecadb58ad4ddfc11ef9f9a2e8d75c5dffe9 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8051 Reviewed-by: Erhan Kurubas Tested-by: jenkins Reviewed-by: Henrik Nordström --- src/helper/bin2char.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/bin2char.sh b/src/helper/bin2char.sh index b89433d869..cf94bee29c 100755 --- a/src/helper/bin2char.sh +++ b/src/helper/bin2char.sh @@ -12,4 +12,4 @@ } echo "/* Autogenerated with $0 */" -od -v -A n -t x1 | sed 's/ *\(..\) */0x\1,/g' +od -v -A n -t x1 | sed 's/ *\(..\) */0x\1,/g;/^$/d' From ee3fb5a0eacb42e8e881239194485d79d128d246 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 14 Mar 2023 18:40:25 +0100 Subject: [PATCH 0674/1312] target/arm_adi_v5: fix DP SELECT logic The original code supported ADIv5 only, just one SELECT register with some reserved bits - the pseudo value DP_SELECT_INVALID was just fine to indicate the DP SELECT register is in an unknown state. Added ADIv6 support required DP SELECT and SELECT1 registers without reserved bits. Therefore DP_SELECT_INVALID value became reachable as a (fortunately not really used) ADIv6 AP ADDR. JTAG DPBANKSEL setting support introduced with ADIv6 does not honor DP_SELECT_INVALID correctly: required select value gets compared to DP_SELECT_INVALID value and the most common zero bank does not trigger DP SELECT write. DP banked registers need just to set DP SELECT. ADIv6 AP register addressing scheme may use both DP SELECT and SELECT1. This further complicates using a single invalid value. Moreover the difference how the SWD line reset influences DPBANKSEL field between ADIv5 and ADIv6 deserves better handling than setting select cache to zero and then to DP_SELECT_INVALID in a very specific code positions. Introduce bool flags indicating the validity of each SELECT register and one SWD specific for DPBANKSEL field. Use the latter to prevent selecting DP BANK before taking the connection out of reset by reading DPIDR. Treat DP SELECT and SELECT1 individually in ADIv6 64-bit mode. Update comments to reflect the difference between ADIv5 and ADIv6 in SWD line reset. Change-Id: Ibbb0b06cb592be072571218b666566a13d8dff0e Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7541 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/adi_v5_jtag.c | 89 +++++++++++++++-------- src/target/adi_v5_swd.c | 148 +++++++++++++++++++++------------------ src/target/arm_adi_v5.c | 6 +- src/target/arm_adi_v5.h | 22 ++++-- 4 files changed, 164 insertions(+), 101 deletions(-) diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index afdc0e5775..8d54a50fb0 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -353,17 +353,25 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, uint64_t sel = (reg_addr >> 4) & DP_SELECT_DPBANK; /* 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); + if (instr == JTAG_DP_DPACC && reg_addr != DP_SELECT && reg_addr != DP_RDBUFF + && (!dap->select_valid || sel != (dap->select & DP_SELECT_DPBANK))) { + /* Use the AP part of dap->select regardless of dap->select_valid: + * if !dap->select_valid + * dap->select contains a speculative value likely going to be used + * in the following swd_queue_ap_bankselect() */ + sel |= dap->select & SELECT_AP_MASK; + + LOG_DEBUG_IO("DP BANK SELECT: %" PRIx32, (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; + + dap->select = sel; + dap->select_valid = true; } buf_set_u32(out_value_buf, 0, 32, outvalue); @@ -520,7 +528,10 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) /* timeout happened */ if (tmp->ack == JTAG_ACK_WAIT) { LOG_ERROR("Timeout during WAIT recovery"); - dap->select = DP_SELECT_INVALID; + dap->select_valid = false; + dap->select1_valid = false; + /* Keep dap->select unchanged, the same AP and AP bank + * is likely going to be used further */ jtag_ap_q_abort(dap, NULL); /* clear the sticky overrun condition */ adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, @@ -580,7 +591,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) /* TODO: ADIv6 DP SELECT1 handling */ - dap->select = DP_SELECT_INVALID; + dap->select_valid = false; } list_for_each_entry_safe(el, tmp, &replay_list, lh) { @@ -615,7 +626,10 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) if (retval == ERROR_OK) { if (el->ack == JTAG_ACK_WAIT) { LOG_ERROR("Timeout during WAIT recovery"); - dap->select = DP_SELECT_INVALID; + dap->select_valid = false; + dap->select1_valid = false; + /* Keep dap->select unchanged, the same AP and AP bank + * is likely going to be used further */ jtag_ap_q_abort(dap, NULL); /* clear the sticky overrun condition */ adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, @@ -748,41 +762,60 @@ static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, return retval; } -/** Select the AP register bank matching bits 7:4 of reg. */ +/** Select the AP register bank */ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) { int retval; struct adiv5_dap *dap = ap->dap; uint64_t sel; - if (is_adiv6(dap)) { + if (is_adiv6(dap)) sel = ap->ap_num | (reg & 0x00000FF0); - if (sel == (dap->select & ~0xfull)) - return ERROR_OK; + else + sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK); - if (dap->select != DP_SELECT_INVALID) - sel |= dap->select & 0xf; - dap->select = sel; - LOG_DEBUG("AP BANKSEL: %" PRIx64, sel); + uint64_t sel_diff = (sel ^ dap->select) & SELECT_AP_MASK; + + bool set_select = !dap->select_valid || (sel_diff & 0xffffffffull); + bool set_select1 = is_adiv6(dap) && dap->asize > 32 + && (!dap->select1_valid + || sel_diff & (0xffffffffull << 32)); + + if (set_select && set_select1) { + /* Prepare DP bank for DP_SELECT1 now to save one write */ + sel |= (DP_SELECT1 >> 4) & DP_SELECT_DPBANK; + } else { + /* Use the DP part of dap->select regardless of dap->select_valid: + * if !dap->select_valid + * dap->select contains a speculative value likely going to be used + * in the following swd_queue_dp_bankselect(). + * Moreover dap->select_valid should never be false here as a DP bank + * is always selected before selecting an AP bank */ + sel |= dap->select & DP_SELECT_DPBANK; + } + + if (set_select) { + LOG_DEBUG_IO("AP BANK SELECT: %" PRIx32, (uint32_t)sel); retval = jtag_dp_q_write(dap, DP_SELECT, (uint32_t)sel); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + dap->select_valid = false; 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 & ADIV5_DP_SELECT_APBANK); + if (set_select1) { + LOG_DEBUG_IO("AP BANK SELECT1: %" PRIx32, (uint32_t)(sel >> 32)); - if (sel == dap->select) - return ERROR_OK; + retval = jtag_dp_q_write(dap, DP_SELECT1, (uint32_t)(sel >> 32)); + if (retval != ERROR_OK) { + dap->select1_valid = false; + return retval; + } + } dap->select = sel; - - return jtag_dp_q_write(dap, DP_SELECT, (uint32_t)sel); + return ERROR_OK; } 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 1b743657c2..968798b324 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -99,27 +99,31 @@ static inline int check_sync(struct adiv5_dap *dap) return do_sync ? swd_run_inner(dap) : ERROR_OK; } -/** Select the DP register bank matching bits 7:4 of reg. */ +/** Select the DP register bank */ static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg) { - /* Only register address 0 and 4 are banked. */ + /* Only register address 0 (ADIv6 only) and 4 are banked. */ if ((reg & 0xf) > 4) return ERROR_OK; - uint64_t sel = (reg & 0x000000F0) >> 4; - if (dap->select != DP_SELECT_INVALID) - sel |= dap->select & ~0xfULL; + uint32_t sel = (reg >> 4) & DP_SELECT_DPBANK; - if (sel == dap->select) + /* DP register 0 is not mapped according to ADIv5 + * whereas ADIv6 ensures DPBANKSEL = 0 after line reset */ + if ((dap->select_valid || ((reg & 0xf) == 0 && dap->select_dpbanksel_valid)) + && (sel == (dap->select & DP_SELECT_DPBANK))) return ERROR_OK; - dap->select = sel; + /* Use the AP part of dap->select regardless of dap->select_valid: + * if !dap->select_valid + * dap->select contains a speculative value likely going to be used + * in the following swd_queue_ap_bankselect() */ + sel |= (uint32_t)(dap->select & SELECT_AP_MASK); - int retval = swd_queue_dp_write_inner(dap, DP_SELECT, (uint32_t)sel); - if (retval != ERROR_OK) - dap->select = DP_SELECT_INVALID; + LOG_DEBUG_IO("DP BANK SELECT: %" PRIx32, sel); - return retval; + /* dap->select cache gets updated in the following call */ + return swd_queue_dp_write_inner(dap, DP_SELECT, sel); } static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg, @@ -147,24 +151,31 @@ static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, swd_finish_read(dap); if (reg == DP_SELECT) { - dap->select = data & (ADIV5_DP_SELECT_APSEL | ADIV5_DP_SELECT_APBANK | DP_SELECT_DPBANK); + dap->select = data | (dap->select & (0xffffffffull << 32)); swd->write_reg(swd_cmd(false, false, reg), data, 0); retval = check_sync(dap); - if (retval != ERROR_OK) - dap->select = DP_SELECT_INVALID; + dap->select_valid = (retval == ERROR_OK); + dap->select_dpbanksel_valid = dap->select_valid; return retval; } + if (reg == DP_SELECT1) + dap->select = ((uint64_t)data << 32) | (dap->select & 0xffffffffull); + retval = swd_queue_dp_bankselect(dap, reg); - if (retval != ERROR_OK) - return retval; + if (retval == ERROR_OK) { + swd->write_reg(swd_cmd(false, false, reg), data, 0); + + retval = check_sync(dap); + } - swd->write_reg(swd_cmd(false, false, reg), data, 0); + if (reg == DP_SELECT1) + dap->select1_valid = (retval == ERROR_OK); - return check_sync(dap); + return retval; } @@ -177,19 +188,17 @@ static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr assert(dap_is_multidrop(dap)); swd_send_sequence(dap, LINE_RESET); - /* From ARM IHI 0074C ADIv6.0, chapter B4.3.3 "Connection and line reset - * sequence": - * - line reset sets DP_SELECT_DPBANK to zero; - * - read of DP_DPIDR takes the connection out of reset; - * - write of DP_TARGETSEL keeps the connection in reset; - * - other accesses return protocol error (SWDIO not driven by target). - * - * Read DP_DPIDR to get out of reset. Initialize dap->select to zero to - * skip the write to DP_SELECT, avoiding the protocol error. Set again - * dap->select to DP_SELECT_INVALID because the rest of the register is - * unknown after line reset. + /* + * Zero dap->select and set dap->select_dpbanksel_valid + * to skip the write to DP_SELECT before DPIDR read, avoiding + * the protocol error. + * Clear the other validity flags because the rest of the DP + * SELECT and SELECT1 registers is unknown after line reset. */ dap->select = 0; + dap->select_dpbanksel_valid = true; + dap->select_valid = false; + dap->select1_valid = false; retval = swd_queue_dp_write_inner(dap, DP_TARGETSEL, dap->multidrop_targetsel); if (retval != ERROR_OK) @@ -209,8 +218,6 @@ static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr return retval; } - dap->select = DP_SELECT_INVALID; - retval = swd_queue_dp_read_inner(dap, DP_DLPIDR, &dlpidr); if (retval != ERROR_OK) return retval; @@ -335,19 +342,20 @@ static int swd_connect_single(struct adiv5_dap *dap) /* The sequences to enter in SWD (JTAG_TO_SWD and DORMANT_TO_SWD) end * with a SWD line reset sequence (50 clk with SWDIO high). - * From ARM IHI 0074C ADIv6.0, chapter B4.3.3 "Connection and line reset - * sequence": - * - line reset sets DP_SELECT_DPBANK to zero; + * From ARM IHI 0031F ADIv5.2 and ARM IHI 0074C ADIv6.0, + * chapter B4.3.3 "Connection and line reset sequence": + * - DPv3 (ADIv6) only: line reset sets DP_SELECT_DPBANK to zero; * - read of DP_DPIDR takes the connection out of reset; * - write of DP_TARGETSEL keeps the connection in reset; * - other accesses return protocol error (SWDIO not driven by target). * - * Read DP_DPIDR to get out of reset. Initialize dap->select to zero to - * skip the write to DP_SELECT, avoiding the protocol error. Set again - * dap->select to DP_SELECT_INVALID because the rest of the register is - * unknown after line reset. + * dap_invalidate_cache() sets dap->select to zero and all validity + * flags to invalid. Set dap->select_dpbanksel_valid only + * to skip the write to DP_SELECT, avoiding the protocol error. + * Read DP_DPIDR to get out of reset. */ - dap->select = 0; + dap->select_dpbanksel_valid = true; + retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr); if (retval == ERROR_OK) { retval = swd_run_inner(dap); @@ -360,8 +368,6 @@ static int swd_connect_single(struct adiv5_dap *dap) dap->switch_through_dormant = !dap->switch_through_dormant; } while (timeval_ms() < timeout); - dap->select = DP_SELECT_INVALID; - if (retval != ERROR_OK) { LOG_ERROR("Error connecting DP: cannot read IDR"); return retval; @@ -494,49 +500,55 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, return swd_queue_dp_write_inner(dap, reg, data); } -/** Select the AP register bank matching bits 7:4 of reg. */ +/** Select the AP register bank */ static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) { int retval; struct adiv5_dap *dap = ap->dap; uint64_t sel; - if (is_adiv6(dap)) { + 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 = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel); + else + sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK); - if (retval == ERROR_OK && dap->asize > 32) - retval = swd_queue_dp_write(dap, DP_SELECT1, (uint32_t)(sel >> 32)); + uint64_t sel_diff = (sel ^ dap->select) & SELECT_AP_MASK; - if (retval != ERROR_OK) - dap->select = DP_SELECT_INVALID; + bool set_select = !dap->select_valid || (sel_diff & 0xffffffffull); + bool set_select1 = is_adiv6(dap) && dap->asize > 32 + && (!dap->select1_valid + || sel_diff & (0xffffffffull << 32)); - return retval; + if (set_select && set_select1) { + /* Prepare DP bank for DP_SELECT1 now to save one write */ + sel |= (DP_SELECT1 & 0x000000f0) >> 4; + } else { + /* Use the DP part of dap->select regardless of dap->select_valid: + * if !dap->select_valid + * dap->select contains a speculative value likely going to be used + * in the following swd_queue_dp_bankselect(). + * Moreover dap->select_valid should never be false here as a DP bank + * is always selected before selecting an AP bank */ + sel |= dap->select & DP_SELECT_DPBANK; } - /* ADIv5 */ - sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK); - if (dap->select != DP_SELECT_INVALID) - sel |= dap->select & DP_SELECT_DPBANK; + if (set_select) { + LOG_DEBUG_IO("AP BANK SELECT: %" PRIx32, (uint32_t)sel); - if (sel == dap->select) - return ERROR_OK; + retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel); + if (retval != ERROR_OK) + return retval; + } - dap->select = sel; + if (set_select1) { + LOG_DEBUG_IO("AP BANK SELECT1: %" PRIx32, (uint32_t)(sel >> 32)); - retval = swd_queue_dp_write_inner(dap, DP_SELECT, sel); - if (retval != ERROR_OK) - dap->select = DP_SELECT_INVALID; + retval = swd_queue_dp_write(dap, DP_SELECT1, (uint32_t)(sel >> 32)); + if (retval != ERROR_OK) + return retval; + } - return retval; + return ERROR_OK; } static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index da5da3197d..434bf50fe1 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -655,7 +655,11 @@ int mem_ap_write_buf_noincr(struct adiv5_ap *ap, */ void dap_invalidate_cache(struct adiv5_dap *dap) { - dap->select = DP_SELECT_INVALID; + dap->select = 0; /* speculate the first AP access will select AP 0, bank 0 */ + dap->select_valid = false; + dap->select1_valid = false; + dap->select_dpbanksel_valid = false; + dap->last_read = NULL; int i; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index e21589363d..e07b577af6 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -100,7 +100,11 @@ #define ADIV5_DP_SELECT_APSEL 0xFF000000 #define ADIV5_DP_SELECT_APBANK 0x000000F0 #define DP_SELECT_DPBANK 0x0000000F -#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */ +/* + * Mask of AP ADDR in select cache, concatenating DP SELECT and DP_SELECT1. + * In case of ADIv5, the mask contains both APSEL and APBANKSEL fields. + */ +#define SELECT_AP_MASK (~(uint64_t)DP_SELECT_DPBANK) #define DP_APSEL_MAX (255) /* Strict limit for ADIv5, number of AP buffers for ADIv6 */ #define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */ @@ -338,11 +342,21 @@ struct adiv5_dap { /* The current manually selected AP by the "dap apsel" command */ uint64_t apsel; + /** Cache for DP SELECT and SELECT1 (ADIv6) register. */ + uint64_t select; + /** Validity of DP SELECT cache. false will force register rewrite */ + bool select_valid; + bool select1_valid; /* ADIv6 only */ /** - * Cache for DP_SELECT register. A value of DP_SELECT_INVALID - * indicates no cached value and forces rewrite of the register. + * Partial DPBANKSEL validity for SWD only. + * ADIv6 line reset sets DP SELECT DPBANKSEL to zero, + * ADIv5 does not. + * We can rely on it for the banked DP register 0 also on ADIv5 + * as ADIv5 has no mapping for DP reg 0 - it is always DPIDR. + * It is important to avoid setting DP SELECT in connection + * reset state before reading DPIDR. */ - uint64_t select; + bool select_dpbanksel_valid; /* information about current pending SWjDP-AHBAP transaction */ uint8_t ack; From bfc12522395af86ba634aa8e085a8051ca6fd43c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 15 Mar 2023 13:58:52 +0100 Subject: [PATCH 0675/1312] target/arm_adi_v5,arm_dap: introduce pre_connect_init() dap operation SWD multidrop requires some initialization once before connecting all daps. Provide an optional pre-connect dap operation. Change-Id: I778215c512c56423a425dda80ab19a739f22f285 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7542 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_adi_v5.h | 3 +++ src/target/arm_dap.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index e07b577af6..fc7fdafd84 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -420,6 +420,9 @@ struct adiv5_dap { * available until run(). */ struct dap_ops { + /** Optional; called once on the first enabled dap before connecting */ + int (*pre_connect_init)(struct adiv5_dap *dap); + /** connect operation for SWD */ int (*connect)(struct adiv5_dap *dap); diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 84cc6c743b..9f4afae743 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -91,6 +91,7 @@ static int dap_init_all(void) { struct arm_dap_object *obj; int retval; + bool pre_connect = true; LOG_DEBUG("Initializing all DAPs ..."); @@ -123,6 +124,14 @@ static int dap_init_all(void) is_adiv6(dap) ? "ADIv6" : "ADIv5"); } + if (pre_connect && dap->ops->pre_connect_init) { + retval = dap->ops->pre_connect_init(dap); + if (retval != ERROR_OK) + return retval; + + pre_connect = false; + } + retval = dap->ops->connect(dap); if (retval != ERROR_OK) return retval; From 357996d99626170c11cb896be91c4cdc2afbca8d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 15 Mar 2023 14:12:47 +0100 Subject: [PATCH 0676/1312] target/adi_v5_swd: optimize sequences in swd_connect_multidrop() swd_connect_multidrop() sent DORMANT_TO_SWD and called swd_multidrop_select_inner(). DORMANT_TO_SWD sequence ends with a LINE_RESET sequence. swd_multidrop_select_inner() sent LINE_RESET sequence again. It was useless in this case. swd_connect_multidrop() emited JTAG_TO_DORMANT and DORMANT_TO_SWD sequences before connecting each DAP in SWD multidrop bus. It is sufficient to emit JTAG_TO_DORMANT and DORMANT_TO_SWD just once and emit the shorter LINE_RESET instead for subsequent DAPs. Introduce a global variable swd_multidrop_in_swd_state and use it to control what sequence is emitted. In case of reconnect after an error, always use the full switch JTAG_TO_DORMANT and DORMANT_TO_SWD. Change-Id: Iba21620f6a9680793208bf398960ed0eb59df3b1 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7218 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/adi_v5_swd.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 968798b324..edcad741e9 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -48,6 +48,8 @@ static bool do_sync; static struct adiv5_dap *swd_multidrop_selected_dap; +static bool swd_multidrop_in_swd_state; + static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, uint32_t data); @@ -187,7 +189,15 @@ static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr assert(dap_is_multidrop(dap)); - swd_send_sequence(dap, LINE_RESET); + /* Send JTAG_TO_DORMANT and DORMANT_TO_SWD just once + * and then use shorter LINE_RESET until communication fails */ + if (!swd_multidrop_in_swd_state) { + swd_send_sequence(dap, JTAG_TO_DORMANT); + swd_send_sequence(dap, DORMANT_TO_SWD); + } else { + swd_send_sequence(dap, LINE_RESET); + } + /* * Zero dap->select and set dap->select_dpbanksel_valid * to skip the write to DP_SELECT before DPIDR read, avoiding @@ -245,6 +255,7 @@ static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32, dap->multidrop_targetsel); swd_multidrop_selected_dap = dap; + swd_multidrop_in_swd_state = true; if (dpidr_ptr) *dpidr_ptr = dpidr; @@ -294,8 +305,9 @@ static int swd_connect_multidrop(struct adiv5_dap *dap) int64_t timeout = timeval_ms() + 500; do { - swd_send_sequence(dap, JTAG_TO_DORMANT); - swd_send_sequence(dap, DORMANT_TO_SWD); + /* Do not make any assumptions about SWD state in case of reconnect */ + if (dap->do_reconnect) + swd_multidrop_in_swd_state = false; /* Clear link state, including the SELECT cache. */ dap->do_reconnect = false; @@ -306,6 +318,7 @@ static int swd_connect_multidrop(struct adiv5_dap *dap) if (retval == ERROR_OK) break; + swd_multidrop_in_swd_state = false; alive_sleep(1); } while (timeval_ms() < timeout); @@ -316,6 +329,7 @@ static int swd_connect_multidrop(struct adiv5_dap *dap) return retval; } + swd_multidrop_in_swd_state = true; LOG_INFO("SWD DPIDR 0x%08" PRIx32 ", DLPIDR 0x%08" PRIx32, dpidr, dlpidr); @@ -392,6 +406,13 @@ static int swd_connect_single(struct adiv5_dap *dap) return retval; } +static int swd_pre_connect(struct adiv5_dap *dap) +{ + swd_multidrop_in_swd_state = false; + + return ERROR_OK; +} + static int swd_connect(struct adiv5_dap *dap) { int status; @@ -627,7 +648,12 @@ static void swd_quit(struct adiv5_dap *dap) done = true; if (dap_is_multidrop(dap)) { + /* Emit the switch seq to dormant state regardless the state mirrored + * in swd_multidrop_in_swd_state. Doing so ensures robust operation + * in the case the variable is out of sync. + * Sending SWD_TO_DORMANT makes no change if the DP is already dormant. */ swd->switch_seq(SWD_TO_DORMANT); + swd_multidrop_in_swd_state = false; /* Revisit! * Leaving DPs in dormant state was tested and offers some safety * against DPs mismatch in case of unintentional use of non-multidrop SWD. @@ -648,6 +674,7 @@ static void swd_quit(struct adiv5_dap *dap) } const struct dap_ops swd_dap_ops = { + .pre_connect_init = swd_pre_connect, .connect = swd_connect, .send_sequence = swd_send_sequence, .queue_dp_read = swd_queue_dp_read, From fc268f83261e08cfb1751f8e8f9a20900bf0e360 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 8 Dec 2023 13:57:44 -0800 Subject: [PATCH 0677/1312] target/armv8: Add more support for decoding memory attributes Change-Id: I7ac7b06d67ec806a9ebffc26a7c6b9c24f024478 Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/8043 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv8.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index d197477ace..daf1ffca38 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -943,6 +943,81 @@ int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr return ERROR_OK; } +static void armv8_decode_cacheability(int attr) +{ + if (attr == 0) { + LOG_USER_N("UNPREDICTABLE"); + return; + } + if (attr == 4) { + LOG_USER_N("Non-cacheable"); + return; + } + switch (attr & 0xC) { + case 0: + LOG_USER_N("Write-Through Transient"); + break; + case 0x4: + LOG_USER_N("Write-Back Transient"); + break; + case 0x8: + LOG_USER_N("Write-Through Non-transient"); + break; + case 0xC: + LOG_USER_N("Write-Back Non-transient"); + break; + } + if (attr & 2) + LOG_USER_N(" Read-Allocate"); + else + LOG_USER_N(" No-Read Allocate"); + if (attr & 1) + LOG_USER_N(" Write-Allocate"); + else + LOG_USER_N(" No-Write Allocate"); +} + +static void armv8_decode_memory_attr(int attr) +{ + if (attr == 0x40) { + LOG_USER("Normal Memory, Inner Non-cacheable, " + "Outer Non-cacheable, XS=0"); + } else if (attr == 0xA0) { + LOG_USER("Normal Memory, Inner Write-through Cacheable, " + "Outer Write-through Cacheable, Read-Allocate, " + "No-Write Allocate, Non-transient, XS=0"); + } else if (attr == 0xF0) { + LOG_USER("Tagged Normal Memory, Inner Write-Back, " + "Outer Write-Back, Read-Allocate, Write-Allocate, " + "Non-transient"); + } else if ((attr & 0xF0) == 0) { + switch (attr & 0xC) { + case 0: + LOG_USER_N("Device-nGnRnE Memory"); + break; + case 0x4: + LOG_USER_N("Device-nGnRE Memory"); + break; + case 0x8: + LOG_USER_N("Device-nGRE Memory"); + break; + case 0xC: + LOG_USER_N("Device-GRE Memory"); + break; + } + if (attr & 1) + LOG_USER(", XS=0"); + else + LOG_USER_N("\n"); + } else { + LOG_USER_N("Normal Memory, Inner "); + armv8_decode_cacheability(attr & 0xF); + LOG_USER_N(", Outer "); + armv8_decode_cacheability(attr >> 4); + LOG_USER_N("\n"); + } +} + /* V8 method VA TO PA */ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, target_addr_t *val, int meminfo) @@ -1025,11 +1100,9 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, int NS = (par >> 9) & 1; int ATTR = (par >> 56) & 0xFF; - char *memtype = (ATTR & 0xF0) == 0 ? "Device Memory" : "Normal Memory"; - LOG_USER("%sshareable, %s", shared_name[SH], secure_name[NS]); - LOG_USER("%s", memtype); + armv8_decode_memory_attr(ATTR); } } From 8d3728f931888d2e9a9bc5a31d26c8327649e676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Nordstr=C3=B6m?= Date: Sun, 17 Dec 2023 23:14:37 +0100 Subject: [PATCH 0678/1312] jtag: add -ir-bypass option to newtap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices with an internal multi-tap JTAG router require a vendor specific bypass instruction to bypass the master TAP when addressing slave taps internal to the same device. On these devices the standard bypass instruction bypasses the whole device. Change-Id: I4506f0e67c9e4dfe39b7fa18c63d67900313e594 Signed-off-by: Henrik Nordström Reviewed-on: https://review.openocd.org/c/openocd/+/8041 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 4 ++++ src/jtag/drivers/driver.c | 8 +++++++- src/jtag/hla/hla_transport.c | 2 ++ src/jtag/jtag.h | 3 +++ src/jtag/tcl.c | 12 ++++++++++++ src/target/adi_v5_dapdirect.c | 2 ++ src/target/adi_v5_swd.c | 1 + 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index ec7c9964a8..7467e6ad96 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4424,6 +4424,10 @@ there seems to be no problems with JTAG scan chain operations. 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. +@item @code{-ir-bypass} @var{NUMBER} +@*Vendor specific bypass instruction, required by some hierarchical JTAG +routers where the normal BYPASS instruction bypasses the whole router and +a vendor specific bypass instruction is required to access child nodes. @end itemize @end deffn diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index 7732315003..fae2aad229 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -85,7 +85,13 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active, tap->bypass = true; field->num_bits = tap->ir_length; - field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length); + if (tap->ir_bypass_value) { + uint8_t *v = cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)); + buf_set_u64(v, 0, tap->ir_length, tap->ir_bypass_value); + field->out_value = v; + } else { + field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length); + } field->in_value = NULL; /* do not collect input for tap's in bypass */ } diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c index 08ee18f365..c0443d8356 100644 --- a/src/jtag/hla/hla_transport.c +++ b/src/jtag/hla/hla_transport.c @@ -45,6 +45,7 @@ static const struct command_registration hl_swd_transport_subcommand_handlers[] "['-ignore-version'] " "['-ignore-bypass'] " "['-ircapture' number] " + "['-ir-bypass' number] " "['-mask' number]", }, COMMAND_REGISTRATION_DONE @@ -74,6 +75,7 @@ static const struct command_registration hl_transport_jtag_subcommand_handlers[] "['-ignore-version'] " "['-ignore-bypass'] " "['-ircapture' number] " + "['-ir-bypass' number] " "['-mask' number]", }, { diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 1d1c495cf1..470ae18334 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -133,6 +133,9 @@ struct jtag_tap { /** Bypass register selected */ bool bypass; + /** Bypass instruction value */ + uint64_t ir_bypass_value; + struct jtag_tap_event_action *event_action; struct jtag_tap *next_tap; diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 85a66aaf62..407aeb1d80 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -386,6 +386,7 @@ static int jtag_tap_configure_cmd(struct jim_getopt_info *goi, struct jtag_tap * #define NTAP_OPT_EXPECTED_ID 5 #define NTAP_OPT_VERSION 6 #define NTAP_OPT_BYPASS 7 +#define NTAP_OPT_IRBYPASS 8 static const struct nvp jtag_newtap_opts[] = { { .name = "-irlen", .value = NTAP_OPT_IRLEN }, @@ -396,6 +397,7 @@ static const struct nvp jtag_newtap_opts[] = { { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID }, { .name = "-ignore-version", .value = NTAP_OPT_VERSION }, { .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS }, + { .name = "-ir-bypass", .value = NTAP_OPT_IRBYPASS }, { .name = NULL, .value = -1 }, }; @@ -499,6 +501,15 @@ static COMMAND_HELPER(handle_jtag_newtap_args, struct jtag_tap *tap) tap->ignore_bypass = true; break; + case NTAP_OPT_IRBYPASS: + if (!CMD_ARGC) + return ERROR_COMMAND_ARGUMENT_INVALID; + + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], tap->ir_bypass_value); + CMD_ARGC--; + CMD_ARGV++; + break; + default: nvp_unknown_command_print(CMD, jtag_newtap_opts, NULL, CMD_ARGV[-1]); return ERROR_COMMAND_ARGUMENT_INVALID; @@ -752,6 +763,7 @@ static const struct command_registration jtag_subcommand_handlers[] = { "['-ignore-version'] " "['-ignore-bypass'] " "['-ircapture' number] " + "['-ir-bypass' number] " "['-mask' number]", }, { diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c index 575092cbf2..f3a90c0b17 100644 --- a/src/target/adi_v5_dapdirect.c +++ b/src/target/adi_v5_dapdirect.c @@ -66,6 +66,7 @@ static const struct command_registration dapdirect_jtag_subcommand_handlers[] = "['-ignore-version'] " "['-ignore-bypass'] " "['-ircapture' number] " + "['-ir-bypass' number] " "['-mask' number]", }, { @@ -156,6 +157,7 @@ static const struct command_registration dapdirect_swd_subcommand_handlers[] = { "['-ignore-version'] " "['-ignore-bypass'] " "['-ircapture' number] " + "['-ir-bypass' number] " "['-mask' number]", }, COMMAND_REGISTRATION_DONE diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index edcad741e9..6d6f287b05 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -705,6 +705,7 @@ static const struct command_registration swd_commands[] = { "['-ignore-version'] " "['-ignore-bypass'] " "['-ircapture' number] " + "['-ir-bypass' number] " "['-mask' number]", }, COMMAND_REGISTRATION_DONE From 65fc586d6ee18813937ec0fdb264b9e0d4bc1c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Nordstr=C3=B6m?= Date: Sun, 17 Dec 2023 17:39:50 +0100 Subject: [PATCH 0679/1312] tcl/target: add Marvell Octeon TX2 CN9130 target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This has a quite complex JTAG router chain requiring both a custom BYPASS instruction to access child taps, and JTAG configuration to enable individual DAP nodes. Change-Id: I6f5345764e1566d70c8526a7e8ec5d250185bd2c Signed-off-by: Henrik Nordström Reviewed-on: https://review.openocd.org/c/openocd/+/8042 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/marvell/cn9130.cfg | 178 ++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 tcl/target/marvell/cn9130.cfg diff --git a/tcl/target/marvell/cn9130.cfg b/tcl/target/marvell/cn9130.cfg new file mode 100644 index 0000000000..23e472f284 --- /dev/null +++ b/tcl/target/marvell/cn9130.cfg @@ -0,0 +1,178 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# cn9130 -- support for the Marvell Octeon TX2 / CN9130 CPU family +# +# henrik.nordstorm@addiva.se, Nov 2023 + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME cn9130 +} + +if { [info exists MASTERTAPID] } { + set _MASTERTAPID $MASTERTAPID +} else { + set _MASTERTAPID 0x07025357 +} + +if { [info exists APTAPID] } { + set _APTAPID $APTAPID +} else { + set _APTAPID 0x4ba00477 +} + +if { [info exists SBTAPID] } { + set _SBTAPID $SBTAPID +} else { + set _SBTAPID 0x4ba00477 +} + +if { [info exists CORES] } { + set _CORES $CORES +} else { + set _CORES 4 +} + +# CTI base address should be possible to read from the CoreSight +# ROM table like how the DBG base address is when not specified. +if { [info exists CTIBASE] } { + set _CTIBASE $CTIBASE +} else { + set _CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000} +} + +# CN9130 is a multi-die chip and has a multi level hierarchical +# JTAG TAP, where all the DAPs are disabled at reset, requiring +# both configuration to enable access to the chip DAPs, and a +# vendor specific bypass IR instruction to access the slave TAPs +# via the master TAP. In addition there is a number of sample +# bits that should be ignored. +# +# The default BYPASS instruction in the master TAP bypasses the +# whole chip and not only the master TAP. And similarly on +# IDCODE the master TAP only responds with it's own ID and +# bypasses the other TAPs on the chip, while OpenOCD expects +# ID from all enabled TAPs in the chain. + +# Bootstrap with the default boundary scan oriented TAP configuration +# where the master,ap,sb TAPs are seen as one big fat TAP, which matches +# what OpenOCD expects from IDCODE and BYPASS. + +jtag newtap $_CHIPNAME bs -irlen 19 -enable -expected-id $_MASTERTAPID + +# Declare the full JTAG chain, but in disabled state during setup + +jtag newtap $_CHIPNAME sample4 -irlen 1 -disable +jtag newtap $_CHIPNAME sample3 -irlen 1 -disable +jtag newtap $_CHIPNAME sample2 -irlen 1 -disable +jtag newtap $_CHIPNAME ap.cpu -irlen 4 -disable -expected-id $_APTAPID +jtag newtap $_CHIPNAME ap -irlen 5 -disable +jtag newtap $_CHIPNAME sample1 -irlen 1 -disable +jtag newtap $_CHIPNAME sb.cpu -irlen 4 -disable -expected-id $_SBTAPID +jtag newtap $_CHIPNAME sb -irlen 5 -disable +jtag newtap $_CHIPNAME master -irlen 5 -disable -ir-bypass 0x11 -expected-id $_MASTERTAPID + +# Once the iniial IDCODE scan has completed switch to more detailed +# scan chain giving access to the individual chip TAPs. + +jtag configure $_CHIPNAME.bs -event setup "cn9130_enable_full_chain $_CHIPNAME" + +proc cn9130_enable_full_chain { _CHIPNAME } { + # Switch to detailed TAP declaration + jtag tapdisable $_CHIPNAME.bs + jtag tapenable $_CHIPNAME.master + jtag tapenable $_CHIPNAME.sb + jtag tapenable $_CHIPNAME.sample1 + jtag tapenable $_CHIPNAME.ap + jtag tapenable $_CHIPNAME.sample2 + jtag tapenable $_CHIPNAME.sample3 + jtag tapenable $_CHIPNAME.sample4 +} + +# AP & SB TAPs have a config register to enable/disable access to +# the auxilary DAP TAP. Default off which hides the DAP TAP from +# the scan chain. +proc cn9130_dap_config { chip tap state } { + irscan $chip.$tap 0x12 + drscan $chip.$tap 32 $state +} + +jtag configure $_CHIPNAME.bs -event tap-disable "" +jtag configure $_CHIPNAME.bs -event tap-enable "" +jtag configure $_CHIPNAME.sample4 -event tap-enable "" +jtag configure $_CHIPNAME.sample3 -event tap-enable "" +jtag configure $_CHIPNAME.sample2 -event tap-enable "" +jtag configure $_CHIPNAME.ap.cpu -event tap-disable "cn9130_dap_config $_CHIPNAME ap 0" +jtag configure cn9130.ap.cpu -event tap-enable "cn9130_dap_config $_CHIPNAME ap 1" +jtag configure $_CHIPNAME.ap -event tap-enable "" +jtag configure $_CHIPNAME.sample1 -event tap-enable "" +jtag configure $_CHIPNAME.sb.cpu -event tap-disable "cn9130_dap_config $_CHIPNAME sb 0" +jtag configure cn9130.sb.cpu -event tap-enable "cn9130_dap_config $_CHIPNAME sb 1" +jtag configure $_CHIPNAME.sb -event tap-enable "" +jtag configure $_CHIPNAME.master -event tap-enable "" + +dap create $_CHIPNAME.ap.dap -chain-position $_CHIPNAME.ap.cpu + +# Main bus +target create $_CHIPNAME.ap.axi mem_ap \ + -dap $_CHIPNAME.ap.dap \ + -ap-num 0 + +# Periperials bus +target create $_CHIPNAME.ap.apb mem_ap \ + -dap $_CHIPNAME.ap.dap \ + -ap-num 1 + +# MSS bus +target create $_CHIPNAME.ap.ahb mem_ap \ + -dap $_CHIPNAME.ap.dap \ + -ap-num 2 + +# AP A72 CPU cores +set _smp_command "" +for { set _core 0 } { $_core < $_CORES } { incr _core 1 } { + cti create $_CHIPNAME.ap.cti.$_core \ + -dap $_CHIPNAME.ap.dap \ + -baseaddr [ lindex $_CTIBASE $_core ] \ + -ap-num 1 + + if { $_core == 0 } { + target create $_CHIPNAME.ap.a72.$_core aarch64 \ + -dap $_CHIPNAME.ap.dap \ + -ap-num 1 \ + -cti $_CHIPNAME.ap.cti.$_core \ + -coreid $_core \ + -rtos hwthread + set _smp_command "target smp $_CHIPNAME.ap.a72.$_core" + } else { + # Defer non-boot cores. Held hard in reset until + # SMP is activated. + target create $_CHIPNAME.ap.a72.$_core aarch64 \ + -dap $_CHIPNAME.ap.dap \ + -ap-num 1 \ + -cti $_CHIPNAME.ap.cti.$_core \ + -coreid $_core \ + -defer-examine + set _smp_command "$_smp_command $_CHIPNAME.ap.a72.$_core" + } + +} + +# Set up the A72 cluster as SMP +# Note: Only the boot core is active by default. The other core DAPs can +# be enabled by arp_examine after they have been released from hard reset. +eval $_smp_command + +# AP MSS M3 CPU core. Defer as it is held in reset until firmware is loaded. +target create $_CHIPNAME.ap.mss cortex_m -dap $_CHIPNAME.ap.dap -ap-num 2 -defer-examine + +# Why is this needed? reset fails with "Debug regions are unpowered" otherwise +$_CHIPNAME.ap.axi configure -event examine-start "dap init" + +# Automate enabling the AP A72 DAP once the full scan chain is enabled +proc cn9130_ap_setup { _CHIPNAME } { + jtag tapenable $_CHIPNAME.ap.cpu + targets $_CHIPNAME.ap.a72.0 +} +jtag configure $_CHIPNAME.ap -event setup "cn9130_ap_setup $_CHIPNAME" From 8df529fa663cef2004a6a26e8f147b8c96e03de9 Mon Sep 17 00:00:00 2001 From: Aleksey Shargalin Date: Tue, 31 Oct 2017 17:23:40 +0300 Subject: [PATCH 0680/1312] bitbang: Add flush before sleep Some bitbang interfaces have no speed regulation and work as fast as they can. Only the sequence of execuded commands is guaranteed but not the timing. It works most of time with one exception: when the JTAG_SLEEP command is executed, we expect that all previous commands already finished so that the sleep interval is guaranteed. For now there may be situations when the sleep time has passed but previous commands are not actually executed. This patch adds a flush command to the bitbang interface, connects it to the existing implementation for remote_bitbang, and runs it when the JTAG_SLEEP command is executed. Change-Id: If40894a63d29a260a4ded134b008df6dd1e89c46 Signed-off-by: Aleksey Shargalin Signed-off-by: David Ryskalczyk Reviewed-on: https://review.openocd.org/c/openocd/+/4284 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/bitbang.c | 2 ++ src/jtag/drivers/bitbang.h | 3 +++ src/jtag/drivers/remote_bitbang.c | 1 + 3 files changed, 6 insertions(+) diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 6e97d15840..186d2098af 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -360,6 +360,8 @@ int bitbang_execute_queue(void) break; case JTAG_SLEEP: LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us); + if (bitbang_interface->flush && (bitbang_interface->flush() != ERROR_OK)) + return ERROR_FAIL; bitbang_sleep(cmd->cmd.sleep->us); break; case JTAG_TMS: diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index e3714df9c8..097a5c0d12 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -57,6 +57,9 @@ struct bitbang_interface { /** Sleep for some number of microseconds. **/ int (*sleep)(unsigned int microseconds); + + /** Force a flush. */ + int (*flush)(void); }; extern const struct swd_driver bitbang_swd; diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index c488f83340..6d0fba2e40 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -281,6 +281,7 @@ static struct bitbang_interface remote_bitbang_bitbang = { .swd_write = &remote_bitbang_swd_write, .blink = &remote_bitbang_blink, .sleep = &remote_bitbang_sleep, + .flush = &remote_bitbang_flush, }; static int remote_bitbang_init_tcp(void) From 5394e5b762ec01bef6bd5b00faa63b3361599e24 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 11 Dec 2023 16:28:17 +0100 Subject: [PATCH 0681/1312] target/cortex_m: Add Cortex-M85 part Change-Id: I91d4c05307d9611ecab11eb52218ab1cb7ed65e3 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8048 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tarek BOCHKATI --- src/target/cortex_m.c | 6 ++++++ src/target/cortex_m.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 3eafee0a16..d9e8b538f9 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -105,6 +105,12 @@ static const struct cortex_m_part_info cortex_m_parts[] = { .arch = ARM_ARCH_V8M, .flags = CORTEX_M_F_HAS_FPV5, }, + { + .impl_part = CORTEX_M85_PARTNO, + .name = "Cortex-M85", + .arch = ARM_ARCH_V8M, + .flags = CORTEX_M_F_HAS_FPV5, + }, { .impl_part = STAR_MC1_PARTNO, .name = "STAR-MC1", diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 0bc139911a..a585b786b9 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -56,6 +56,7 @@ enum cortex_m_impl_part { CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21), CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31), CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22), + CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD23), INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0), REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20), REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22), From a90b1642ec1c5dc12c7d9d2af806efee582f7b19 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 13 May 2023 12:24:04 +0200 Subject: [PATCH 0682/1312] flash/nor/stm32f1x: Add support for Geehy APM32F0 series Tested with APM32F030C8T. Change-Id: I63cd8b66424135dae481a96ba560e6f0b1f9544e Suggested-by: Christian U Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8014 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- doc/openocd.texi | 10 ++++------ src/flash/nor/stm32f1x.c | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 7467e6ad96..395d03ca29 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7707,12 +7707,10 @@ applied to all of them. @end deffn @deffn {Flash Driver} {stm32f1x} -All members of the STM32F0, STM32F1 and STM32F3 microcontroller families -from STMicroelectronics and all members of the GD32F1x0, GD32F3x0 and GD32E23x microcontroller -families from GigaDevice include internal flash and use ARM Cortex-M0/M3/M4/M23 cores. -The driver also works with GD32VF103 powered by RISC-V core. -The driver automatically recognizes a number of these chips using -the chip identification register, and autoconfigures itself. +This driver supports the STM32F0, STM32F1 and STM32F3 microcontroller series from STMicroelectronics. +The driver is also compatible with the GD32F1, GD32VF103 (RISC-V core), GD32F3 and GD32E23 microcontroller series from GigaDevice. +The driver also supports the APM32F0 series from Geehy Semiconductor. +The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @example flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index b3bb843358..5a3c2da663 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -745,6 +745,7 @@ static int stm32x_get_property_addr(struct target *target, struct stm32x_propert switch (cortex_m_get_impl_part(target)) { case CORTEX_M0_PARTNO: /* STM32F0x devices */ + case CORTEX_M0P_PARTNO: /* APM32F0x devices */ addr->device_id = 0x40015800; addr->flash_size = 0x1FFFF7CC; return ERROR_OK; From d46a3d635e3d41e2c531a20c97bde217431b5f76 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 13 May 2023 12:37:12 +0200 Subject: [PATCH 0683/1312] tcl/target: Add Geehy APM32F0x config Tested with APM32F030C8T using SWD transport. All flash operations, including sector and device protection, work as expected. Revision identifier (0x0011) is not updated due to missing documentation. Introduce a new directory structure that contains the manufacturer for the sake of clarity. Change-Id: I679387943b09fef640f8f8b6904e542f4e4b29aa Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8015 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/geehy/apm32f0x.cfg | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tcl/target/geehy/apm32f0x.cfg diff --git a/tcl/target/geehy/apm32f0x.cfg b/tcl/target/geehy/apm32f0x.cfg new file mode 100644 index 0000000000..502c092751 --- /dev/null +++ b/tcl/target/geehy/apm32f0x.cfg @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Geehy APM32F0x target +# +# https://global.geehy.com/MCU +# + +# +# APM32F0x devices support SWD transport only. +# +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME apm32f0x +} + +# Work-area is a space in RAM used for flash programming, by default use 1 KiB. +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x400 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x0bc11477 +} + +swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME + +adapter speed 1000 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to perform a soft reset. + cortex_m reset_config sysresetreq +} From 7f3aba13191debc68742f70580de7cf8465d3611 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 14 May 2023 15:03:07 +0200 Subject: [PATCH 0684/1312] tcl/target: Add Geehy APM32F4x config Tested with APM32407RGT6 using JTAG and SWD transport. All flash operations, including sector and device protection, work as expected. Revision identifier (0x0009) is not updated due to missing documentation. Change-Id: I33f4630fd00096656369ecc923aea2dcad77c7d3 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8016 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/geehy/apm32f4x.cfg | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tcl/target/geehy/apm32f4x.cfg diff --git a/tcl/target/geehy/apm32f4x.cfg b/tcl/target/geehy/apm32f4x.cfg new file mode 100644 index 0000000000..3ed58d15b5 --- /dev/null +++ b/tcl/target/geehy/apm32f4x.cfg @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Geehy APM32F4x target +# +# https://global.geehy.com/MCU +# + +# +# APM32F4x devices support JTAG and SWD transport. +# +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME apm32f4x +} + +# Work-area is a space in RAM used for flash programming, by default use 4 KiB. +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + set _CPUTAPID 0x4ba00477 + } else { + set _CPUTAPID 0x2ba01477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if { [using_jtag] } { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME + +adapter speed 1000 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to perform a soft reset. + cortex_m reset_config sysresetreq +} From b0f99dfed0d0f95d3f9190f1767b4f2f6969f5bc Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 8 Nov 2023 10:27:36 +0100 Subject: [PATCH 0685/1312] tcl/target: Add Geehy APM32F1x config Tested with APM32F103CBT6 using JTAG and SWD transport. All flash operations, including sector and device protection, work as expected. Change-Id: Ibefe1a65d710aea87b86ab7ff8a4153512a0ea4f Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8017 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- tcl/target/geehy/apm32f1x.cfg | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tcl/target/geehy/apm32f1x.cfg diff --git a/tcl/target/geehy/apm32f1x.cfg b/tcl/target/geehy/apm32f1x.cfg new file mode 100644 index 0000000000..dc42e060a6 --- /dev/null +++ b/tcl/target/geehy/apm32f1x.cfg @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Geehy APM32F1x target +# +# https://global.geehy.com/MCU +# + +# +# APM32F1x devices support JTAG and SWD transport. +# +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME apm32f1x +} + +# Work-area is a space in RAM used for flash programming, by default use 4 KiB. +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + set _CPUTAPID 0x4ba00477 + } { + set _CPUTAPID 0x2ba01477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME + +adapter speed 1000 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to perform a soft reset. + cortex_m reset_config sysresetreq +} From 5c53034d85480d0855394c4683733f61b27b6c5e Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 14 Nov 2023 10:55:46 +0100 Subject: [PATCH 0686/1312] doc/openocd: Mention APM32F1 and APM32F4 series Change-Id: I2ff28b0fdf4923a58771a44ad6e83ac871d6fa9e Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8018 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- doc/openocd.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 395d03ca29..cc133f7916 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7709,7 +7709,7 @@ applied to all of them. @deffn {Flash Driver} {stm32f1x} This driver supports the STM32F0, STM32F1 and STM32F3 microcontroller series from STMicroelectronics. The driver is also compatible with the GD32F1, GD32VF103 (RISC-V core), GD32F3 and GD32E23 microcontroller series from GigaDevice. -The driver also supports the APM32F0 series from Geehy Semiconductor. +The driver also supports the APM32F0 and APM32F1 series from Geehy Semiconductor. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. @example @@ -7771,6 +7771,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @deffn {Flash Driver} {stm32f2x} All members of the STM32F2, STM32F4 and STM32F7 microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M3/M4/M7 cores. +The driver also works for the APM32F4 series from Geehy Semiconductor. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. From b7173732471c230a7fdc56efe23be35f60dbaae9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 10 Dec 2023 21:35:10 +0100 Subject: [PATCH 0687/1312] doc: usb_adapters: update the script for unavailable reports When Linux HID driver binds the USB endpoints of the adapter, 'lsusb' fails to read all the reports and prints ** UNAVAILABLE ** Detect this case and alert the user, providing also the proper command to unbind the driver before running the script again. Put this test at the end of the output, so user can easily see it. Change-Id: Iaca00040e666b62ceebe4b842a24932799bde56a Signed-off-by: Antonio Borneo Reported-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8046 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/usb_adapters/dump.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/usb_adapters/dump.sh b/doc/usb_adapters/dump.sh index 1ecfb40f08..557ef7f4c9 100755 --- a/doc/usb_adapters/dump.sh +++ b/doc/usb_adapters/dump.sh @@ -1,6 +1,22 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0-or-later +hid_unavailable_report() { + a=$(echo $1 | tr '[:lower:]' '[:upper:]') + b=$(basename $(dirname $(ls -d /sys/bus/usb/drivers/usbhid/*/*:$a.*))) + + echo "" + echo "ATTENTION!" + echo "Unable to read completely the USB descriptors." + echo "Please run the following command(s) and then run this script again" + for i in $b; do + echo " sudo sh -c \"echo -n $i > /sys/bus/usb/drivers/usbhid/unbind\"" + done + echo "" + echo "Please notice that the USB device will not function after the above" + echo "operations; you should unplug and replug it to get it working again." +} + devs=$(lsusb -d $1:$2 | wc -l) case "$devs" in 0 ) @@ -22,3 +38,5 @@ echo '' echo '# Optional comment' lsusb -v -d $1:$2 | sed 's/ *$//' + +lsusb -v -d $1:$2 2>&1 | grep -Fq '** UNAVAILABLE **' && (hid_unavailable_report $1:$2 > /dev/stderr) From 7de4b1202d5049dead386b3bcfa238b299f7c742 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Tue, 26 Sep 2023 17:21:42 +0800 Subject: [PATCH 0688/1312] target/mips32: add cpu info detection Add detection for mips cpu types by using prid. Add cpuinfo command for inspecting more verbose info. Add MIPS Architecture specs in openocd docs. Change-Id: I28573b7c51783628db986bad0e226dcc399b4fa6 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7912 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- doc/openocd.texi | 58 ++++++++ src/target/mips32.c | 333 ++++++++++++++++++++++++++++++++++++++++-- src/target/mips32.h | 165 ++++++++++++--------- src/target/mips_cpu.h | 13 +- 4 files changed, 482 insertions(+), 87 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index cc133f7916..cf41bc538a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -10981,6 +10981,64 @@ addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system @end deffn +@section MIPS Architecture +@cindex microMIPS +@cindex MIPS32 +@cindex MIPS64 + +@uref{http://mips.com/, MIPS} is a simple, streamlined, highly scalable RISC +architecture. The architecture is evolving over time, from MIPS I~V to +MIPS release 1~6 iterations, the architecture is now able to handle various tasks +with different ASEs, including SIMD(MSA), DSP, VZ, MT and more. +MIPS32 supports 32-bit programs while MIPS64 can support both 32-bit and 64-bit programs. + +@subsection MIPS Terminology + +The term ASE means Application-Specific Extension, ASEs provide features that +improve the efficiency and performance of certain workloads, such as +digital signal processing(DSP), Virtualization(VZ), Multi-Threading(MT), +SIMD(MSA) and more. +The MIPS CPU Uses Coprocessors to configure its behaviour or to let software +know the capabilities of current CPU, the commonly used ones are Config0~3 Registers +and Status register. + +@subsection MIPS FPU & Vector Registers + +MIPS processors does not all comes with FPU co-processor, and when it does, the FPU +appears as Coprocessor 1 whereas the Coprocessor 0 is for the main processor. + +Most of MIPS FPUs are 64 bits, IEEE 754 standard, and they provides both 32-bit +single precision and 64-bit double precision calculations. Fixed point format +calculations are also provided with both 32 and 64-bit modes. + +The MIPS SIMD Architecture(MSA) operates on 32 128-bit wide vector registers. +If both MSA and the scalar floating-point unit (FPU) are present, the 128-bit MSA +vector registers extend and share the 64-bit FPU registers. MSA and FPU can not be +both present, unless the FPU has 64-bit floating-point register. + +@subsection MIPS Configuration Commands + +@deffn {Command} {mips32 cpuinfo} +Displays detailed information about current CPU core. This includes core type, +vendor, instruction set, cache size, and other relevant details. +@end deffn + +@deffn {Config Command} {mips32 scan_delay} [nanoseconds] +Display or set scan delay in nano seconds. A value below 2_000_000 will set the +scan delay into legacy mode. +@end deffn + +@deffn {Config Command} {mips32 cp0} regnum select [value] +Displays or sets coprocessor 0 register by register number and select. + +For common MIPS Coprocessor 0 registers, you can find the definitions of them +on MIPS Privileged Resource Architecture Documents(MIPS Document MD00090). + +For core specific cp0 registers, you can find the definitions of them on Core +Specific Software User's Manual, for example, MIPS M5150 Software User Manual +(MD00980). +@end deffn + @section RISC-V Architecture @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG diff --git a/src/target/mips32.c b/src/target/mips32.c index 5c346c42dd..af5f2c50d8 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -160,6 +160,7 @@ static const struct { #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) + static int mips32_get_core_reg(struct reg *reg) { int retval; @@ -333,9 +334,7 @@ int mips32_restore_context(struct target *target) } /* write core regs */ - mips32_pracc_write_regs(mips32); - - return ERROR_OK; + return mips32_pracc_write_regs(mips32); } int mips32_arch_state(struct target *target) @@ -764,18 +763,56 @@ static int mips32_read_c0_prid(struct target *target) return retval; } -/* - * Detect processor type and apply required quirks. +/** + * mips32_find_cpu_by_prid - Find CPU information by processor ID. + * @param[in] prid: Processor ID of the CPU. + * + * @brief This function looks up the CPU entry in the mips32_cpu_entry array based on the provided + * processor ID. It also handles special cases like AMD/Alchemy CPUs that use Company Options + * instead of Processor IDs. + * + * @return Pointer to the corresponding cpu_entry struct, or the 'unknown' entry if not found. + */ +static const struct cpu_entry *mips32_find_cpu_by_prid(uint32_t prid) +{ + /* AMD/Alchemy CPU uses Company Options instead of Processor ID. + * Therefore an extra transform step for prid to map it to an assigned ID, + */ + if ((prid & PRID_COMP_MASK) == PRID_COMP_ALCHEMY) { + /* Clears Processor ID field, then put Company Option field to its place */ + prid = (prid & 0xFFFF00FF) | ((prid & 0xFF000000) >> 16); + } + + /* Mask out Company Option */ + prid &= 0x00FFFFFF; + + for (unsigned int i = 0; i < MIPS32_NUM_CPU_ENTRIES; i++) { + const struct cpu_entry *entry = &mips32_cpu_entry[i]; + if ((entry->prid & MIPS32_CORE_MASK) <= prid && prid <= entry->prid) + return entry; + } + + /* If nothing matched, then return unknown entry */ + return &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1]; +} + +/** + * mips32_cpu_probe - Detects processor type and applies necessary quirks. + * @param[in] target: The target CPU to probe. + * + * @brief This function probes the CPU, reads its PRID (Processor ID), and determines the CPU type. + * It applies any quirks necessary for specific processor types. * * NOTE: The proper detection of certain CPUs can become quite complicated. * Please consult the following Linux kernel code when adding new CPUs: * arch/mips/include/asm/cpu.h * arch/mips/kernel/cpu-probe.c + * + * @return ERROR_OK on success; error code on failure. */ int mips32_cpu_probe(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); - const char *cpu_name = "unknown"; int retval; if (mips32->prid) @@ -785,11 +822,12 @@ int mips32_cpu_probe(struct target *target) if (retval != ERROR_OK) return retval; + const struct cpu_entry *entry = mips32_find_cpu_by_prid(mips32->prid); + switch (mips32->prid & PRID_COMP_MASK) { case PRID_COMP_INGENIC_E1: switch (mips32->prid & PRID_IMP_MASK) { case PRID_IMP_XBURST_REV1: - cpu_name = "Ingenic XBurst rev1"; mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET; break; default: @@ -800,13 +838,14 @@ int mips32_cpu_probe(struct target *target) break; } - LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, mips32->prid); + mips32->cpu_info = entry; + LOG_DEBUG("CPU: %s (PRId %08x)", entry->cpu_name, mips32->prid); return ERROR_OK; } /* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/ -void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) +static void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); if (dsp_present) { @@ -818,7 +857,7 @@ void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejt } /* read fpu implementation info from CP0 Config1 register {CU1, FP}*/ -int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) +static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { int retval; uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT; @@ -858,8 +897,23 @@ int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejta return ERROR_OK; } -/* Checks if current target implements Common Device Memory Map and therefore Fast Debug Channel (MD00090) */ -void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr) +/** + * mips32_read_config_fdc - Read Fast Debug Channel configuration + * @param[in,out] mips32: MIPS32 common structure + * @param[in] ejtag_info: EJTAG information structure + * @param[in] dcr: Device Configuration Register value + * + * @brief Checks if the current target implements the Common Device Memory Map (CDMM) and Fast Debug Channel (FDC). + * + * This function examines the configuration registers and the Device Configuration Register (DCR) to determine + * if the current MIPS32 target supports the Common Device Memory Map (CDMM) and the Fast Debug Channel (FDC). + * If supported, it sets the corresponding flags in the MIPS32 common structure. \n + * + * NOTE:These are defined on MD00090, page 67 and MD00047F, page 82, respectively. + * MIPS Documents are pretty much all available online, + * it should pop up first when you search "MDxxxxx" + */ +static void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr) { if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) { mips32->fdc = 1; @@ -1112,6 +1166,51 @@ static int mips32_verify_pointer(struct command_invocation *cmd, return ERROR_OK; } +/** + * mips32_read_config_mmu - Reads MMU configuration and logs relevant information. + * @param[in] ejtag_info: EJTAG interface information. + * + * @brief Reads the MMU configuration from the CP0 register and calculates the number of TLB entries, + * ways, and sets. Handles different MMU types like VTLB only, root RPU/Fixed, and VTLB and FTLB. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_read_config_mmu(struct mips_ejtag *ejtag_info) +{ + uint32_t config4, tlb_entries = 0, ways = 0, sets = 0; + uint32_t config0 = ejtag_info->config[0]; + uint32_t config1 = ejtag_info->config[1]; + uint32_t config3 = ejtag_info->config[3]; + uint32_t mmu_type = (config0 >> 7) & 7; + uint32_t vz_present = (config3 & BIT(23)); + + int retval = mips32_cp0_read(ejtag_info, &config4, 16, 4); + if (retval != ERROR_OK) + return retval; + + /* mmu type = 1: VTLB only (Note: Does not account for Config4.ExtVTLB) + * mmu type = 3: root RPU/Fixed (Note: Only valid with VZ ASE) + * mmu type = 4: VTLB and FTLB + */ + if ((mmu_type == 1 || mmu_type == 4) || (mmu_type == 3 && vz_present)) { + tlb_entries = (uint32_t)(((config1 >> 25) & 0x3f) + 1); + if (mmu_type == 4) { + /* Release 6 definition for Config4[0:15] (MD01251, page 243) */ + /* The FTLB ways field is defined as [2, 3, 4, 5, 6, 7, 8, ...0 (reserved)] */ + int index = ((config4 >> 4) & 0xf); + ways = index > 6 ? 0 : index + 2; + + /* The FTLB sets field is defined as [1, 2, 4, 8, ..., 16384, 32768] (powers of 2) */ + index = (config4 & 0xf); + sets = 1 << index; + tlb_entries = tlb_entries + (ways * sets); + } + } + LOG_USER("TLB Entries: %d (%d ways, %d sets per way)", tlb_entries, ways, sets); + + return ERROR_OK; +} + /** * MIPS32 targets expose command interface * to manipulate CP0 registers @@ -1172,6 +1271,207 @@ COMMAND_HANDLER(mips32_handle_cp0_command) return ERROR_OK; } +/** + * mips32_handle_cpuinfo_command - Handles the 'cpuinfo' command. + * @param[in] cmd: Command invocation context. + * + * @brief Executes the 'cpuinfo' command which displays detailed information about the current CPU core. + * This includes core type, vendor, instruction set, cache size, and other relevant details. + * + * @return ERROR_OK on success; error code on failure. + */ +COMMAND_HANDLER(mips32_handle_cpuinfo_command) +{ + int retval; + struct target *target = get_current_target(CMD_CTX); + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + uint32_t prid = mips32->prid; /* cp0 PRID - 15, 0 */ + uint32_t config0 = ejtag_info->config[0]; /* cp0 config - 16, 0 */ + uint32_t config1 = ejtag_info->config[1]; /* cp0 config - 16, 1 */ + uint32_t config3 = ejtag_info->config[3]; /* cp0 config - 16, 3 */ + + /* Following configs are not read during probe */ + uint32_t config5; /* cp0 config - 16, 5 */ + + /* No args for now */ + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (target->state != TARGET_HALTED) { + command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME); + return ERROR_TARGET_NOT_HALTED; + } + + retval = mips32_cp0_read(ejtag_info, &config5, 16, 5); + if (retval != ERROR_OK) + return retval; + + /* Determine Core info */ + const struct cpu_entry *entry = mips32->cpu_info; + /* Display Core Type info */ + command_print(CMD, "CPU Core: %s", entry->cpu_name); + + /* Display Core Vendor ID if it's unknown */ + if (entry == &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1]) + command_print(CMD, "Vendor: Unknown CPU vendor code %x.", ((prid & 0x00ffff00) >> 16)); + else + command_print(CMD, "Vendor: %s", entry->vendor); + + /* If MIPS release 2 or above, then get exception base info */ + enum mips32_isa_rel ar = mips32->isa_rel; + if (ar > MIPS32_RELEASE_1) { /* release 2 and above */ + uint32_t ebase; + retval = mips32_cp0_read(ejtag_info, &ebase, 15, 1); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, "Current CPU ID: %d", (ebase & 0x1ff)); + } else { + command_print(CMD, "Current CPU ID: 0"); + } + + char *instr; + switch ((config3 & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT) { + case 0: + instr = "MIPS32"; + break; + case 1: + instr = "microMIPS"; + break; + case 2: + instr = "MIPS32 (at reset) and microMIPS"; + break; + case 3: + instr = "microMIPS (at reset) and MIPS32"; + break; + } + + /* Display Instruction Set Info */ + command_print(CMD, "Instr set: %s", instr); + command_print(CMD, "Instr rel: %s", + ar == MIPS32_RELEASE_1 ? "1" + : ar == MIPS32_RELEASE_2 ? "2" + : ar == MIPS32_RELEASE_6 ? "6" + : "unknown"); + command_print(CMD, "PRId: %x", prid); + /* Some of MIPS CPU Revisions(for M74K) can be seen on MD00541, page 26 */ + uint32_t rev = prid & 0x000000ff; + command_print(CMD, "RTL Rev: %d.%d.%d", (rev & 0xE0), (rev & 0x1C), (rev & 0x3)); + + command_print(CMD, "Max Number of Instr Breakpoints: %d", mips32->num_inst_bpoints); + command_print(CMD, "Max Number of Data Breakpoints: %d", mips32->num_data_bpoints); + + /* MMU Support */ + uint32_t mmu_type = (config0 >> 7) & 7; /* MMU Type Info */ + char *mmu; + switch (mmu_type) { + case MIPS32_MMU_TLB: + mmu = "TLB"; + break; + case MIPS32_MMU_BAT: + mmu = "BAT"; + break; + case MIPS32_MMU_FIXED: + mmu = "FIXED"; + break; + case MIPS32_MMU_DUAL_VTLB_FTLB: + mmu = "DUAL VAR/FIXED"; + break; + default: + mmu = "Unknown"; + } + command_print(CMD, "MMU Type: %s", mmu); + + retval = mips32_read_config_mmu(ejtag_info); + if (retval != ERROR_OK) + return retval; + + /* Definitions of I/D Cache Sizes are available on MD01251, page 224~226 */ + int index; + uint32_t ways, sets, bpl; + + /* Determine Instr Cache Size */ + /* Ways mapping = [1, 2, 3, 4, 5, 6, 7, 8] */ + ways = ((config1 >> MIPS32_CFG1_IASHIFT) & 7); + + /* Sets per way = [64, 128, 256, 512, 1024, 2048, 4096, 32] */ + index = ((config1 >> MIPS32_CFG1_ISSHIFT) & 7); + sets = index == 7 ? 32 : 32 << (index + 1); + + /* Bytes per line = [0, 4, 8, 16, 32, 64, 128, Reserved] */ + index = ((config1 >> MIPS32_CFG1_ILSHIFT) & 7); + bpl = index == 0 ? 0 : 4 << (index - 1); + command_print(CMD, "Instr Cache: %d (%d ways, %d lines, %d byte per line)", ways * sets * bpl, ways, sets, bpl); + + /* Determine data cache size, same as above */ + ways = ((config1 >> MIPS32_CFG1_DASHIFT) & 7); + + index = ((config1 >> MIPS32_CFG1_DSSHIFT) & 7); + sets = index == 7 ? 32 : 32 << (index + 1); + + index = ((config1 >> MIPS32_CFG1_DLSHIFT) & 7); + bpl = index == 0 ? 0 : 4 << (index - 1); + command_print(CMD, " Data Cache: %d (%d ways, %d lines, %d byte per line)", ways * sets * bpl, ways, sets, bpl); + + /* does the core hava FPU*/ + mips32_read_config_fpu(mips32, ejtag_info); + + /* does the core support a DSP */ + mips32_read_config_dsp(mips32, ejtag_info); + + /* VZ module */ + uint32_t vzase = (config3 & BIT(23)); + if (vzase) + command_print(CMD, "VZ implemented: yes"); + else + command_print(CMD, "VZ implemented: no"); + + /* multithreading */ + uint32_t mtase = (config3 & BIT(2)); + if (mtase) { + command_print(CMD, "MT implemented: yes"); + + /* Get VPE and Thread info */ + uint32_t tcbind; + uint32_t mvpconf0; + + /* Read tcbind register */ + retval = mips32_cp0_read(ejtag_info, &tcbind, 2, 2); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, " | Current VPE: %d", (tcbind & 0xf)); + command_print(CMD, " | Current TC: %d", ((tcbind >> 21) & 0xff)); + + /* Read mvpconf0 register */ + retval = mips32_cp0_read(ejtag_info, &mvpconf0, 0, 2); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, " | Total TC: %d", (mvpconf0 & 0xf) + 1); + command_print(CMD, " | Total VPE: %d", ((mvpconf0 >> 10) & 0xf) + 1); + } else { + command_print(CMD, "MT implemented: no"); + } + + /* MIPS SIMD Architecture (MSA) */ + uint32_t msa = (config3 & BIT(28)); + command_print(CMD, "MSA implemented: %s", msa ? "yes" : "no"); + + /* Move To/From High COP0 (MTHC0/MFHC0) instructions are implemented. + * Implicates current ISA release >= 5.*/ + uint32_t mvh = (config5 & BIT(5)); + command_print(CMD, "MVH implemented: %s", mvh ? "yes" : "no"); + + /* Common Device Memory Map implemented? */ + uint32_t cdmm = (config3 & BIT(3)); + command_print(CMD, "CDMM implemented: %s", cdmm ? "yes" : "no"); + + return ERROR_OK; +} + COMMAND_HANDLER(mips32_handle_scan_delay_command) { struct target *target = get_current_target(CMD_CTX); @@ -1203,7 +1503,14 @@ static const struct command_registration mips32_exec_command_handlers[] = { .usage = "regnum select [value]", .help = "display/modify cp0 register", }, - { + { + .name = "cpuinfo", + .handler = mips32_handle_cpuinfo_command, + .mode = COMMAND_EXEC, + .help = "display CPU information", + .usage = "", + }, + { .name = "scan_delay", .handler = mips32_handle_scan_delay_command, .mode = COMMAND_ANY, diff --git a/src/target/mips32.h b/src/target/mips32.h index fc896248b6..1bb75da995 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -263,6 +263,96 @@ enum mips32_isa_rel { MIPS32_RELEASE_UNKNOWN, }; +enum mips32_isa_supported { + MIPS16, + MIPS32, + MIPS64, + MICROMIPS_ONLY, + MIPS32_AT_RESET_AND_MICROMIPS, + MICROMIPS_AT_RESET_AND_MIPS32, +}; +#define MIPS32_CORE_MASK 0xFFFFFF00 +#define MIPS32_VARIANT_MASK 0x00FF + +/* This struct contains mips cpu types with their name respectively. + * The PrID register format is as following: + * - Company Optionsp[31:24] + * - Company ID[23:16] + * - Processor ID[15:8] + * - Revision[7:0] + * Here the revision field represents the maximum value of revision. + */ +static const struct cpu_entry { + uint32_t prid; + enum mips32_isa_supported isa; + const char *vendor; + const char *cpu_name; +} mips32_cpu_entry[] = { + /* MIPS Technologies cores */ + {0x000180FF, MIPS32, "MIPS", "4Kc"}, + {0x000181FF, MIPS64, "MIPS", "5Kc"}, + {0x000182FF, MIPS64, "MIPS", "20Kc"}, + {0x000183FF, MIPS32, "MIPS", "4KM"}, + + {0x000184FF, MIPS32, "MIPS", "4KEc"}, + {0x000190FF, MIPS32, "MIPS", "4KEc"}, + + {0x000185FF, MIPS32, "MIPS", "4KEm"}, + {0x000191FF, MIPS32, "MIPS", "4KEm"}, + + {0x000186FF, MIPS32, "MIPS", "4KSc"}, + {0x000187FF, MIPS32, "MIPS", "M4K"}, + {0x000188FF, MIPS64, "MIPS", "25Kf"}, + {0x000189FF, MIPS64, "MIPS", "5KEc"}, + {0x000192FF, MIPS32, "MIPS", "4KSD"}, + {0x000193FF, MIPS32, "MIPS", "24Kc"}, + {0x000195FF, MIPS32, "MIPS", "34Kc"}, + {0x000196FF, MIPS32, "MIPS", "24KEc"}, + {0x000197FF, MIPS32, "MIPS", "74Kc"}, + {0x000199FF, MIPS32, "MIPS", "1004Kc"}, + {0x00019AFF, MIPS32, "MIPS", "1074Kc"}, + {0x00019BFF, MIPS32, "MIPS", "M14K"}, + {0x00019CFF, MIPS32, "MIPS", "M14Kc"}, + {0x00019DFF, MIPS32, "MIPS", "microAptiv_UC(M14KE)"}, + {0x00019EFF, MIPS32, "MIPS", "microAptiv_UP(M14KEc)"}, + {0x0001A0FF, MIPS32, "MIPS", "interAptiv"}, + {0x0001A1FF, MIPS32, "MIPS", "interAptiv_CM"}, + {0x0001A2FF, MIPS32, "MIPS", "proAptiv"}, + {0x0001A3FF, MIPS32, "MIPS", "proAptiv_CM"}, + {0x0001A6FF, MIPS32, "MIPS", "M5100"}, + {0x0001A7FF, MIPS32, "MIPS", "M5150"}, + {0x0001A8FF, MIPS32, "MIPS", "P5600"}, + {0x0001A9FF, MIPS32, "MIPS", "I5500"}, + + /* Broadcom */ + {0x000200FF, MIPS32, "Broadcom", "Broadcom"}, + + /* AMD Alchemy Series*/ + /* NOTE: AMD/Alchemy series uses Company Option instead of + * Processor ID, to match the find function, Processor ID field + * is the copy of Company Option field */ + {0x000300FF, MIPS32, "AMD Alchemy", "AU1000"}, + {0x010301FF, MIPS32, "AMD Alchemy", "AU1500"}, + {0x020302FF, MIPS32, "AMD Alchemy", "AU1100"}, + {0x030303FF, MIPS32, "AMD Alchemy", "AU1550"}, + {0x04030401, MIPS32, "AMD Alchemy", "AU1200"}, + {0x040304FF, MIPS32, "AMD Alchemy", "AU1250"}, + {0x050305FF, MIPS32, "AMD Alchemy", "AU1210"}, + + /* Altera */ + {0x001000FF, MIPS32, "Altera", "Altera"}, + + /* Lexra */ + {0x000B00FF, MIPS32, "Lexra", "Lexra"}, + + /* Ingenic */ + {0x00e102FF, MIPS32, "Ingenic", "Ingenic XBurst rev1"}, + + {0xFFFFFFFF, MIPS32, "Unknown", "Unknown"} +}; + +#define MIPS32_NUM_CPU_ENTRIES (ARRAY_SIZE(mips32_cpu_entry)) + enum mips32_fp_imp { MIPS32_FP_IMP_NONE = 0, MIPS32_FP_IMP_32 = 1, @@ -306,7 +396,6 @@ struct mips32_common { int fdc; int semihosting; - uint32_t cp0_mask; /* FPU enabled (cp0.status.cu1) */ bool fpu_enabled; @@ -315,6 +404,8 @@ struct mips32_common { /* processor identification register */ uint32_t prid; + /* detected CPU type */ + const struct cpu_entry *cpu_info; /* CPU specific quirks */ uint32_t cpu_quirks; @@ -708,78 +799,6 @@ struct mips32_algorithm { #define MIPS32_MMU_FIXED 3 #define MIPS32_MMU_DUAL_VTLB_FTLB 4 -enum mips32_cpu_vendor { - MIPS32_CPU_VENDOR_MTI, - MIPS32_CPU_VENDOR_ALCHEMY, - MIPS32_CPU_VENDOR_BROADCOM, - MIPS32_CPU_VENDOR_ALTERA, - MIPS32_CPU_VENDOR_LEXRA, -}; - -enum mips32_isa_supported { - MIPS16, - MIPS32, - MIPS64, - MICROMIPS_ONLY, - MIPS32_AT_RESET_AND_MICROMIPS, - MICROMIPS_AT_RESET_AND_MIPS32, -}; - -struct mips32_cpu_features { - /* Type of CPU (4Kc, 24Kf, etc.) */ - uint32_t cpu_core; - - /* Internal representation of cpu type */ - uint32_t cpu_type; - - /* Processor vendor */ - enum mips32_cpu_vendor vendor; - - /* Supported ISA and boot config */ - enum mips32_isa_supported isa; - - /* PRID */ - uint32_t prid; - - /* Processor implemented the MultiThreading ASE */ - bool mtase; - - /* Processor implemented the DSP ASE */ - bool dspase; - - /* Processor implemented the SmartMIPS ASE */ - bool smase; - - /* Processor implemented the MIPS16[e] ASE */ - bool m16ase; - - /* Processor implemented the microMIPS ASE */ - bool micromipsase; - - /* Processor implemented the Virtualization ASE */ - uint32_t vzase; - - uint32_t vz_guest_id_width; - - /* ebase.cpuid number */ - uint32_t cpuid; - - uint32_t inst_cache_size; - uint32_t data_cache_size; - uint32_t mmu_type; - uint32_t tlb_entries; - uint32_t num_shadow_regs; - - /* Processor implemented the MSA module */ - bool msa; - - /* Processor implemented mfhc0 and mthc0 instructions */ - bool mvh; - - bool guest_ctl1_present; - bool cdmm; -}; - extern const struct command_registration mips32_command_handlers[]; int mips32_arch_state(struct target *target); diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h index 8190b32e43..2f31dbd664 100644 --- a/src/target/mips_cpu.h +++ b/src/target/mips_cpu.h @@ -12,7 +12,12 @@ /* Assigned Company values for bits 23:16 of the PRId register. */ #define PRID_COMP_MASK 0xff0000 -#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_MTI 0x010000 +#define PRID_COMP_BROADCOM 0x020000 +#define PRID_COMP_ALCHEMY 0x030000 +#define PRID_COMP_LEXRA 0x0b0000 +#define PRID_COMP_ALTERA 0x100000 #define PRID_COMP_INGENIC_E1 0xe10000 /* @@ -22,6 +27,12 @@ */ #define PRID_IMP_MASK 0xff00 +#define PRID_IMP_MAPTIV_UC 0x9D00 +#define PRID_IMP_MAPTIV_UP 0x9E00 +#define PRID_IMP_IAPTIV_CM 0xA000 +#define PRID_IMP_IAPTIV 0xA100 +#define PRID_IMP_M5150 0xA700 + #define PRID_IMP_XBURST_REV1 0x0200 /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */ #endif /* OPENOCD_TARGET_MIPS_CPU_H */ From b2172ed7d785ff1cd816d93cbed30afb45f1402b Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Fri, 17 Nov 2023 15:13:21 +0800 Subject: [PATCH 0689/1312] target/mips32: update coprocessor 0 command Update mips32 cp0 command, it accepts cp0 reg names now. Updated mips32 cp0 description. Change-Id: Ib23dd13519def77a657c9c5bb039276746207b9b Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7905 Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel Tested-by: jenkins --- doc/openocd.texi | 12 +- src/target/mips32.c | 311 ++++++++++++++++++++++++++++++++++++++------ src/target/mips32.h | 10 +- 3 files changed, 288 insertions(+), 45 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index cf41bc538a..a2af45114f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -10998,9 +10998,10 @@ The term ASE means Application-Specific Extension, ASEs provide features that improve the efficiency and performance of certain workloads, such as digital signal processing(DSP), Virtualization(VZ), Multi-Threading(MT), SIMD(MSA) and more. -The MIPS CPU Uses Coprocessors to configure its behaviour or to let software -know the capabilities of current CPU, the commonly used ones are Config0~3 Registers -and Status register. + +MIPS Cores use Coprocessors(CPx) to configure their behaviour or to let software +know the capabilities of current CPU, the main Coprocessor is CP0, containing 32 +registers with a maximum select number of 7. @subsection MIPS FPU & Vector Registers @@ -11028,8 +11029,9 @@ Display or set scan delay in nano seconds. A value below 2_000_000 will set the scan delay into legacy mode. @end deffn -@deffn {Config Command} {mips32 cp0} regnum select [value] -Displays or sets coprocessor 0 register by register number and select. +@deffn {Config Command} {mips32 cp0} [[reg_name|regnum select] [value]] +Displays or sets coprocessor 0 register by register number and select or their name. +This command shows all available cp0 register if no arguments are provided. For common MIPS Coprocessor 0 registers, you can find the definitions of them on MIPS Privileged Resource Architecture Documents(MIPS Document MD00090). diff --git a/src/target/mips32.c b/src/target/mips32.c index af5f2c50d8..9cebc48f61 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -834,6 +834,27 @@ int mips32_cpu_probe(struct target *target) break; } break; + + /* Determine which CP0 registers are available in the current processor core */ + case PRID_COMP_MTI: + switch (entry->prid & PRID_IMP_MASK) { + case PRID_IMP_MAPTIV_UC: + mips32->cp0_mask = MIPS_CP0_MAPTIV_UC; + break; + case PRID_IMP_MAPTIV_UP: + case PRID_IMP_M5150: + mips32->cp0_mask = MIPS_CP0_MAPTIV_UP; + break; + case PRID_IMP_IAPTIV: + case PRID_IMP_IAPTIV_CM: + mips32->cp0_mask = MIPS_CP0_IAPTIV; + break; + default: + /* CP0 mask should be the same as MK4 by default */ + mips32->cp0_mask = MIPS_CP0_MK4; + break; + } + default: break; } @@ -1212,12 +1233,239 @@ static int mips32_read_config_mmu(struct mips_ejtag *ejtag_info) } /** - * MIPS32 targets expose command interface - * to manipulate CP0 registers + * mips32_cp0_find_register_by_name - Find CP0 register by its name. + * @param[in] cp0_mask: Mask to filter out irrelevant registers. + * @param[in] reg_name: Name of the register to find. + * + * @brief This function iterates through mips32_cp0_regs to find a register + * matching reg_name, considering cp0_mask to filter out registers + * not relevant for the current core. + * + * @return Pointer to the found register, or NULL if not found. + */ +static const struct mips32_cp0 *mips32_cp0_find_register_by_name(uint32_t cp0_mask, const char *reg_name) +{ + if (reg_name) + for (unsigned int i = 0; i < MIPS32NUMCP0REGS; i++) { + if ((mips32_cp0_regs[i].core & cp0_mask) == 0) + continue; + + if (strcmp(mips32_cp0_regs[i].name, reg_name) == 0) + return &mips32_cp0_regs[i]; + } + return NULL; +} + +/** + * mips32_cp0_get_all_regs - Print all CP0 registers and their values. + * @param[in] cmd: Command invocation context. + * @param[in] ejtag_info: EJTAG interface information. + * @param[in] cp0_mask: Mask to identify relevant registers. + * + * @brief Iterates over all CP0 registers, reads their values, and prints them. + * Only considers registers relevant to the current core, as defined by cp0_mask. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_cp0_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info, uint32_t cp0_mask) +{ + uint32_t value; + + for (unsigned int i = 0; i < MIPS32NUMCP0REGS; i++) { + /* Register name not valid for this core */ + if ((mips32_cp0_regs[i].core & cp0_mask) == 0) + continue; + + int retval = mips32_cp0_read(ejtag_info, &value, mips32_cp0_regs[i].reg, mips32_cp0_regs[i].sel); + if (retval != ERROR_OK) { + command_print(CMD, "Error: couldn't access reg %s", mips32_cp0_regs[i].name); + return retval; + } + + command_print(CMD, "%*s: 0x%8.8" PRIx32, 14, mips32_cp0_regs[i].name, value); + } + return ERROR_OK; +} + +/** + * mips32_cp0_get_reg_by_name - Read and print a CP0 register's value by name. + * @param[in] cmd: Command invocation context. + * @param[in] ejtag_info: EJTAG interface information. + * @param[in] cp0_mask: Mask to identify relevant registers. + * + * @brief Finds a CP0 register by name, reads its value, and prints it. + * Handles error scenarios like register not found or read failure. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_cp0_get_reg_by_name(struct command_invocation *cmd, struct mips_ejtag *ejtag_info, uint32_t cp0_mask) +{ + const struct mips32_cp0 *cp0_regs = mips32_cp0_find_register_by_name(cp0_mask, CMD_ARGV[0]); + if (!cp0_regs) { + command_print(CMD, "Error: Register '%s' not found", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + uint32_t value; + int retval = mips32_cp0_read(ejtag_info, &value, cp0_regs->reg, cp0_regs->sel); + if (retval != ERROR_OK) { + command_print(CMD, "Error: Encounter an Error while reading cp0 reg %d sel %d", + cp0_regs->reg, cp0_regs->sel); + return retval; + } + + command_print(CMD, "0x%8.8" PRIx32, value); + return ERROR_OK; +} + +/** + * mips32_cp0_get_reg_by_number - Read and print a CP0 register's value by number. + * @param[in] cmd: Command invocation context. + * @param[in] ejtag_info: EJTAG interface information. + * + * @brief Reads a specific CP0 register (identified by number and selection) and prints its value. + * The register number and selection are parsed from the command arguments. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_cp0_get_reg_by_number(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +{ + uint32_t cp0_reg, cp0_sel, value; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel); + + int retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel); + if (retval != ERROR_OK) { + command_print(CMD, + "Error: couldn't access reg %" PRIu32, + cp0_reg); + return retval; + } + + command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32, + cp0_reg, cp0_sel, value); + return ERROR_OK; +} + +/** + * mips32_cp0_set_reg_by_name - Write to a CP0 register identified by name. + * @param[in] cmd: Command invocation context. + * @param[in] mips32: Common MIPS32 data structure. + * @param[in] ejtag_info: EJTAG interface information. + * + * @brief Writes a value to a CP0 register specified by name. Updates internal + * cache if specific registers (STATUS, CAUSE, DEPC, GUESTCTL1) are modified. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_cp0_set_reg_by_name(struct command_invocation *cmd, + struct mips32_common *mips32, struct mips_ejtag *ejtag_info) +{ + const struct mips32_cp0 *cp0_regs = mips32_cp0_find_register_by_name(mips32->cp0_mask, CMD_ARGV[0]); + if (!cp0_regs) { + command_print(CMD, "Error: Register '%s' not found", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + + uint32_t value; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + + if (cp0_regs->reg == MIPS32_C0_STATUS && cp0_regs->sel == 0) { + /* Update cached Status register if user is writing to Status */ + mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_STATUS_INDEX].dirty = 1; + } else if (cp0_regs->reg == MIPS32_C0_CAUSE && cp0_regs->sel == 0) { + /* Update register cache with new value if its Cause */ + mips32->core_regs.cp0[MIPS32_REG_C0_CAUSE_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_CAUSE_INDEX].dirty = 1; + } else if (cp0_regs->reg == MIPS32_C0_DEPC && cp0_regs->sel == 0) { + /* Update cached PC if its DEPC */ + mips32->core_regs.cp0[MIPS32_REG_C0_PC_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = 1; + } else if (cp0_regs->reg == MIPS32_C0_GUESTCTL1 && cp0_regs->sel == 4) { + /* Update cached guestCtl1 */ + mips32->core_regs.cp0[MIPS32_REG_C0_GUESTCTL1_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_GUESTCTL1_INDEX].dirty = 1; + } + + int retval = mips32_cp0_write(ejtag_info, value, + cp0_regs->reg, + cp0_regs->sel); + if (retval != ERROR_OK) { + command_print(CMD, "Error: Encounter an Error while writing to cp0 reg %d, sel %d", + cp0_regs->reg, cp0_regs->sel); + return retval; + } + + command_print(CMD, "cp0 reg %s (%u, select %u: %8.8" PRIx32 ")", + CMD_ARGV[0], cp0_regs->reg, cp0_regs->sel, value); + return ERROR_OK; +} + +/** + * mips32_cp0_set_reg_by_number - Write to a CP0 register identified by number. + * @param[in] cmd: Command invocation context. + * @param[in] mips32: Common MIPS32 data structure. + * @param[in] ejtag_info: EJTAG interface information. + * + * @brief Writes a value to a CP0 register specified by number and selection. + * Handles special cases like updating the internal cache for certain registers. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_cp0_set_reg_by_number(struct command_invocation *cmd, + struct mips32_common *mips32, struct mips_ejtag *ejtag_info) +{ + uint32_t cp0_reg, cp0_sel, value; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); + + if (cp0_reg == MIPS32_C0_STATUS && cp0_sel == 0) { + /* Update cached status register if user is writing to Status register */ + mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_STATUS_INDEX].dirty = 1; + } else if (cp0_reg == MIPS32_C0_CAUSE && cp0_sel == 0) { + /* Update register cache with new value if its Cause register */ + mips32->core_regs.cp0[MIPS32_REG_C0_CAUSE_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_CAUSE_INDEX].dirty = 1; + } else if (cp0_reg == MIPS32_C0_DEPC && cp0_sel == 0) { + /* Update cached PC if its DEPC */ + mips32->core_regs.cp0[MIPS32_REG_C0_PC_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = 1; + } else if (cp0_reg == MIPS32_C0_GUESTCTL1 && cp0_sel == 4) { + /* Update cached guestCtl1, too */ + mips32->core_regs.cp0[MIPS32_REG_C0_GUESTCTL1_INDEX] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_C0_GUESTCTL1_INDEX].dirty = 1; + } + + int retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel); + if (retval != ERROR_OK) { + command_print(CMD, + "Error: couldn't access cp0 reg %" PRIu32 ", select %" PRIu32, + cp0_reg, cp0_sel); + return retval; + } + + command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32, + cp0_reg, cp0_sel, value); + return ERROR_OK; +} + +/** + * mips32_handle_cp0_command - Handle commands related to CP0 registers. + * @cmd: Command invocation context. + * + * Orchestrates different operations on CP0 registers based on the command arguments. + * Supports operations like reading all registers, reading/writing a specific register + * by name or number. + * + * Return: ERROR_OK on success; error code on failure. */ COMMAND_HANDLER(mips32_handle_cp0_command) { - int retval; + int retval, tmp; struct target *target = get_current_target(CMD_CTX); struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; @@ -1232,43 +1480,30 @@ COMMAND_HANDLER(mips32_handle_cp0_command) return ERROR_TARGET_NOT_HALTED; } - /* two or more argument, access a single register/select (write if third argument is given) */ - if (CMD_ARGC < 2) - return ERROR_COMMAND_SYNTAX_ERROR; - else { - uint32_t cp0_reg, cp0_sel; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel); - - if (CMD_ARGC == 2) { - uint32_t value; - - retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel); - if (retval != ERROR_OK) { - command_print(CMD, - "couldn't access reg %" PRIu32, - cp0_reg); - return ERROR_OK; - } - command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32, - cp0_reg, cp0_sel, value); + switch (CMD_ARGC) { + case 0: /* No arg => print out all cp0 regs */ + retval = mips32_cp0_get_all_regs(CMD, ejtag_info, mips32->cp0_mask); + break; + case 1: /* 1 arg => get cp0 #reg/#sel value by name */ + retval = mips32_cp0_get_reg_by_name(CMD, ejtag_info, mips32->cp0_mask); + break; + case 2: /* 2 args => get cp0 reg/sel value or set value by name */ + tmp = *CMD_ARGV[0]; + if (isdigit(tmp)) /* starts from number then args are #reg and #sel */ + retval = mips32_cp0_get_reg_by_number(CMD, ejtag_info); + else /* or set value by register name */ + retval = mips32_cp0_set_reg_by_name(CMD, mips32, ejtag_info); - } else if (CMD_ARGC == 3) { - uint32_t value; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); - retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel); - if (retval != ERROR_OK) { - command_print(CMD, - "couldn't access cp0 reg %" PRIu32 ", select %" PRIu32, - cp0_reg, cp0_sel); - return ERROR_OK; - } - command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32, - cp0_reg, cp0_sel, value); - } + break; + case 3: /* 3 args => set cp0 reg/sel value*/ + retval = mips32_cp0_set_reg_by_number(CMD, mips32, ejtag_info); + break; + default: /* Other argc => err */ + retval = ERROR_COMMAND_SYNTAX_ERROR; + break; } - return ERROR_OK; + return retval; } /** @@ -1500,7 +1735,7 @@ static const struct command_registration mips32_exec_command_handlers[] = { .name = "cp0", .handler = mips32_handle_cp0_command, .mode = COMMAND_EXEC, - .usage = "regnum select [value]", + .usage = "[[reg_name|regnum select] [value]]", .help = "display/modify cp0 register", }, { diff --git a/src/target/mips32.h b/src/target/mips32.h index 1bb75da995..46c2ad933c 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -84,7 +84,7 @@ /* CP1 FIR register fields */ #define MIPS32_CP1_FIR_F64_SHIFT 22 -static const struct { +static const struct mips32_cp0 { unsigned int reg; unsigned int sel; const char *name; @@ -202,7 +202,7 @@ static const struct { {31, 3, "kscratch2", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP}, }; -#define MIPS32NUMCP0REGS ((int)ARRAY_SIZE(mips32_cp0_regs)) +#define MIPS32NUMCP0REGS (ARRAY_SIZE(mips32_cp0_regs)) /* Insert extra NOPs after the DRET instruction on exit from debug. */ #define EJTAG_QUIRK_PAD_DRET BIT(0) @@ -397,6 +397,12 @@ struct mips32_common { int fdc; int semihosting; + /* The cp0 registers implemented on different processor cores could be different, too. + * Here you can see most of the registers are implemented on interAptiv, which is + * a 2c4t SMP processor, it has more features than M-class processors, like vpe + * and other config registers for multhreading. */ + uint32_t cp0_mask; + /* FPU enabled (cp0.status.cu1) */ bool fpu_enabled; /* FPU mode (cp0.status.fr) */ From 019bf5f83c79353392471529f7cb961c5c603bfd Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Fri, 17 Nov 2023 15:13:55 +0800 Subject: [PATCH 0690/1312] target/mips32: add mips ejtag command Add mips32 ejtag_reg command for inspecting ejtag status. Add description for mips32 ejtag_reg command. Change-Id: Icd173d3397d568b0c004a8cc3f45518d7b48ce43 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7906 Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 9 +++++- src/target/mips32.c | 70 +++++++++++++++++++++++++++++++++++++++++ src/target/mips_ejtag.c | 4 +-- src/target/mips_ejtag.h | 19 +++++++++++ 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index a2af45114f..e482c43b4e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11037,10 +11037,17 @@ For common MIPS Coprocessor 0 registers, you can find the definitions of them on MIPS Privileged Resource Architecture Documents(MIPS Document MD00090). For core specific cp0 registers, you can find the definitions of them on Core -Specific Software User's Manual, for example, MIPS M5150 Software User Manual +Specific Software User's Manual(SUM), for example, MIPS M5150 Software User Manual (MD00980). @end deffn +@deffn {Command} {mips32 ejtag_reg} +Reads EJTAG Registers for inspection. + +EJTAG Register Specification could be found in MIPS Document MD00047F, for +core specific EJTAG Register definition, please check Core Specific SUM manual. +@end deffn + @section RISC-V Architecture @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG diff --git a/src/target/mips32.c b/src/target/mips32.c index 9cebc48f61..b25fae88e4 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -1707,6 +1707,69 @@ COMMAND_HANDLER(mips32_handle_cpuinfo_command) return ERROR_OK; } +/** + * mips32_handle_ejtag_reg_command - Handler commands related to EJTAG + * @param[in] cmd: Command invocation context + * + * @brief Prints all EJTAG Registers including DCR features. + * + * @return ERROR_OK on success; error code on failure. + */ +COMMAND_HANDLER(mips32_handle_ejtag_reg_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + uint32_t ejtag_ctrl; + uint32_t dcr; + int retval; + + retval = mips_ejtag_get_idcode(ejtag_info); + if (retval != ERROR_OK) + command_print(CMD, "Error: Encounter an Error while getting idcode"); + else + command_print(CMD, " idcode: 0x%8.8" PRIx32, ejtag_info->idcode); + + retval = mips_ejtag_get_impcode(ejtag_info); + if (retval != ERROR_OK) + command_print(CMD, "Error: Encounter an Error while getting impcode"); + else + command_print(CMD, " impcode: 0x%8.8" PRIx32, ejtag_info->impcode); + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); + ejtag_ctrl = ejtag_info->ejtag_ctrl; + retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); + if (retval != ERROR_OK) + command_print(CMD, "Error: Encounter an Error while executing drscan reading EJTAG Control register"); + else + command_print(CMD, "ejtag control: 0x%8.8" PRIx32, ejtag_ctrl); + + ejtag_main_print_imp(ejtag_info); + + /* Display current DCR */ + retval = target_read_u32(target, EJTAG_DCR, &dcr); + if (retval != ERROR_OK) + command_print(CMD, "Error: Encounter an Error while reading Debug Control Register"); + else + command_print(CMD, " DCR: 0x%8.8" PRIx32, dcr); + + for (unsigned int i = 0; i < EJTAG_DCR_ENTRIES; i++) { + if (dcr & BIT(dcr_features[i].bit)) + command_print(CMD, "%s supported", dcr_features[i].name); + } + + return ERROR_OK; +} + +/** + * mips32_handle_scan_delay_command - Handler command for changing scan delay + * @param[in] cmd: Command invocation context + * + * @brief Changes current scan mode between legacy and fast queued mode. + * + * @return ERROR_OK on success; error code on failure. + */ COMMAND_HANDLER(mips32_handle_scan_delay_command) { struct target *target = get_current_target(CMD_CTX); @@ -1752,6 +1815,13 @@ static const struct command_registration mips32_exec_command_handlers[] = { .help = "display/set scan delay in nano seconds", .usage = "[value]", }, + { + .name = "ejtag_reg", + .handler = mips32_handle_ejtag_reg_command, + .mode = COMMAND_ANY, + .help = "read ejtag registers", + .usage = "", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 5c92bf9ee3..389461cae6 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -47,7 +47,7 @@ int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info) return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->idcode); } -static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info) +int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info) { mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE); @@ -332,7 +332,7 @@ static void ejtag_v26_print_imp(struct mips_ejtag *ejtag_info) EJTAG_IMP_HAS(EJTAG_V26_IMP_DINT) ? " DINT" : ""); } -static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) +void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) { LOG_DEBUG("EJTAG main: features:%s%s%s%s%s", EJTAG_IMP_HAS(EJTAG_IMP_ASID8) ? " ASID_8" : "", diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 852444a519..172ac5955b 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -186,6 +186,22 @@ #define EJTAG64_V25_IBA0 0xFFFFFFFFFF301100ull #define EJTAG64_V25_IBS 0xFFFFFFFFFF301000ull +static const struct dcr_feature { + int bit; + const char *name; +} dcr_features[] = { + {22, "DAS"}, + {18, "FDC"}, + {17, "DataBrk"}, + {16, "InstBrk"}, + {15, "Inverted Data value"}, + {14, "Data value stored"}, + {10, "Complex Breakpoints"}, + { 9, "PC Sampling"}, +}; + +#define EJTAG_DCR_ENTRIES (ARRAY_SIZE(dcr_features)) + struct mips_ejtag { struct jtag_tap *tap; uint32_t impcode; @@ -244,6 +260,9 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info); int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step); int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, bool enable_step); +void ejtag_main_print_imp(struct mips_ejtag *ejtag_info); +int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info); + static inline void mips_le_to_h_u32(jtag_callback_data_t arg) { uint8_t *in = (uint8_t *)arg; From b1231287372a03e1c255052dd17016ca03c07c35 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Tue, 29 Aug 2023 13:27:49 +0800 Subject: [PATCH 0691/1312] target/mips32: optimize pracc access Update mips32 instructions, add barrier and sync related insts. Add SYNC and barrier instruction blocks for memory access safety. These instructions are not supported on Lexra and/or MIPSr1 CPUs, detections were added and they will be executed conditionally. Rework mips32_pracc_read/write_regs function. Checkpatch-ignore: MACRO_ARG_REUSE Change-Id: Ib14112f37ff1f060b1633df73d671a6b09bb2178 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7865 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- src/target/mips32.c | 38 ++++++++++++ src/target/mips32.h | 87 ++++++++++++++++++---------- src/target/mips32_pracc.c | 119 +++++++++++++++++++++++++++++++++++--- src/target/mips32_pracc.h | 2 + src/target/mips_ejtag.h | 1 + 5 files changed, 208 insertions(+), 39 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index b25fae88e4..8a3ddbf0b7 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -796,6 +796,44 @@ static const struct cpu_entry *mips32_find_cpu_by_prid(uint32_t prid) return &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1]; } +static bool mips32_cpu_is_lexra(struct mips_ejtag *ejtag_info) +{ + return (ejtag_info->prid & PRID_COMP_MASK) == PRID_COMP_LEXRA; +} + +static int mips32_cpu_get_release(struct mips_ejtag *ejtag_info) +{ + return (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; +} + +/** + * mips32_cpu_support_sync - Checks CPU supports ordering + * @param[in] ejtag_info: MIPS EJTAG information structure. + * + * @brief MIPS ISA implemented on Lexra CPUs is MIPS-I, similar to R3000, + * which does not have the SYNC instruction alone with unaligned + * load/store instructions. + * + * @returns true if current CPU supports sync instruction(CPU is not Lexra) +*/ +bool mips32_cpu_support_sync(struct mips_ejtag *ejtag_info) +{ + return !mips32_cpu_is_lexra(ejtag_info); +} + +/** + * mips32_cpu_support_hazard_barrier - Checks CPU supports hazard barrier + * @param[in] ejtag_info: MIPS EJTAG information structure. + * + * @brief hazard barrier instructions EHB and *.HB was introduced to MIPS from release 2. + * + * @returns true if current CPU supports hazard barrier(release > 1) +*/ +bool mips32_cpu_support_hazard_barrier(struct mips_ejtag *ejtag_info) +{ + return mips32_cpu_get_release(ejtag_info) > MIPS32_RELEASE_1; +} + /** * mips32_cpu_probe - Detects processor type and applies necessary quirks. * @param[in] target: The target CPU to probe. diff --git a/src/target/mips32.h b/src/target/mips32.h index 46c2ad933c..208c9da174 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -454,6 +454,7 @@ struct mips32_algorithm { #define MIPS32_OP_BEQ 0x04u #define MIPS32_OP_BGTZ 0x07u #define MIPS32_OP_BNE 0x05u +#define MIPS32_OP_ADD 0x20u #define MIPS32_OP_ADDI 0x08u #define MIPS32_OP_AND 0x24u #define MIPS32_OP_CACHE 0x2Fu @@ -481,6 +482,7 @@ struct mips32_algorithm { #define MIPS32_OP_SRA 0x03u #define MIPS32_OP_SYNCI 0x1Fu #define MIPS32_OP_SLL 0x00u +#define MIPS32_OP_SLLV 0x04u #define MIPS32_OP_SLTI 0x0Au #define MIPS32_OP_MOVN 0x0Bu @@ -490,8 +492,11 @@ struct mips32_algorithm { #define MIPS32_OP_SPECIAL2 0x07u #define MIPS32_OP_SPECIAL3 0x1Fu -#define MIPS32_COP0_MF 0x00u -#define MIPS32_COP0_MT 0x04u +#define MIPS32_COP_MF 0x00u +#define MIPS32_COP_CF 0x02u +#define MIPS32_COP_MFH 0x03u +#define MIPS32_COP_MT 0x04u +#define MIPS32_COP_MTH 0x07u #define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \ (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct)) @@ -500,6 +505,7 @@ struct mips32_algorithm { #define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr)) #define MIPS32_ISA_NOP 0 +#define MIPS32_ISA_ADD(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADD) #define MIPS32_ISA_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) #define MIPS32_ISA_ADDIU(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDIU, src, tar, val) #define MIPS32_ISA_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDU) @@ -513,6 +519,7 @@ struct mips32_algorithm { #define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) #define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) #define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) +#define MIPS32_ISA_JRHB(reg) MIPS32_R_INST(0, reg, 0, 0, 0x10, MIPS32_OP_JR) #define MIPS32_ISA_LB(reg, off, base) MIPS32_I_INST(MIPS32_OP_LB, base, reg, off) #define MIPS32_ISA_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) @@ -520,14 +527,16 @@ struct mips32_algorithm { #define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) #define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) -#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) -#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) +#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MF, gpr, cpr, 0, sel) +#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MT, gpr, cpr, 0, sel) #define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) #define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) #define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) #define MIPS32_ISA_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) +#define MIPS32_ISA_MUL(dst, src, t) MIPS32_R_INST(28, src, t, dst, 0, MIPS32_OP_MUL) #define MIPS32_ISA_MOVN(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_MOVN) +#define MIPS32_ISA_OR(dst, src, val) MIPS32_R_INST(0, src, val, dst, 0, 37) #define MIPS32_ISA_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) #define MIPS32_ISA_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) #define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) @@ -535,6 +544,7 @@ struct mips32_algorithm { #define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) #define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) +#define MIPS32_ISA_SLLV(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLLV) #define MIPS32_ISA_SLTI(tar, src, val) MIPS32_I_INST(MIPS32_OP_SLTI, src, tar, val) #define MIPS32_ISA_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) #define MIPS32_ISA_SRA(reg, src, off) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, reg, off, MIPS32_OP_SRA) @@ -563,10 +573,12 @@ struct mips32_algorithm { #define MIPS16_ISA_SDBBP 0xE801u /*MICRO MIPS INSTRUCTIONS, see doc MD00582 */ -#define POOL32A 0X00u -#define POOL32AXF 0x3Cu -#define POOL32B 0x08u -#define POOL32I 0x10u +#define MMIPS32_POOL32A 0x00u +#define MMIPS32_POOL32F 0x15u +#define MMIPS32_POOL32FXF 0x3Bu +#define MMIPS32_POOL32AXF 0x3Cu +#define MMIPS32_POOL32B 0x08u +#define MMIPS32_POOL32I 0x10u #define MMIPS32_OP_ADDI 0x04u #define MMIPS32_OP_ADDIU 0x0Cu #define MMIPS32_OP_ADDU 0x150u @@ -578,6 +590,7 @@ struct mips32_algorithm { #define MMIPS32_OP_CACHE 0x06u #define MMIPS32_OP_J 0x35u #define MMIPS32_OP_JALR 0x03Cu +#define MMIPS32_OP_JALRHB 0x07Cu #define MMIPS32_OP_LB 0x07u #define MMIPS32_OP_LBU 0x05u #define MMIPS32_OP_LHU 0x0Du @@ -605,55 +618,59 @@ struct mips32_algorithm { #define MMIPS32_ADDI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ADDI, tar, src, val) #define MMIPS32_ADDIU(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ADDIU, tar, src, val) -#define MMIPS32_ADDU(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_ADDU) -#define MMIPS32_AND(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_AND) +#define MMIPS32_ADDU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_ADDU) +#define MMIPS32_AND(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_AND) #define MMIPS32_ANDI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ANDI, tar, src, val) #define MMIPS32_B(off) MMIPS32_BEQ(0, 0, off) #define MMIPS32_BEQ(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BEQ, tar, src, off) -#define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(POOL32I, MMIPS32_OP_BGTZ, reg, off) +#define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_BGTZ, reg, off) #define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) -#define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) +#define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(MMIPS32_POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) #define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) -#define MMIPS32_JR(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_JALR, POOL32AXF) +#define MMIPS32_JR(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALR, MMIPS32_POOL32AXF) +#define MMIPS32_JRHB(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALRHB, MMIPS32_POOL32AXF) #define MMIPS32_LB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LB, reg, base, off) #define MMIPS32_LBU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LBU, reg, base, off) #define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off) -#define MMIPS32_LUI(reg, val) MIPS32_I_INST(POOL32I, MMIPS32_OP_LUI, reg, val) +#define MMIPS32_LUI(reg, val) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_LUI, reg, val) #define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off) -#define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(POOL32A, gpr, cpr, sel, MMIPS32_OP_MFC0, POOL32AXF) -#define MMIPS32_MFLO(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, POOL32AXF) -#define MMIPS32_MFHI(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, POOL32AXF) -#define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(POOL32A, gpr, cpr, sel, MMIPS32_OP_MTC0, POOL32AXF) -#define MMIPS32_MTLO(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, POOL32AXF) -#define MMIPS32_MTHI(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, POOL32AXF) +#define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ + MMIPS32_OP_MFC0, MMIPS32_POOL32AXF) +#define MMIPS32_MFLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, MMIPS32_POOL32AXF) +#define MMIPS32_MFHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, MMIPS32_POOL32AXF) +#define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ + MMIPS32_OP_MTC0, MMIPS32_POOL32AXF) +#define MMIPS32_MTLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, MMIPS32_POOL32AXF) +#define MMIPS32_MTHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, MMIPS32_POOL32AXF) -#define MMIPS32_MOVN(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_MOVN) +#define MMIPS32_MOVN(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_MOVN) #define MMIPS32_NOP 0 #define MMIPS32_ORI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ORI, tar, src, val) -#define MMIPS32_RDHWR(tar, dst) MIPS32_R_INST(POOL32A, dst, tar, 0, MMIPS32_OP_RDHWR, POOL32AXF) +#define MMIPS32_RDHWR(tar, dst) MIPS32_R_INST(MMIPS32_POOL32A, dst, tar, 0, MMIPS32_OP_RDHWR, MMIPS32_POOL32AXF) #define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off) #define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off) #define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off) -#define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) -#define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) -#define MMIPS32_SYNCI(off, base) MIPS32_I_INST(POOL32I, MMIPS32_OP_SYNCI, base, off) -#define MMIPS32_SLL(dst, src, sa) MIPS32_R_INST(POOL32A, dst, src, sa, 0, MMIPS32_OP_SLL) +#define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(MMIPS32_POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) +#define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) +#define MMIPS32_SYNCI(off, base) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_SYNCI, base, off) +#define MMIPS32_SLL(dst, src, sa) MIPS32_R_INST(MMIPS32_POOL32A, dst, src, sa, 0, MMIPS32_OP_SLL) +#define MMIPS32_SLLV(dst, src, sa) MIPS32_R_INST(MMIPS32_POOL32A, dst, src, sa, 0, MMIPS32_OP_SLLV) #define MMIPS32_SLTI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_SLTI, tar, src, val) -#define MMIPS32_SYNC 0x00001A7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1ADu, POOL32AXF) */ +#define MMIPS32_SYNC 0x00001A7Cu /* MIPS32_R_INST(MMIPS32_POOL32A, 0, 0, 0, 0x1ADu, MMIPS32_POOL32AXF) */ -#define MMIPS32_XOR(reg, val1, val2) MIPS32_R_INST(POOL32A, val1, val2, reg, 0, MMIPS32_OP_XOR) +#define MMIPS32_XOR(reg, val1, val2) MIPS32_R_INST(MMIPS32_POOL32A, val1, val2, reg, 0, MMIPS32_OP_XOR) #define MMIPS32_XORI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_XORI, tar, src, val) #define MMIPS32_SYNCI_STEP 0x1u /* reg num od address step size to be used with synci instruction */ /* ejtag specific instructions */ -#define MMIPS32_DRET 0x0000E37Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x38D, POOL32AXF) */ -#define MMIPS32_SDBBP 0x0000DB7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1BD, POOL32AXF) */ +#define MMIPS32_DRET 0x0000E37Cu /* MIPS32_R_INST(MMIPS32_POOL32A, 0, 0, 0, 0x38D, MMIPS32_POOL32AXF) */ +#define MMIPS32_SDBBP 0x0000DB7Cu /* MIPS32_R_INST(MMIPS32_POOL32A, 0, 0, 0, 0x1BD, MMIPS32_POOL32AXF) */ #define MMIPS16_SDBBP 0x46C0u /* POOL16C instr */ /* instruction code with isa selection */ @@ -672,6 +689,7 @@ struct mips32_algorithm { #define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) #define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) +#define MIPS32_JRHB(isa, reg) (isa ? MMIPS32_JRHB(reg) : MIPS32_ISA_JRHB(reg)) #define MIPS32_LB(isa, reg, off, base) (isa ? MMIPS32_LB(reg, off, base) : MIPS32_ISA_LB(reg, off, base)) #define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) #define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) @@ -685,6 +703,7 @@ struct mips32_algorithm { #define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) #define MIPS32_MTHI(isa, reg) (isa ? MMIPS32_MTHI(reg) : MIPS32_ISA_MTHI(reg)) +#define MIPS32_MUL(isa, dst, src, t) (MIPS32_ISA_MUL(dst, src, t)) #define MIPS32_MOVN(isa, dst, src, tar) (isa ? MMIPS32_MOVN(dst, src, tar) : MIPS32_ISA_MOVN(dst, src, tar)) #define MIPS32_ORI(isa, tar, src, val) (isa ? MMIPS32_ORI(tar, src, val) : MIPS32_ISA_ORI(tar, src, val)) #define MIPS32_RDHWR(isa, tar, dst) (isa ? MMIPS32_RDHWR(tar, dst) : MIPS32_ISA_RDHWR(tar, dst)) @@ -693,6 +712,8 @@ struct mips32_algorithm { #define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) #define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) +#define MIPS32_EHB(isa) (isa ? MMIPS32_SLL(0, 0, 3) : MIPS32_ISA_SLL(0, 0, 3)) +#define MIPS32_SLLV(isa, dst, src, sa) (MIPS32_ISA_SLLV(dst, src, sa)) #define MIPS32_SLTI(isa, tar, src, val) (isa ? MMIPS32_SLTI(tar, src, val) : MIPS32_ISA_SLTI(tar, src, val)) #define MIPS32_SLTU(isa, dst, src, tar) (isa ? MMIPS32_SLTU(dst, src, tar) : MIPS32_ISA_SLTU(dst, src, tar)) #define MIPS32_SRL(isa, reg, src, off) (isa ? MMIPS32_SRL(reg, src, off) : MIPS32_ISA_SRL(reg, src, off)) @@ -710,6 +731,9 @@ struct mips32_algorithm { #define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP) +/* ejtag specific instructions */ +#define MICRO_MIPS32_SDBBP 0x000046C0 +#define MICRO_MIPS_SDBBP 0x46C0 /* * MIPS32 Config1 Register (CP0 Register 16, Select 1) */ @@ -843,4 +867,7 @@ int mips32_checksum_memory(struct target *target, target_addr_t address, int mips32_blank_check_memory(struct target *target, struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value); +bool mips32_cpu_support_sync(struct mips_ejtag *ejtag_info); +bool mips32_cpu_support_hazard_barrier(struct mips_ejtag *ejtag_info); + #endif /* OPENOCD_TARGET_MIPS32_H */ diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index db50ef9285..22edf6a410 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -61,6 +61,7 @@ #include #include +#include "mips_cpu.h" #include "mips32.h" #include "mips32_pracc.h" @@ -452,6 +453,8 @@ static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, u pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper addr */ pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ + if (mips32_cpu_support_sync(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa)); pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ @@ -508,6 +511,8 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size else pracc_add(&ctx, 0, MIPS32_LBU(ctx.isa, 8, LOWER16(addr), 9)); + if (mips32_cpu_support_sync(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa)); pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, /* store $8 at param out */ MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + i * 4, 15)); addr += size; @@ -550,6 +555,8 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r pracc_queue_init(&ctx); pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + if (mips32_cpu_support_hazard_barrier(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ @@ -571,6 +578,8 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */ pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ + if (mips32_cpu_support_hazard_barrier(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ @@ -786,6 +795,7 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff))) return retval; /*Nothing to do*/ + /* Reads Config0 */ mips32_cp0_read(ejtag_info, &conf, 16, 0); switch (KSEGX(addr)) { @@ -813,11 +823,28 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz uint32_t start_addr = addr; uint32_t end_addr = addr + count * size; uint32_t rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; - if (rel > 1) { - LOG_DEBUG("Unknown release in cache code"); + /* FIXME: In MIPS Release 6, the encoding of CACHE instr has changed */ + if (rel > MIPS32_RELEASE_2) { + LOG_DEBUG("Unsupported MIPS Release ( > 5)"); return ERROR_FAIL; } retval = mips32_pracc_synchronize_cache(ejtag_info, start_addr, end_addr, cached, rel); + } else { + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; + + pracc_queue_init(&ctx); + if (mips32_cpu_support_sync(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa)); + if (mips32_cpu_support_hazard_barrier(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_NOP); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); + if (ctx.retval != ERROR_OK) { + LOG_ERROR("Unable to barrier"); + retval = ctx.retval; + } + pracc_queue_free(&ctx); } return retval; @@ -866,6 +893,8 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) pracc_add(&ctx, 0, cp0_write_code[i]); } + if (mips32_cpu_support_hazard_barrier(ejtag_info)) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, gprs[i], 1); @@ -1019,6 +1048,70 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) return ctx.retval; } +/** + * mips32_pracc_fastdata_xfer_synchronize_cache - Synchronize cache for fast data transfer + * @param[in] ejtag_info: EJTAG information structure + * @param[in] addr: Starting address for cache synchronization + * @param[in] size: Size of each data element + * @param[in] count: Number of data elements + * + * @brief Synchronizes the cache for fast data transfer based on + * the specified address and cache configuration. + * If the region is cacheable (write-back cache or write-through cache), + * it synchronizes the cache for the specified range. + * The synchronization is performed using the MIPS32 cache synchronization function. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_pracc_fastdata_xfer_synchronize_cache(struct mips_ejtag *ejtag_info, + uint32_t addr, int size, int count) +{ + int retval = ERROR_OK; + + if ((KSEGX(addr) == KSEG1) || (addr >= 0xff200000 && addr <= 0xff3fffff)) // DESEG? + return retval; /*Nothing to do*/ + + int cached = 0; + uint32_t conf = 0; + + mips32_cp0_read(ejtag_info, &conf, 16, 0); + + switch (KSEGX(addr)) { + case KUSEG: + cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT; + break; + case KSEG0: + cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT; + break; + case KSEG2: + case KSEG3: + cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT; + break; + default: + /* what ? */ + break; + } + + /** + * Check cacheability bits coherency algorithm + * is the region cacheable or uncached. + * If cacheable we have to synchronize the cache + */ + if (cached == 3 || cached == 0) { /* Write back cache or write through cache */ + uint32_t start_addr = addr; + uint32_t end_addr = addr + count * size; + uint32_t rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; + /* FIXME: In MIPS Release 6, the encoding of CACHE instr has changed */ + if (rel > MIPS32_RELEASE_2) { + LOG_DEBUG("Unsupported MIPS Release ( > 5)"); + return ERROR_FAIL; + } + retval = mips32_pracc_synchronize_cache(ejtag_info, start_addr, end_addr, cached, rel); + } + + return retval; +} + /* fastdata upload/download requires an initialized working area * to load the download code; it should not be called otherwise * fetch order from the fastdata area @@ -1039,13 +1132,17 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are /* start of fastdata area in t0 */ MIPS32_LUI(isa, 8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), MIPS32_ORI(isa, 8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), - MIPS32_LW(isa, 9, 0, 8), /* start addr in t1 */ - MIPS32_LW(isa, 10, 0, 8), /* end addr to t2 */ - /* loop: */ + MIPS32_LW(isa, 9, 0, 8), /* start addr in t1 */ + mips32_cpu_support_sync(ejtag_info) ? MIPS32_SYNC(isa) : MIPS32_NOP, /* barrier for ordering */ + MIPS32_LW(isa, 10, 0, 8), /* end addr to t2 */ + mips32_cpu_support_sync(ejtag_info) ? MIPS32_SYNC(isa) : MIPS32_NOP, /* barrier for ordering */ + /* loop: */ write_t ? MIPS32_LW(isa, 11, 0, 8) : MIPS32_LW(isa, 11, 0, 9), /* from xfer area : from memory */ write_t ? MIPS32_SW(isa, 11, 0, 9) : MIPS32_SW(isa, 11, 0, 8), /* to memory : to xfer area */ - MIPS32_BNE(isa, 10, 9, NEG16(3 << isa)), /* bne $t2,t1,loop */ + mips32_cpu_support_sync(ejtag_info) ? MIPS32_SYNC(isa) : MIPS32_NOP, /* barrier for ordering */ + + MIPS32_BNE(isa, 10, 9, NEG16(4 << isa)), /* bne $t2,t1,loop */ MIPS32_ADDI(isa, 9, 9, 4), /* addi t1,t1,4 */ MIPS32_LW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), @@ -1055,7 +1152,9 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are MIPS32_LUI(isa, 15, UPPER16(MIPS32_PRACC_TEXT)), MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_PRACC_TEXT) | isa), /* isa bit for JR instr */ - MIPS32_JR(isa, 15), /* jr start */ + mips32_cpu_support_hazard_barrier(ejtag_info) + ? MIPS32_JRHB(isa, 15) + : MIPS32_JR(isa, 15), /* jr start */ MIPS32_MFC0(isa, 15, 31, 0), /* move COP0 DeSave to $15 */ }; @@ -1075,7 +1174,9 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are uint32_t jmp_code[] = { MIPS32_LUI(isa, 15, UPPER16(source->address)), /* load addr of jump in $15 */ MIPS32_ORI(isa, 15, 15, LOWER16(source->address) | isa), /* isa bit for JR instr */ - MIPS32_JR(isa, 15), /* jump to ram program */ + mips32_cpu_support_hazard_barrier(ejtag_info) + ? MIPS32_JRHB(isa, 15) + : MIPS32_JR(isa, 15), /* jump to ram program */ isa ? MIPS32_XORI(isa, 15, 15, 1) : MIPS32_NOP, /* drop isa bit, needed for LW/SW instructions */ }; @@ -1139,5 +1240,5 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) LOG_ERROR("mini program did not return to start"); - return retval; + return mips32_pracc_fastdata_xfer_synchronize_cache(ejtag_info, addr, 4, count); } diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 587a446918..78d087213c 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -53,6 +53,8 @@ struct pracc_queue_info { struct pa_list *pracc_list; /* Code and store addresses at dmseg */ }; +struct mips32_common; + void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); void pracc_queue_free(struct pracc_queue_info *ctx); diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 172ac5955b..7376e5141d 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -206,6 +206,7 @@ struct mips_ejtag { struct jtag_tap *tap; uint32_t impcode; uint32_t idcode; + uint32_t prid; uint32_t ejtag_ctrl; int fast_access_save; uint32_t config_regs; /* number of config registers read */ From 0886730f5a003253a517807204a4ab7c4024c459 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Mon, 25 Dec 2023 13:03:54 +0300 Subject: [PATCH 0692/1312] doc: `address` is optional in `*_image` commands Change-Id: I3d4320634bf59be18bbcb22c9e4b13a3ccd7a45a Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8061 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Jan Matyas --- doc/openocd.texi | 22 +++++++++++++++------- src/target/target.c | 8 ++++---- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index e482c43b4e..fb1610dfb6 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9328,7 +9328,7 @@ Loads an image stored in memory by @command{fast_load_image} to the current target. Must be preceded by fast_load_image. @end deffn -@deffn {Command} {fast_load_image} filename address [@option{bin}|@option{ihex}|@option{elf}|@option{s19}] +@deffn {Command} {fast_load_image} filename [address [@option{bin}|@option{ihex}|@option{elf}|@option{s19} [@option{min_addr} [@option{max_length}]]]]]] Normally you should be using @command{load_image} or GDB load. However, for testing purposes or when I/O overhead is significant(OpenOCD running on an embedded host), storing the image in memory and uploading the image to the target @@ -9339,8 +9339,10 @@ target programming performance as I/O and target programming can easily be profi separately. @end deffn -@deffn {Command} {load_image} filename address [[@option{bin}|@option{ihex}|@option{elf}|@option{s19}] @option{min_addr} @option{max_length}] -Load image from file @var{filename} to target memory offset by @var{address} from its load address. +@deffn {Command} {load_image} filename [address [@option{bin}|@option{ihex}|@option{elf}|@option{s19} [@option{min_addr} [@option{max_length}]]]] +Load image from file @var{filename} to target memory. +If an @var{address} is specified, it is used as an offset to the file format +defined addressing (e.g. @option{bin} file is loaded at that address). The file format may optionally be specified (@option{bin}, @option{ihex}, @option{elf}, or @option{s19}). In addition the following arguments may be specified: @@ -9364,15 +9366,21 @@ The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) @end deffn -@deffn {Command} {verify_image} filename address [@option{bin}|@option{ihex}|@option{elf}] -Verify @var{filename} against target memory starting at @var{address}. +@deffn {Command} {verify_image} filename [address [@option{bin}|@option{ihex}|@option{elf}]] +Verify @var{filename} against target memory. +If an @var{address} is specified, it is used as an offset to the file format +defined addressing (e.g. @option{bin} file is compared against memory starting +at that address). The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare. @end deffn -@deffn {Command} {verify_image_checksum} filename address [@option{bin}|@option{ihex}|@option{elf}] -Verify @var{filename} against target memory starting at @var{address}. +@deffn {Command} {verify_image_checksum} filename [address [@option{bin}|@option{ihex}|@option{elf}]] +Verify @var{filename} against target memory. +If an @var{address} is specified, it is used as an offset to the file format +defined addressing (e.g. @option{bin} file is compared against memory starting +at that address). The file format may optionally be specified (@option{bin}, @option{ihex}, or @option{elf}) This perform a comparison using a CRC checksum only diff --git a/src/target/target.c b/src/target/target.c index 5605d29202..61890aa3e5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -6926,8 +6926,8 @@ static const struct command_registration target_exec_command_handlers[] = { .mode = COMMAND_ANY, .help = "Load image into server memory for later use by " "fast_load; primarily for profiling", - .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " - "[min_address [max_length]]", + .usage = "filename [address ['bin'|'ihex'|'elf'|'s19' " + "[min_address [max_length]]]]", }, { .name = "fast_load", @@ -7100,8 +7100,8 @@ static const struct command_registration target_exec_command_handlers[] = { .name = "load_image", .handler = handle_load_image_command, .mode = COMMAND_EXEC, - .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " - "[min_address] [max_length]", + .usage = "filename [address ['bin'|'ihex'|'elf'|'s19' " + "[min_address [max_length]]]]", }, { .name = "dump_image", From a77d280bd07b355b5ec981a91eefa88695081bf1 Mon Sep 17 00:00:00 2001 From: David Vidrie Leon Date: Wed, 27 Apr 2022 14:45:04 -0400 Subject: [PATCH 0693/1312] flash/nor/kinetis: add support for NXP S32K series MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit S32K General-Purpose Microcontrollers Scalable, low-power Arm® Cortex®-M series-based microcontrollers AEC-Q100 qualified with advanced safety and security and software support for industrial and automotive ASIL B/D applications in body, zone control, and electrification. Change-Id: I4143258535437c18b81802436267bfd561de9d31 Signed-off-by: David Vidrie Leon Reviewed-on: https://review.openocd.org/c/openocd/+/8012 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/openocd.texi | 16 ++- src/flash/nor/kinetis.c | 260 +++++++++++++++++++++++++++++++++++++--- tcl/target/s32k.cfg | 79 ++++++++++++ 3 files changed, 334 insertions(+), 21 deletions(-) create mode 100644 tcl/target/s32k.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index fb1610dfb6..53730eafaf 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6824,16 +6824,23 @@ nor is Chip Erase (only Sector Erase is implemented).} @deffn {Flash Driver} {kinetis} @cindex kinetis -Kx, KLx, KVx and KE1x members of the Kinetis microcontroller family -from NXP (former Freescale) include -internal flash and use ARM Cortex-M0+ or M4 cores. The driver automatically +Several microcontrollers from NXP (former Freescale), including +Kx, KLx, KVx and KE1x members of the Kinetis family, +and S32K11x/S32K14x microcontrollers, include +internal flash and use ARM Cortex-M0+ or M4 cores. +Kinetis and S32K1 families use incompatible +identification registers, so the driver assumes Kinetis and requires +a driver option to indicate S32K1 is to be used. +Within the familiy, the driver automatically recognizes flash size and a number of flash banks (1-4) using the chip identification register, and autoconfigures itself. Use kinetis_ke driver for KE0x and KEAx devices. The @var{kinetis} driver defines option: @itemize -@item -sim-base @var{addr} ... base of System Integration Module where chip identification resides. Driver tries two known locations if option is omitted. +@item -s32k select S32K11x/S32K14x microcontroller flash support. + +@item -sim-base @var{addr} ... base of System Integration Module where chip identification resides. Driver tries known locations if option is omitted. @end itemize @example @@ -6882,6 +6889,7 @@ command completes. @deffn {Command} {kinetis nvm_partition} For FlexNVM devices only (KxxDX and KxxFX). +Not supported (yet) on S32K1 devices. Command shows or sets data flash or EEPROM backup size in kilobytes, sets two EEPROM blocks sizes in bytes and enables/disables loading of EEPROM contents to FlexRAM during reset. diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 7137b4aa07..e8074e35bb 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -80,6 +80,7 @@ #define FLEXRAM 0x14000000 #define MSCM_OCMDR0 0x40001400 +#define MSCM_OCMDR1 0x40001404 #define FMC_PFB01CR 0x4001f004 #define FTFX_FSTAT 0x40020000 #define FTFX_FCNFG 0x40020001 @@ -230,6 +231,28 @@ #define KINETIS_SDID_PROJECTID_KE1XF 0x00000080 #define KINETIS_SDID_PROJECTID_KE1XZ 0x00000100 +/* The S32K series uses a different, incompatible SDID layout : + * Bit 31-28 : GENERATION + * Bit 27-24 : SUBSERIES + * Bit 23-20 : DERIVATE + * Bit 19-16 : RAMSIZE + * Bit 15-12 : REVID + * Bit 11-8 : PACKAGE + * Bit 7-0 : FEATURES + */ + +#define KINETIS_SDID_S32K_SERIES_MASK 0xFF000000 /* GENERATION + SUBSERIES */ +#define KINETIS_SDID_S32K_SERIES_K11X 0x11000000 +#define KINETIS_SDID_S32K_SERIES_K14X 0x14000000 + +#define KINETIS_SDID_S32K_DERIVATE_MASK 0x00F00000 +#define KINETIS_SDID_S32K_DERIVATE_KXX2 0x00200000 +#define KINETIS_SDID_S32K_DERIVATE_KXX3 0x00300000 +#define KINETIS_SDID_S32K_DERIVATE_KXX4 0x00400000 +#define KINETIS_SDID_S32K_DERIVATE_KXX5 0x00500000 +#define KINETIS_SDID_S32K_DERIVATE_KXX6 0x00600000 +#define KINETIS_SDID_S32K_DERIVATE_KXX8 0x00800000 + struct kinetis_flash_bank { struct kinetis_chip *k_chip; bool probed; @@ -275,6 +298,11 @@ struct kinetis_chip { uint32_t progr_accel_ram; uint32_t sim_base; + enum { + CT_KINETIS = 0, + CT_S32K, + } chip_type; + enum { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, @@ -290,6 +318,7 @@ struct kinetis_chip { KINETIS_CACHE_K, /* invalidate using FMC->PFB0CR/PFB01CR */ KINETIS_CACHE_L, /* invalidate using MCM->PLACR */ KINETIS_CACHE_MSCM, /* devices like KE1xF, invalidate MSCM->OCMDR0 */ + KINETIS_CACHE_MSCM2, /* devices like S32K, invalidate MSCM->OCMDR0 and MSCM->OCMDR1 */ } cache_type; enum { @@ -392,6 +421,7 @@ const struct flash_driver kinetis_flash; static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); static int kinetis_probe_chip(struct kinetis_chip *k_chip); +static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip); static int kinetis_auto_probe(struct flash_bank *bank); @@ -877,6 +907,8 @@ static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const cha if (strcmp(argv[i], "-sim-base") == 0) { if (i + 1 < argc) k_chip->sim_base = strtoul(argv[++i], NULL, 0); + } else if (strcmp(argv[i], "-s32k") == 0) { + k_chip->chip_type = CT_S32K; } else LOG_ERROR("Unsupported flash bank option %s", argv[i]); } @@ -1140,7 +1172,13 @@ static int kinetis_disable_wdog(struct kinetis_chip *k_chip) int retval; if (!k_chip->probed) { - retval = kinetis_probe_chip(k_chip); + switch (k_chip->chip_type) { + case CT_S32K: + retval = kinetis_probe_chip_s32k(k_chip); + break; + default: + retval = kinetis_probe_chip(k_chip); + } if (retval != ERROR_OK) return retval; } @@ -1639,6 +1677,12 @@ static void kinetis_invalidate_flash_cache(struct kinetis_chip *k_chip) /* disable data prefetch and flash speculate */ break; + case KINETIS_CACHE_MSCM2: + target_write_u32(target, MSCM_OCMDR0, 0x30); + target_write_u32(target, MSCM_OCMDR1, 0x30); + /* disable data prefetch and flash speculate */ + break; + default: break; } @@ -2048,6 +2092,174 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, } +static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip) +{ + int result; + uint8_t fcfg1_eesize, fcfg1_depart; + uint32_t ee_size = 0; + uint32_t pflash_size_k, nvm_size_k, dflash_size_k; + unsigned int generation = 0, subseries = 0, derivate = 0; + + struct target *target = k_chip->target; + k_chip->probed = false; + k_chip->pflash_sector_size = 0; + k_chip->pflash_base = 0; + k_chip->nvm_base = 0x10000000; + k_chip->progr_accel_ram = FLEXRAM; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + k_chip->watchdog_type = KINETIS_WDOG32_KE1X; + + if (k_chip->sim_base == 0) + k_chip->sim_base = SIM_BASE; + + result = target_read_u32(target, k_chip->sim_base + SIM_SDID_OFFSET, &k_chip->sim_sdid); + if (result != ERROR_OK) + return result; + + generation = (k_chip->sim_sdid) >> 28 & 0x0f; + subseries = (k_chip->sim_sdid) >> 24 & 0x0f; + derivate = (k_chip->sim_sdid) >> 20 & 0x0f; + + switch (k_chip->sim_sdid & KINETIS_SDID_S32K_SERIES_MASK) { + case KINETIS_SDID_S32K_SERIES_K11X: + k_chip->cache_type = KINETIS_CACHE_L; + k_chip->num_pflash_blocks = 1; + k_chip->num_nvm_blocks = 1; + /* Non-interleaved */ + k_chip->max_flash_prog_size = 512; + + switch (k_chip->sim_sdid & KINETIS_SDID_S32K_DERIVATE_MASK) { + case KINETIS_SDID_S32K_DERIVATE_KXX6: + /* S32K116 CPU 48Mhz Flash 128KB RAM 17KB+2KB */ + /* Non-Interleaved */ + k_chip->pflash_size = 128 << 10; + k_chip->pflash_sector_size = 2 << 10; + /* Non-Interleaved */ + k_chip->nvm_size = 32 << 10; + k_chip->nvm_sector_size = 2 << 10; + break; + case KINETIS_SDID_S32K_DERIVATE_KXX8: + /* S32K118 CPU 80Mhz Flash 256KB+32KB RAM 32KB+4KB */ + /* Non-Interleaved */ + k_chip->pflash_size = 256 << 10; + k_chip->pflash_sector_size = 2 << 10; + /* Non-Interleaved */ + k_chip->nvm_size = 32 << 10; + k_chip->nvm_sector_size = 2 << 10; + break; + } + break; + + case KINETIS_SDID_S32K_SERIES_K14X: + k_chip->cache_type = KINETIS_CACHE_MSCM2; + k_chip->num_pflash_blocks = 1; + k_chip->num_nvm_blocks = 1; + /* Non-interleaved */ + k_chip->max_flash_prog_size = 512; + switch (k_chip->sim_sdid & KINETIS_SDID_S32K_DERIVATE_MASK) { + case KINETIS_SDID_S32K_DERIVATE_KXX2: + case KINETIS_SDID_S32K_DERIVATE_KXX3: + /* S32K142/S32K142W CPU 80Mhz Flash 256KB+64KB RAM 32KB+4KB */ + /* Non-Interleaved */ + k_chip->pflash_size = 256 << 10; + k_chip->pflash_sector_size = 2 << 10; + /* Non-Interleaved */ + k_chip->nvm_size = 64 << 10; + k_chip->nvm_sector_size = 2 << 10; + break; + case KINETIS_SDID_S32K_DERIVATE_KXX4: + case KINETIS_SDID_S32K_DERIVATE_KXX5: + /* S32K144/S32K144W CPU 80Mhz Flash 512KB+64KB RAM 64KB+4KB */ + /* Interleaved */ + k_chip->pflash_size = 512 << 10; + k_chip->pflash_sector_size = 4 << 10; + /* Non-Interleaved */ + k_chip->nvm_size = 64 << 10; + k_chip->nvm_sector_size = 2 << 10; + break; + case KINETIS_SDID_S32K_DERIVATE_KXX6: + /* S32K146 CPU 80Mhz Flash 1024KB+64KB RAM 128KB+4KB */ + /* Interleaved */ + k_chip->pflash_size = 1024 << 10; + k_chip->pflash_sector_size = 4 << 10; + k_chip->num_pflash_blocks = 2; + /* Non-Interleaved */ + k_chip->nvm_size = 64 << 10; + k_chip->nvm_sector_size = 2 << 10; + break; + case KINETIS_SDID_S32K_DERIVATE_KXX8: + /* S32K148 CPU 80Mhz Flash 1536KB+512KB RAM 256KB+4KB */ + /* Interleaved */ + k_chip->pflash_size = 1536 << 10; + k_chip->pflash_sector_size = 4 << 10; + k_chip->num_pflash_blocks = 3; + /* Interleaved */ + k_chip->nvm_size = 512 << 10; + k_chip->nvm_sector_size = 4 << 10; + /* Interleaved */ + k_chip->max_flash_prog_size = 1 << 10; + break; + } + break; + + default: + LOG_ERROR("Unsupported S32K1xx-series"); + } + + if (k_chip->pflash_sector_size == 0) { + LOG_ERROR("MCU is unsupported, SDID 0x%08" PRIx32, k_chip->sim_sdid); + return ERROR_FLASH_OPER_UNSUPPORTED; + } + + result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &k_chip->sim_fcfg1); + if (result != ERROR_OK) + return result; + k_chip->sim_fcfg2 = 0; /* S32K1xx does not implement FCFG2 register. */ + + fcfg1_depart = (k_chip->sim_fcfg1 >> 12) & 0x0f; + fcfg1_eesize = (k_chip->sim_fcfg1 >> 16) & 0x0f; + if (fcfg1_eesize <= 9) + ee_size = (16 << (10 - fcfg1_eesize)); + if ((fcfg1_depart & 0x8) == 0) { + /* Binary 0xxx values encode the amount reserved for EEPROM emulation. */ + if (fcfg1_depart) + k_chip->dflash_size = k_chip->nvm_size - (4096 << fcfg1_depart); + else + k_chip->dflash_size = k_chip->nvm_size; + } else { + /* Binary 1xxx valued encode the DFlash size. */ + if (fcfg1_depart & 0x7) + k_chip->dflash_size = 4096 << (fcfg1_depart & 0x7); + else + k_chip->dflash_size = 0; + } + + snprintf(k_chip->name, sizeof(k_chip->name), "S32K%u%u%u", + generation, subseries, derivate); + + pflash_size_k = k_chip->pflash_size / 1024; + dflash_size_k = k_chip->dflash_size / 1024; + + LOG_INFO("%s detected: %u flash blocks", k_chip->name, k_chip->num_pflash_blocks + k_chip->num_nvm_blocks); + LOG_INFO("%u PFlash banks: %" PRIu32 " KiB total", k_chip->num_pflash_blocks, pflash_size_k); + + nvm_size_k = k_chip->nvm_size / 1024; + + if (k_chip->num_nvm_blocks) { + LOG_INFO("%u FlexNVM banks: %" PRIu32 " KiB total, %" PRIu32 " KiB available as data flash, %" + PRIu32 " bytes FlexRAM", + k_chip->num_nvm_blocks, nvm_size_k, dflash_size_k, ee_size); + } + + k_chip->probed = true; + + if (create_banks) + kinetis_create_missing_banks(k_chip); + + return ERROR_OK; +} + + static int kinetis_probe_chip(struct kinetis_chip *k_chip) { int result; @@ -2693,7 +2905,13 @@ static int kinetis_probe(struct flash_bank *bank) k_bank->probed = false; if (!k_chip->probed) { - result = kinetis_probe_chip(k_chip); + switch (k_chip->chip_type) { + case CT_S32K: + result = kinetis_probe_chip_s32k(k_chip); + break; + default: + result = kinetis_probe_chip(k_chip); + } if (result != ERROR_OK) return result; } @@ -2765,23 +2983,26 @@ static int kinetis_probe(struct flash_bank *bank) return ERROR_FLASH_BANK_INVALID; } - fcfg2_pflsh = (uint8_t)((k_chip->sim_fcfg2 >> 23) & 0x01); - fcfg2_maxaddr0 = (uint8_t)((k_chip->sim_fcfg2 >> 24) & 0x7f); - fcfg2_maxaddr1 = (uint8_t)((k_chip->sim_fcfg2 >> 16) & 0x7f); + /* S32K1xx does not implement FCFG2 register. Skip checks. */ + if (k_chip->chip_type != CT_S32K) { + fcfg2_pflsh = (uint8_t)((k_chip->sim_fcfg2 >> 23) & 0x01); + fcfg2_maxaddr0 = (uint8_t)((k_chip->sim_fcfg2 >> 24) & 0x7f); + fcfg2_maxaddr1 = (uint8_t)((k_chip->sim_fcfg2 >> 16) & 0x7f); - if (k_bank->bank_number == 0 && k_chip->fcfg2_maxaddr0_shifted != bank->size) - LOG_WARNING("MAXADDR0 0x%02" PRIx8 " check failed," - " please report to OpenOCD mailing list", fcfg2_maxaddr0); + if (k_bank->bank_number == 0 && k_chip->fcfg2_maxaddr0_shifted != bank->size) + LOG_WARNING("MAXADDR0 0x%02" PRIx8 " check failed," + " please report to OpenOCD mailing list", fcfg2_maxaddr0); - if (fcfg2_pflsh) { - if (k_bank->bank_number == 1 && k_chip->fcfg2_maxaddr1_shifted != bank->size) - LOG_WARNING("MAXADDR1 0x%02" PRIx8 " check failed," - " please report to OpenOCD mailing list", fcfg2_maxaddr1); - } else { - if (k_bank->bank_number == first_nvm_bank - && k_chip->fcfg2_maxaddr1_shifted != k_chip->dflash_size) - LOG_WARNING("FlexNVM MAXADDR1 0x%02" PRIx8 " check failed," - " please report to OpenOCD mailing list", fcfg2_maxaddr1); + if (fcfg2_pflsh) { + if (k_bank->bank_number == 1 && k_chip->fcfg2_maxaddr1_shifted != bank->size) + LOG_WARNING("MAXADDR1 0x%02" PRIx8 " check failed," + " please report to OpenOCD mailing list", fcfg2_maxaddr1); + } else { + if (k_bank->bank_number == first_nvm_bank + && k_chip->fcfg2_maxaddr1_shifted != k_chip->dflash_size) + LOG_WARNING("FlexNVM MAXADDR1 0x%02" PRIx8 " check failed," + " please report to OpenOCD mailing list", fcfg2_maxaddr1); + } } free(bank->sectors); @@ -2932,6 +3153,11 @@ COMMAND_HANDLER(kinetis_nvm_partition) k_chip = kinetis_get_chip(target); + if (k_chip->chip_type == CT_S32K) { + LOG_ERROR("NVM partition not supported on S32K1xx (yet)."); + return ERROR_FAIL; + } + if (CMD_ARGC >= 2) { if (strcmp(CMD_ARGV[0], "dataflash") == 0) sz_type = DF_SIZE; diff --git a/tcl/target/s32k.cfg b/tcl/target/s32k.cfg new file mode 100644 index 0000000000..3ff3239739 --- /dev/null +++ b/tcl/target/s32k.cfg @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Freescale S32K devices +# Similar to Kinetis Kx series devices. +# + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME s32k +} + +# Work-area is a space in RAM used for flash programming +# By default use 4kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x0995001d +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.pflash +flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME -s32k +kinetis create_banks + +adapter speed 1000 + +reset_config srst_nogate + +if {[using_hla]} { + echo "" + echo "!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!" + echo " Kinetis MCUs have a MDM-AP dedicated mainly to MCU security related functions." + echo " A high level adapter (like a ST-Link) you are currently using cannot access" + echo " the MDM-AP, so commands like 'mdm mass_erase' are not available in your" + echo " configuration. Also security locked state of the device will not be reported." + echo " Expect problems connecting to a blank device without boot ROM." + echo "" + echo " Be very careful as you can lock the device though there is no way to unlock" + echo " it without mass erase. Don't set write protection on the first block." + echo "!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!" + echo "" +} else { + # Detect secured MCU or boot lock-up in RESET/WDOG loop + $_TARGETNAME configure -event examine-fail { + kinetis mdm check_security + } + # During RESET/WDOG loop the target is sometimes falsely examined + $_TARGETNAME configure -event examine-end { + kinetis mdm check_security + } + + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +# Disable watchdog not to disturb OpenOCD algorithms running on MCU +# (e.g. armv7m_checksum_memory() in verify_image) +# Flash driver also disables watchdog before FTFA flash programming. +$_TARGETNAME configure -event reset-init { + kinetis disable_wdog +} From 5039848424f818241a8d256b7e49f6c3152c4dc6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 2 Apr 2023 18:27:17 +0200 Subject: [PATCH 0694/1312] target/arm_adi_v5: simplify TI BE 32 quirk workaround Introduce ti_be_lane_xor for byte lane correction and use common code for both quirk and regular conversion. The same lane correction takes place in both mem_ap_read/write() - it was obfuscated in original code with different bitwise and arithmetic operations. Change-Id: I6a30672b908770323d30813a714e06ab8695fe26 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7574 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_adi_v5.c | 75 +++++++++++++---------------------------- 1 file changed, 24 insertions(+), 51 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 434bf50fe1..6998577731 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -338,7 +338,6 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; - target_addr_t addr_xor; int retval = ERROR_OK; /* TI BE-32 Quirks mode: @@ -354,15 +353,17 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * setting the TAP, and we set the TAP after every transfer rather then relying on * address increment. */ + target_addr_t ti_be_lane_xor = dap->ti_be_32_quirks ? 3 : 0; + target_addr_t ti_be_addr_xor; if (size == 4) { csw_size = CSW_32BIT; - addr_xor = 0; + ti_be_addr_xor = 0; } else if (size == 2) { csw_size = CSW_16BIT; - addr_xor = dap->ti_be_32_quirks ? 2 : 0; + ti_be_addr_xor = dap->ti_be_32_quirks ? 2 : 0; } else if (size == 1) { csw_size = CSW_8BIT; - addr_xor = dap->ti_be_32_quirks ? 3 : 0; + ti_be_addr_xor = dap->ti_be_32_quirks ? 3 : 0; } else { return ERROR_TARGET_UNALIGNED_ACCESS; } @@ -385,7 +386,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz if (retval != ERROR_OK) break; - retval = mem_ap_setup_tar(ap, address ^ addr_xor); + retval = mem_ap_setup_tar(ap, address ^ ti_be_addr_xor); if (retval != ERROR_OK) return retval; @@ -393,23 +394,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * depends on the type of transfer and alignment. See ARM document IHI0031C. */ uint32_t outvalue = 0; uint32_t drw_byte_idx = address; - if (dap->ti_be_32_quirks) { - switch (this_size) { - case 4: - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx & 3) ^ addr_xor); - break; - case 2: - outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx++ & 3) ^ addr_xor); - outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx & 3) ^ addr_xor); - break; - case 1: - outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (drw_byte_idx & 3) ^ addr_xor); - break; - } - } else if (dap->nu_npcx_quirks) { + if (dap->nu_npcx_quirks) { switch (this_size) { case 4: outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); @@ -432,14 +417,14 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz } else { switch (this_size) { case 4: - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); + outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); /* fallthrough */ case 2: - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); /* fallthrough */ case 1: - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); + outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx & 3) ^ ti_be_lane_xor); } } @@ -496,7 +481,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint * They read from the physical address requested, but with DRW byte-reversed. * For example, a byte read from address 0 will place the result in the high bytes of DRW. * Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes, - * so avoid them. */ + * so avoid them (ap->packed_transfers is forced to false in mem_ap_init). */ if (size == 4) csw_size = CSW_32BIT; @@ -576,6 +561,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint } } + target_addr_t ti_be_lane_xor = dap->ti_be_32_quirks ? 3 : 0; + /* Replay loop to populate caller's buffer from the correct word and byte lane */ while (nbytes > 0) { uint32_t this_size = size; @@ -585,30 +572,16 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint this_size = 4; } - if (dap->ti_be_32_quirks) { - switch (this_size) { - case 4: - *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); - *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); - /* fallthrough */ - case 2: - *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); - /* fallthrough */ - case 1: - *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3)); - } - } else { - switch (this_size) { - case 4: - *buffer++ = *read_ptr >> 8 * (address++ & 3); - *buffer++ = *read_ptr >> 8 * (address++ & 3); - /* fallthrough */ - case 2: - *buffer++ = *read_ptr >> 8 * (address++ & 3); - /* fallthrough */ - case 1: - *buffer++ = *read_ptr >> 8 * (address++ & 3); - } + switch (this_size) { + case 4: + *buffer++ = *read_ptr >> 8 * ((address++ & 3) ^ ti_be_lane_xor); + *buffer++ = *read_ptr >> 8 * ((address++ & 3) ^ ti_be_lane_xor); + /* fallthrough */ + case 2: + *buffer++ = *read_ptr >> 8 * ((address++ & 3) ^ ti_be_lane_xor); + /* fallthrough */ + case 1: + *buffer++ = *read_ptr >> 8 * ((address++ & 3) ^ ti_be_lane_xor); } read_ptr++; From ffdcec938fb6bd2d6f7f1f4aed7b41c627934a24 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 2 Apr 2023 18:49:12 +0200 Subject: [PATCH 0695/1312] target/arm_adi_v5: rework Nuvoton NPCX quirk workaround. Prevent packed writes with Nuvoton NPCX quirks because the workaround uses all byte lanes for one byte or halfword and thus precludes packing. Eliminate quirk code for size 4 as it is equivalent to the common code. Make the quirk code for sizes 2 and 1 easier readable. Change-Id: I72324e56a49b4712bd3769e03dce01427d9fcd73 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7575 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_adi_v5.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 6998577731..0f1e648a9e 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -376,6 +376,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz /* Select packed transfer if possible */ if (addrinc && ap->packed_transfers && nbytes >= 4 + && !dap->nu_npcx_quirks && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); @@ -394,25 +395,28 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * depends on the type of transfer and alignment. See ARM document IHI0031C. */ uint32_t outvalue = 0; uint32_t drw_byte_idx = address; - if (dap->nu_npcx_quirks) { + if (dap->nu_npcx_quirks && this_size <= 2) { switch (this_size) { - case 4: - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); - break; case 2: - outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*(buffer+1) << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); + { + /* Alternate low and high byte to all byte lanes */ + uint32_t low = *buffer++; + uint32_t high = *buffer++; + outvalue |= low << 8 * (drw_byte_idx++ & 3); + outvalue |= high << 8 * (drw_byte_idx++ & 3); + outvalue |= low << 8 * (drw_byte_idx++ & 3); + outvalue |= high << 8 * (drw_byte_idx & 3); + } break; case 1: - outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer << 8 * (drw_byte_idx++ & 3); - outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3); + { + /* Mirror output byte to all byte lanes */ + uint32_t data = *buffer++; + outvalue |= data; + outvalue |= data << 8; + outvalue |= data << 16; + outvalue |= data << 24; + } } } else { switch (this_size) { From adcc8ef87bc1ed47c95f1f2d23072b2b916e1555 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 2 Apr 2023 17:23:46 +0200 Subject: [PATCH 0696/1312] target/adiv5: probe MEM-AP supported transfer sizes including large data Based on Daniel Goehring's [1] and Peter Collingbourne's [2] work. Probe for support of 8, 16 bit and if the large data extension is available also probe for 64, 128 and 256 bit operations. Probe for the ability of packing 8 and 16 bit data (formerly probed in mem_ap_init()). The probe is integrated to mem_ap_read/write() routines and takes place just before the first memory access of the specific size. Add 64, 128 and 256 bit MEM-AP read/writes. Introduce specific error codes for unsupported transfer size and for unsupported packing. Change-Id: I180c4ef17d2fc3189e8e2f14bafd22d857f29608 Link: 7191: target/adiv5: add MEM-AP 64-bit access support | https://review.openocd.org/c/openocd/+/7191 Link: 7436: arm_adi_v5: Support reads wider than 32 bits | https://review.openocd.org/c/openocd/+/7436 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7576 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/arm_adi_v5.c | 366 ++++++++++++++++++++++++++-------------- src/target/arm_adi_v5.h | 26 ++- src/target/target.h | 2 + 3 files changed, 268 insertions(+), 126 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 0f1e648a9e..ff12658c83 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -50,7 +50,8 @@ /* * Relevant specifications from ARM include: * - * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031E + * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031F + * ARM(tm) Debug Interface v6 Architecture Specification ARM IHI 0074C * CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B * * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D @@ -164,6 +165,12 @@ static uint32_t mem_ap_get_tar_increment(struct adiv5_ap *ap) return 2; case CSW_32BIT: return 4; + case CSW_64BIT: + return 8; + case CSW_128BIT: + return 16; + case CSW_256BIT: + return 32; default: return 0; } @@ -319,12 +326,145 @@ int mem_ap_write_atomic_u32(struct adiv5_ap *ap, target_addr_t address, return dap_run(ap->dap); } +/** + * Queue transactions setting up transfer parameters for the + * currently selected MEM-AP. If transfer size or packing + * has not been probed, run the queue, read back CSW and check if the requested + * transfer mode is supported. + * + * @param ap The MEM-AP. + * @param size Transfer width in bytes. Corresponding CSW.Size will be set. + * @param address Transfer address, MEM-AP TAR will be set to this value. + * @param addrinc TAR will be autoincremented. + * @param pack Try to setup packed transfer. + * @param this_size Points to a variable set to the size of single transfer + * or to 4 when transferring packed bytes or halfwords + * + * @return ERROR_OK if the transaction was properly queued, else a fault code. + */ +static int mem_ap_setup_transfer_verify_size_packing(struct adiv5_ap *ap, + unsigned int size, target_addr_t address, + bool addrinc, bool pack, unsigned int *this_size) +{ + int retval; + uint32_t csw_size; + + switch (size) { + case 1: + csw_size = CSW_8BIT; + break; + case 2: + csw_size = CSW_16BIT; + break; + case 4: + csw_size = CSW_32BIT; + break; + case 8: + csw_size = CSW_64BIT; + break; + case 16: + csw_size = CSW_128BIT; + break; + case 32: + csw_size = CSW_256BIT; + break; + default: + LOG_ERROR("Size %u not supported", size); + return ERROR_TARGET_SIZE_NOT_SUPPORTED; + } + + if (!addrinc || size >= 4 + || (ap->packed_transfers_probed && !ap->packed_transfers_supported) + || max_tar_block_size(ap->tar_autoincr_block, address) < 4) + pack = false; + + uint32_t csw_addrinc = pack ? CSW_ADDRINC_PACKED : + addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; + retval = mem_ap_setup_csw(ap, csw_size | csw_addrinc); + if (retval != ERROR_OK) + return retval; + + bool do_probe = !(ap->csw_size_probed_mask & size) + || (pack && !ap->packed_transfers_probed); + if (do_probe) { + uint32_t csw_readback; + retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(ap->dap), &csw_readback); + if (retval != ERROR_OK) + return retval; + + retval = dap_run(ap->dap); + if (retval != ERROR_OK) + return retval; + + bool size_supported = ((csw_readback & CSW_SIZE_MASK) == csw_size); + LOG_DEBUG("AP#0x%" PRIx64 " probed size %u: %s", ap->ap_num, size, + size_supported ? "supported" : "not supported"); + ap->csw_size_probed_mask |= size; + if (size_supported) { + ap->csw_size_supported_mask |= size; + if (pack && !ap->packed_transfers_probed) { + ap->packed_transfers_probed = true; + ap->packed_transfers_supported = + ((csw_readback & CSW_ADDRINC_MASK) == csw_addrinc); + LOG_DEBUG("probed packing: %s", + ap->packed_transfers_supported ? "supported" : "not supported"); + } + } + } + + if (!(ap->csw_size_supported_mask & size)) { + LOG_ERROR("Size %u not supported", size); + return ERROR_TARGET_SIZE_NOT_SUPPORTED; + } + + if (pack && !ap->packed_transfers_supported) + return ERROR_TARGET_PACKING_NOT_SUPPORTED; + + *this_size = pack ? 4 : size; + + return mem_ap_setup_tar(ap, address); +} + +/** + * Queue transactions setting up transfer parameters for the + * currently selected MEM-AP. If transfer size or packing + * has not been probed, run the queue, read back CSW and check if the requested + * transfer mode is supported. + * If packing is not supported fallback and prepare CSW for unpacked transfer. + * + * @param ap The MEM-AP. + * @param size Transfer width in bytes. Corresponding CSW.Size will be set. + * @param address Transfer address, MEM-AP TAR will be set to this value. + * @param addrinc TAR will be autoincremented. + * @param pack Try to setup packed transfer. + * @param this_size Points to a variable set to the size of single transfer + * or to 4 when transferring packed bytes or halfwords + * + * @return ERROR_OK if the transaction was properly queued, else a fault code. + */ +static int mem_ap_setup_transfer_verify_size_packing_fallback(struct adiv5_ap *ap, + unsigned int size, target_addr_t address, + bool addrinc, bool pack, unsigned int *this_size) +{ + int retval = mem_ap_setup_transfer_verify_size_packing(ap, + size, address, + addrinc, pack, this_size); + if (retval == ERROR_TARGET_PACKING_NOT_SUPPORTED) { + /* Retry without packing */ + retval = mem_ap_setup_transfer_verify_size_packing(ap, + size, address, + addrinc, false, this_size); + } + return retval; +} + /** * Synchronous write of a block of memory, using a specific access size. * * @param ap The MEM-AP to access. * @param buffer The data buffer to write. No particular alignment is assumed. - * @param size Which access size to use, in bytes. 1, 2 or 4. + * @param size Which access size to use, in bytes. 1, 2, or 4. + * If large data extension is available also accepts sizes 8, 16, 32. * @param count The number of writes to do (in size units, not bytes). * @param address Address to be written; it must be writable by the currently selected MEM-AP. * @param addrinc Whether the target address should be increased for each write or not. This @@ -336,8 +476,6 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz { struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; - const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; - uint32_t csw_size; int retval = ERROR_OK; /* TI BE-32 Quirks mode: @@ -352,93 +490,85 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * To make writes of size < 4 work as expected, we xor a value with the address before * setting the TAP, and we set the TAP after every transfer rather then relying on * address increment. */ - - target_addr_t ti_be_lane_xor = dap->ti_be_32_quirks ? 3 : 0; - target_addr_t ti_be_addr_xor; - if (size == 4) { - csw_size = CSW_32BIT; - ti_be_addr_xor = 0; - } else if (size == 2) { - csw_size = CSW_16BIT; - ti_be_addr_xor = dap->ti_be_32_quirks ? 2 : 0; - } else if (size == 1) { - csw_size = CSW_8BIT; - ti_be_addr_xor = dap->ti_be_32_quirks ? 3 : 0; - } else { - return ERROR_TARGET_UNALIGNED_ACCESS; + target_addr_t ti_be_addr_xor = 0; + target_addr_t ti_be_lane_xor = 0; + if (dap->ti_be_32_quirks) { + ti_be_lane_xor = 3; + switch (size) { + case 1: + ti_be_addr_xor = 3; + break; + case 2: + ti_be_addr_xor = 2; + break; + case 4: + break; + default: + LOG_ERROR("Write more than 32 bits not supported with ti_be_32_quirks"); + return ERROR_TARGET_SIZE_NOT_SUPPORTED; + } } if (ap->unaligned_access_bad && (address % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; - while (nbytes > 0) { - uint32_t this_size = size; + /* Nuvoton NPCX quirks prevent packed writes */ + bool pack = !dap->nu_npcx_quirks; - /* Select packed transfer if possible */ - if (addrinc && ap->packed_transfers && nbytes >= 4 - && !dap->nu_npcx_quirks - && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { - this_size = 4; - retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); - } else { - retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr); - } - - if (retval != ERROR_OK) - break; - - retval = mem_ap_setup_tar(ap, address ^ ti_be_addr_xor); + while (nbytes > 0) { + unsigned int this_size; + retval = mem_ap_setup_transfer_verify_size_packing_fallback(ap, + size, address ^ ti_be_addr_xor, + addrinc, pack && nbytes >= 4, &this_size); if (retval != ERROR_OK) return retval; /* How many source bytes each transfer will consume, and their location in the DRW, * depends on the type of transfer and alignment. See ARM document IHI0031C. */ - uint32_t outvalue = 0; uint32_t drw_byte_idx = address; - if (dap->nu_npcx_quirks && this_size <= 2) { - switch (this_size) { - case 2: - { - /* Alternate low and high byte to all byte lanes */ - uint32_t low = *buffer++; - uint32_t high = *buffer++; - outvalue |= low << 8 * (drw_byte_idx++ & 3); - outvalue |= high << 8 * (drw_byte_idx++ & 3); - outvalue |= low << 8 * (drw_byte_idx++ & 3); - outvalue |= high << 8 * (drw_byte_idx & 3); - } - break; - case 1: - { - /* Mirror output byte to all byte lanes */ - uint32_t data = *buffer++; - outvalue |= data; - outvalue |= data << 8; - outvalue |= data << 16; - outvalue |= data << 24; + unsigned int drw_ops = DIV_ROUND_UP(this_size, 4); + + while (drw_ops--) { + uint32_t outvalue = 0; + if (dap->nu_npcx_quirks && this_size <= 2) { + switch (this_size) { + case 2: + { + /* Alternate low and high byte to all byte lanes */ + uint32_t low = *buffer++; + uint32_t high = *buffer++; + outvalue |= low << 8 * (drw_byte_idx++ & 3); + outvalue |= high << 8 * (drw_byte_idx++ & 3); + outvalue |= low << 8 * (drw_byte_idx++ & 3); + outvalue |= high << 8 * (drw_byte_idx & 3); + } + break; + case 1: + { + /* Mirror output byte to all byte lanes */ + uint32_t data = *buffer++; + outvalue |= data; + outvalue |= data << 8; + outvalue |= data << 16; + outvalue |= data << 24; + } } + } else { + unsigned int drw_bytes = MIN(this_size, 4); + while (drw_bytes--) + outvalue |= (uint32_t)*buffer++ << + 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); } - } else { - switch (this_size) { - case 4: - outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); - outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); - /* fallthrough */ - case 2: - outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx++ & 3) ^ ti_be_lane_xor); - /* fallthrough */ - case 1: - outvalue |= (uint32_t)*buffer++ << 8 * ((drw_byte_idx & 3) ^ ti_be_lane_xor); - } - } - nbytes -= this_size; - - retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue); + retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue); + if (retval != ERROR_OK) + break; + } if (retval != ERROR_OK) break; mem_ap_update_tar_cache(ap); + nbytes -= this_size; if (addrinc) address += this_size; } @@ -463,7 +593,8 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * * @param ap The MEM-AP to access. * @param buffer The data buffer to receive the data. No particular alignment is assumed. - * @param size Which access size to use, in bytes. 1, 2 or 4. + * @param size Which access size to use, in bytes. 1, 2, or 4. + * If large data extension is available also accepts sizes 8, 16, 32. * @param count The number of reads to do (in size units, not bytes). * @param adr Address to be read; it must be readable by the currently selected MEM-AP. * @param addrinc Whether the target address should be increased after each read or not. This @@ -475,8 +606,6 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint { struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; - const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; - uint32_t csw_size; target_addr_t address = adr; int retval = ERROR_OK; @@ -487,14 +616,10 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint * Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes, * so avoid them (ap->packed_transfers is forced to false in mem_ap_init). */ - if (size == 4) - csw_size = CSW_32BIT; - else if (size == 2) - csw_size = CSW_16BIT; - else if (size == 1) - csw_size = CSW_8BIT; - else - return ERROR_TARGET_UNALIGNED_ACCESS; + if (dap->ti_be_32_quirks && size > 4) { + LOG_ERROR("Read more than 32 bits not supported with ti_be_32_quirks"); + return ERROR_TARGET_SIZE_NOT_SUPPORTED; + } if (ap->unaligned_access_bad && (adr % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; @@ -502,7 +627,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint /* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant * over-allocation if packed transfers are going to be used, but determining the real need at * this point would be messy. */ - uint32_t *read_buf = calloc(count, sizeof(uint32_t)); + uint32_t *read_buf = calloc(count, MAX(sizeof(uint32_t), size)); + /* Multiplication count * sizeof(uint32_t) may overflow, calloc() is safe */ uint32_t *read_ptr = read_buf; if (!read_buf) { @@ -514,26 +640,20 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint * useful bytes it contains, and their location in the word, depends on the type of transfer * and alignment. */ while (nbytes > 0) { - uint32_t this_size = size; - - /* Select packed transfer if possible */ - if (addrinc && ap->packed_transfers && nbytes >= 4 - && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { - this_size = 4; - retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); - } else { - retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr); - } + unsigned int this_size; + retval = mem_ap_setup_transfer_verify_size_packing_fallback(ap, + size, address, + addrinc, nbytes >= 4, &this_size); if (retval != ERROR_OK) break; - retval = mem_ap_setup_tar(ap, address); - if (retval != ERROR_OK) - break; - retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++); - if (retval != ERROR_OK) - break; + unsigned int drw_ops = DIV_ROUND_UP(this_size, 4); + while (drw_ops--) { + retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++); + if (retval != ERROR_OK) + break; + } nbytes -= this_size; if (addrinc) @@ -552,7 +672,9 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint /* If something failed, read TAR to find out how much data was successfully read, so we can * at least give the caller what we have. */ - if (retval != ERROR_OK) { + if (retval == ERROR_TARGET_SIZE_NOT_SUPPORTED) { + nbytes = 0; + } else if (retval != ERROR_OK) { target_addr_t tar; if (mem_ap_read_tar(ap, &tar) == ERROR_OK) { /* TAR is incremented after failed transfer on some devices (eg Cortex-M4) */ @@ -569,11 +691,12 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint /* Replay loop to populate caller's buffer from the correct word and byte lane */ while (nbytes > 0) { - uint32_t this_size = size; + /* Convert transfers longer than 32-bit on word-at-a-time basis */ + unsigned int this_size = MIN(size, 4); - if (addrinc && ap->packed_transfers && nbytes >= 4 + if (size < 4 && addrinc && ap->packed_transfers_supported && nbytes >= 4 && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { - this_size = 4; + this_size = 4; /* Packed read of 4 bytes or 2 halfwords */ } switch (this_size) { @@ -764,7 +887,7 @@ int dap_dp_init_or_reconnect(struct adiv5_dap *dap) int mem_ap_init(struct adiv5_ap *ap) { /* check that we support packed transfers */ - uint32_t csw, cfg; + uint32_t cfg; int retval; struct adiv5_dap *dap = ap->dap; @@ -781,30 +904,23 @@ int mem_ap_init(struct adiv5_ap *ap) ap->cfg_reg = cfg; ap->tar_valid = false; ap->csw_value = 0; /* force csw and tar write */ - retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0); - if (retval != ERROR_OK) - return retval; - retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(dap), &csw); - if (retval != ERROR_OK) - return retval; + /* CSW 32-bit size must be supported (IHI 0031F and 0074D). */ + ap->csw_size_supported_mask = BIT(CSW_32BIT); + ap->csw_size_probed_mask = BIT(CSW_32BIT); - retval = dap_run(dap); - if (retval != ERROR_OK) - return retval; + /* Suppress probing sizes longer than 32 bit if AP has no large data extension */ + if (!(cfg & MEM_AP_REG_CFG_LD)) + ap->csw_size_probed_mask |= BIT(CSW_64BIT) | BIT(CSW_128BIT) | BIT(CSW_256BIT); - if (csw & CSW_ADDRINC_PACKED) - ap->packed_transfers = true; - else - ap->packed_transfers = false; - - /* Packed transfers on TI BE-32 processors do not work correctly in + /* Both IHI 0031F and 0074D state: Implementations that support transfers + * smaller than a word must support packed transfers. Unfortunately at least + * Cortex-M0 and Cortex-M0+ do not comply with this rule. + * Probe for packed transfers except we know they are broken. + * Packed transfers on TI BE-32 processors do not work correctly in * many cases. */ - if (dap->ti_be_32_quirks) - ap->packed_transfers = false; - - LOG_DEBUG("MEM_AP Packed Transfers: %s", - ap->packed_transfers ? "enabled" : "disabled"); + ap->packed_transfers_supported = false; + ap->packed_transfers_probed = dap->ti_be_32_quirks ? true : false; /* The ARM ADI spec leaves implementation-defined whether unaligned * memory accesses work, only work partially, or cause a sticky error. diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index fc7fdafd84..60c161f3ca 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -165,6 +165,9 @@ #define CSW_8BIT 0 #define CSW_16BIT 1 #define CSW_32BIT 2 +#define CSW_64BIT 3 +#define CSW_128BIT 4 +#define CSW_256BIT 5 #define CSW_ADDRINC_MASK (3UL << 4) #define CSW_ADDRINC_OFF 0UL #define CSW_ADDRINC_SINGLE (1UL << 4) @@ -269,6 +272,26 @@ struct adiv5_ap { */ uint32_t csw_value; + /** + * Save the supported CSW.Size data types for the MEM-AP. + * Each bit corresponds to a data type. + * 0b1 = Supported data size. 0b0 = Not supported. + * Bit 0 = Byte (8-bits) + * Bit 1 = Halfword (16-bits) + * Bit 2 = Word (32-bits) - always supported by spec. + * Bit 3 = Doubleword (64-bits) + * Bit 4 = 128-bits + * Bit 5 = 256-bits + */ + uint32_t csw_size_supported_mask; + /** + * Probed CSW.Size data types for the MEM-AP. + * Each bit corresponds to a data type. + * 0b1 = Data size has been probed. 0b0 = Not yet probed. + * Bits assigned to sizes same way as above. + */ + uint32_t csw_size_probed_mask; + /** * Cache for (MEM-AP) AP_REG_TAR register value This is written to * configure the address being read or written @@ -286,7 +309,8 @@ struct adiv5_ap { uint32_t tar_autoincr_block; /* true if packed transfers are supported by the MEM-AP */ - bool packed_transfers; + bool packed_transfers_supported; + bool packed_transfers_probed; /* true if unaligned memory access is not supported by the MEM-AP */ bool unaligned_access_bad; diff --git a/src/target/target.h b/src/target/target.h index 6caf598874..f69ee77ac4 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -796,6 +796,8 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t #define ERROR_TARGET_NOT_EXAMINED (-311) #define ERROR_TARGET_DUPLICATE_BREAKPOINT (-312) #define ERROR_TARGET_ALGO_EXIT (-313) +#define ERROR_TARGET_SIZE_NOT_SUPPORTED (-314) +#define ERROR_TARGET_PACKING_NOT_SUPPORTED (-315) extern bool get_target_reset_nag(void); From 15f74c2595fe20235b27ce079a35e066d6b6611c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 20 Dec 2023 13:20:27 +0100 Subject: [PATCH 0697/1312] drivers/libusb_helper: introduce oocd_libusb_dev_mem_alloc() helper On some systems (at least Windows/CYGWIN and macOS) libusb_dev_mem_alloc() simply returns NULL. Use the result of the very first libusb_dev_mem_alloc() call to decide if the underlining system supports dev mem allocation or we should fall-back to plain heap malloc(). From the decision time on, keep using the selected type of memory allocator and deallocator. Signed-off-by: Tomas Vanek Change-Id: Ia1f0965cea44b4bb6d936b02ec43f5a16a46f080 Reviewed-on: https://review.openocd.org/c/openocd/+/8059 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/libusb_helper.c | 56 ++++++++++++++++++++++++++++++++ src/jtag/drivers/libusb_helper.h | 23 +++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 9d788ee394..57ea8cd3fa 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -377,3 +377,59 @@ int jtag_libusb_handle_events_completed(int *completed) { return libusb_handle_events_completed(jtag_libusb_context, completed); } + +static enum { + DEV_MEM_NOT_YET_DECIDED, + DEV_MEM_AVAILABLE, + DEV_MEM_FALLBACK_MALLOC +} dev_mem_allocation; + +/* Older libusb does not implement following API calls - define stubs instead */ +#if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000105) +static uint8_t *libusb_dev_mem_alloc(libusb_device_handle *devh, size_t length) +{ + return NULL; +} + +static int libusb_dev_mem_free(libusb_device_handle *devh, + uint8_t *buffer, size_t length) +{ + return LIBUSB_ERROR_NOT_SUPPORTED; +} +#endif + +uint8_t *oocd_libusb_dev_mem_alloc(libusb_device_handle *devh, + size_t length) +{ + uint8_t *buffer = NULL; + if (dev_mem_allocation != DEV_MEM_FALLBACK_MALLOC) + buffer = libusb_dev_mem_alloc(devh, length); + + if (dev_mem_allocation == DEV_MEM_NOT_YET_DECIDED) + dev_mem_allocation = buffer ? DEV_MEM_AVAILABLE : DEV_MEM_FALLBACK_MALLOC; + + if (dev_mem_allocation == DEV_MEM_FALLBACK_MALLOC) + buffer = malloc(length); + + return buffer; +} + +int oocd_libusb_dev_mem_free(libusb_device_handle *devh, + uint8_t *buffer, size_t length) +{ + if (!buffer) + return ERROR_OK; + + switch (dev_mem_allocation) { + case DEV_MEM_AVAILABLE: + return jtag_libusb_error(libusb_dev_mem_free(devh, buffer, length)); + + case DEV_MEM_FALLBACK_MALLOC: + free(buffer); + return ERROR_OK; + + case DEV_MEM_NOT_YET_DECIDED: + return ERROR_FAIL; + } + return ERROR_FAIL; +} diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h index 09309b40c2..3cd83c6b38 100644 --- a/src/jtag/drivers/libusb_helper.h +++ b/src/jtag/drivers/libusb_helper.h @@ -67,4 +67,27 @@ int jtag_libusb_choose_interface(struct libusb_device_handle *devh, int jtag_libusb_get_pid(struct libusb_device *dev, uint16_t *pid); int jtag_libusb_handle_events_completed(int *completed); +/** + * Attempts to allocate a block of persistent DMA memory suitable for transfers + * against the USB device. Fall-back to the ordinary heap malloc() + * if the first libusb_dev_mem_alloc() call fails. + * @param devh _libusb_ device handle. + * @param length size of desired data buffer + * @returns a pointer to the newly allocated memory, or NULL on failure + */ +uint8_t *oocd_libusb_dev_mem_alloc(libusb_device_handle *devh, + size_t length); + +/** + * Free device memory allocated with oocd_libusb_dev_mem_alloc(). + * Uses either libusb_dev_mem_free() or free() consistently with + * the used method of allocation. + * @param devh _libusb_ device handle. + * @param buffer pointer to the previously allocated memory + * @param length size of desired data buffer + * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. + */ +int oocd_libusb_dev_mem_free(libusb_device_handle *devh, + uint8_t *buffer, size_t length); + #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H */ From 44e02e1f49cc09703cb3b4088d0c1c4f9e2d9c87 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 10 Dec 2023 11:58:43 +0100 Subject: [PATCH 0698/1312] jtag/drivers/cmsis_dap: use oocd_libusb_dev_mem_alloc() helper On some systems (at least Windows/CYGWIN and macOS) libusb_dev_mem_alloc() simply returns NULL. The helper can fall-back to malloc() to allocate CMSIS-DAP pending command/response buffers. Fixes: fd75e9e54270 (jtag/drivers/cmsis_dap_bulk: use asynchronous libusb transfer) Signed-off-by: Tomas Vanek Change-Id: I89660f6747ad9d494b8192711cbbee5764e058fa Reviewed-on: https://review.openocd.org/c/openocd/+/8044 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/cmsis_dap_usb_bulk.c | 41 ++++++++++++--------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 17e490f05a..92a972a04f 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -33,12 +33,6 @@ #include "cmsis_dap.h" #include "libusb_helper.h" -#if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000105) \ - || defined(_WIN32) || defined(__CYGWIN__) - #define libusb_dev_mem_alloc(dev, sz) malloc(sz) - #define libusb_dev_mem_free(dev, buffer, sz) free(buffer) -#endif - enum { CMSIS_DAP_TRANSFER_PENDING = 0, /* must be 0, used in libusb_handle_events_completed */ CMSIS_DAP_TRANSFER_IDLE, @@ -599,33 +593,34 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz) dap->command = dap->packet_buffer; dap->response = dap->packet_buffer; + struct cmsis_dap_backend_data *bdata = dap->bdata; for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - dap->bdata->command_transfers[i].buffer = - libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz); - if (!dap->bdata->command_transfers[i].buffer) { - LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); - return ERROR_FAIL; - } - dap->bdata->response_transfers[i].buffer = - libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz); - if (!dap->bdata->response_transfers[i].buffer) { - LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); + bdata->command_transfers[i].buffer = + oocd_libusb_dev_mem_alloc(bdata->dev_handle, pkt_sz); + + bdata->response_transfers[i].buffer = + oocd_libusb_dev_mem_alloc(bdata->dev_handle, pkt_sz); + + if (!bdata->command_transfers[i].buffer + || !bdata->response_transfers[i].buffer) { + LOG_ERROR("unable to allocate CMSIS-DAP pending packet buffer"); return ERROR_FAIL; } } - return ERROR_OK; } static void cmsis_dap_usb_free(struct cmsis_dap *dap) { + struct cmsis_dap_backend_data *bdata = dap->bdata; + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - libusb_dev_mem_free(dap->bdata->dev_handle, - dap->bdata->command_transfers[i].buffer, dap->packet_size); - dap->bdata->command_transfers[i].buffer = NULL; - libusb_dev_mem_free(dap->bdata->dev_handle, - dap->bdata->response_transfers[i].buffer, dap->packet_size); - dap->bdata->response_transfers[i].buffer = NULL; + oocd_libusb_dev_mem_free(bdata->dev_handle, + bdata->command_transfers[i].buffer, dap->packet_size); + oocd_libusb_dev_mem_free(bdata->dev_handle, + bdata->response_transfers[i].buffer, dap->packet_size); + bdata->command_transfers[i].buffer = NULL; + bdata->response_transfers[i].buffer = NULL; } free(dap->packet_buffer); From d2b2ac28d9a240a534a8e8bbe2fb0e791f003807 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sun, 12 Mar 2023 01:43:32 +0100 Subject: [PATCH 0699/1312] ipdbg: improve ipdbg-host speed By queuing multiple jtag transfers the connection speed between JTAG-Host and JTAG-Hub is improved. This is due to much less calls to OS functions. An improvement of about x30 has been measured with ftdi-based jtag adapters For this to work the JTAG-Host server needs to know if flow control is enabled on the JTAG-Hub ports. This is possible with newer JTAG-Hub/JtagCDC. For old JTAG-Hubs the queuing is not enabled so this change is backwards compatible. Change-Id: I8a5108adbe2a2c1e3d3620b5c9ff77a546bfc14e Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7978 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/ipdbg.c | 276 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 209 insertions(+), 67 deletions(-) diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index c1bdb29395..0733230322 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -20,6 +20,17 @@ #define IPDBG_MIN_DR_LENGTH 11 #define IPDBG_MAX_DR_LENGTH 13 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6 +#define IPDBG_SCRATCH_MEMORY_SIZE 1024 +#define IPDBG_EMPTY_DOWN_TRANSFERS 1024 +#define IPDBG_CONSECUTIVE_UP_TRANSFERS 1024 + +#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_EMPTY_DOWN_TRANSFERS +#error "scratch Memory must be at least IPDBG_EMPTY_DOWN_TRANSFERS" +#endif + +#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_CONSECUTIVE_UP_TRANSFERS +#error "scratch Memory must be at least IPDBG_CONSECUTIVE_UP_TRANSFERS" +#endif /* private connection data for IPDBG */ struct ipdbg_fifo { @@ -48,6 +59,13 @@ struct ipdbg_virtual_ir_info { uint32_t value; }; +struct ipdbg_hub_scratch_memory { + uint8_t *dr_out_vals; + uint8_t *dr_in_vals; + uint8_t *vir_out_val; + struct scan_field *fields; +}; + struct ipdbg_hub { uint32_t user_instruction; uint32_t max_tools; @@ -62,7 +80,9 @@ struct ipdbg_hub { struct connection **connections; uint8_t data_register_length; uint8_t dn_xoff; + uint8_t flow_control_enabled; struct ipdbg_virtual_ir_info *virtual_ir; + struct ipdbg_hub_scratch_memory scratch_memory; }; static struct ipdbg_hub *ipdbg_first_hub; @@ -236,20 +256,28 @@ static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uin { *hub = NULL; struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub)); - if (!new_hub) { - free(virtual_ir); - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } + if (!new_hub) + goto mem_err_hub; + const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8); new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length); + + new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size); + new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size); + new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field)); new_hub->connections = calloc(new_hub->max_tools, sizeof(struct connection *)); - if (!new_hub->connections) { - free(virtual_ir); - free(new_hub); - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } + + if (virtual_ir) + new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8)); + + if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals || + !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) || + !new_hub->connections) + goto mem_err2; + + if (virtual_ir) + buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value); + new_hub->tap = tap; new_hub->user_instruction = user_instruction; new_hub->data_register_length = data_register_length; @@ -260,8 +288,19 @@ static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uin new_hub->virtual_ir = virtual_ir; *hub = new_hub; - return ERROR_OK; + +mem_err2: + free(new_hub->scratch_memory.vir_out_val); + free(new_hub->connections); + free(new_hub->scratch_memory.fields); + free(new_hub->scratch_memory.dr_in_vals); + free(new_hub->scratch_memory.dr_out_vals); + free(new_hub); +mem_err_hub: + free(virtual_ir); + LOG_ERROR("Out of memory"); + return ERROR_FAIL; } static void ipdbg_free_hub(struct ipdbg_hub *hub) @@ -270,6 +309,10 @@ static void ipdbg_free_hub(struct ipdbg_hub *hub) return; free(hub->connections); free(hub->virtual_ir); + free(hub->scratch_memory.dr_out_vals); + free(hub->scratch_memory.dr_in_vals); + free(hub->scratch_memory.fields); + free(hub->scratch_memory.vir_out_val); free(hub); } @@ -348,20 +391,11 @@ static int ipdbg_shift_vir(struct ipdbg_hub *hub) if (!tap) return ERROR_FAIL; - uint8_t *dr_out_val = calloc(DIV_ROUND_UP(hub->virtual_ir->length, 8), 1); - if (!dr_out_val) { - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } - buf_set_u32(dr_out_val, 0, hub->virtual_ir->length, hub->virtual_ir->value); - - struct scan_field fields; - ipdbg_init_scan_field(&fields, NULL, hub->virtual_ir->length, dr_out_val); - jtag_add_dr_scan(tap, 1, &fields, TAP_IDLE); + ipdbg_init_scan_field(hub->scratch_memory.fields, NULL, + hub->virtual_ir->length, hub->scratch_memory.vir_out_val); + jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields, TAP_IDLE); retval = jtag_execute_queue(); - free(dr_out_val); - return retval; } @@ -374,33 +408,15 @@ static int ipdbg_shift_data(struct ipdbg_hub *hub, uint32_t dn_data, uint32_t *u if (!tap) return ERROR_FAIL; - uint8_t *dr_out_val = calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1); - if (!dr_out_val) { - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } - buf_set_u32(dr_out_val, 0, hub->data_register_length, dn_data); - - uint8_t *dr_in_val = NULL; - if (up_data) { - dr_in_val = calloc(DIV_ROUND_UP(hub->data_register_length, 8), 1); - if (!dr_in_val) { - LOG_ERROR("Out of memory"); - free(dr_out_val); - return ERROR_FAIL; - } - } + buf_set_u32(hub->scratch_memory.dr_out_vals, 0, hub->data_register_length, dn_data); - struct scan_field fields; - ipdbg_init_scan_field(&fields, dr_in_val, hub->data_register_length, dr_out_val); - jtag_add_dr_scan(tap, 1, &fields, TAP_IDLE); + ipdbg_init_scan_field(hub->scratch_memory.fields, hub->scratch_memory.dr_in_vals, + hub->data_register_length, hub->scratch_memory.dr_out_vals); + jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields, TAP_IDLE); int retval = jtag_execute_queue(); if (up_data && retval == ERROR_OK) - *up_data = buf_get_u32(dr_in_val, 0, hub->data_register_length); - - free(dr_out_val); - free(dr_in_val); + *up_data = buf_get_u32(hub->scratch_memory.dr_in_vals, 0, hub->data_register_length); return retval; } @@ -432,6 +448,60 @@ static int ipdbg_distribute_data_from_hub(struct ipdbg_hub *hub, uint32_t up) return ERROR_OK; } +static void ipdbg_check_for_xoff(struct ipdbg_hub *hub, size_t tool, + uint32_t rx_data) +{ + if ((rx_data & hub->xoff_mask) && hub->last_dn_tool != hub->max_tools) { + hub->dn_xoff |= BIT(hub->last_dn_tool); + LOG_INFO("tool %d sent xoff", hub->last_dn_tool); + } + + hub->last_dn_tool = tool; +} + +static int ipdbg_shift_empty_data(struct ipdbg_hub *hub) +{ + if (!hub) + return ERROR_FAIL; + + struct jtag_tap *tap = hub->tap; + if (!tap) + return ERROR_FAIL; + + const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8); + memset(hub->scratch_memory.dr_out_vals, 0, dreg_buffer_size); + for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) { + ipdbg_init_scan_field(hub->scratch_memory.fields + i, + hub->scratch_memory.dr_in_vals + i * dreg_buffer_size, + hub->data_register_length, + hub->scratch_memory.dr_out_vals); + jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields + i, TAP_IDLE); + } + + int retval = jtag_execute_queue(); + + if (retval == ERROR_OK) { + uint32_t up_data; + for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) { + up_data = buf_get_u32(hub->scratch_memory.dr_in_vals + + i * dreg_buffer_size, 0, + hub->data_register_length); + int rv = ipdbg_distribute_data_from_hub(hub, up_data); + if (rv != ERROR_OK) + retval = rv; + + if (i == 0) { + /* check if xoff sent is only needed on the first transfer which + may contain the xoff of the prev down transfer. + */ + ipdbg_check_for_xoff(hub, hub->max_tools, up_data); + } + } + } + + return retval; +} + static int ipdbg_jtag_transfer_byte(struct ipdbg_hub *hub, size_t tool, struct ipdbg_connection *connection) { uint32_t dn = hub->valid_mask | ((tool & hub->tool_mask) << 8) | @@ -445,14 +515,63 @@ static int ipdbg_jtag_transfer_byte(struct ipdbg_hub *hub, size_t tool, struct i if (ret != ERROR_OK) return ret; - if ((up & hub->xoff_mask) && (hub->last_dn_tool != hub->max_tools)) { - hub->dn_xoff |= BIT(hub->last_dn_tool); - LOG_INFO("tool %d sent xoff", hub->last_dn_tool); + ipdbg_check_for_xoff(hub, tool, up); + + return ERROR_OK; +} + +static int ipdbg_jtag_transfer_bytes(struct ipdbg_hub *hub, + size_t tool, struct ipdbg_connection *connection) +{ + if (!hub) + return ERROR_FAIL; + + struct jtag_tap *tap = hub->tap; + if (!tap) + return ERROR_FAIL; + + const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8); + size_t num_tx = (connection->dn_fifo.count < IPDBG_CONSECUTIVE_UP_TRANSFERS) ? + connection->dn_fifo.count : IPDBG_CONSECUTIVE_UP_TRANSFERS; + + for (size_t i = 0; i < num_tx; ++i) { + uint32_t dn_data = hub->valid_mask | ((tool & hub->tool_mask) << 8) | + (0x00fful & ipdbg_get_from_fifo(&connection->dn_fifo)); + buf_set_u32(hub->scratch_memory.dr_out_vals + i * dreg_buffer_size, 0, + hub->data_register_length, dn_data); + + ipdbg_init_scan_field(hub->scratch_memory.fields + i, + hub->scratch_memory.dr_in_vals + + i * dreg_buffer_size, + hub->data_register_length, + hub->scratch_memory.dr_out_vals + + i * dreg_buffer_size); + jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields + i, TAP_IDLE); } - hub->last_dn_tool = tool; + int retval = jtag_execute_queue(); - return ERROR_OK; + if (retval == ERROR_OK) { + uint32_t up_data; + for (size_t i = 0; i < num_tx; ++i) { + up_data = buf_get_u32(hub->scratch_memory.dr_in_vals + + i * dreg_buffer_size, + 0, hub->data_register_length); + int rv = ipdbg_distribute_data_from_hub(hub, up_data); + if (rv != ERROR_OK) + retval = rv; + if (i == 0) { + /* check if xoff sent is only needed on the first transfer which + may contain the xoff of the prev down transfer. + No checks for this channel because this function is only + called for channels without enabled flow control. + */ + ipdbg_check_for_xoff(hub, tool, up_data); + } + } + } + + return retval; } static int ipdbg_polling_callback(void *priv) @@ -468,33 +587,25 @@ static int ipdbg_polling_callback(void *priv) return ret; /* transfer dn buffers to jtag-hub */ - unsigned int num_transfers = 0; for (size_t tool = 0; tool < hub->max_tools; ++tool) { struct connection *conn = hub->connections[tool]; if (conn && conn->priv) { struct ipdbg_connection *connection = conn->priv; while (((hub->dn_xoff & BIT(tool)) == 0) && !ipdbg_fifo_is_empty(&connection->dn_fifo)) { - ret = ipdbg_jtag_transfer_byte(hub, tool, connection); + if (hub->flow_control_enabled & BIT(tool)) + ret = ipdbg_jtag_transfer_byte(hub, tool, connection); + else + ret = ipdbg_jtag_transfer_bytes(hub, tool, connection); if (ret != ERROR_OK) return ret; - ++num_transfers; } } } /* some transfers to get data from jtag-hub in case there is no dn data */ - while (num_transfers++ < hub->max_tools) { - uint32_t dn = 0; - uint32_t up = 0; - - int retval = ipdbg_shift_data(hub, dn, &up); - if (retval != ERROR_OK) - return ret; - - retval = ipdbg_distribute_data_from_hub(hub, up); - if (retval != ERROR_OK) - return ret; - } + ret = ipdbg_shift_empty_data(hub); + if (ret != ERROR_OK) + return ret; /* write from up fifos to sockets */ for (size_t tool = 0; tool < hub->max_tools; ++tool) { @@ -510,6 +621,33 @@ static int ipdbg_polling_callback(void *priv) return ERROR_OK; } +static int ipdbg_get_flow_control_info_from_hub(struct ipdbg_hub *hub) +{ + uint32_t up_data; + + /* on older implementations the flow_control_enable_word is not sent to us. + so we don't know -> assume it's enabled on all channels */ + hub->flow_control_enabled = 0x7f; + + int ret = ipdbg_shift_data(hub, 0UL, &up_data); + if (ret != ERROR_OK) + return ret; + + const bool valid_up_data = up_data & hub->valid_mask; + if (valid_up_data) { + const size_t tool = (up_data >> 8) & hub->tool_mask; + /* the first valid data from hub is flow_control_enable_word */ + if (tool == hub->tool_mask) + hub->flow_control_enabled = up_data & 0x007f; + else + ipdbg_distribute_data_from_hub(hub, up_data); + } + + LOG_INFO("Flow control enabled on IPDBG JTAG Hub: 0x%02x", hub->flow_control_enabled); + + return ERROR_OK; +} + static int ipdbg_start_polling(struct ipdbg_service *service, struct connection *connection) { struct ipdbg_hub *hub = service->hub; @@ -536,6 +674,10 @@ static int ipdbg_start_polling(struct ipdbg_service *service, struct connection if (ret != ERROR_OK) return ret; + ret = ipdbg_get_flow_control_info_from_hub(hub); + if (ret != ERROR_OK) + return ret; + LOG_INFO("IPDBG start_polling"); const int time_ms = 20; From 22ebb693b62fd05bcbe2c0101e180b92ca5b11f3 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 28 Apr 2022 03:46:35 +0100 Subject: [PATCH 0700/1312] cortex_m: add detection of MVE feature for Armv8.1-M cores For Armv8.1-M based cores, detect if the core implements the optional M-profile vector extension (MVE), using MVFR1 register. While at there rework armv7m->fp_feature detection based on MVFR0 and MVFR1 registers. Change-Id: I92d5b1759aea9f7561d285f46acdec51d6efb7b4 Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6950 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv7m.h | 2 ++ src/target/cortex_m.c | 51 +++++++++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 8693404d27..2878dd1c76 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -211,6 +211,8 @@ enum { FPV4_SP, FPV5_SP, FPV5_DP, + FPV5_MVE_I, + FPV5_MVE_F, }; #define ARMV7M_NUM_CORE_REGS (ARMV7M_CORE_LAST_REG - ARMV7M_CORE_FIRST_REG + 1) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index d9e8b538f9..6a29a5fd4c 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2486,16 +2486,17 @@ static bool cortex_m_has_tz(struct target *target) return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0; } -#define MVFR0 0xe000ef40 -#define MVFR1 0xe000ef44 -#define MVFR0_DEFAULT_M4 0x10110021 -#define MVFR1_DEFAULT_M4 0x11000011 +#define MVFR0 0xE000EF40 +#define MVFR0_SP_MASK 0x000000F0 +#define MVFR0_SP 0x00000020 +#define MVFR0_DP_MASK 0x00000F00 +#define MVFR0_DP 0x00000200 -#define MVFR0_DEFAULT_M7_SP 0x10110021 -#define MVFR0_DEFAULT_M7_DP 0x10110221 -#define MVFR1_DEFAULT_M7_SP 0x11000011 -#define MVFR1_DEFAULT_M7_DP 0x12000011 +#define MVFR1 0xE000EF44 +#define MVFR1_MVE_MASK 0x00000F00 +#define MVFR1_MVE_I 0x00000100 +#define MVFR1_MVE_F 0x00000200 static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp, struct adiv5_ap **debug_ap) @@ -2509,7 +2510,7 @@ static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp, int cortex_m_examine(struct target *target) { int retval; - uint32_t cpuid, fpcr, mvfr0, mvfr1; + uint32_t cpuid, fpcr; struct cortex_m_common *cortex_m = target_to_cm(target); struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap; struct armv7m_common *armv7m = target_to_armv7m(target); @@ -2584,25 +2585,37 @@ int cortex_m_examine(struct target *target) LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid); if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) { + uint32_t mvfr0; target_read_u32(target, MVFR0, &mvfr0); - target_read_u32(target, MVFR1, &mvfr1); - /* test for floating point feature on Cortex-M4 */ - if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { - LOG_TARGET_DEBUG(target, "%s floating point feature FPv4_SP found", cortex_m->core_info->name); + if ((mvfr0 & MVFR0_SP_MASK) == MVFR0_SP) { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv4_SP found", + cortex_m->core_info->name); armv7m->fp_feature = FPV4_SP; } } else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) { + uint32_t mvfr0, mvfr1; target_read_u32(target, MVFR0, &mvfr0); target_read_u32(target, MVFR1, &mvfr1); - /* test for floating point features on Cortex-M7 */ - if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { - LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_SP found", cortex_m->core_info->name); + if ((mvfr0 & MVFR0_DP_MASK) == MVFR0_DP) { + if ((mvfr1 & MVFR1_MVE_MASK) == MVFR1_MVE_F) { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP + MVE-F found", + cortex_m->core_info->name); + armv7m->fp_feature = FPV5_MVE_F; + } else { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP found", + cortex_m->core_info->name); + armv7m->fp_feature = FPV5_DP; + } + } else if ((mvfr0 & MVFR0_SP_MASK) == MVFR0_SP) { + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_SP found", + cortex_m->core_info->name); armv7m->fp_feature = FPV5_SP; - } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { - LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP found", cortex_m->core_info->name); - armv7m->fp_feature = FPV5_DP; + } else if ((mvfr1 & MVFR1_MVE_MASK) == MVFR1_MVE_I) { + LOG_TARGET_DEBUG(target, "%s floating point feature MVE-I found", + cortex_m->core_info->name); + armv7m->fp_feature = FPV5_MVE_I; } } From 04eda372634f995c732bed4f67855be258ab0e41 Mon Sep 17 00:00:00 2001 From: ianst Date: Wed, 6 Dec 2023 14:34:09 -0800 Subject: [PATCH 0701/1312] target/xtensa: extra debug info for "xtensa exe" failures - Read and display EXCCAUSE on exe error - Clean up error messages - Clarify "xtensa exe" documentation Signed-off-by: ianst Change-Id: I90ed39f6afb6543c0c873301501435384b4dccbe Reviewed-on: https://review.openocd.org/c/openocd/+/7982 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 9 +++++---- src/target/xtensa/xtensa.c | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 53730eafaf..e4d4dc5d68 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11600,13 +11600,14 @@ This feature is not well implemented and tested yet. @end deffn @deffn {Command} {xtensa exe} -Execute arbitrary instruction(s) provided as an ascii string. The string represents an integer -number of instruction bytes, thus its length must be even. +Execute one arbitrary instruction provided as an ascii string. The string represents an integer +number of instruction bytes, thus its length must be even. The instruction can be of any width +that is valid for the Xtensa core configuration. @end deffn @deffn {Command} {xtensa dm} (address) [value] -Read or write Xtensa Debug Module (DM) registers. @var{address} is required for both reads -and writes and is a 4-byte-aligned value typically between 0 and 0x3ffc. @var{value} is specified +Read or write Xtensa Debug Module (DM) registers. @var{address} is required for both reads +and writes and is a 4-byte-aligned value typically between 0 and 0x3ffc. @var{value} is specified only for write accesses. @end deffn diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index d2ca32c1d1..ab3bfbb097 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3483,15 +3483,21 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) LOG_TARGET_DEBUG(target, "execute stub: %s", CMD_ARGV[0]); xtensa_queue_exec_ins_wide(xtensa, ops, oplen); /* Handles endian-swap */ status = xtensa_dm_queue_execute(&xtensa->dbg_mod); - if (status != ERROR_OK) - LOG_TARGET_ERROR(target, "TIE queue execute: %d\n", status); - status = xtensa_core_status_check(target); - if (status != ERROR_OK) - LOG_TARGET_ERROR(target, "TIE instr execute: %d\n", status); + if (status != ERROR_OK) { + LOG_TARGET_ERROR(target, "exec: queue error %d", status); + } else { + status = xtensa_core_status_check(target); + if (status != ERROR_OK) + LOG_TARGET_ERROR(target, "exec: status error %d", status); + } /* Reread register cache and restore saved regs after instruction execution */ if (xtensa_fetch_all_regs(target) != ERROR_OK) - LOG_TARGET_ERROR(target, "%s: Failed to fetch register cache (post-exec).", target_name(target)); + LOG_TARGET_ERROR(target, "post-exec: register fetch error"); + if (status != ERROR_OK) { + LOG_TARGET_ERROR(target, "post-exec: EXCCAUSE 0x%02" PRIx32, + xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE)); + } xtensa_reg_set(target, XT_REG_IDX_EXCCAUSE, exccause); xtensa_reg_set(target, XT_REG_IDX_CPENABLE, cpenable); return status; From 2c10e3e2577604f5ec75b7f688f53fa2b3cbb0e7 Mon Sep 17 00:00:00 2001 From: Evgeniy Didin Date: Fri, 31 Jul 2020 00:13:12 +0300 Subject: [PATCH 0702/1312] target/arc: restore breakpoints in arc_resume() Presently, we rely on gdb to restore break/watchpoints upon resuming execution in arc_resume(). To match this behavior in absence of gdb (more specifically, when handle_breakpoints is true), this patch explicitly re-enables all breakpoints and watchpoints in arc_resume(). This has previously been committed to the Zephyr project's openocd repo (see https://github.com/zephyrproject-rtos/openocd/pull/31). Change-Id: I59e9c91270ef0b5fd19cfc570663dc67a6022dbd Signed-off-by: Evgeniy Didin Signed-off-by: Stephanos Ioannidis Signed-off-by: Artemiy Volkov Reviewed-on: https://review.openocd.org/c/openocd/+/7816 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- src/target/arc.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/target/arc.c b/src/target/arc.c index 0f7b11025d..f3449aada9 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -50,6 +50,8 @@ static int arc_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); +static int arc_enable_watchpoints(struct target *target); +static int arc_enable_breakpoints(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) @@ -1262,6 +1264,13 @@ static int arc_resume(struct target *target, int current, target_addr_t address, return ERROR_TARGET_NOT_HALTED; } + if (!debug_execution) { + /* (gdb) continue = execute until we hit break/watch-point */ + target_free_all_working_areas(target); + CHECK_RETVAL(arc_enable_breakpoints(target)); + CHECK_RETVAL(arc_enable_watchpoints(target)); + } + /* current = 1: continue on current PC, otherwise continue at
*/ if (!current) { target_buffer_set_u32(target, pc->value, address); @@ -1658,6 +1667,19 @@ static int arc_unset_breakpoint(struct target *target, return retval; } +static int arc_enable_breakpoints(struct target *target) +{ + struct breakpoint *breakpoint = target->breakpoints; + + /* set any pending breakpoints */ + while (breakpoint) { + if (!breakpoint->is_set) + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + breakpoint = breakpoint->next; + } + + return ERROR_OK; +} static int arc_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { @@ -1895,6 +1917,20 @@ static int arc_unset_watchpoint(struct target *target, return retval; } +static int arc_enable_watchpoints(struct target *target) +{ + struct watchpoint *watchpoint = target->watchpoints; + + /* set any pending watchpoints */ + while (watchpoint) { + if (!watchpoint->is_set) + CHECK_RETVAL(arc_set_watchpoint(target, watchpoint)); + watchpoint = watchpoint->next; + } + + return ERROR_OK; +} + static int arc_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { From 0de852f56130bfffa427bbc04bcea0370eecb0f3 Mon Sep 17 00:00:00 2001 From: Evgeniy Didin Date: Fri, 31 Jul 2020 00:13:12 +0300 Subject: [PATCH 0703/1312] target/arc: skip over breakpoints in arc_resume() When requested by the core code (handle_breakpoints = true), arc_resume() should be able to advance over a potential breakpoint set at the resume address instead of getting stuck in one place. This is achieved by removing the breakpoint, executing one instruction, resetting the breakpoint, then proceeding forward as normal. With this patch applied, openocd is now able to resume from a breakpoint halt when debugging ARCv2 targets via telnet. This has previously been committed to the Zephyr project's openocd repo (see https://github.com/zephyrproject-rtos/openocd/pull/31). Change-Id: I17dba0dcea311d394b303c587bc2dfaa99d67859 Signed-off-by: Evgeniy Didin Signed-off-by: Stephanos Ioannidis Signed-off-by: Artemiy Volkov Reviewed-on: https://review.openocd.org/c/openocd/+/7817 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/arc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/target/arc.c b/src/target/arc.c index f3449aada9..72e4d918de 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -52,6 +52,11 @@ static int arc_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); static int arc_enable_watchpoints(struct target *target); static int arc_enable_breakpoints(struct target *target); +static int arc_unset_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int arc_set_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int arc_single_step_core(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) @@ -750,6 +755,29 @@ static int arc_examine(struct target *target) return ERROR_OK; } +static int arc_exit_debug(struct target *target) +{ + uint32_t value; + struct arc_common *arc = target_to_arc(target); + + /* Do read-modify-write sequence, or DEBUG.UB will be reset unintentionally. */ + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, &value)); + value |= SET_CORE_FORCE_HALT; /* set the HALT bit */ + CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); + alive_sleep(1); + + target->state = TARGET_HALTED; + CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); + + if (debug_level >= LOG_LVL_DEBUG) { + LOG_DEBUG("core stopped (halted) debug-reg: 0x%08" PRIx32, value); + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); + LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + } + + return ERROR_OK; +} + static int arc_halt(struct target *target) { uint32_t value, irq_state; @@ -1251,7 +1279,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, uint32_t value; struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]; - LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints(not supported yet):%i," + LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," " debug_execution:%i", current, address, handle_breakpoints, debug_execution); /* We need to reset ARC cache variables so caches @@ -1296,6 +1324,19 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value)); } + /* the front-end may request us not to handle breakpoints here */ + if (handle_breakpoints) { + /* Single step past breakpoint at current address */ + struct breakpoint *breakpoint = breakpoint_find(target, resume_pc); + if (breakpoint) { + LOG_DEBUG("skipping past breakpoint at 0x%08" TARGET_PRIxADDR, + breakpoint->address); + CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); + CHECK_RETVAL(arc_single_step_core(target)); + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + } + } + /* Restore IRQ state if not in debug_execution*/ if (!debug_execution) CHECK_RETVAL(arc_enable_interrupts(target, arc->irq_state)); @@ -2027,6 +2068,22 @@ static int arc_config_step(struct target *target, int enable_step) return ERROR_OK; } +static int arc_single_step_core(struct target *target) +{ + CHECK_RETVAL(arc_debug_entry(target)); + + /* disable interrupts while stepping */ + CHECK_RETVAL(arc_enable_interrupts(target, 0)); + + /* configure single step mode */ + CHECK_RETVAL(arc_config_step(target, 1)); + + /* exit debug mode */ + CHECK_RETVAL(arc_exit_debug(target)); + + return ERROR_OK; +} + static int arc_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { From 305f293201a1d75f24eaa188294b78b284c8185b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 4 Jan 2024 22:26:38 +0100 Subject: [PATCH 0704/1312] LICENSES: drop SPDX tag 'GPL-2.0' and use 'GPL-2.0-only' The SPDX tag 'GPL-2.0' has been deprecated in https://spdx.org/licenses/GPL-2.0.html and the preferred tag is now 'GPL-2.0-only' https://spdx.org/licenses/GPL-2.0-only.html Update the LICENSES documents and the SPDX of the only file that reports the deprecated tag. Change-Id: I3c3215438bc4378ff470bb9fa8fa962505a9ae50 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8064 Tested-by: jenkins --- LICENSES/license-rules.txt | 3 --- LICENSES/preferred/GPL-2.0 | 3 --- src/target/mips_cpu.h | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/LICENSES/license-rules.txt b/LICENSES/license-rules.txt index c75192930d..ecc8e4db16 100644 --- a/LICENSES/license-rules.txt +++ b/LICENSES/license-rules.txt @@ -173,7 +173,6 @@ OpenOCD, can be broken down into: File format examples:: - Valid-License-Identifier: GPL-2.0 Valid-License-Identifier: GPL-2.0-only Valid-License-Identifier: GPL-2.0-or-later SPDX-URL: https://spdx.org/licenses/GPL-2.0.html @@ -182,8 +181,6 @@ OpenOCD, can be broken down into: tag/value pairs into a comment according to the placement guidelines in the licensing rules documentation. For 'GNU General Public License (GPL) version 2 only' use: - SPDX-License-Identifier: GPL-2.0 - or SPDX-License-Identifier: GPL-2.0-only For 'GNU General Public License (GPL) version 2 or any later version' use: SPDX-License-Identifier: GPL-2.0-or-later diff --git a/LICENSES/preferred/GPL-2.0 b/LICENSES/preferred/GPL-2.0 index 2ca4651c35..687bdddb11 100644 --- a/LICENSES/preferred/GPL-2.0 +++ b/LICENSES/preferred/GPL-2.0 @@ -1,4 +1,3 @@ -Valid-License-Identifier: GPL-2.0 Valid-License-Identifier: GPL-2.0-only Valid-License-Identifier: GPL-2.0-or-later SPDX-URL: https://spdx.org/licenses/GPL-2.0.html @@ -7,8 +6,6 @@ Usage-Guide: tag/value pairs into a comment according to the placement guidelines in the licensing rules documentation. For 'GNU General Public License (GPL) version 2 only' use: - SPDX-License-Identifier: GPL-2.0 - or SPDX-License-Identifier: GPL-2.0-only For 'GNU General Public License (GPL) version 2 or any later version' use: SPDX-License-Identifier: GPL-2.0-or-later diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h index 2f31dbd664..c3b7b54ba7 100644 --- a/src/target/mips_cpu.h +++ b/src/target/mips_cpu.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef OPENOCD_TARGET_MIPS_CPU_H #define OPENOCD_TARGET_MIPS_CPU_H From 6e6d486de2c668e14f9534fab820eea305826753 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Dec 2023 18:10:45 +0100 Subject: [PATCH 0705/1312] target: drop deprecated code for mem2array and array2mem Commit e370e06b724f ("target: Deprecate 'array2mem' and 'mem2array''") has already replaced the deprecated root versions of commands mem2array and array2mem with TCL proc's that use 'read_memory' and 'write_memory'. It has left the deprecated code of the target's version of the commands because the effort to code the TCL replacement was not considered valuable. To drop the last jim_handler commands, I consider much easier and less error-prone to code them in TCL instead of converting the deprecated code to COMMAND_HANDLER. Drop the code in target.c and extend the TCL proc's. While there, add the TCL procs to _telnet_autocomplete_skip. Change-Id: I97d2370d8af479434ddf5af68541f90913982bc0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8052 Tested-by: jenkins --- src/target/startup.tcl | 57 +++--- src/target/target.c | 419 ----------------------------------------- 2 files changed, 35 insertions(+), 441 deletions(-) diff --git a/src/target/startup.tcl b/src/target/startup.tcl index 35492a6d91..75e0edc77d 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -219,31 +219,44 @@ proc init_target_events {} { proc init_board {} { } -proc mem2array {arrayname bitwidth address count {phys ""}} { - echo "DEPRECATED! use 'read_memory' not 'mem2array'" - - upvar $arrayname $arrayname - set $arrayname "" - set i 0 - - foreach elem [read_memory $address $bitwidth $count {*}$phys] { - set ${arrayname}($i) $elem - incr i - } -} - -proc array2mem {arrayname bitwidth address count {phys ""}} { - echo "DEPRECATED! use 'write_memory' not 'array2mem'" - - upvar $arrayname $arrayname - set data "" +lappend _telnet_autocomplete_skip _post_init_target_array_mem +proc _post_init_target_array_mem {} { + set targets [target names] + lappend targets "" - for {set i 0} {$i < $count} {incr i} { - lappend data [expr $${arrayname}($i)] + foreach t $targets { + if {$t != ""} { + set t "$t " + } + eval [format {lappend ::_telnet_autocomplete_skip "%smem2array"} $t] + eval [format {proc {%smem2array} {arrayname bitwidth address count {phys ""}} { + echo "DEPRECATED! use 'read_memory' not 'mem2array'" + + upvar $arrayname $arrayname + set $arrayname "" + set i 0 + + foreach elem [%sread_memory $address $bitwidth $count {*}$phys] { + set ${arrayname}($i) $elem + incr i + } + }} $t $t] + eval [format {lappend ::_telnet_autocomplete_skip "%sarray2mem"} $t] + eval [format {proc {%sarray2mem} {arrayname bitwidth address count {phys ""}} { + echo "DEPRECATED! use 'write_memory' not 'array2mem'" + + upvar $arrayname $arrayname + set data "" + + for {set i 0} {$i < $count} {incr i} { + lappend data [expr $${arrayname}($i)] + } + + %swrite_memory $address $bitwidth $data {*}$phys + }} $t $t] } - - write_memory $address $bitwidth $data {*}$phys } +lappend post_init_commands _post_init_target_array_mem # smp_on/smp_off were already DEPRECATED in v0.11.0 through http://openocd.zylin.com/4615 lappend _telnet_autocomplete_skip "aarch64 smp_on" diff --git a/src/target/target.c b/src/target/target.c index 61890aa3e5..920511e963 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -56,10 +56,6 @@ static int target_read_buffer_default(struct target *target, target_addr_t addre uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); -static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj * const *argv); -static int target_mem2array(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj * const *argv); static int target_register_user_commands(struct command_context *cmd_ctx); static int target_get_gdb_fileio_info_default(struct target *target, struct gdb_fileio_info *fileio_info); @@ -4397,192 +4393,6 @@ COMMAND_HANDLER(handle_profile_command) return retval; } -static int new_u64_array_element(Jim_Interp *interp, const char *varname, int idx, uint64_t val) -{ - char *namebuf; - Jim_Obj *obj_name, *obj_val; - int result; - - namebuf = alloc_printf("%s(%d)", varname, idx); - if (!namebuf) - return JIM_ERR; - - obj_name = Jim_NewStringObj(interp, namebuf, -1); - jim_wide wide_val = val; - obj_val = Jim_NewWideObj(interp, wide_val); - if (!obj_name || !obj_val) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(obj_name); - Jim_IncrRefCount(obj_val); - result = Jim_SetVariable(interp, obj_name, obj_val); - Jim_DecrRefCount(interp, obj_name); - Jim_DecrRefCount(interp, obj_val); - free(namebuf); - /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ - return result; -} - -static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) -{ - int e; - - LOG_WARNING("DEPRECATED! use 'read_memory' not 'mem2array'"); - - /* argv[0] = name of array to receive the data - * argv[1] = desired element width in bits - * argv[2] = memory address - * argv[3] = count of times to read - * argv[4] = optional "phys" - */ - if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); - return JIM_ERR; - } - - /* Arg 0: Name of the array variable */ - const char *varname = Jim_GetString(argv[0], NULL); - - /* Arg 1: Bit width of one element */ - long l; - e = Jim_GetLong(interp, argv[1], &l); - if (e != JIM_OK) - return e; - const unsigned int width_bits = l; - - if (width_bits != 8 && - width_bits != 16 && - width_bits != 32 && - width_bits != 64) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "Invalid width param. Must be one of: 8, 16, 32 or 64.", NULL); - return JIM_ERR; - } - const unsigned int width = width_bits / 8; - - /* Arg 2: Memory address */ - jim_wide wide_addr; - e = Jim_GetWide(interp, argv[2], &wide_addr); - if (e != JIM_OK) - return e; - target_addr_t addr = (target_addr_t)wide_addr; - - /* Arg 3: Number of elements to read */ - e = Jim_GetLong(interp, argv[3], &l); - if (e != JIM_OK) - return e; - size_t len = l; - - /* Arg 4: phys */ - bool is_phys = false; - if (argc > 4) { - int str_len = 0; - const char *phys = Jim_GetString(argv[4], &str_len); - if (!strncmp(phys, "phys", str_len)) - is_phys = true; - else - return JIM_ERR; - } - - /* Argument checks */ - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); - return JIM_ERR; - } - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "mem2array: too large read request, exceeds 64K items", NULL); - return JIM_ERR; - } - - if ((width == 1) || - ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0)) || - ((width == 8) && ((addr & 7) == 0))) { - /* alignment correct */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "mem2array address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* index counter */ - size_t idx = 0; - - const size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - if (!buffer) - return JIM_ERR; - - /* assume ok */ - e = JIM_OK; - while (len) { - /* Slurp... in buffer size chunks */ - const unsigned int max_chunk_len = buffersize / width; - const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - - int retval; - if (is_phys) - retval = target_read_phys_memory(target, addr, width, chunk_len, buffer); - else - retval = target_read_memory(target, addr, width, chunk_len, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("mem2array: Read @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", - addr, - width, - chunk_len); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); - e = JIM_ERR; - break; - } else { - for (size_t i = 0; i < chunk_len ; i++, idx++) { - uint64_t v = 0; - switch (width) { - case 8: - v = target_buffer_get_u64(target, &buffer[i*width]); - break; - case 4: - v = target_buffer_get_u32(target, &buffer[i*width]); - break; - case 2: - v = target_buffer_get_u16(target, &buffer[i*width]); - break; - case 1: - v = buffer[i] & 0x0ff; - break; - } - new_u64_array_element(interp, varname, idx, v); - } - len -= chunk_len; - addr += chunk_len * width; - } - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; -} - COMMAND_HANDLER(handle_target_read_memory) { /* @@ -4706,201 +4516,6 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_OK; } -static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val) -{ - char *namebuf = alloc_printf("%s(%zu)", varname, idx); - if (!namebuf) - return JIM_ERR; - - Jim_Obj *obj_name = Jim_NewStringObj(interp, namebuf, -1); - if (!obj_name) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(obj_name); - Jim_Obj *obj_val = Jim_GetVariable(interp, obj_name, JIM_ERRMSG); - Jim_DecrRefCount(interp, obj_name); - free(namebuf); - if (!obj_val) - return JIM_ERR; - - jim_wide wide_val; - int result = Jim_GetWide(interp, obj_val, &wide_val); - *val = wide_val; - return result; -} - -static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj *const *argv) -{ - int e; - - LOG_WARNING("DEPRECATED! use 'write_memory' not 'array2mem'"); - - /* argv[0] = name of array from which to read the data - * argv[1] = desired element width in bits - * argv[2] = memory address - * argv[3] = number of elements to write - * argv[4] = optional "phys" - */ - if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); - return JIM_ERR; - } - - /* Arg 0: Name of the array variable */ - const char *varname = Jim_GetString(argv[0], NULL); - - /* Arg 1: Bit width of one element */ - long l; - e = Jim_GetLong(interp, argv[1], &l); - if (e != JIM_OK) - return e; - const unsigned int width_bits = l; - - if (width_bits != 8 && - width_bits != 16 && - width_bits != 32 && - width_bits != 64) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "Invalid width param. Must be one of: 8, 16, 32 or 64.", NULL); - return JIM_ERR; - } - const unsigned int width = width_bits / 8; - - /* Arg 2: Memory address */ - jim_wide wide_addr; - e = Jim_GetWide(interp, argv[2], &wide_addr); - if (e != JIM_OK) - return e; - target_addr_t addr = (target_addr_t)wide_addr; - - /* Arg 3: Number of elements to write */ - e = Jim_GetLong(interp, argv[3], &l); - if (e != JIM_OK) - return e; - size_t len = l; - - /* Arg 4: Phys */ - bool is_phys = false; - if (argc > 4) { - int str_len = 0; - const char *phys = Jim_GetString(argv[4], &str_len); - if (!strncmp(phys, "phys", str_len)) - is_phys = true; - else - return JIM_ERR; - } - - /* Argument checks */ - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: zero width read?", NULL); - return JIM_ERR; - } - - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: too large memory write request, exceeds 64K items", NULL); - return JIM_ERR; - } - - if ((width == 1) || - ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0)) || - ((width == 8) && ((addr & 7) == 0))) { - /* alignment correct */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: " TARGET_ADDR_FMT " is not aligned for %" PRIu32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* assume ok */ - e = JIM_OK; - - const size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - if (!buffer) - return JIM_ERR; - - /* index counter */ - size_t idx = 0; - - while (len) { - /* Slurp... in buffer size chunks */ - const unsigned int max_chunk_len = buffersize / width; - - const size_t chunk_len = MIN(len, max_chunk_len); /* in elements.. */ - - /* Fill the buffer */ - for (size_t i = 0; i < chunk_len; i++, idx++) { - uint64_t v = 0; - if (get_u64_array_element(interp, varname, idx, &v) != JIM_OK) { - free(buffer); - return JIM_ERR; - } - switch (width) { - case 8: - target_buffer_set_u64(target, &buffer[i * width], v); - break; - case 4: - target_buffer_set_u32(target, &buffer[i * width], v); - break; - case 2: - target_buffer_set_u16(target, &buffer[i * width], v); - break; - case 1: - buffer[i] = v & 0x0ff; - break; - } - } - len -= chunk_len; - - /* Write the buffer to memory */ - int retval; - if (is_phys) - retval = target_write_phys_memory(target, addr, width, chunk_len, buffer); - else - retval = target_write_memory(target, addr, width, chunk_len, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("array2mem: Write @ " TARGET_ADDR_FMT ", w=%u, cnt=%zu, failed", - addr, - width, - chunk_len); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); - e = JIM_ERR; - break; - } - addr += chunk_len * width; - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; -} - static int target_jim_write_memory(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { @@ -5637,24 +5252,6 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a return target_configure(&goi, target); } -static int jim_target_mem2array(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); - return target_mem2array(interp, target, argc - 1, argv + 1); -} - -static int jim_target_array2mem(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); - return target_array2mem(interp, target, argc - 1, argv + 1); -} - COMMAND_HANDLER(handle_target_examine) { bool allow_defer = false; @@ -5976,22 +5573,6 @@ static const struct command_registration target_instance_command_handlers[] = { .help = "Display target memory as 8-bit bytes", .usage = "address [count]", }, - { - .name = "array2mem", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_array2mem, - .help = "Writes Tcl array of 8/16/32 bit numbers " - "to target memory", - .usage = "arrayname bitwidth address count", - }, - { - .name = "mem2array", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mem2array, - .help = "Loads Tcl array of 8/16/32 bit numbers " - "from target memory", - .usage = "arrayname bitwidth address count", - }, { .name = "get_reg", .mode = COMMAND_EXEC, From 5e1468da186e65029316a359493e2d2353e21512 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 10:40:03 +0200 Subject: [PATCH 0706/1312] helper/command: drop unused variables In both functions script_debug() and script_command_args_alloc() the variable len is never used, and Jim_GetString() does not mandate it. Drop the variable and pass NULL to Jim_GetString(). Change-Id: I754b27a59c6087cde729496be42609d2a7145b0c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8053 Tested-by: jenkins --- src/helper/command.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index ef50ab5bd0..96023336c9 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -145,8 +145,7 @@ static void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const char *dbg = alloc_printf("command -"); for (unsigned i = 0; i < argc; i++) { - int len; - const char *w = Jim_GetString(argv[i], &len); + const char *w = Jim_GetString(argv[i], NULL); char *t = alloc_printf("%s %s", dbg, w); free(dbg); dbg = t; @@ -171,8 +170,7 @@ static char **script_command_args_alloc( unsigned i; for (i = 0; i < argc; i++) { - int len; - const char *w = Jim_GetString(argv[i], &len); + const char *w = Jim_GetString(argv[i], NULL); words[i] = strdup(w); if (!words[i]) { script_command_args_free(words, i); From 712c1244e8486bb4519ad0144a03c3c48c030214 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 10:32:46 +0200 Subject: [PATCH 0707/1312] helper/command: simplify script_command_args_alloc() The output parameter nwords is always equal to the input parameter argc, when the function succeeds. Drop the parameter nwords and let the caller use directly the value in argc. While there, convert some 'unsigned' to 'unsigned int'. Change-Id: Ie3d8ce1351792f3c07fe39cdcbcd180fd24dc928 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8054 Tested-by: jenkins --- src/helper/command.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 96023336c9..f7ec0e21fa 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -161,15 +161,13 @@ static void script_command_args_free(char **words, unsigned nwords) free(words); } -static char **script_command_args_alloc( - unsigned argc, Jim_Obj * const *argv, unsigned *nwords) +static char **script_command_args_alloc(unsigned int argc, Jim_Obj * const *argv) { char **words = malloc(argc * sizeof(char *)); if (!words) return NULL; - unsigned i; - for (i = 0; i < argc; i++) { + for (unsigned int i = 0; i < argc; i++) { const char *w = Jim_GetString(argv[i], NULL); words[i] = strdup(w); if (!words[i]) { @@ -177,7 +175,6 @@ static char **script_command_args_alloc( return NULL; } } - *nwords = i; return words; } @@ -901,8 +898,8 @@ static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx, return c->jim_handler(interp, argc, argv); /* use c->handler */ - unsigned int nwords; - char **words = script_command_args_alloc(argc, argv, &nwords); + unsigned int nwords = argc; + char **words = script_command_args_alloc(argc, argv); if (!words) return JIM_ERR; From f9ea9ce24cf4423111a7fa033f8ceff61d17aa5b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 11:34:28 +0200 Subject: [PATCH 0708/1312] helper/command: simplify exec_command() The jimtcl interpreter guarantees that the Jim objects in argv[] are not deallocated during the command execution. Thus, there is no need to copy the string content of argv[]. Simplify exec_command() by inlining its two sub-functions and dropping the strdup(). While there, add a LOG_ERROR() for out of memory. Change-Id: I3e21ed7da50ca0bd072edbd49fca9740c81f95b0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8055 Tested-by: jenkins --- src/helper/command.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index f7ec0e21fa..8860cf81fd 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -154,30 +154,6 @@ static void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const free(dbg); } -static void script_command_args_free(char **words, unsigned nwords) -{ - for (unsigned i = 0; i < nwords; i++) - free(words[i]); - free(words); -} - -static char **script_command_args_alloc(unsigned int argc, Jim_Obj * const *argv) -{ - char **words = malloc(argc * sizeof(char *)); - if (!words) - return NULL; - - for (unsigned int i = 0; i < argc; i++) { - const char *w = Jim_GetString(argv[i], NULL); - words[i] = strdup(w); - if (!words[i]) { - script_command_args_free(words, i); - return NULL; - } - } - return words; -} - struct command_context *current_command_context(Jim_Interp *interp) { /* grab the command context from the associated data */ @@ -898,13 +874,17 @@ static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx, return c->jim_handler(interp, argc, argv); /* use c->handler */ - unsigned int nwords = argc; - char **words = script_command_args_alloc(argc, argv); - if (!words) + const char **words = malloc(argc * sizeof(char *)); + if (!words) { + LOG_ERROR("Out of memory"); return JIM_ERR; + } - int retval = run_command(cmd_ctx, c, (const char **)words, nwords); - script_command_args_free(words, nwords); + for (int i = 0; i < argc; i++) + words[i] = Jim_GetString(argv[i], NULL); + + int retval = run_command(cmd_ctx, c, words, argc); + free(words); return command_retval_set(interp, retval); } From f857db98bd2a3d97ada208a8137c48c47e9d3a78 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 12:26:25 +0200 Subject: [PATCH 0709/1312] helper/command: inline run_command() in exec_command() Simplify the command execution by inlining run_command() inside exec_command(). Change-Id: Id932b006846720cfd867d22d142cd35831dbd1a2 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8056 Tested-by: jenkins --- src/helper/command.c | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 8860cf81fd..57db2adc15 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -489,14 +489,27 @@ static bool command_can_run(struct command_context *cmd_ctx, struct command *c, return false; } -static int run_command(struct command_context *context, - struct command *c, const char **words, unsigned num_words) +static int exec_command(Jim_Interp *interp, struct command_context *context, + struct command *c, int argc, Jim_Obj * const *argv) { + if (c->jim_handler) + return c->jim_handler(interp, argc, argv); + + /* use c->handler */ + const char **words = malloc(argc * sizeof(char *)); + if (!words) { + LOG_ERROR("Out of memory"); + return JIM_ERR; + } + + for (int i = 0; i < argc; i++) + words[i] = Jim_GetString(argv[i], NULL); + struct command_invocation cmd = { .ctx = context, .current = c, .name = c->name, - .argc = num_words - 1, + .argc = argc - 1, .argv = words + 1, }; @@ -526,7 +539,8 @@ static int run_command(struct command_context *context, } Jim_DecrRefCount(context->interp, cmd.output); - return retval; + free(words); + return command_retval_set(interp, retval); } int command_run_line(struct command_context *context, char *line) @@ -867,27 +881,6 @@ static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv) return all; } -static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx, - struct command *c, int argc, Jim_Obj * const *argv) -{ - if (c->jim_handler) - return c->jim_handler(interp, argc, argv); - - /* use c->handler */ - const char **words = malloc(argc * sizeof(char *)); - if (!words) { - LOG_ERROR("Out of memory"); - return JIM_ERR; - } - - for (int i = 0; i < argc; i++) - words[i] = Jim_GetString(argv[i], NULL); - - int retval = run_command(cmd_ctx, c, words, argc); - free(words); - return command_retval_set(interp, retval); -} - static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { /* check subcommands */ From e680841fd276439844ecf340f4005860d6e22582 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 12:38:54 +0200 Subject: [PATCH 0710/1312] helper/command: pass command arguments also as Jim_Obj Some OpenOCD command gets fragment of TCL scripts as command-line argument, fragments that will be kept and executed later on. E.g. the command 'configure' gets the body of an OpenOCD event: $TARGET configure -event halted {TCL code} These commands store the argument as a Jim_Obj and pass it to the jimtcl interpreter when the TCL fragment has to be executed. Using Jim_Obj as storage is relevant to let the jimtcl interpreter to recover extra info of the TCL fragment, like the file-name and the line-number that contain the fragment, that will be printed out in case of run-time errors. While converting the commands to COMMAND_HANDLER, we should avoid storing the argument as C strings otherwise we will loose precious info in case of run-time errors making challenging the debugging of such TCL fragments. Extend the struct command_invocation to contain the array that points to the Jim_Obj of the command arguments. This will be used while converting commands to COMMAND_HANDLER. Change-Id: If37c5f20e9a71349f77ba1571baf1e6778e28aa5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8057 Tested-by: jenkins --- doc/manual/helper.txt | 2 ++ src/helper/command.c | 1 + src/helper/command.h | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/doc/manual/helper.txt b/doc/manual/helper.txt index d5710ddde8..b59fd664fb 100644 --- a/doc/manual/helper.txt +++ b/doc/manual/helper.txt @@ -79,6 +79,8 @@ command handlers and helpers: - @c CMD_NAME - invoked command name - @c CMD_ARGC - the number of command arguments - @c CMD_ARGV - array of command argument strings +- @c CMD_JIMTCL_ARGV - array containing the Jim_Obj equivalent of command + argument in @c CMD_ARGV. @section helpercmdregister Command Registration diff --git a/src/helper/command.c b/src/helper/command.c index 57db2adc15..a775c730b8 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -511,6 +511,7 @@ static int exec_command(Jim_Interp *interp, struct command_context *context, .name = c->name, .argc = argc - 1, .argv = words + 1, + .jimtcl_argv = argv + 1, }; cmd.output = Jim_NewEmptyStringObj(context->interp); diff --git a/src/helper/command.h b/src/helper/command.h index 42cb9cb7d8..dc45070420 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -79,6 +79,7 @@ struct command_invocation { const char *name; unsigned argc; const char **argv; + Jim_Obj * const *jimtcl_argv; Jim_Obj *output; }; @@ -153,6 +154,11 @@ void *jimcmd_privdata(Jim_Cmd *cmd); * rather than accessing the variable directly. It may be moved. */ #define CMD_ARGV (cmd->argv) +/** + * Use this macro to access the jimtcl arguments for the command being + * handled, rather than accessing the variable directly. It may be moved. + */ +#define CMD_JIMTCL_ARGV (cmd->jimtcl_argv) /** * Use this macro to access the name of the command being handled, * rather than accessing the variable directly. It may be moved. From 53811fc584dc8837546be9ac17b77fdf8ad1e8bd Mon Sep 17 00:00:00 2001 From: ianst Date: Wed, 1 Nov 2023 16:41:43 -0700 Subject: [PATCH 0711/1312] target/xtensa: enable xtensa algo support - Add extra error checking - Cache PS; lower PS.INTLEVEL to allow breakpoint trigger (LX) - Xtensa algo support functional on LX per functional flash driver - Test on NX via manual algo validation Change-Id: Ie7cff4933979a0551308b382fa33c33c66376f25 Signed-off-by: ianst Reviewed-on: https://review.openocd.org/c/openocd/+/8075 Reviewed-by: Antonio Borneo Reviewed-by: Erhan Kurubas Tested-by: jenkins --- src/target/xtensa/xtensa.c | 20 +++++++++++++++++--- src/target/xtensa/xtensa.h | 3 ++- src/target/xtensa/xtensa_chip.c | 4 ++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index ab3bfbb097..1ec091c9f2 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -2646,6 +2646,7 @@ int xtensa_start_algorithm(struct target *target, struct xtensa_algorithm *algorithm_info = arch_info; int retval = ERROR_OK; bool usr_ps = false; + uint32_t newps; /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint * at the exit point */ @@ -2660,7 +2661,17 @@ int xtensa_start_algorithm(struct target *target, buf_cpy(reg->value, xtensa->algo_context_backup[i], reg->size); } /* save debug reason, it will be changed */ + if (!algorithm_info) { + LOG_ERROR("BUG: arch_info not specified"); + return ERROR_FAIL; + } algorithm_info->ctx_debug_reason = target->debug_reason; + if (xtensa->core_config->core_type == XT_LX) { + /* save PS and set to debug_level - 1 */ + algorithm_info->ctx_ps = xtensa_reg_get(target, xtensa->eps_dbglevel_idx); + newps = (algorithm_info->ctx_ps & ~0xf) | (xtensa->core_config->debug.irq_level - 1); + xtensa_reg_set(target, xtensa->eps_dbglevel_idx, newps); + } /* write mem params */ for (int i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_IN) { @@ -2688,7 +2699,7 @@ int xtensa_start_algorithm(struct target *target, } if (memcmp(reg_params[i].reg_name, "ps", 3)) { usr_ps = true; - } else { + } else if (xtensa->core_config->core_type == XT_LX) { unsigned int reg_id = xtensa->eps_dbglevel_idx; assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!"); reg = &xtensa->core_cache->reg_list[reg_id]; @@ -2697,7 +2708,7 @@ int xtensa_start_algorithm(struct target *target, reg->valid = 1; } /* ignore custom core mode if custom PS value is specified */ - if (!usr_ps) { + if (!usr_ps && xtensa->core_config->core_type == XT_LX) { unsigned int eps_reg_idx = xtensa->eps_dbglevel_idx; xtensa_reg_val_t ps = xtensa_reg_get(target, eps_reg_idx); enum xtensa_mode core_mode = XT_PS_RING_GET(ps); @@ -2741,7 +2752,8 @@ int xtensa_wait_algorithm(struct target *target, return retval; LOG_TARGET_ERROR(target, "not halted %d, pc 0x%" PRIx32 ", ps 0x%" PRIx32, retval, xtensa_reg_get(target, XT_REG_IDX_PC), - xtensa_reg_get(target, xtensa->eps_dbglevel_idx)); + xtensa_reg_get(target, (xtensa->core_config->core_type == XT_LX) ? + xtensa->eps_dbglevel_idx : XT_REG_IDX_PS)); return ERROR_TARGET_TIMEOUT; } pc = xtensa_reg_get(target, XT_REG_IDX_PC); @@ -2813,6 +2825,8 @@ int xtensa_wait_algorithm(struct target *target, } } target->debug_reason = algorithm_info->ctx_debug_reason; + if (xtensa->core_config->core_type == XT_LX) + xtensa_reg_set(target, xtensa->eps_dbglevel_idx, algorithm_info->ctx_ps); retval = xtensa_write_dirty_registers(target); if (retval != ERROR_OK) diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 3b37122d6b..f799208f0b 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -228,8 +228,9 @@ struct xtensa_sw_breakpoint { struct xtensa_algorithm { /** User can set this to specify which core mode algorithm should be run in. */ enum xtensa_mode core_mode; - /** Used internally to backup and restore debug_reason. */ + /** Used internally to backup and restore core state. */ enum target_debug_reason ctx_debug_reason; + xtensa_reg_val_t ctx_ps; }; #define XTENSA_COMMON_MAGIC 0x54E4E555U diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index 668aa3acc7..ac758ed830 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -184,6 +184,10 @@ struct target_type xtensa_chip_target = { .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = xtensa_breakpoint_add, .remove_breakpoint = xtensa_breakpoint_remove, From c47d77780cdaeac241e3be5d4433c7e4c8b475b9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 6 Jan 2024 17:54:24 +0100 Subject: [PATCH 0712/1312] target/mips32: fix false positive from clang clang build triggers an error for an uninitialized value of the variable 'instr'. This is a false positive, as the macro #define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT) guarantees the switch/case already covers all the possible values with cases 0, 1, 2 and 3. Silent clang by adding a useless default case to the switch. While there, fix the indentation of the switch/case accordingly to OpenOCD coding style. Change-Id: I0ae316754ce7d091dd8366bf314b8e6ee780e313 Signed-off-by: Antonio Borneo Fixes: 7de4b1202d50 ("target/mips32: add cpu info detection") Reviewed-on: https://review.openocd.org/c/openocd/+/8065 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/target/mips32.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 8a3ddbf0b7..5b94e6c894 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -1607,17 +1607,18 @@ COMMAND_HANDLER(mips32_handle_cpuinfo_command) char *instr; switch ((config3 & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT) { - case 0: - instr = "MIPS32"; + case 0: + instr = "MIPS32"; break; - case 1: - instr = "microMIPS"; + case 1: + instr = "microMIPS"; break; - case 2: - instr = "MIPS32 (at reset) and microMIPS"; + case 2: + instr = "MIPS32 (at reset) and microMIPS"; break; - case 3: - instr = "microMIPS (at reset) and MIPS32"; + case 3: + default: + instr = "microMIPS (at reset) and MIPS32"; break; } From fce7aa754f40475228db345c9dd0bf3eb929fc7b Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Wed, 15 Nov 2023 11:26:28 +0100 Subject: [PATCH 0713/1312] contrib/firmware: update gpif FSM configuration file Change the GPIF state machine, configuring only one of the 4 waveforms to generate the clock signal (CCLK) used to program the FPGA, and send one byte every cycle using an 8-bit bus. Change-Id: I43cf5480b9d5c40cc2f6a62a52ecfe078b76458e Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7976 Reviewed-by: Antonio Borneo Tested-by: jenkins --- contrib/firmware/angie/c/src/gpif.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/firmware/angie/c/src/gpif.c b/contrib/firmware/angie/c/src/gpif.c index 80a9571087..f4028be400 100644 --- a/contrib/firmware/angie/c/src/gpif.c +++ b/contrib/firmware/angie/c/src/gpif.c @@ -13,25 +13,25 @@ /****************************** GPIF PROGRAM CODE ********************************/ /* DO NOT EDIT ... */ const char wavedata[128] = { -/* Wave 0 */ +// Wave 0 /* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, /* Opcode*/ 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, /* Output*/ 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* LFun */ 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, -/* Wave 1 */ -/* LenBr */ 0x88, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x07, -/* Opcode*/ 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, -/* Output*/ 0x07, 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, -/* LFun */ 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x3F, -/* Wave 2 */ +// Wave 1 /* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, /* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +/* Output*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, -/* Wave 3 */ +// Wave 2 /* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, /* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +/* Output*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 3 +/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, }; /* END DO NOT EDIT */ From 995a7af21d6f97f628382e26dc21dc38e4fa846e Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Tue, 21 Nov 2023 17:45:55 +0100 Subject: [PATCH 0714/1312] jtag/drivers: send bitstream size to firmware via libusb Send bitstream size to firmware to initialize the GPIF count registers, since we're going to send this size via GPIF, we need to give the exact number of bytes to be sent, then the GPIF counter will decrement with every clock cycle (every byte sent) until reaching zero and stops. Change-Id: Ib4e8e0f95a6a4a95ef4888ba8a04a0ea45567f5a Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7988 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/angie.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index b6bde5b3b9..b7d1f8ac32 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -17,6 +17,7 @@ #include #include #include "helper/system.h" +#include #include #include #include @@ -61,7 +62,7 @@ #define ANGIE_FIRMWARE_FILE PKGDATADIR "/angie/angie_firmware.bin" /** Default location of ANGIE firmware image. */ -#define ANGIE_BITSTREAM_FILE PKGDATADIR "/angie/angie_bitstream.bit" +#define ANGIE_BITSTREAM_FILE PKGDATADIR "/angie/angie_bitstream.bit" /** Maximum size of a single firmware section. Entire EZ-USB ANGIE code space = 16kB */ #define SECTION_BUFFERSIZE 16384 @@ -404,15 +405,7 @@ static int angie_load_bitstream(struct angie *device, const char *filename) FILE *bitstream_file = NULL; char *bitstream_data = NULL; size_t bitstream_size = 0; - - /* CFGopen */ - ret = jtag_libusb_control_transfer(device->usb_device_handle, - 0x00, 0xB0, 0, 0, NULL, 0, LIBUSB_TIMEOUT_MS, &transferred); - if (ret != ERROR_OK) { - LOG_ERROR("Failed opencfg"); - /* Abort if libusb sent less data than requested */ - return ERROR_FAIL; - } + uint8_t gpifcnt[4]; /* Open the bitstream file */ bitstream_file = fopen(bitstream_file_path, "rb"); @@ -442,6 +435,17 @@ static int angie_load_bitstream(struct angie *device, const char *filename) return ERROR_FAIL; } + h_u32_to_be(gpifcnt, bitstream_size); + + /* CFGopen */ + ret = jtag_libusb_control_transfer(device->usb_device_handle, + 0x00, 0xB0, 0, 0, (char *)gpifcnt, 4, LIBUSB_TIMEOUT_MS, &transferred); + if (ret != ERROR_OK) { + LOG_ERROR("Failed opencfg"); + /* Abort if libusb sent less data than requested */ + return ERROR_FAIL; + } + /* Send the bitstream data to the microcontroller */ int actual_length = 0; ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x02, bitstream_data, bitstream_size, 1000, &actual_length); From c7073853ebcbb8a94af0ef405cb05f94b7fd02e5 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Wed, 29 Nov 2023 15:21:27 +0100 Subject: [PATCH 0715/1312] contrib/firmware: Add direction control for 'SCL' i2c signal We want to keep the tri-state buffers located between the FPGA and the board, in 'Z' state until we launch an i2c connection. We launch an i2c start condition, make the SCL direction 'OUT' to start the i2c protocol and at the end of the i2c connection at the stop condition, we re-make the tri-state buffers at 'Z' state. Change-Id: Ic597a70d0427832547f6b539864c24ce20a18c64 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7989 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/include/io.h | 2 +- contrib/firmware/angie/c/src/i2c.c | 7 +++++++ contrib/firmware/angie/c/src/usb.c | 6 ------ .../angie/hdl/src/angie_bitstream.ucf | 1 + .../angie/hdl/src/angie_bitstream.vhd | 19 ++++++++++++------ src/jtag/drivers/angie/angie_bitstream.bit | Bin 340704 -> 340704 bytes src/jtag/drivers/angie/angie_firmware.bin | Bin 10158 -> 10256 bytes 7 files changed, 22 insertions(+), 13 deletions(-) diff --git a/contrib/firmware/angie/c/include/io.h b/contrib/firmware/angie/c/include/io.h index af488f4ed9..19289d11d8 100644 --- a/contrib/firmware/angie/c/include/io.h +++ b/contrib/firmware/angie/c/include/io.h @@ -66,7 +66,7 @@ #define PIN_SDA IOD0 #define PIN_SCL IOD1 #define PIN_SDA_DIR IOD2 -/* PD3 Not Connected */ +#define PIN_SCL_DIR IOD3 /* PD4 Not Connected */ /* PD5 Not Connected */ /* PD6 Not Connected */ diff --git a/contrib/firmware/angie/c/src/i2c.c b/contrib/firmware/angie/c/src/i2c.c index 53840100b9..10a463bf7d 100644 --- a/contrib/firmware/angie/c/src/i2c.c +++ b/contrib/firmware/angie/c/src/i2c.c @@ -14,6 +14,9 @@ void start_cd(void) { + PIN_SCL_DIR = 0; + PIN_SDA_DIR = 0; + delay_us(10); PIN_SDA = 0; //SDA = 1; delay_us(1); PIN_SCL = 0; //SCL = 1; @@ -40,6 +43,10 @@ void stop_cd(void) delay_us(1); PIN_SDA = 1; delay_us(1); + PIN_SDA_DIR = 1; + delay_us(1); + PIN_SCL_DIR = 1; + delay_us(1); } void clock_cd(void) diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index 1b7aa47658..de19641307 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -886,9 +886,6 @@ void io_init(void) PORTACFG = 0x01; /* 0: normal ou 1: alternate function (each bit) */ OEA = 0xEF; /* all OUT exept INIT_B IN */ IOA = 0xFF; - PIN_RDWR_B = 1; - PIN_CSI_B = 1; - PIN_PROGRAM_B = 1; /* PORT B */ OEB = 0xEF; /* all OUT exept TDO */ @@ -899,8 +896,6 @@ void io_init(void) PIN_TDI = 0; PIN_SRST = 1; - - /* PORT C */ PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */ OEC = 0xFF; @@ -909,5 +904,4 @@ void io_init(void) /* PORT D */ OED = 0xFF; IOD = 0xFF; - PIN_SDA_DIR = 0; } diff --git a/contrib/firmware/angie/hdl/src/angie_bitstream.ucf b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf index 92a89c99e1..9eb0c85c39 100644 --- a/contrib/firmware/angie/hdl/src/angie_bitstream.ucf +++ b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf @@ -20,6 +20,7 @@ net SRST LOC = 'P61' ; net SDA LOC = 'P50' ; net SCL LOC = 'P51' ; net SDA_DIR LOC = 'P56' ; +net SCL_DIR LOC = 'P57' ; net SI_TDO LOC = 'P16' ; net SO_TRST LOC = 'P32' ; diff --git a/contrib/firmware/angie/hdl/src/angie_bitstream.vhd b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd index 21ddb844af..6004bf2ff5 100644 --- a/contrib/firmware/angie/hdl/src/angie_bitstream.vhd +++ b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd @@ -26,8 +26,9 @@ entity S609 is port( SDA : inout std_logic; SDA_DIR : in std_logic; SCL : in std_logic; + SCL_DIR : in std_logic; - FTP : out std_logic_vector(7 downto 0):=(others => '1'); -- Test points + FTP : out std_logic_vector(7 downto 0); -- Test points SI_TDO : in std_logic; ST_0 : out std_logic; ST_1 : out std_logic; @@ -55,8 +56,6 @@ begin ST_0 <= '0'; ST_1 <= '1'; -ST_4 <= '0'; - --TDO: TDO <= not SI_TDO; @@ -75,13 +74,21 @@ SO_SDA_OUT <= SDA; process(SDA_DIR) begin - if(SDA_DIR = '1') then - ST_5 <= '1'; - else + if(SDA_DIR = '0') then ST_5 <= '0'; + else + ST_5 <= '1'; end if; end process; +process(SCL_DIR) +begin + if(SCL_DIR = '0') then + ST_4 <= '0'; + else + ST_4 <= '1'; + end if; +end process; --Points de test: FTP(0) <= SDA; diff --git a/src/jtag/drivers/angie/angie_bitstream.bit b/src/jtag/drivers/angie/angie_bitstream.bit index aebd3700b3c36cf4d1d83d7a3939a94eebcf1d41..7b3a88f7c8739accf2dc2512a6eab0480ccbda27 100644 GIT binary patch delta 1183 zcmZuwO-NKx6!yG3Z~mPbLvw7z8H>SmqI`pxnu^szf)Ui(v?v~En_8%}QlBJK($B>3 z;%S$hupdFNMT|Y@f?&*|O`D=cZ4A;u7ZJG9YNeg~#&J~M=5XIR-}%mWe%{J@>B@Sk z+EpS+XQItT{Y4I`p{1d*rM_|D`m1)m^IM<5d^O+~bXoBUPu*bCg5goR^N397vNT2X zkCS&mfN^bgc$}dZK$BB;=075MiLPc(7U!U9_Gp0CD?%Se<1`c?6EyQ3$|zEYxH)dT zjMSPk;Rfj4%9mm+pb?s=B?`}o>*-|5mV1Q&K$lZC0eue0`Q(%cw113*Fl|fJM_x}_ z>B~)Gr|C^Hgi>OjJ@r`dO`$Y$lv*+At$2X^m<@el+ip@t0dKq*=WrcJ2n&ZWvzZ8B z;f-<*o+4~Tw3LV(qiEfVo!Oi)2U-X^c-RB_Gy5FCd94I`-@D=Oz#%dYs%$rL-V2yG zd%Y&kyOmsmCeUt0*uuj9=(>x<_YFyw<{dazFUj?#X1{uk^&wU@;ky+;Fpf#hUJalL zmh%l?U})OF1io6uu!nO&lTa+6Wg<-`0nT>mdw!B0Zd>H2) z;`Wd@p~*^&2eaH1G|m8LND?|cPj2I2MB4R}I9c#Cc_`9t7dY6jHFD+9cy1awpohT1 zPx`mf)&0ZrHU! delta 1061 zcmZ`&O-NKx6!zRZ&-X^h=BEiXK?lXm#+)C62D2P#;YMNlp`9Wqt)i5QK%X!UY2bhv zuezmTY2l)R#$I$G$YvV^Zju%*8bX6MLSR&@I_Hfulc1Z+x#yhwedm4WdzlSyX2Uzx zM)_MwWW!Pswr*>toVY59Q44)m`kq15~5BZdm-C;A3XY<5d{M zjrP^J!~}rRJL5E7bm~}n?acMGx$yeAL93wmA^Vxpny=^mx7VZ{f^ut-e#AYw$ ztkFWsUZhC>tklB90fUeSwVplKB-Zb7nNe(Rg|KxarfX6yfknVcqg37p=0j}}pxto8 z**6aObp=_M|C_{`i8_0ltdNfFPsZqGF9{sqD}7y?|?-1b?D> z7o^TgBkhmuQkbeLBy(DwQHi$7W~3$)B$!!U_lXIlP9XDG))^hE!&p{j{Q)L9$<@uo z$Orz)(oj6!;+jZp@j-l0Vax9dG&%K>KXv3OqZF-6T=ZL)IU48a49{VW;3m0vGz67+ zKUj)Z`Uq*%_0SIBHWy0Lv%`D+nz-!bs&Q$yf;6ikCpO5H5q=DCuiYSfXs3k*VhxO*5G1u+w#cj>4L}@FeXgfN=*+d6fQxoJRBHvoW&g0|m7iwYG+-^vWwEb?c8TqCKp?0J{-;-Qmx}26!b?d0r1cT<`#L{w zL$(g=`3Xr( z_9?W0PFRmX**pSm6O;HW zs+q_n z@CN>t)f}d6wUZlOunBmDPCNpV`*`biQN+yRk6D%VWkh8Y4(&5ReN}9 zP=KD8W=90*iYDsS4lswQ%0HxOQ>I}NCZa;mMq+i%jFZBs%aYM=v)0%P1nG_Qkg{W5Vy8z?Ca$Zwq zlpPS1O^uftVtc4-_Vk_kjp?Nzb&xuD<;|;IzJ94w@(oL^wL#|avg}b6VYsU5lR}h< zs``X}|5b@Iy+S+}`X;L;)3g~a*WXnpu&R2DWUC$!2L0DTua7e|ipgJ+nrrjhCT__d43cw2CRX7G{8!hgB+O z4IgF!Zw;#fKM}S9-WRS0ygzIMd@@`E_?@sF=zO?V#pqpO2hamyC(u*jI-pm=>s5^5 zdyL`bUiFAkKmXWpYs5&b zHxy{|+=}3JeHp%}FEhfN5L2Gd${P#HCl#hw4W3FeK^~Gdjhj|ok|2h>o2vqQei@T> z^u+*8S$SiA`R7??bKYDQH`Iil;KDL&!Zd9h)aj4-#Bs5Sb@6= zk1;%tS>qA92_H4i14TsvB3deXk1W$%0Ax=V{|D&ik^vBfJ}lADWb5P7pMdb$vZM4M z{;X_-ZVL66yJ&hZp5!a&8T?m%9ewfjitih51~@)YToEX#43wIF+W9xId>_`o6Bi!< z_>_P@0r-r74*~pxfR6xtPQaf5#0Z!H@J|9RNVe$^T!-*b@N?6r$(sP{IIIjmcS+$d z0q>PJ?o-GZ5CyWIH2{Y)A5t7C`x(dg+hycg`}_1Soe|f|4m}h1GO>=Ijz5-`4WSkM zoM$3U(jZasKGQ=LaF^^M`BGJ=hh{9HKo=j_TLIl$ zxvwMSZU=>X7MCf68Ya3+QF@|FJ+YVgw}j%UuGC&war0WU*V>LYOh9<+bEtlzoADh) zUzOQTv`t?3qb9Q2-bG)R*N@SYWVM7)vm*bd!aqgKTTzQFo<^7%9!0--OB?WQkc$wM*tVT^NCKG z#o8JNV=uuE*L=iS)Oe`|fn~Sd3G@xS1L&093N&W_8c;{=zUJ8|4LNFjXBTAqkprV> zP&LGw|CpvN|9(oADS1E`QVU-!NFtKZ&k2F&{kC_6-}>R7+R&%9Mmq0`L+5ljH#+ex Zhn=Taep*WTDLjo^oqXPdnQrHn{{w)H#4-Q? delta 2916 zcmai0Yj7J^72dn6hb3FGyppYzCHW!i(I!pm(ozOv@@T>%v>DkX4K1w`QIa2hBzWxI zPVB^%vPPLwKeU;Pe*lSrq(54M?PB2$Gfid1aRQW3b~MB5pXgX}n8dLt6_~`fICu51 zV9KyFI`=!@x#ygF&$)Y7Qpc2Ede!1hi2;VDPV`ZK-Ae`R{gmXJI`{fPuZh(jX6uct z?l!BpO6gE?Pg0+esCz7zCfb4IKQpYcFRDWCpx~I49_HzcATlgB7J5lq+O?RGmUd^P z^y>xkKPK#x(pQpMk)=&j;`Gn}H6})eMl-Be-S7EC^vOX~f=Iap5xJx^ z{w#B|ZA;KArK2k_{pb9a46Pa;XfI>hGoceC>-weS{_dIqvCJgmovQ8XJ6VzU;vUtP z_Ky8joE)0UXga#ZXR5X?a;8^E0FCDg&y8vT(eq zP=Q2PqV!Na+^BIuk@g9Ced^t&rRr&Yt$rm?AyJ4JpViE_?q0;Od$Mn``C%0aKyzb~ z*Z;`|{G_&lw7|swsE|uavt`)4SfVZb#S*UNKP=(V%_(ItvdNag@A09MUkQ`^sxpJB zbR2-+48xVdd}Ux`^E1*amCVf{I>gYrCyA2fq*av6Nvm{nLt15$>(Z(!xi%`6nqlv` zERuEz90jZ@9%NX1&!i|bvT7LhQ>0;WCXV7X|8YFYd*K&~Ct0U2b;f-^dxou-$xK1-pm=EOX*aIMc5!=Gh#>Z)6+n{>VWLSQ5 zJh`?EN%8)win^3Zl@-G^UQ$Wcc$I95Hn!v4Rc5@k%Al(eHkk%|xKdluUL;x#b$G*2 zXUd-z)_QBx&{k<3DQJUgh-E3Jc}PiPQfjxE##nK!=)1eht*cEGwf{=NSvC!AI_q?~ z#=*hJFTK^!X5rEWZIBAmN>1(&9yDx2?YIz=Ei9YsF3uziHRE-|3uq7rj9s7FKP`s- zk*W!prF0}!Q)ppI7g!T?l$0)eeM=Cp7|&E%Z}ES7TDsp)z3IbqCL8{4^#pCbg&#AW zK^FXuX&K}jHDN++Wv`RrBQ^}&N%Kb_U$%?@75$e*gNO;$eH+NLb!Sl*HdrT-CHk(l z6(I)S;cVzU*4Q3I6S&p(qUl_i<-%rL*is*^wX=?g@LM)MX#10_jliqS5-?}b3!=WD z3{nwsYzS_2#FG=7<#QRycOGuN^xpwoAmAE+2?DMH_#pxF0DeqB9Kb~aKF$c!+QHSJ zH}ZYq2dlz`MPY&pLTyeZrS$0xK3`u+uB(OO`zEEY!$s>m37$7#>?0w5380^VUjaBp zz^?(ECg6Pl0|fjAz#suP0R##7ZN@eKwsMn4=YIwx%|#OhJwbGqi{|Y?0EG!fhvEdq zfjAZ&{>Qwce_|#dSeV@?x?FsF@zI=Ohq`i6VKxU>tdgA+-jxy$;y>EmwkT`o$RP`v zl{Ms#BO$TH;YCsWIY&K;Mh`h^5pDYrA9q^SjvVb=#@}%^nH@RSxhz{<(_-8o?}&G@ z&gbzJ=OdgyCFT|mR%c0jojtOauRf9$X=e{sH@xD|ukmPG_W8vf*{;apJGpL#_Ixns zA-BHg1|DsA1nKcygQM0T3iGn3dly4DKAh@y-{>F!XBr%|XBitCA9r*PAiAM5e3T0x zv*j=4{B=*WFd@*`YVYK?&vw`Hx!I%Y*<&PrL+4`lX!aP4_;RB&*m$4cIt%F=v;4N% zZaUP*KS9(c#P3nYDt<2+UC;7gRK{=dUnXNiC%>=2f2E*5Mcg}hzd{H24l*{s!5<*> ztNg*jtfv+8G5#54e96auJ#V00y@O;cLO_w@zfFb zdbT&*d*rQNT;sCfg(frY`91z~Qy22%&os9{37>0z81QiO*6Q(VsowFIQ~dZVP)pZ1 zzTWJvi3nm-{tpd&A8FR<$M>28X1^e|0T#qoMV=)5ahK0NvY9;mRq{D37TP(2r(K_h zJSkV3>XLB4hg({nGynA^1lb-QhK%inHD~y$jxi7a#Ju1FxZ-2p%n>)f9QOYOV6>E1 bBe4^OJbA0OsQ+I({)^9vGd?Ze@Ui~}lS*Uq From 74807daeb36a3be891913d2e03e58d0a23b6fcb9 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Mon, 4 Dec 2023 10:58:05 +0100 Subject: [PATCH 0716/1312] jtag/drivers: correct the angie_reset function remove angie_clear_queue function from executing before the angie_execute_queued_commands function and making it at the end of the reset function. Change-Id: Id8a0664fbd5b8f9730545ce0f8f272ae0b0e7e78 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7990 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/angie.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index b7d1f8ac32..79195a9479 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -1725,14 +1725,16 @@ static int angie_reset(int trst, int srst) high |= SIGNAL_SRST; int ret = angie_append_set_signals_cmd(device, low, high); - if (ret == ERROR_OK) - angie_clear_queue(device); + if (ret != ERROR_OK) + return ret; ret = angie_execute_queued_commands(device, LIBUSB_TIMEOUT_MS); - if (ret == ERROR_OK) - angie_clear_queue(device); + if (ret != ERROR_OK) + return ret; - return ret; + angie_clear_queue(device); + + return ERROR_OK; } /** From 868700e72073ca04ab71e8d03f56e5df031d5a7b Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Wed, 6 Dec 2023 15:28:16 +0100 Subject: [PATCH 0717/1312] jtag/drivers: give ANGIE a new PID after renumeration Give ANGIE a new PID after renumeration to be able to distinguish the two cases (programmed and not programmed) Change-Id: I30a91d8ed2e8e261221488b98d40a027ca41da52 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/7991 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/60-openocd.rules | 1 + contrib/firmware/angie/c/Makefile | 3 +++ contrib/firmware/angie/c/src/usb.c | 2 +- src/jtag/drivers/angie.c | 13 +++++++------ src/jtag/drivers/angie/angie_firmware.bin | Bin 10256 -> 10256 bytes 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index b0e229d07f..fe8b00cb7a 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -225,6 +225,7 @@ ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="660", GROUP="plugdev", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", TAG+="uaccess" # ANGIE USB-JTAG Adapter +ATTRS{idVendor}=="584e", ATTRS{idProduct}=="414f", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4255", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4355", MODE="660", GROUP="plugdev", TAG+="uaccess" diff --git a/contrib/firmware/angie/c/Makefile b/contrib/firmware/angie/c/Makefile index e919cd0114..1bcc1f7d1e 100644 --- a/contrib/firmware/angie/c/Makefile +++ b/contrib/firmware/angie/c/Makefile @@ -74,3 +74,6 @@ clean: bin: angie_firmware.ihx makebin -p angie_firmware.ihx angie_firmware.bin + +hex: angie_firmware.ihx + $(PACKIHX) angie_firmware.ihx > fx2.hex diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index de19641307..a1b72e2d6e 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -42,7 +42,7 @@ __code struct usb_device_descriptor device_descriptor = { .bdeviceprotocol = 0x01, .bmaxpacketsize0 = 64, .idvendor = 0x584e, - .idproduct = 0x424e, + .idproduct = 0x414f, .bcddevice = 0x0000, .imanufacturer = 1, .iproduct = 2, diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 79195a9479..d4219d3c52 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -31,10 +31,11 @@ /** USB Product ID of ANGIE device in unconfigured state (no firmware loaded * yet) or with its firmware. */ -#define ANGIE_PID 0x424e -#define ANGIE_PID_2 0x4255 -#define ANGIE_PID_3 0x4355 -#define ANGIE_PID_4 0x4a55 +#define ANGIE_PID 0x414F +#define ANGIE_PID_2 0x424e +#define ANGIE_PID_3 0x4255 +#define ANGIE_PID_4 0x4355 +#define ANGIE_PID_5 0x4a55 /** Address of EZ-USB ANGIE CPU Control & Status register. This register can be * written by issuing a Control EP0 vendor request. */ @@ -255,8 +256,8 @@ static struct angie *angie_handle; static int angie_usb_open(struct angie *device) { struct libusb_device_handle *usb_device_handle; - const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0}; - const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, 0}; + const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0}; + const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, ANGIE_PID_5, 0}; int ret = jtag_libusb_open(vids, pids, NULL, &usb_device_handle, NULL); diff --git a/src/jtag/drivers/angie/angie_firmware.bin b/src/jtag/drivers/angie/angie_firmware.bin index 23c4a8234a8500e8ccbd8c5a0661ffb1608d80b6..c793abb2f2dc4ee10d35531c51f02022898c3c8a 100644 GIT binary patch delta 15 WcmbObFd<;WG&LrF$IUa;Di{GVvIVIC delta 15 WcmbObFd<;WG&Lqar_D3eDi{GVu?49B From b50a8dbe4116c4fa18ab066f961f04d2fb075224 Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Mon, 11 Dec 2023 14:39:57 +0100 Subject: [PATCH 0718/1312] jtag/drivers: Add GPIO extender configuration function to ANGIE driver Add GPIO extender initial configuration that is needed to configure some important GPIOs and ensure that the dev board is ready to work. Add i2c_write function that make a write transfer to any slave device. Give a new Product ID to ANGIE to make it different than the non programmed ANGIE. Change-Id: I0a8dacb7fe218145b7d3ed1cb75f106ed6256714 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/8072 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/include/usb.h | 1 - contrib/firmware/angie/c/src/usb.c | 11 -- ...84e_424e_angie.txt => 584e_414f_angie.txt} | 13 +- src/jtag/drivers/angie.c | 118 +++++++++++++++++- src/jtag/drivers/angie/angie_firmware.bin | Bin 10256 -> 10248 bytes 5 files changed, 116 insertions(+), 27 deletions(-) rename doc/usb_adapters/angie/{584e_424e_angie.txt => 584e_414f_angie.txt} (89%) diff --git a/contrib/firmware/angie/c/include/usb.h b/contrib/firmware/angie/c/include/usb.h index 07cb12ae6a..e10947d334 100644 --- a/contrib/firmware/angie/c/include/usb.h +++ b/contrib/firmware/angie/c/include/usb.h @@ -32,7 +32,6 @@ #define DESCRIPTOR_TYPE_STRING 0x03 #define DESCRIPTOR_TYPE_INTERFACE 0x04 #define DESCRIPTOR_TYPE_ENDPOINT 0x05 -#define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0B #define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } } diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index a1b72e2d6e..a137d3d37e 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -65,17 +65,6 @@ __code struct usb_config_descriptor config_descriptor = { .maxpower = 50 /* 100 mA */ }; -__code struct usb_interface_association_descriptor interface_association_descriptor = { - .blength = sizeof(struct usb_interface_association_descriptor), - .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, - .bfirstinterface = 0x01, - .binterfacecount = 0x02, - .bfunctionclass = 0x02, - .bfunctionsubclass = 0x00, - .bfunctionprotocol = 0x00, - .ifunction = 0x00 -}; - __code struct usb_interface_descriptor interface_descriptor00 = { .blength = sizeof(struct usb_interface_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE, diff --git a/doc/usb_adapters/angie/584e_424e_angie.txt b/doc/usb_adapters/angie/584e_414f_angie.txt similarity index 89% rename from doc/usb_adapters/angie/584e_424e_angie.txt rename to doc/usb_adapters/angie/584e_414f_angie.txt index d68657a98c..6c25f43b3f 100644 --- a/doc/usb_adapters/angie/584e_424e_angie.txt +++ b/doc/usb_adapters/angie/584e_414f_angie.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later -Bus 001 Device 029: ID 584e:424e NanoXplore, SAS. ANGIE Adapter +Bus 002 Device 105: ID 584e:414f NanoXplore, SAS. ANGIE Adapter Device Descriptor: bLength 18 bDescriptorType 1 @@ -10,7 +10,7 @@ Device Descriptor: bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x584e - idProduct 0x424e + idProduct 0x414f bcdDevice 0.00 iManufacturer 1 NanoXplore, SAS. iProduct 2 ANGIE Adapter @@ -26,15 +26,6 @@ Device Descriptor: bmAttributes 0x80 (Bus Powered) MaxPower 100mA - Interface Association: - bLength 8 - bDescriptorType 11 - bFirstInterface 1 - bInterfaceCount 2 - bFunctionClass 2 Communications - bFunctionSubClass 0 - bFunctionProtocol 0 - iFunction 0 Interface Descriptor: bLength 9 bDescriptorType 4 diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index d4219d3c52..dfe65a2085 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -167,7 +167,8 @@ static int angie_load_firmware_and_renumerate(struct angie *device, const char * uint32_t delay_us); static int angie_load_firmware(struct angie *device, const char *filename); static int angie_load_bitstream(struct angie *device, const char *filename); - +static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_data_size); +static void angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value, uint8_t value); static int angie_write_firmware_section(struct angie *device, struct image *firmware_image, int section_index); @@ -338,7 +339,15 @@ static int angie_load_firmware_and_renumerate(struct angie *device, usleep(delay_us); - return angie_usb_open(device); + ret = angie_usb_open(device); + if (ret != ERROR_OK) + return ret; + + ret = libusb_claim_interface(angie_handle->usb_device_handle, 0); + if (ret != LIBUSB_SUCCESS) + return ERROR_FAIL; + + return ERROR_OK; } /** @@ -475,6 +484,72 @@ static int angie_load_bitstream(struct angie *device, const char *filename) return ERROR_OK; } +/** + * Send an i2c write operation to dev-board components. + * + * @param device pointer to struct angie identifying ANGIE driver instance. + * @param i2c_data table of i2c data that we want to write to slave device. + * @param i2c_data_size the size of i2c data table. + * @return on success: ERROR_OK + * @return on failure: ERROR_FAIL + */ +static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_data_size) +{ + char i2c_data_buffer[i2c_data_size + 2]; + char buffer_received[1]; + int ret, transferred; + i2c_data_buffer[0] = 0; // write = 0 + i2c_data_buffer[1] = i2c_data_size - 1; // i2c_data count (without address) + + for (uint8_t i = 0; i < i2c_data_size; i++) + i2c_data_buffer[i + 2] = i2c_data[i]; + + // Send i2c packet to Dev-board and configure its clock source / + ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x06, i2c_data_buffer, + i2c_data_size + 2, 1000, &transferred); + if (ret != ERROR_OK) { + LOG_ERROR("Error in i2c clock gen configuration : ret ERROR"); + angie_quit(); + return ret; + } + if (transferred != i2c_data_size + 2) { + LOG_ERROR("Error in i2c clock gen configuration : bytes transferred"); + angie_quit(); + return ERROR_FAIL; + } + + usleep(500); + + // Receive packet from ANGIE / + ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x88, buffer_received, 1, 1000, &transferred); + if (ret != ERROR_OK) { + LOG_ERROR("Error in i2c clock gen configuration : ret ERROR"); + angie_quit(); + return ret; + } + return ERROR_OK; +} + +/** + * Configure dev-board gpio extender modules by configuring their + * register 3 and register 1 responsible for IO directions and values. + * + * @param device pointer to struct angie identifying ANGIE driver instance. + * @param i2c_adr i2c address of the gpio extender. + * @param cfg_value IOs configuration to be written in register Number 3. + * @param value the IOs value to be written in register Number 1. + * @return on success: ERROR_OK + * @return on failure: ERROR_FAIL + */ +static void angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value, uint8_t value) +{ + uint8_t ioconfig[3] = {i2c_adr, 3, cfg_value}; + angie_i2c_write(device, ioconfig, 3); + uint8_t iovalue[3] = {i2c_adr, 1, value}; + angie_i2c_write(device, iovalue, 3); + usleep(500); +} + /** * Send one contiguous firmware section to the ANGIE's EZ-USB microcontroller * over the USB bus. @@ -2175,7 +2250,7 @@ static int angie_init(void) if (download_firmware) { LOG_INFO("Loading ANGIE firmware. This is reversible by power-cycling ANGIE device."); - if (libusb_claim_interface(angie_handle->usb_device_handle, 0) != ERROR_OK) + if (libusb_claim_interface(angie_handle->usb_device_handle, 0) != LIBUSB_SUCCESS) LOG_ERROR("Could not claim interface"); ret = angie_load_firmware_and_renumerate(angie_handle, @@ -2191,14 +2266,49 @@ static int angie_init(void) angie_quit(); return ret; } + if (libusb_claim_interface(angie_handle->usb_device_handle, 1) != LIBUSB_SUCCESS) { + LOG_ERROR("Could not claim interface 1"); + angie_quit(); + return ERROR_FAIL; + } + angie_io_extender_config(angie_handle, 0x22, 0xFF, 0xFF); + if (ret != ERROR_OK) { + LOG_ERROR("Could not configure io extender 22"); + angie_quit(); + return ret; + } + angie_io_extender_config(angie_handle, 0x23, 0xFF, 0xFF); + if (ret != ERROR_OK) { + LOG_ERROR("Could not configure io extender 23"); + angie_quit(); + return ret; + } + angie_io_extender_config(angie_handle, 0x24, 0x1F, 0x9F); + if (ret != ERROR_OK) { + LOG_ERROR("Could not configure io extender 24"); + angie_quit(); + return ret; + } + angie_io_extender_config(angie_handle, 0x25, 0x07, 0x00); + if (ret != ERROR_OK) { + LOG_ERROR("Could not configure io extender 25"); + angie_quit(); + return ret; + } + if (libusb_release_interface(angie_handle->usb_device_handle, 1) != LIBUSB_SUCCESS) { + LOG_ERROR("Fail release interface 1"); + angie_quit(); + return ERROR_FAIL; + } } else { LOG_INFO("ANGIE device is already running ANGIE firmware"); } /* Get ANGIE USB IN/OUT endpoints and claim the interface */ ret = jtag_libusb_choose_interface(angie_handle->usb_device_handle, - &angie_handle->ep_in, &angie_handle->ep_out, -1, -1, -1, -1); + &angie_handle->ep_in, &angie_handle->ep_out, 0xFF, 0, 0, -1); if (ret != ERROR_OK) { + LOG_ERROR("Choose and claim interface failed"); angie_quit(); return ret; } diff --git a/src/jtag/drivers/angie/angie_firmware.bin b/src/jtag/drivers/angie/angie_firmware.bin index c793abb2f2dc4ee10d35531c51f02022898c3c8a..bc85208415324c9d2e92c0639a52433b8b98f5d2 100644 GIT binary patch delta 215 zcmbOb&=D}9laXU%*9vCdJN0T4o^5{rVZyU5C3hyBXCvnjhLBctEu zdXBS#4&RXv*BXBvnjhLBV*X+ zdXBS#4*#A^p78ARhY9NcL5#y6CTK8#7zcq2MiAo=kiiUM8~`#{K#VURO4qa3Mb)eK z&nlfAHMvJh&;Axr_!!WP+aUSlK*k*q;{=d#7sNOTWZVNWP5~MBL5$Nt#sd)J43P0~ t^G_)?4i?tZV2#bn$}P+s9NdgdObiSRlb5T_XMdr_rLLxKGTB#sHvo~rbOZnZ From b9f5262d42f00c563750bfacea97640cda9afbdc Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Fri, 22 Dec 2023 10:59:52 +0100 Subject: [PATCH 0719/1312] contrib/firmware: Change USB interruption handling for JTAG/I2C communications Before this change, when we send an I2C Bulk data at the same time while Jtag bitbanging functions execute, the microcontroller puts JTAG bitbanging on wait and executes all I2C bitbanging function, which causes problems like loss of Ack in DAP responses and other errors. With this commit, When I2C interruption occurs, it sets a variable to true and continues JTAG bitbanging, when it finish it executes the I2C bitbang. Change-Id: Ia80bac21f8a259f4a1176b5346bf74ed0aa6e38b Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/8074 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/firmware/angie/c/include/usb.h | 1 + contrib/firmware/angie/c/src/protocol.c | 50 ++++++++++++---------- contrib/firmware/angie/c/src/usb.c | 6 +-- src/jtag/drivers/angie/angie_firmware.bin | Bin 10248 -> 10216 bytes 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/contrib/firmware/angie/c/include/usb.h b/contrib/firmware/angie/c/include/usb.h index e10947d334..ad8be787e4 100644 --- a/contrib/firmware/angie/c/include/usb.h +++ b/contrib/firmware/angie/c/include/usb.h @@ -129,6 +129,7 @@ struct setup_data { * the USB module */ extern volatile bool ep1_out; extern volatile bool ep1_in; +extern volatile bool ep6_out; extern volatile __xdata __at 0xE6B8 struct setup_data setup_data; diff --git a/contrib/firmware/angie/c/src/protocol.c b/contrib/firmware/angie/c/src/protocol.c index d84534bf2f..e32808db8f 100644 --- a/contrib/firmware/angie/c/src/protocol.c +++ b/contrib/firmware/angie/c/src/protocol.c @@ -157,30 +157,36 @@ void command_loop(void) cmd_id_index = 0; payload_index_in = 0; - /* Wait until host sends EP1 Bulk-OUT packet */ - while (!ep1_out) + /* Wait until host sends Bulk-OUT packet */ + while ((!ep1_out) && (!ep6_out)) ; - ep1_out = false; - - /* Execute the commands */ - last_command = false; - while (!last_command) - last_command = execute_command(); - - /* Send back EP6 Bulk-IN packet if required */ - if (payload_index_in > 0) { - EP1INBC = payload_index_in; + if (ep6_out) { + /* Execute I2C command */ + i2c_recieve(); + ep6_out = false; + } + if (ep1_out) { + ep1_out = false; + /* Execute the commands */ + last_command = false; + while (!last_command) + last_command = execute_command(); + + /* Send back EP1 Bulk-IN packet if required */ + if (payload_index_in > 0) { + EP1INBC = payload_index_in; + syncdelay(3); + + while (!ep1_in) + ; + ep1_in = false; + } + + /* Re-arm EP1-OUT after command execution */ + EP1OUTBC = 0; + syncdelay(3); + EP1OUTBC = 0; syncdelay(3); - - while (!ep1_in) - ; - ep1_in = false; } - - /* Re-arm EP1-OUT after command execution */ - EP1OUTBC = 0; - syncdelay(3); - EP1OUTBC = 0; - syncdelay(3); } } diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index a137d3d37e..ed23dcfa5a 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -25,6 +25,7 @@ */ volatile bool ep1_out; volatile bool ep1_in; +volatile bool ep6_out; volatile __xdata __at 0xE6B8 struct setup_data setup_data; @@ -195,27 +196,24 @@ void ep0out_isr(void)__interrupt EP0OUT_ISR void ep1in_isr(void)__interrupt EP1IN_ISR { ep1_in = true; - EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ EPIRQ = 0x04; /* Clear individual EP1IN IRQ */ } void ep1out_isr(void)__interrupt EP1OUT_ISR { ep1_out = true; - EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ EPIRQ = 0x08; /* Clear individual EP1OUT IRQ */ } void ep2_isr(void)__interrupt EP2_ISR { - ep1_out = false; /* Does nothing but required by the compiler */ } void ep4_isr(void)__interrupt EP4_ISR { } void ep6_isr(void)__interrupt EP6_ISR { - i2c_recieve(); + ep6_out = true; EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ EPIRQ = 0x40; /* Clear individual EP6OUT IRQ */ diff --git a/src/jtag/drivers/angie/angie_firmware.bin b/src/jtag/drivers/angie/angie_firmware.bin index bc85208415324c9d2e92c0639a52433b8b98f5d2..68486ef8f09865c663966cf80cc334ec93405b5c 100644 GIT binary patch delta 4380 zcmai1dvp_38lOiVrSD8znn}`&XP9r5#uYDzwdhcbbL>xZ9rZ-rxQ1 z@4Mgk-Phc#tv_~`^hDur6`_%)h~-ZcKio_-+Mgk$iev5T=6jut`AWuC%1k)PWR^(r zfLteMsuFRQv7W}QdGZ;R$$b(T$mwJQx{kchR$U#I!$LU7XOi>U2c>ueSF1*YQ6Va$ zf01R?7yfk#oWEhzeWsqKsOkZCW>6Cb+&Mul7+aZ@=c@KrU-1WOy8n5CB0E4jLH2^AJ^}nG$N`YgK%yWAK@Nd@4)PC>e}a4gav0=GkRu>p zfqV_}4ME*XeoIL4J+dY+}-($Sev#Mi03 zKr_}&QhYr}B{7;pPp8Q5&{BFKu6pU2*EcjT^LwTEu0b&A=9a0H;h|<xI zYz~{k#;^fGiyETFs7Z={HlTN;tEG7Kgsx0yM$JVZb!>n$a-^J}^!zU)U>3@i2D^XQD5KmCH}!L!v}v!X8GGOhulxy+Uu0 z-%X6s0=My5naXbG(Y&s#qO8Hj42d8y^L|sE-!Z7~&_TCF-=XN$o>0%^!v~H|CfLa) z{Ab1je+<_gEBnA7>=O3%~n6`#C-0R)KoBOxFD8N7jm0ZxQP2cgoBBF1?bNYV@-o&iv{WR?v#cI*d`O9b>mi@r~n|;v@Ld0IX?hu3)M#c3qGtP7xC7 z6q*S|8M zoKP$VO%NF`UQZ_XAkKrzopCW$b{j`^u1>Uwzf4SwGezbGom@CON%m0}jEj6(rpqna z+5HgKxqcj0pFS5F3mXInR6LYsicV%1krs4&j?-Vfaa@0itWrr`sgIFg^vki1hpH2q z&wrVimekE*b3TMt^!<1UkQG{yRq#I(vAWaQsYG&$_g-3Wja*WHtM&A_p72w8)Ygab zCkJa4#vM-XrWU$S-O6P3!MvXB!`kC`Ui(#8TD%DVKit5$8<=0r_Fr<9wt@EI#j`0E zw_*6gCADv}3|x7U){$IjYb$mbF!{&;0LOpN&?p9z}A7@tA-iNPi_lX*v%5IC(cjRjJ?O<|J9PMOd+ z%uj&#McT!hf`LDyley34vFilbdEChb(z$1d*DBE7d=@>Q_ks!ZRPhj+mcI%^#_C3I z~*~t=BT_EXgGbWg_bmZRMifEjrL1 z>tz|Nk+%_y;}+C!Wyx*G#9mHzqAHf1P#^{iMYTwqh~~1@9u`==GV8ue4SY#I`IvB@t^g7G=*<(?28@^UC*qf8d3z^A=k7yHGgYf+(IecqsTtby9 zzJRZ6{67E=V-NxGB?j*TID$bhfUhwK1Na7mA634~?5p-yw7tN;Sk1o_<2S)(kmAqE zQhb$)HrlfAhjHKdw?K;Thqq6~POy9r>Rot<_W^Wc@Bx4x3_b+#76u;y_$vk<19%&Q zPXN4w!KbRLcNcs(@hd0NyF-7&M0($ZnzBX?CEJIf?T5$BMTBt!Ou+pq0~k>nTaLc4K&%KifWp`FsT`ha}T=(w-VJ7P5n-4K?-8sU2qI1TI-ua!#?=KDQxp|a>( zdnpTFyIJ}#Is4eL4 zV27bO0_{;yBu-8OIg z{LTe$+{4?Q>&%0dnr)zbK6#7nY~SQ_{WZfUYDNZXMkB{N*xHQakq-839Zf3s!bF=L z%_^;Q%pT^*DcXav8?{Aki~AEzH090T>%mVqZw6{9y^5TT_Le$o+5;jN^)%Je)T9+k zllwjR0XS&|m*`otpl9h^@iA6hW`oT;_Jj)4aDu&+D0k9y2Wlp%QY0>6#ibV$8YflR z5jVA`sR)l`>{*K4mZF%pL|Y0q+B&J!e*-tU2ZC~5!%gXFq5@BIv-D;iSEtu^ayR4J z^&)qxUcbrx3fHBGyDh1|J=va(&Fi_lboFMg9@k}YZXQ-Y!Oc&y7U@*h!q`A1ZVf)=?sFgxU~fby){3uT$d3FR!$El{rYJnrv~l8~+`@a}+a zzkOvV*Fv`%O8%Z8OZ#T)x?~dI2ETCwavS!DUEeE+_XS;V2wQ{jtGtok5*Ugo!V8+9 z1YgvGaBbjoxL*jX_#j4AkGfw!)*kpF=W?DYtU6t|Hi$UyA#>RKy?4}`jpkJB{x5yq BRIC61 delta 4302 zcmbVPdvFv*8lRbcX7k#eyk>WkCE08?c#1?KXyM}miPmunL>>pH2BLsxX{6#YW1UK} z%j^vWfh2=n@y-`0(JDcb5Ob;0LzguXz4OpoIrL7;x*Lz34U*SzIwX+C-q*96B_Q{Y zNqybF{vQ4H_kG>dy=PbMsurKh-X-(3I*Qo(H1S;(QR{q$5a*irHLdYh(54Nv<4)RA zOj}lpQNL6vSrn1DMB8)mXtgw^&>4r2o?JxkL${IZ4V;-+umG9KIcc=Hc=f(fF}jhh zP(W0GI?2N4s71a%5ES`GAPMLK&<3C}pmCs!K$n0ffF^;afUtaqrUAzYiXwnWAPPta zqz5tp8G%edW}p-x3s5Rh8c;e=20<;SG6|XqiqSnRrEt6su>Ub}pdzA(14|S!+LT~k zp|DJhz9*?XO<6nnu0R9P!nX#R71~>e!jvohipkIfwTPmus9g5|?nK>^+xIo>^?Ai; z&nQg)Cw8ww>DwCi&*JP?{9Cbusdj03y{+M!S)y-Hy8cG;Zgji8Y~iCEPtnw)V)P)a zT#UX3D~>kf)ly9G2;ULtRAOTEGt3B?LdK9Gq=(qhYx-PYFsu(7#AtX}6UGIY6*h)V zV)XMN#m%KvaOneLG$^SV?UI@)M&FTQWdr4%8C{wEY{mY_fofx8g^%#-F{dS!vk?8V zr7gAECR<9;K%x_XW6PL}D*2<17~W zSm8ismnFwCT5A>w5-d@vv2xvtQI92{@}nMG0D|3i;>!VLpeBW|*DScF#)$t+i9ed! z2j_`&<7g`-QgPF|Tdrixk~E_ajLh9pnXg}-RByPT}G7Gj|=FWmIu>Pc75@Y}RSpt3X zoB{vxG|Vg*FBF8=_qI4r!0sU_zm7@?;DO4BG~mIC=h5?!!c-r<>0chF7(Z~D0Q8QOUeJ!zg_h{4QR zNcVpV2M6YIg!OxQ+Nmjp%r{w!4)I|stZU-;1in*f=Wh|2!u+PF3p+I6eKZQpCfd1J zjJ`Y*R@f*;Um1Y{CKCgB!PtFOR5%`3eJ9^Q;8TlN2?w)<$52~f4*3R2MK1$8HfeGgI~~GKE2Wrh)vLT<^Wxgk8Ru~vR7Ty8RV9yMTGQ1OZEqwM zku5EEZG4hDG+B0CLe@xKW16WW*0i)CSjNN z-)GOA;S)Y8o}8WdHo;uk<_RVCO|x!LdCQhM2pPRJh`Hx*Mu!wA;!nx{t20jTzgDLI zPw{X`e_T_$Z1w0TudcM?h!xo~vI?9t74O6z{l-SpPc;&wB{tR8VMR+a=G|ulv=<|$c zGnpnHb{TtqtvK-v@n$JHV6`JQ^F<@@DTYDW*6kS5Oci?GdN$6jLcg~)SeV^-i^A2- zpi~-eh89i#6y0dX65v;%^;yGleigbWd#A=Xfqu_d*%WDH_Gkv*=JTW0chuTW2b!q;wxEWf-+)6V`MYq5g35;8?7Yh!L;6yJobIpu_vlDdw7Ic!alP6J> zxsLn{S?%@|S_otbO17GV7T6b*FrdXb2+m1}Pafrz)JTY;^S>8pM#!=Y*$yGcN$0nq z-FDXJFo#X8_=}0b@pKEvTM~mtqLpt6z@1C7_=~8rF-0uB0JmlIdjMk?^aB{j-~#{` zG3Wy@fk6nsBnCeyT$ibFm9Mn*Mee0l+$#}oKWqju`m7{Iw<~D7BNbn8A6~Bf33%C* zo&w8{p#M9b;$r}(G58CBFEIEkfG;ul1i(Kq_#1$KVsH|`R~US%xchqG0)&?ebEfYo zes@6M4L!x2Ih7cng0W8%T%|B$fEBPjX#f*yZUutAjWvI=LHsvq(F~e>4kv7L@o3kQosEwI~;S`Lgff1|Z$*+Th?!(H2 z%nOY2`ecV92QZj760jWa6;drGza$b?oghvBd?KY3D6EYoCjO~K_O5hC>tW`uhsk22ZY>>V!=a{Yh@@; z-l67sCSt7{6CxQ#<2xTT@2oNJ+yF|nYb8w3#fMggszdkD1wp?lv^=x|5|^_B{~Ojt zP-nrMwcRow`*2OB_FO199X7F<8&#evI4$tZTdR(&?pV{g_VBMbM`4p`biQgIDPBX~ zWxq6d{lrlDj~EtV0J}`Q_byfen|`SLmoY`{a7hN7WdxvEI#Vd$+6-9%qC) zJ8a(gFOQH8POx_+8gVVk?`a?@SC6on5w`qTp<+&%vxmL0w>}5YWa!<3-MV@r>SlEd z^k~lDsz84l%xQ?CITTl6)W|wNiO>CvsZ)K}+?>@%ft@WR?zrek#hh3K7|1vSY z7n@hJD>Zf>Tdnm*b~R={#jZ(ct<~5cv+K3~B zh1c1;@iQ_0oTS`i@`ac-a>^rt~vdy{{eZl)N(lvOm#!JKi zZt(NfFSTNi*!4PISRZg7=HCjy59wN6yMMf2=3i8KIq;GifUgEVh9~%tg3n=CDN#;n ir@91wd$|k8vdb=H?+Tzb-cu&YOO?7xZ$R@(kNpo)EHF<1 From ea2e26f7d521f5755b4bfda7bf12d99650277421 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Aug 2023 23:14:15 +0200 Subject: [PATCH 0720/1312] jtag: rewrite jim_jtag_configure() as COMMAND_HANDLER The function is used for commands: - jtag configure - jtag cget While there, add the missing .usage field. Change-Id: I97ddc4898259ddb7fd2d057a997f33a6f4b0e2a8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8058 Tested-by: jenkins --- src/jtag/hla/hla_transport.c | 3 +- src/jtag/tcl.c | 197 +++++++++++++--------------------- src/jtag/tcl.h | 3 +- src/target/adi_v5_dapdirect.c | 3 +- 4 files changed, 82 insertions(+), 124 deletions(-) diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c index c0443d8356..b826eb0fe6 100644 --- a/src/jtag/hla/hla_transport.c +++ b/src/jtag/hla/hla_transport.c @@ -127,7 +127,8 @@ static const struct command_registration hl_transport_jtag_subcommand_handlers[] { .name = "cget", .mode = COMMAND_EXEC, - .jim_handler = jim_jtag_configure, + .handler = handle_jtag_configure, + .usage = "", }, { .name = "names", diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 407aeb1d80..163edfa19e 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -41,7 +41,7 @@ * Holds support for accessing JTAG-specific mechanisms from TCl scripts. */ -static const struct jim_nvp nvp_jtag_tap_event[] = { +static const struct nvp nvp_jtag_tap_event[] = { { .value = JTAG_TRST_ASSERTED, .name = "post-reset" }, { .value = JTAG_TAP_EVENT_SETUP, .name = "setup" }, { .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" }, @@ -259,123 +259,104 @@ enum jtag_tap_cfg_param { JCFG_IDCODE, }; -static struct jim_nvp nvp_config_opts[] = { +static struct nvp nvp_config_opts[] = { { .name = "-event", .value = JCFG_EVENT }, { .name = "-idcode", .value = JCFG_IDCODE }, { .name = NULL, .value = -1 } }; -static int jtag_tap_configure_event(struct jim_getopt_info *goi, struct jtag_tap *tap) +static int jtag_tap_set_event(struct command_context *cmd_ctx, struct jtag_tap *tap, + const struct nvp *event, Jim_Obj *body) { - if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ..."); - return JIM_ERR; - } - - struct jim_nvp *n; - int e = jim_getopt_nvp(goi, nvp_jtag_tap_event, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_jtag_tap_event, 1); - return e; - } - - if (goi->isconfigure) { - if (goi->argc != 1) { - Jim_WrongNumArgs(goi->interp, - goi->argc, - goi->argv, - "-event "); - return JIM_ERR; - } - } else { - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event "); - return JIM_ERR; - } - } + struct jtag_tap_event_action *jteap = tap->event_action; - struct jtag_tap_event_action *jteap = tap->event_action; - /* replace existing event body */ - bool found = false; while (jteap) { - if (jteap->event == (enum jtag_event)n->value) { - found = true; + if (jteap->event == (enum jtag_event)event->value) break; - } jteap = jteap->next; } - Jim_SetEmptyResult(goi->interp); - - if (goi->isconfigure) { - if (!found) - jteap = calloc(1, sizeof(*jteap)); - else if (jteap->body) - Jim_DecrRefCount(goi->interp, jteap->body); + if (!jteap) { + jteap = calloc(1, sizeof(*jteap)); + if (!jteap) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } - jteap->interp = goi->interp; - jteap->event = n->value; + /* add to head of event list */ + jteap->next = tap->event_action; + tap->event_action = jteap; + } else { + Jim_DecrRefCount(cmd_ctx->interp, jteap->body); + } - Jim_Obj *o; - jim_getopt_obj(goi, &o); - jteap->body = Jim_DuplicateObj(goi->interp, o); - Jim_IncrRefCount(jteap->body); + jteap->interp = cmd_ctx->interp; + jteap->event = (enum jtag_event)event->value; + jteap->body = Jim_DuplicateObj(cmd_ctx->interp, body); + Jim_IncrRefCount(jteap->body); - if (!found) { - /* add to head of event list */ - jteap->next = tap->event_action; - tap->event_action = jteap; - } - } else if (found) { - jteap->interp = goi->interp; - Jim_SetResult(goi->interp, - Jim_DuplicateObj(goi->interp, jteap->body)); - } - return JIM_OK; + return ERROR_OK; } -static int jtag_tap_configure_cmd(struct jim_getopt_info *goi, struct jtag_tap *tap) +__COMMAND_HANDLER(handle_jtag_configure) { - /* parse config or cget options */ - while (goi->argc > 0) { - Jim_SetEmptyResult(goi->interp); - - struct jim_nvp *n; - int e = jim_getopt_nvp(goi, nvp_config_opts, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_config_opts, 0); - return e; - } + bool is_configure = !strcmp(CMD_NAME, "configure"); + + if (CMD_ARGC < (is_configure ? 3 : 2)) + return ERROR_COMMAND_SYNTAX_ERROR; + /* FIXME: rework jtag_tap_by_jim_obj */ + struct jtag_tap *tap = jtag_tap_by_jim_obj(CMD_CTX->interp, CMD_JIMTCL_ARGV[0]); + if (!tap) + return ERROR_FAIL; + + for (unsigned int i = 1; i < CMD_ARGC; i++) { + const struct nvp *n = nvp_name2value(nvp_config_opts, CMD_ARGV[i]); switch (n->value) { - case JCFG_EVENT: - e = jtag_tap_configure_event(goi, tap); - if (e != JIM_OK) - return e; - break; - case JCFG_IDCODE: - if (goi->isconfigure) { - Jim_SetResultFormatted(goi->interp, - "not settable: %s", n->name); - return JIM_ERR; - } else { - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, - goi->argc, goi->argv, - "NO PARAMS"); - return JIM_ERR; + case JCFG_EVENT: + if (i + (is_configure ? 3 : 2) >= CMD_ARGC) { + command_print(CMD, "wrong # args: should be \"-event %s\"", + is_configure ? " " : ""); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + const struct nvp *event = nvp_name2value(nvp_jtag_tap_event, CMD_ARGV[i + 1]); + if (!event->name) { + nvp_unknown_command_print(CMD, nvp_jtag_tap_event, CMD_ARGV[i], CMD_ARGV[i + 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + if (is_configure) { + int retval = jtag_tap_set_event(CMD_CTX, tap, event, CMD_JIMTCL_ARGV[i + 2]); + if (retval != ERROR_OK) + return retval; + } else { + struct jtag_tap_event_action *jteap = tap->event_action; + while (jteap) { + if (jteap->event == (enum jtag_event)event->value) { + command_print(CMD, "%s", Jim_GetString(jteap->body, NULL)); + break; } + jteap = jteap->next; } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, tap->idcode)); - break; - default: - Jim_SetResultFormatted(goi->interp, "unknown value: %s", n->name); - return JIM_ERR; + } + + i += is_configure ? 2 : 1; + break; + case JCFG_IDCODE: + if (is_configure) { + command_print(CMD, "not settable: %s", n->name); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + command_print(CMD, "0x%08x", tap->idcode); + break; + default: + nvp_unknown_command_print(CMD, nvp_config_opts, NULL, CMD_ARGV[i]); + return ERROR_COMMAND_ARGUMENT_INVALID; } } - - return JIM_OK; + return ERROR_OK; } #define NTAP_OPT_IRLEN 0 @@ -558,7 +539,7 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e) if (jteap->event != e) continue; - struct jim_nvp *nvp = jim_nvp_value2name_simple(nvp_jtag_tap_event, e); + const struct nvp *nvp = nvp_value2name(nvp_jtag_tap_event, e); LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s", tap->dotted_name, e, nvp->name, Jim_GetString(jteap->body, NULL)); @@ -675,30 +656,6 @@ __COMMAND_HANDLER(handle_jtag_tap_enabler) return ERROR_OK; } -int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct command *c = jim_to_command(interp); - const char *cmd_name = c->name; - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc-1, argv + 1); - goi.isconfigure = !strcmp(cmd_name, "configure"); - if (goi.argc < 2 + goi.isconfigure) { - Jim_WrongNumArgs(goi.interp, 0, NULL, - " ..."); - return JIM_ERR; - } - - struct jtag_tap *t; - - Jim_Obj *o; - jim_getopt_obj(&goi, &o); - t = jtag_tap_by_jim_obj(goi.interp, o); - if (!t) - return JIM_ERR; - - return jtag_tap_configure_cmd(&goi, t); -} - COMMAND_HANDLER(handle_jtag_names) { if (CMD_ARGC != 0) @@ -793,7 +750,7 @@ static const struct command_registration jtag_subcommand_handlers[] = { { .name = "configure", .mode = COMMAND_ANY, - .jim_handler = jim_jtag_configure, + .handler = handle_jtag_configure, .help = "Provide a Tcl handler for the specified " "TAP event.", .usage = "tap_name '-event' event_name handler", @@ -801,7 +758,7 @@ static const struct command_registration jtag_subcommand_handlers[] = { { .name = "cget", .mode = COMMAND_EXEC, - .jim_handler = jim_jtag_configure, + .handler = handle_jtag_configure, .help = "Return any Tcl handler for the specified " "TAP event.", .usage = "tap_name '-event' event_name", diff --git a/src/jtag/tcl.h b/src/jtag/tcl.h index 66867ab0ff..4e49e8579f 100644 --- a/src/jtag/tcl.h +++ b/src/jtag/tcl.h @@ -20,8 +20,7 @@ #include -int jim_jtag_configure(Jim_Interp *interp, int argc, - Jim_Obj * const *argv); +__COMMAND_HANDLER(handle_jtag_configure); __COMMAND_HANDLER(handle_jtag_tap_enabler); #endif /* OPENOCD_JTAG_TCL_H */ diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c index f3a90c0b17..d198dacf39 100644 --- a/src/target/adi_v5_dapdirect.c +++ b/src/target/adi_v5_dapdirect.c @@ -118,7 +118,8 @@ static const struct command_registration dapdirect_jtag_subcommand_handlers[] = { .name = "cget", .mode = COMMAND_EXEC, - .jim_handler = jim_jtag_configure, + .handler = handle_jtag_configure, + .usage = "", }, { .name = "names", From 43e1d60e77b7984e21a9250a530a34f64bab78c0 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 10 Dec 2023 15:03:46 +0100 Subject: [PATCH 0721/1312] jtag/drivers/cmsis_dap_usb_bulk: fix clang warning Clang static analyzer warnings "1st function call argument is an uninitialized value" on the first libusb_free_transfer() parameter (lines 423, 424) could turn into a real problem in a corner case: If allocation of a libusb transfer struct fails, the pointers of not yet allocated transfers remain uninitialized. Use calloc() to zero whole struct cmsis_dap_backend_data. Fixes: fd75e9e54270 (jtag/drivers/cmsis_dap_bulk: use asynchronous libusb transfer) Signed-off-by: Tomas Vanek Change-Id: I0e489757d82d10ed7416c5e8c215e1facc7f8093 Reviewed-on: https://review.openocd.org/c/openocd/+/8045 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/cmsis_dap_usb_bulk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 92a972a04f..8d0cb544d7 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -362,7 +362,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p if (err) LOG_WARNING("could not claim interface: %s", libusb_strerror(err)); - dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data)); + dap->bdata = calloc(1, sizeof(struct cmsis_dap_backend_data)); if (!dap->bdata) { LOG_ERROR("unable to allocate memory"); libusb_release_interface(dev_handle, interface_num); From d8499687f8d2899508cb7cab3de750d944181b6a Mon Sep 17 00:00:00 2001 From: Ahmed BOUDJELIDA Date: Mon, 15 Jan 2024 15:45:49 +0100 Subject: [PATCH 0722/1312] jtag/drivers: Correct ANGIE driver and GPIO Extender configuration Correct GPIO Extender configuration, after reconsideration, we need to configure the IO extender 0x23 pins as all inputs. Add more LOG_ERRORs to the code to better track bugs. Re-organize angie_init function Change-Id: I1fcf4919ba9ea95576803dd35cce7dafa26853b4 Signed-off-by: Ahmed BOUDJELIDA Reviewed-on: https://review.openocd.org/c/openocd/+/8079 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/angie.c | 93 ++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index dfe65a2085..62079f0156 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -168,7 +168,7 @@ static int angie_load_firmware_and_renumerate(struct angie *device, const char * static int angie_load_firmware(struct angie *device, const char *filename); static int angie_load_bitstream(struct angie *device, const char *filename); static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_data_size); -static void angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value, uint8_t value); +static int angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value); static int angie_write_firmware_section(struct angie *device, struct image *firmware_image, int section_index); @@ -262,8 +262,10 @@ static int angie_usb_open(struct angie *device) int ret = jtag_libusb_open(vids, pids, NULL, &usb_device_handle, NULL); - if (ret != ERROR_OK) + if (ret != ERROR_OK) { + LOG_ERROR("Could not find and open ANGIE"); return ret; + } device->usb_device_handle = usb_device_handle; device->type = ANGIE; @@ -281,8 +283,10 @@ static int angie_usb_open(struct angie *device) static int angie_usb_close(struct angie *device) { if (device->usb_device_handle) { - if (libusb_release_interface(device->usb_device_handle, 0) != 0) + if (libusb_release_interface(device->usb_device_handle, 0) != 0) { + LOG_ERROR("Could not release interface 0"); return ERROR_FAIL; + } jtag_libusb_close(device->usb_device_handle); device->usb_device_handle = NULL; @@ -383,8 +387,10 @@ static int angie_load_firmware(struct angie *device, const char *filename) /* Download all sections in the image to ANGIE */ for (unsigned int i = 0; i < angie_firmware_image.num_sections; i++) { ret = angie_write_firmware_section(device, &angie_firmware_image, i); - if (ret != ERROR_OK) + if (ret != ERROR_OK) { + LOG_ERROR("Could not write firmware section"); return ret; + } } image_close(&angie_firmware_image); @@ -477,7 +483,7 @@ static int angie_load_bitstream(struct angie *device, const char *filename) ret = jtag_libusb_control_transfer(device->usb_device_handle, 0x00, 0xB1, 0, 0, NULL, 0, LIBUSB_TIMEOUT_MS, &transferred); if (ret != ERROR_OK) { - LOG_INFO("error cfgclose"); + LOG_ERROR("Failed cfgclose"); /* Abort if libusb sent less data than requested */ return ERROR_FAIL; } @@ -509,12 +515,10 @@ static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_ i2c_data_size + 2, 1000, &transferred); if (ret != ERROR_OK) { LOG_ERROR("Error in i2c clock gen configuration : ret ERROR"); - angie_quit(); return ret; } if (transferred != i2c_data_size + 2) { LOG_ERROR("Error in i2c clock gen configuration : bytes transferred"); - angie_quit(); return ERROR_FAIL; } @@ -524,7 +528,6 @@ static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_ ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x88, buffer_received, 1, 1000, &transferred); if (ret != ERROR_OK) { LOG_ERROR("Error in i2c clock gen configuration : ret ERROR"); - angie_quit(); return ret; } return ERROR_OK; @@ -541,13 +544,15 @@ static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_ * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ -static void angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value, uint8_t value) +static int angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value) { uint8_t ioconfig[3] = {i2c_adr, 3, cfg_value}; - angie_i2c_write(device, ioconfig, 3); - uint8_t iovalue[3] = {i2c_adr, 1, value}; - angie_i2c_write(device, iovalue, 3); + int ret = angie_i2c_write(device, ioconfig, 3); + if (ret != ERROR_OK) + return ret; + usleep(500); + return ret; } /** @@ -851,19 +856,27 @@ static int angie_execute_queued_commands(struct angie *device, int timeout_ms) /* Send packet to ANGIE */ ret = jtag_libusb_bulk_write(device->usb_device_handle, device->ep_out, (char *)buffer, count_out, timeout_ms, &transferred); - if (ret != ERROR_OK) + if (ret != ERROR_OK) { + LOG_ERROR("Libusb bulk write queued commands failed."); return ret; - if (transferred != count_out) + } + if (transferred != count_out) { + LOG_ERROR("Libusb bulk write queued commands failed: transferred byte count"); return ERROR_FAIL; + } /* Wait for response if commands contain IN payload data */ if (count_in > 0) { ret = jtag_libusb_bulk_write(device->usb_device_handle, device->ep_in, (char *)buffer, count_in, timeout_ms, &transferred); - if (ret != ERROR_OK) - return ret; - if (transferred != count_in) - return ERROR_FAIL; + if (ret != ERROR_OK) { + LOG_ERROR("Libusb bulk write input payload data failed"); + return ret; + } + if (transferred != count_in) { + LOG_ERROR("Libusb bulk write input payload data failed: transferred byte count"); + return ERROR_FAIL; + } /* Write back IN payload data */ index_in = 0; @@ -2230,7 +2243,6 @@ static int angie_init(void) ret = angie_usb_open(angie_handle); if (ret != ERROR_OK) { - LOG_ERROR("Could not open ANGIE device"); free(angie_handle); angie_handle = NULL; return ret; @@ -2249,10 +2261,10 @@ static int angie_init(void) if (download_firmware) { LOG_INFO("Loading ANGIE firmware. This is reversible by power-cycling ANGIE device."); - - if (libusb_claim_interface(angie_handle->usb_device_handle, 0) != LIBUSB_SUCCESS) - LOG_ERROR("Could not claim interface"); - + if (libusb_claim_interface(angie_handle->usb_device_handle, 0) != LIBUSB_SUCCESS) { + LOG_ERROR("Could not claim interface 0"); + return ERROR_FAIL; + } ret = angie_load_firmware_and_renumerate(angie_handle, ANGIE_FIRMWARE_FILE, ANGIE_RENUMERATION_DELAY_US); if (ret != ERROR_OK) { @@ -2266,45 +2278,29 @@ static int angie_init(void) angie_quit(); return ret; } + if (libusb_release_interface(angie_handle->usb_device_handle, 0) != LIBUSB_SUCCESS) { + LOG_ERROR("Fail release interface 0"); + return ERROR_FAIL; + } if (libusb_claim_interface(angie_handle->usb_device_handle, 1) != LIBUSB_SUCCESS) { LOG_ERROR("Could not claim interface 1"); - angie_quit(); return ERROR_FAIL; } - angie_io_extender_config(angie_handle, 0x22, 0xFF, 0xFF); - if (ret != ERROR_OK) { - LOG_ERROR("Could not configure io extender 22"); - angie_quit(); - return ret; - } - angie_io_extender_config(angie_handle, 0x23, 0xFF, 0xFF); + /* Configure io extender 23: all input */ + ret = angie_io_extender_config(angie_handle, 0x23, 0xFF); if (ret != ERROR_OK) { LOG_ERROR("Could not configure io extender 23"); - angie_quit(); - return ret; - } - angie_io_extender_config(angie_handle, 0x24, 0x1F, 0x9F); - if (ret != ERROR_OK) { - LOG_ERROR("Could not configure io extender 24"); - angie_quit(); - return ret; - } - angie_io_extender_config(angie_handle, 0x25, 0x07, 0x00); - if (ret != ERROR_OK) { - LOG_ERROR("Could not configure io extender 25"); - angie_quit(); return ret; } if (libusb_release_interface(angie_handle->usb_device_handle, 1) != LIBUSB_SUCCESS) { LOG_ERROR("Fail release interface 1"); - angie_quit(); return ERROR_FAIL; } } else { LOG_INFO("ANGIE device is already running ANGIE firmware"); } - /* Get ANGIE USB IN/OUT endpoints and claim the interface */ + /* Get ANGIE USB IN/OUT endpoints and claim the interface 0 */ ret = jtag_libusb_choose_interface(angie_handle->usb_device_handle, &angie_handle->ep_in, &angie_handle->ep_out, 0xFF, 0, 0, -1); if (ret != ERROR_OK) { @@ -2319,6 +2315,7 @@ static int angie_init(void) /* Issue one test command with short timeout */ ret = angie_append_test_cmd(angie_handle); if (ret != ERROR_OK) { + LOG_ERROR("Append test command failed."); angie_quit(); return ret; } @@ -2345,14 +2342,16 @@ static int angie_init(void) angie_clear_queue(angie_handle); + /* Execute get signals command */ ret = angie_append_get_signals_cmd(angie_handle); if (ret != ERROR_OK) { + LOG_ERROR("Append get signals command failed"); angie_quit(); return ret; } - ret = angie_execute_queued_commands(angie_handle, 200); if (ret != ERROR_OK) { + LOG_ERROR("Execute get signals command failed"); angie_quit(); return ret; } From 3fb729980c6e711146157c8c43a5e06ea6b99758 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 11 Nov 2023 20:10:41 +0100 Subject: [PATCH 0723/1312] LICENSES: Add the Apache-2.0 license for standalone files Add the full text of the Apache-2.0 license to the OpenOCD tree. It has the same content from: https://spdx.org/licenses/Apache-2.0.html#licenseText but reformatted as in the Linux kernel document and added the required tags for reference and tooling. While this commit is specific for standalone files, it already reports the information for dual licensing. Change-Id: I1fd427256c310ab733fb5d50f344ac52c64a56f5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8005 Tested-by: jenkins Reviewed-by: Erhan Kurubas --- LICENSES/stand-alone/Apache-2.0 | 189 ++++++++++++++++++++++++++++++++ Makefile.am | 1 + 2 files changed, 190 insertions(+) create mode 100644 LICENSES/stand-alone/Apache-2.0 diff --git a/LICENSES/stand-alone/Apache-2.0 b/LICENSES/stand-alone/Apache-2.0 new file mode 100644 index 0000000000..ae8128b7e6 --- /dev/null +++ b/LICENSES/stand-alone/Apache-2.0 @@ -0,0 +1,189 @@ +Valid-License-Identifier: Apache-2.0 +SPDX-URL: https://spdx.org/licenses/Apache-2.0.html +Usage-Guide: + Do NOT use on OpenOCD code. The Apache-2.0 is not GPL2 compatible. It may only + be used for dual-licensed files where the other license is GPL2 compatible. + If you end up using this it MUST be used together with a GPL2 compatible + license using "OR". + It may also be used for stand-alone code NOT linked within the OpenOCD binary + but distributed with OpenOCD. + To use the Apache License version 2.0 put the following SPDX tag/value + pair into a comment according to the placement guidelines in the + licensing rules documentation: + SPDX-License-Identifier: Apache-2.0 +License-Text: + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly + perform, sublicense, and distribute the Work and such Derivative Works + in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, + sell, import, and otherwise transfer the Work, where such license + applies only to those patent claims licensable by such Contributor that + are necessarily infringed by their Contribution(s) alone or by + combination of their Contribution(s) with the Work to which such + Contribution(s) was submitted. If You institute patent litigation + against any entity (including a cross-claim or counterclaim in a + lawsuit) alleging that the Work or a Contribution incorporated within + the Work constitutes direct or contributory patent infringement, then + any patent licenses granted to You under this License for that Work + shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, + and in Source or Object form, provided that You meet the following + conditions: + + a. You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + b. You must cause any modified files to carry prominent notices stating + that You changed the files; and + + c. You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices + from the Source form of the Work, excluding those notices that do not + pertain to any part of the Derivative Works; and + + d. If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained within + such NOTICE file, excluding those notices that do not pertain to any + part of the Derivative Works, in at least one of the following + places: within a NOTICE text file distributed as part of the + Derivative Works; within the Source form or documentation, if + provided along with the Derivative Works; or, within a display + generated by the Derivative Works, if and wherever such third-party + notices normally appear. The contents of the NOTICE file are for + informational purposes only and do not modify the License. You may + add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the + Work, provided that such additional attribution notices cannot be + construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated + in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to + the Licensor shall be under the terms and conditions of this License, + without any additional terms or conditions. Notwithstanding the above, + nothing herein shall supersede or modify the terms of any separate + license agreement you may have executed with Licensor regarding such + Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to + in writing, Licensor provides the Work (and each Contributor provides + its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied, including, without limitation, + any warranties or conditions of TITLE, NON-INFRINGEMENT, + MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely + responsible for determining the appropriateness of using or + redistributing the Work and assume any risks associated with Your + exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether + in tort (including negligence), contract, or otherwise, unless required + by applicable law (such as deliberate and grossly negligent acts) or + agreed to in writing, shall any Contributor be liable to You for + damages, including any direct, indirect, special, incidental, or + consequential damages of any character arising as a result of this + License or out of the use or inability to use the Work (including but + not limited to damages for loss of goodwill, work stoppage, computer + failure or malfunction, or any and all other commercial damages or + losses), even if such Contributor has been advised of the possibility of + such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the + Work or Derivative Works thereof, You may choose to offer, and charge a + fee for, acceptance of support, warranty, indemnity, or other liability + obligations and/or rights consistent with this License. However, in + accepting such obligations, You may act only on Your own behalf and on + Your sole responsibility, not on behalf of any other Contributor, and + only if You agree to indemnify, defend, and hold each Contributor + harmless for any liability incurred by, or claims asserted against, such + Contributor by reason of your accepting any such warranty or additional + liability. + +END OF TERMS AND CONDITIONS diff --git a/Makefile.am b/Makefile.am index 153c471a9b..1313d151b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,7 @@ EXTRA_DIST += \ LICENSES/preferred/GPL-2.0 \ LICENSES/preferred/LGPL-2.1 \ LICENSES/preferred/MIT \ + LICENSES/stand-alone/Apache-2.0 \ LICENSES/stand-alone/GPL-3.0 \ tools/logger.pl \ tools/rlink_make_speed_table \ From d7ee0e422eb5b18106b8c50b867fc20c6bcf047c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 9 Nov 2023 15:18:22 +0100 Subject: [PATCH 0724/1312] contrib/rtos-helpers/uCOS-III-openocd: change license to Apache-2.0 This file is intended to be included in any user's project that plans to use OpenOCD awareness for uCOS-III. It is supposed to be distributed under a license compatible with the uCOS-III code, that is Apache-2.0 license. Distribute it under Apache License 2.0. Change-Id: I51ecd469c8ccdd23a069d21e89b7d90886691395 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/7996 Tested-by: jenkins --- contrib/rtos-helpers/uCOS-III-openocd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/contrib/rtos-helpers/uCOS-III-openocd.c b/contrib/rtos-helpers/uCOS-III-openocd.c index 9869adf7ea..ff2789e0ab 100644 --- a/contrib/rtos-helpers/uCOS-III-openocd.c +++ b/contrib/rtos-helpers/uCOS-III-openocd.c @@ -1,4 +1,13 @@ -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-License-Identifier: Apache-2.0 + +/* + * The original version of this file did not reported any license nor + * copyright, but the author clearly stated that: + * "This file should be linked along with the [uC/OS-III user's] project + * to enable RTOS support for uC/OS-III." + * Such statement implies the willing to have this file's license compatible + * with the license Apache 2.0 of uC/OS-III. + */ /* * uC/OS-III does not provide a fixed layout for OS_TCB, which makes it From 987a274a85732e5b23c58456287982260a5959b2 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Mon, 8 Jan 2024 10:43:05 -0800 Subject: [PATCH 0725/1312] target/xtensa: update COMMAND_HELPER output to use command_print() API - Change LOG_ERROR() and LOG_INFO() output, but keep DEBUG and WARNING levels for verbosity - Update command error code return values and remove unnecessary output. Signed-off-by: Ian Thompson Change-Id: I4ef0753b3a56be02716f2db43a7d4370a1917237 Reviewed-on: https://review.openocd.org/c/openocd/+/8076 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/xtensa/xtensa.c | 86 +++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 1ec091c9f2..b516c17ab8 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3459,8 +3459,8 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) const char *parm = CMD_ARGV[0]; unsigned int parm_len = strlen(parm); if ((parm_len >= 64) || (parm_len & 1)) { - LOG_ERROR("Invalid parameter length (%d): must be even, < 64 characters", parm_len); - return ERROR_FAIL; + command_print(CMD, "Invalid parameter length (%d): must be even, < 64 characters", parm_len); + return ERROR_COMMAND_ARGUMENT_INVALID; } uint8_t ops[32]; @@ -3480,7 +3480,7 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) */ int status = xtensa_write_dirty_registers(target); if (status != ERROR_OK) { - LOG_ERROR("%s: Failed to write back register cache.", target_name(target)); + command_print(CMD, "%s: Failed to write back register cache.", target_name(target)); return ERROR_FAIL; } xtensa_reg_val_t exccause = xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE); @@ -3498,18 +3498,18 @@ static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target) xtensa_queue_exec_ins_wide(xtensa, ops, oplen); /* Handles endian-swap */ status = xtensa_dm_queue_execute(&xtensa->dbg_mod); if (status != ERROR_OK) { - LOG_TARGET_ERROR(target, "exec: queue error %d", status); + command_print(CMD, "exec: queue error %d", status); } else { status = xtensa_core_status_check(target); if (status != ERROR_OK) - LOG_TARGET_ERROR(target, "exec: status error %d", status); + command_print(CMD, "exec: status error %d", status); } /* Reread register cache and restore saved regs after instruction execution */ if (xtensa_fetch_all_regs(target) != ERROR_OK) - LOG_TARGET_ERROR(target, "post-exec: register fetch error"); + command_print(CMD, "post-exec: register fetch error"); if (status != ERROR_OK) { - LOG_TARGET_ERROR(target, "post-exec: EXCCAUSE 0x%02" PRIx32, + command_print(CMD, "post-exec: EXCCAUSE 0x%02" PRIx32, xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE)); } xtensa_reg_set(target, XT_REG_IDX_EXCCAUSE, exccause); @@ -3534,8 +3534,8 @@ COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa) } else if (strcasecmp(core_name, "NX") == 0) { xtensa->core_config->core_type = XT_NX; } else { - LOG_ERROR("xtdef [LX|NX]\n"); - return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "xtdef [LX|NX]\n"); + return ERROR_COMMAND_ARGUMENT_INVALID; } return ERROR_OK; } @@ -3592,7 +3592,7 @@ COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa) if (!xtensa_cmd_xtopt_legal_val("excmlevel", opt_val, 1, 6)) return ERROR_COMMAND_ARGUMENT_INVALID; if (!xtensa->core_config->high_irq.enabled) { - LOG_ERROR("xtopt excmlevel requires hipriints\n"); + command_print(CMD, "xtopt excmlevel requires hipriints\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->core_config->high_irq.excm_level = opt_val; @@ -3605,7 +3605,7 @@ COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa) return ERROR_COMMAND_ARGUMENT_INVALID; } if (!xtensa->core_config->high_irq.enabled) { - LOG_ERROR("xtopt intlevels requires hipriints\n"); + command_print(CMD, "xtopt intlevels requires hipriints\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->core_config->high_irq.level_num = opt_val; @@ -3662,10 +3662,8 @@ COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa) int mem_access = 0; bool is_dcache = false; - if (CMD_ARGC == 0) { - LOG_ERROR("xtmem [parameters]\n"); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } const char *mem_name = CMD_ARGV[0]; if (strcasecmp(mem_name, "icache") == 0) { @@ -3696,25 +3694,21 @@ COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa) memp = &xtensa->core_config->srom; mem_access = XT_MEM_ACCESS_READ; } else { - LOG_ERROR("xtmem types: \n"); + command_print(CMD, "xtmem types: \n"); return ERROR_COMMAND_ARGUMENT_INVALID; } if (cachep) { - if ((CMD_ARGC != 4) && (CMD_ARGC != 5)) { - LOG_ERROR("xtmem [writeback]\n"); + if (CMD_ARGC != 4 && CMD_ARGC != 5) return ERROR_COMMAND_SYNTAX_ERROR; - } cachep->line_size = strtoul(CMD_ARGV[1], NULL, 0); cachep->size = strtoul(CMD_ARGV[2], NULL, 0); cachep->way_count = strtoul(CMD_ARGV[3], NULL, 0); cachep->writeback = ((CMD_ARGC == 5) && is_dcache) ? strtoul(CMD_ARGV[4], NULL, 0) : 0; } else if (memp) { - if (CMD_ARGC != 3) { - LOG_ERROR("xtmem \n"); + if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; - } struct xtensa_local_mem_region_config *memcfgp = &memp->regions[memp->count]; memcfgp->base = strtoul(CMD_ARGV[1], NULL, 0); memcfgp->size = strtoul(CMD_ARGV[2], NULL, 0); @@ -3734,10 +3728,8 @@ COMMAND_HANDLER(xtensa_cmd_xtmem) /* xtmpu */ COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa) { - if (CMD_ARGC != 4) { - LOG_ERROR("xtmpu \n"); + if (CMD_ARGC != 4) return ERROR_COMMAND_SYNTAX_ERROR; - } unsigned int nfgseg = strtoul(CMD_ARGV[0], NULL, 0); unsigned int minsegsize = strtoul(CMD_ARGV[1], NULL, 0); @@ -3745,16 +3737,16 @@ COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa) unsigned int execonly = strtoul(CMD_ARGV[3], NULL, 0); if ((nfgseg > 32)) { - LOG_ERROR(" must be within [0..32]\n"); + command_print(CMD, " must be within [0..32]\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if (minsegsize & (minsegsize - 1)) { - LOG_ERROR(" must be a power of 2 >= 32\n"); + command_print(CMD, " must be a power of 2 >= 32\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if (lockable > 1) { - LOG_ERROR(" must be 0 or 1\n"); + command_print(CMD, " must be 0 or 1\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if (execonly > 1) { - LOG_ERROR(" must be 0 or 1\n"); + command_print(CMD, " must be 0 or 1\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -3775,18 +3767,16 @@ COMMAND_HANDLER(xtensa_cmd_xtmpu) /* xtmmu */ COMMAND_HELPER(xtensa_cmd_xtmmu_do, struct xtensa *xtensa) { - if (CMD_ARGC != 2) { - LOG_ERROR("xtmmu \n"); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } unsigned int nirefillentries = strtoul(CMD_ARGV[0], NULL, 0); unsigned int ndrefillentries = strtoul(CMD_ARGV[1], NULL, 0); if ((nirefillentries != 16) && (nirefillentries != 32)) { - LOG_ERROR(" must be 16 or 32\n"); + command_print(CMD, " must be 16 or 32\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } else if ((ndrefillentries != 16) && (ndrefillentries != 32)) { - LOG_ERROR(" must be 16 or 32\n"); + command_print(CMD, " must be 16 or 32\n"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -3809,13 +3799,13 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) if (CMD_ARGC == 1) { int32_t numregs = strtoul(CMD_ARGV[0], NULL, 0); if ((numregs <= 0) || (numregs > UINT16_MAX)) { - LOG_ERROR("xtreg : Invalid 'numregs' (%d)", numregs); - return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "xtreg : Invalid 'numregs' (%d)", numregs); + return ERROR_COMMAND_ARGUMENT_INVALID; } if ((xtensa->genpkt_regs_num > 0) && (numregs < (int32_t)xtensa->genpkt_regs_num)) { - LOG_ERROR("xtregs (%d) must be larger than numgenregs (%d) (if xtregfmt specified)", + command_print(CMD, "xtregs (%d) must be larger than numgenregs (%d) (if xtregfmt specified)", numregs, xtensa->genpkt_regs_num); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->total_regs_num = numregs; xtensa->core_regs_num = 0; @@ -3844,17 +3834,17 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) const char *regname = CMD_ARGV[0]; unsigned int regnum = strtoul(CMD_ARGV[1], NULL, 0); if (regnum > UINT16_MAX) { - LOG_ERROR(" must be a 16-bit number"); + command_print(CMD, " must be a 16-bit number"); return ERROR_COMMAND_ARGUMENT_INVALID; } if ((xtensa->num_optregs + xtensa->core_regs_num) >= xtensa->total_regs_num) { if (xtensa->total_regs_num) - LOG_ERROR("'xtreg %s 0x%04x': Too many registers (%d expected, %d core %d extended)", + command_print(CMD, "'xtreg %s 0x%04x': Too many registers (%d expected, %d core %d extended)", regname, regnum, xtensa->total_regs_num, xtensa->core_regs_num, xtensa->num_optregs); else - LOG_ERROR("'xtreg %s 0x%04x': Number of registers unspecified", + command_print(CMD, "'xtreg %s 0x%04x': Number of registers unspecified", regname, regnum); return ERROR_FAIL; } @@ -3934,7 +3924,7 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) idx = XT_NX_REG_IDX_MESRCLR; if (idx < XT_NX_REG_IDX_NUM) { if (xtensa->nx_reg_idx[idx] != 0) { - LOG_ERROR("nx_reg_idx[%d] previously set to %d", + command_print(CMD, "nx_reg_idx[%d] previously set to %d", idx, xtensa->nx_reg_idx[idx]); return ERROR_FAIL; } @@ -3981,9 +3971,9 @@ COMMAND_HELPER(xtensa_cmd_xtregfmt_do, struct xtensa *xtensa) if ((numgregs <= 0) || ((numgregs > xtensa->total_regs_num) && (xtensa->total_regs_num > 0))) { - LOG_ERROR("xtregfmt: if specified, numgregs (%d) must be <= numregs (%d)", + command_print(CMD, "xtregfmt: if specified, numgregs (%d) must be <= numregs (%d)", numgregs, xtensa->total_regs_num); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } xtensa->genpkt_regs_num = numgregs; } @@ -4099,7 +4089,7 @@ COMMAND_HELPER(xtensa_cmd_perfmon_dump_do, struct xtensa *xtensa) "%-12" PRIu64 "%s", result.value, result.overflow ? " (overflow)" : ""); - LOG_INFO("%s", result_buf); + command_print(CMD, "%s", result_buf); } return ERROR_OK; @@ -4349,21 +4339,21 @@ COMMAND_HELPER(xtensa_cmd_tracedump_do, struct xtensa *xtensa, const char *fname } memsz = trace_config.memaddr_end - trace_config.memaddr_start + 1; - LOG_INFO("Total trace memory: %d words", memsz); + command_print(CMD, "Total trace memory: %d words", memsz); if ((trace_config.addr & ((TRAXADDR_TWRAP_MASK << TRAXADDR_TWRAP_SHIFT) | TRAXADDR_TWSAT)) == 0) { /*Memory hasn't overwritten itself yet. */ wmem = trace_config.addr & TRAXADDR_TADDR_MASK; - LOG_INFO("...but trace is only %d words", wmem); + command_print(CMD, "...but trace is only %d words", wmem); if (wmem < memsz) memsz = wmem; } else { if (trace_config.addr & TRAXADDR_TWSAT) { - LOG_INFO("Real trace is many times longer than that (overflow)"); + command_print(CMD, "Real trace is many times longer than that (overflow)"); } else { uint32_t trc_sz = (trace_config.addr >> TRAXADDR_TWRAP_SHIFT) & TRAXADDR_TWRAP_MASK; trc_sz = (trc_sz * memsz) + (trace_config.addr & TRAXADDR_TADDR_MASK); - LOG_INFO("Real trace is %d words, but the start has been truncated.", trc_sz); + command_print(CMD, "Real trace is %d words, but the start has been truncated.", trc_sz); } } From 80b970bd29093a1e3e3b5fdeacda4958721a5afd Mon Sep 17 00:00:00 2001 From: Jacek Wuwer Date: Tue, 9 Jan 2024 11:23:56 +0100 Subject: [PATCH 0726/1312] jtag/vdebug: fix socket options on CYGWIN the socket option RCVLOWAT is not supported on CYGWIN. implemented ifdef __CYGWIN not to set this option. Change-Id: I9f6e81fa98ecf5261ea286deb4675658aae59b8e Signed-off-by: Jacek Wuwer Reviewed-on: https://review.openocd.org/c/openocd/+/8066 Tested-by: jenkins Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo --- src/jtag/drivers/vdebug.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index d2311b2ea8..d51d248bfc 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -53,7 +53,7 @@ #include "helper/log.h" #include "helper/list.h" -#define VD_VERSION 46 +#define VD_VERSION 47 #define VD_BUFFER_LEN 4024 #define VD_CHEADER_LEN 24 #define VD_SHEADER_LEN 16 @@ -253,6 +253,11 @@ static int vdebug_socket_open(char *server_addr, uint32_t port) hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (hsock == INVALID_SOCKET) rc = vdebug_socket_error(); +#elif defined __CYGWIN__ + /* SO_RCVLOWAT unsupported on CYGWIN */ + hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (hsock < 0) + rc = errno; #else uint32_t rcvwat = VD_SHEADER_LEN; /* size of the rcv header, as rcv min watermark */ hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); From 151b743714382120dbe0dee0e0eeb75826ef5b3a Mon Sep 17 00:00:00 2001 From: Jacek Wuwer Date: Tue, 9 Jan 2024 14:57:29 +0100 Subject: [PATCH 0727/1312] jtag/vdebug: add support for DAP6 This change implements the support for the ARM Debug Interface v6. The DAP-level interface properly selects the DP Banks and AP address. Sample ARM configuration DAP and JTAG scripts have been updated. Change-Id: I7df87ef764bca587697c778810443649a7f46c2b Signed-off-by: Jacek Wuwer Reviewed-on: https://review.openocd.org/c/openocd/+/8067 Tested-by: jenkins Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo --- src/jtag/drivers/vdebug.c | 87 +++++++++++++++++++++++++++---------- tcl/board/vd_a53x2_dap.cfg | 19 ++++---- tcl/board/vd_a53x2_jtag.cfg | 20 +++++---- tcl/board/vd_a75x4_dap.cfg | 30 +++++++++++++ tcl/board/vd_a75x4_jtag.cfg | 30 +++++++++++++ tcl/board/vd_m4_dap.cfg | 14 +++--- tcl/board/vd_m4_jtag.cfg | 15 +++---- tcl/board/vd_m7_jtag.cfg | 15 +++---- tcl/target/vd_aarch64.cfg | 50 ++++++++++++--------- tcl/target/vd_cortex_m.cfg | 11 ++--- 10 files changed, 200 insertions(+), 91 deletions(-) create mode 100644 tcl/board/vd_a75x4_dap.cfg create mode 100644 tcl/board/vd_a75x4_jtag.cfg diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index d51d248bfc..6d9016e9c6 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -53,7 +53,7 @@ #include "helper/log.h" #include "helper/list.h" -#define VD_VERSION 47 +#define VD_VERSION 48 #define VD_BUFFER_LEN 4024 #define VD_CHEADER_LEN 24 #define VD_SHEADER_LEN 16 @@ -66,7 +66,8 @@ * @brief List of transactor types */ enum { - VD_BFM_JTDP = 0x0001, /* transactor DAP JTAG DP */ + VD_BFM_TPIU = 0x0000, /* transactor trace TPIU */ + VD_BFM_DAP6 = 0x0001, /* transactor DAP ADI V6 */ VD_BFM_SWDP = 0x0002, /* transactor DAP SWD DP */ VD_BFM_AHB = 0x0003, /* transactor AMBA AHB */ VD_BFM_APB = 0x0004, /* transactor AMBA APB */ @@ -467,14 +468,14 @@ static int vdebug_run_reg_queue(int hsock, struct vd_shm *pm, unsigned int count for (unsigned int j = 0; j < num; j++) memcpy(&data[j * awidth], &pm->rd8[(rwords + j) * awidth], awidth); } - LOG_DEBUG_IO("read %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, - aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, + LOG_DEBUG("read %04x AS:%1x RG:%1x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, + aspace, addr << 2, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, (num ? le_to_h_u32(&pm->rd8[rwords * 4]) : 0xdead)); rwords += num * wwidth; waddr += sizeof(uint64_t) / 4; /* waddr past header */ } else { - LOG_DEBUG_IO("write %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, - aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, + LOG_DEBUG("write %04x AS:%1x RG:%1x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, + aspace, addr << 2, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, le_to_h_u32(&pm->wd8[(waddr + num + 1) * 4])); waddr += sizeof(uint64_t) / 4 + (num * wwidth * awidth + 3) / 4; } @@ -518,7 +519,7 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path, rc = VD_ERR_VERSION; } else { pm->cmd = VD_CMD_CONNECT; - pm->type = type; /* BFM type to connect to, here JTAG */ + pm->type = type; /* BFM type to connect to */ h_u32_to_le(pm->rwdata, sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16)); h_u16_to_le(pm->wbytes, strlen(path) + 1); h_u16_to_le(pm->rbytes, 12); @@ -922,7 +923,7 @@ static int vdebug_reset(int trst, int srst) static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush) { - LOG_INFO("tms len:%d tms:%x", num, *tms); + LOG_DEBUG_IO("tms len:%d tms:%x", num, *tms); return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num, *tms, 0, NULL, 0, 0, NULL, f_flush); } @@ -930,7 +931,7 @@ static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush) static int vdebug_jtag_path_move(struct pathmove_command *cmd, uint8_t f_flush) { uint8_t tms[DIV_ROUND_UP(cmd->num_states, 8)]; - LOG_INFO("path num states %d", cmd->num_states); + LOG_DEBUG_IO("path num states %d", cmd->num_states); memset(tms, 0, DIV_ROUND_UP(cmd->num_states, 8)); @@ -950,7 +951,7 @@ static int vdebug_jtag_tlr(tap_state_t state, uint8_t f_flush) tap_state_t cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); - LOG_INFO("tlr from %x to %x", cur, state); + LOG_DEBUG_IO("tlr from %x to %x", cur, state); if (cur != state) { rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, 0, NULL, 0, 0, NULL, f_flush); tap_set_state(state); @@ -970,7 +971,7 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) uint8_t tms_post = tap_get_tms_path(state, cmd->end_state); uint8_t num_post = tap_get_tms_path_len(state, cmd->end_state); int num_bits = jtag_scan_size(cmd); - LOG_DEBUG("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x", + LOG_DEBUG_IO("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x", num_bits, cmd->num_fields, cmd->ir_scan, cur, cmd->end_state); for (int i = 0; i < cmd->num_fields; i++) { uint8_t cur_num_pre = i == 0 ? num_pre : 0; @@ -996,7 +997,7 @@ static int vdebug_jtag_runtest(int cycles, tap_state_t state, uint8_t f_flush) tap_state_t cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); - LOG_DEBUG("idle len:%d state cur:%x end:%x", cycles, cur, state); + LOG_DEBUG_IO("idle len:%d state cur:%x end:%x", cycles, cur, state); int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, cycles, NULL, 0, 0, NULL, f_flush); if (cur != state) tap_set_state(state); @@ -1006,7 +1007,7 @@ static int vdebug_jtag_runtest(int cycles, tap_state_t state, uint8_t f_flush) static int vdebug_jtag_stableclocks(int num, uint8_t f_flush) { - LOG_INFO("stab len:%d state cur:%x", num, tap_get_state()); + LOG_DEBUG("stab len:%d state cur:%x", num, tap_get_state()); return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num, NULL, 0, 0, NULL, f_flush); } @@ -1081,6 +1082,41 @@ static int vdebug_jtag_execute_queue(void) return rc; } +static int vdebug_dap_bankselect(struct adiv5_ap *ap, unsigned int reg) +{ + int rc = ERROR_OK; + uint64_t sel; + + if (is_adiv6(ap->dap)) { + sel = ap->ap_num | (reg & 0x00000FF0); + if (sel != (ap->dap->select & ~0xfull)) { + sel |= ap->dap->select & DP_SELECT_DPBANK; + if (ap->dap->asize > 32) + sel |= (DP_SELECT1 >> 4) & DP_SELECT_DPBANK; + ap->dap->select = sel; + ap->dap->select_valid = true; + rc = vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, (uint32_t)sel, VD_ASPACE_DP, 0); + if (rc == ERROR_OK) { + ap->dap->select_valid = true; + if (ap->dap->asize > 32) + rc = vdebug_reg_write(vdc.hsocket, pbuf, (DP_SELECT1 & DP_SELECT_DPBANK) >> 2, + (uint32_t)(sel >> 32), VD_ASPACE_DP, 0); + if (rc == ERROR_OK) + ap->dap->select1_valid = true; + } + } + } else { /* ADIv5 */ + sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK); + if (sel != ap->dap->select) { + ap->dap->select = sel; + rc = vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, (uint32_t)sel, VD_ASPACE_DP, 0); + if (rc == ERROR_OK) + ap->dap->select_valid = true; + } + } + return rc; +} + static int vdebug_dap_connect(struct adiv5_dap *dap) { return dap_dp_init(dap); @@ -1093,20 +1129,29 @@ static int vdebug_dap_send_sequence(struct adiv5_dap *dap, enum swd_special_seq static int vdebug_dap_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) { + if (reg != DP_SELECT && reg != DP_RDBUFF + && (!dap->select_valid || ((reg >> 4) & DP_SELECT_DPBANK) != (dap->select & DP_SELECT_DPBANK))) { + dap->select = (dap->select & ~DP_SELECT_DPBANK) | ((reg >> 4) & DP_SELECT_DPBANK); + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, dap->select, VD_ASPACE_DP, 0); + dap->select_valid = true; + } return vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0); } static int vdebug_dap_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { + if (reg != DP_SELECT && reg != DP_RDBUFF + && (!dap->select_valid || ((reg >> 4) & DP_SELECT_DPBANK) != (dap->select & DP_SELECT_DPBANK))) { + dap->select = (dap->select & ~DP_SELECT_DPBANK) | ((reg >> 4) & DP_SELECT_DPBANK); + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, dap->select, VD_ASPACE_DP, 0); + dap->select_valid = true; + } return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0); } static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { - if ((reg & ADIV5_DP_SELECT_APBANK) != ap->dap->select) { - vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & ADIV5_DP_SELECT_APBANK, VD_ASPACE_DP, 0); - ap->dap->select = reg & ADIV5_DP_SELECT_APBANK; - } + vdebug_dap_bankselect(ap, reg); vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0); @@ -1115,11 +1160,7 @@ static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint3 static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { - if ((reg & ADIV5_DP_SELECT_APBANK) != ap->dap->select) { - vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & ADIV5_DP_SELECT_APBANK, VD_ASPACE_DP, 0); - ap->dap->select = reg & ADIV5_DP_SELECT_APBANK; - } - + vdebug_dap_bankselect(ap, reg); return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0); } @@ -1175,7 +1216,7 @@ COMMAND_HANDLER(vdebug_set_bfm) break; } if (transport_is_dapdirect_swd()) - vdc.bfm_type = VD_BFM_SWDP; + vdc.bfm_type = strstr(vdc.bfm_path, "dap6") ? VD_BFM_DAP6 : VD_BFM_SWDP; else vdc.bfm_type = VD_BFM_JTAG; LOG_DEBUG("bfm_path: %s clk_period %ups", vdc.bfm_path, vdc.bfm_period); diff --git a/tcl/board/vd_a53x2_dap.cfg b/tcl/board/vd_a53x2_dap.cfg index 4cf5594d32..bcf8b44098 100644 --- a/tcl/board/vd_a53x2_dap.cfg +++ b/tcl/board/vd_a53x2_dap.cfg @@ -4,10 +4,13 @@ source [find interface/vdebug.cfg] -set _CORES 2 -set _CHIPNAME a53 -set _MEMSTART 0x00000000 -set _MEMSIZE 0x1000000 +set CORES 2 +set CHIPNAME a53 +set ACCESSPORT 0 +set MEMSTART 0x00000000 +set MEMSIZE 0x1000000 +set DBGBASE {0x80810000 0x80910000} +set CTIBASE {0x80820000 0x80920000} # vdebug select transport transport select dapdirect_swd @@ -19,11 +22,9 @@ adapter srst delay 5 # BFM hierarchical path and input clk period vdebug bfm_path tbench.u_vd_swdp_bfm 10ns -# DMA Memories to access backdoor (up to 4) -vdebug mem_path tbench.u_memory.mem_array $_MEMSTART $_MEMSIZE +# DMA Memories to access backdoor (up to 20) +vdebug mem_path tbench.u_memory.mem_array $MEMSTART $MEMSIZE -source [find target/swj-dp.tcl] - -swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf +swd newdap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf source [find target/vd_aarch64.cfg] diff --git a/tcl/board/vd_a53x2_jtag.cfg b/tcl/board/vd_a53x2_jtag.cfg index a5e8d24e55..0c3eebd7a7 100644 --- a/tcl/board/vd_a53x2_jtag.cfg +++ b/tcl/board/vd_a53x2_jtag.cfg @@ -4,11 +4,14 @@ source [find interface/vdebug.cfg] -set _CORES 2 -set _CHIPNAME a53 -set _MEMSTART 0x00000000 -set _MEMSIZE 0x1000000 -set _CPUTAPID 0x5ba00477 +set CORES 2 +set CHIPNAME a53 +set ACCESSPORT 0 +set MEMSTART 0x00000000 +set MEMSIZE 0x1000000 +set DBGBASE {0x80810000 0x80910000} +set CTIBASE {0x80820000 0x80920000} +set CPUTAPID 0x5ba00477 # vdebug select transport transport select jtag @@ -21,11 +24,10 @@ adapter srst delay 5 # BFM hierarchical path and input clk period vdebug bfm_path tbench.u_vd_jtag_bfm 10ns -# DMA Memories to access backdoor (up to 4) -vdebug mem_path tbench.u_memory.mem_array $_MEMSTART $_MEMSIZE - -jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +# DMA Memories to access backdoor (up to 20) +vdebug mem_path tbench.u_memory.mem_array $MEMSTART $MEMSIZE +jtag newtap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $CPUTAPID jtag arp_init-reset source [find target/vd_aarch64.cfg] diff --git a/tcl/board/vd_a75x4_dap.cfg b/tcl/board/vd_a75x4_dap.cfg new file mode 100644 index 0000000000..5c2a2efe87 --- /dev/null +++ b/tcl/board/vd_a75x4_dap.cfg @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex A53x2 through DAP + +source [find interface/vdebug.cfg] + +set CORES 4 +set CHIPNAME a75 +set ACCESSPORT 0x00040000 +set MEMSTART 0x00000000 +set MEMSIZE 0x1000000 +set DBGBASE {0x01010000 0x01110000 0x01210000 0x01310000} +set CTIBASE {0x01020000 0x01120000 0x01220000 0x01320000} + +# vdebug select transport +transport select dapdirect_swd + +# JTAG reset config, frequency and reset delay +adapter speed 200000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_dap6_bfm 2250ps + +# DMA Memories to access backdoor (up to 20) +#vdebug mem_path tbench.u_memory.mem_array $_MEMSTART $_MEMSIZE + +swd newdap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf + +source [find target/vd_aarch64.cfg] diff --git a/tcl/board/vd_a75x4_jtag.cfg b/tcl/board/vd_a75x4_jtag.cfg new file mode 100644 index 0000000000..c94a71972d --- /dev/null +++ b/tcl/board/vd_a75x4_jtag.cfg @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex A53x2 through DAP + +source [find interface/vdebug.cfg] + +set CORES 4 +set CHIPNAME a75 +set ACCESSPORT 0x00040000 +set MEMSTART 0x00000000 +set MEMSIZE 0x1000000 +set DBGBASE {0x01010000 0x01110000 0x01210000 0x01310000} +set CTIBASE {0x01020000 0x01120000 0x01220000 0x01320000} +set CPUTAPID 0x4ba06477 + +# vdebug select transport +transport select jtag + +# JTAG reset config, frequency and reset delay +reset_config trst_and_srst +adapter speed 1500000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_jtag_bfm 333ps + +jtag newtap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $CPUTAPID +jtag arp_init-reset + +source [find target/vd_aarch64.cfg] diff --git a/tcl/board/vd_m4_dap.cfg b/tcl/board/vd_m4_dap.cfg index 691b6235f6..5d3605aa37 100644 --- a/tcl/board/vd_m4_dap.cfg +++ b/tcl/board/vd_m4_dap.cfg @@ -4,9 +4,9 @@ source [find interface/vdebug.cfg] -set _CHIPNAME m4 -set _MEMSTART 0x00000000 -set _MEMSIZE 0x10000 +set CHIPNAME m4 +set MEMSTART 0x00000000 +set MEMSIZE 0x10000 # vdebug select transport transport select dapdirect_swd @@ -16,11 +16,9 @@ adapter srst delay 5 # BFM hierarchical path and input clk period vdebug bfm_path tbench.u_vd_swdp_bfm 20ns -# DMA Memories to access backdoor (up to 4) -vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $_MEMSTART $_MEMSIZE +# DMA Memories to access backdoor (up to 20) +vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $MEMSTART $MEMSIZE -source [find target/swj-dp.tcl] - -swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf +swd newdap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf source [find target/vd_cortex_m.cfg] diff --git a/tcl/board/vd_m4_jtag.cfg b/tcl/board/vd_m4_jtag.cfg index 4c795ebfd0..3b32e17be3 100644 --- a/tcl/board/vd_m4_jtag.cfg +++ b/tcl/board/vd_m4_jtag.cfg @@ -4,10 +4,10 @@ source [find interface/vdebug.cfg] -set _CHIPNAME m4 -set _MEMSTART 0x00000000 -set _MEMSIZE 0x10000 -set _CPUTAPID 0x4ba00477 +set CHIPNAME m4 +set MEMSTART 0x00000000 +set MEMSIZE 0x10000 +set CPUTAPID 0x4ba00477 # vdebug select transport transport select jtag @@ -20,11 +20,10 @@ adapter srst delay 5 # BFM hierarchical path and input clk period vdebug bfm_path tbench.u_vd_jtag_bfm 20ns -# DMA Memories to access backdoor (up to 4) -vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $_MEMSTART $_MEMSIZE - -jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +# DMA Memories to access backdoor (up to 20) +vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $MEMSTART $MEMSIZE +jtag newtap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $CPUTAPID jtag arp_init-reset source [find target/vd_cortex_m.cfg] diff --git a/tcl/board/vd_m7_jtag.cfg b/tcl/board/vd_m7_jtag.cfg index 880ef9b4c2..9a89584c83 100644 --- a/tcl/board/vd_m7_jtag.cfg +++ b/tcl/board/vd_m7_jtag.cfg @@ -4,10 +4,10 @@ source [find interface/vdebug.cfg] -set _CHIPNAME m7 -set _MEMSTART 0x00000000 -set _MEMSIZE 0x100000 -set _CPUTAPID 0x0ba02477 +set CHIPNAME m7 +set MEMSTART 0x00000000 +set MEMSIZE 0x100000 +set CPUTAPID 0x0ba02477 # vdebug select JTAG transport transport select jtag @@ -20,11 +20,10 @@ adapter srst delay 5 # BFM hierarchical path and input clk period vdebug bfm_path tbench.u_vd_jtag_bfm 10ns -# DMA Memories to access backdoor (up to 4) -vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $_MEMSTART $_MEMSIZE - -jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +# DMA Memories to access backdoor (up to 20) +vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $MEMSTART $MEMSIZE +jtag newtap $CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $CPUTAPID jtag arp_init-reset source [find target/vd_cortex_m.cfg] diff --git a/tcl/target/vd_aarch64.cfg b/tcl/target/vd_aarch64.cfg index 619134aa64..177416bd0a 100644 --- a/tcl/target/vd_aarch64.cfg +++ b/tcl/target/vd_aarch64.cfg @@ -2,36 +2,44 @@ # Cadence virtual debug interface # Arm v8 64b Cortex A -if {![info exists _CORES]} { - set _CORES 1 +if {![info exists CORES]} { + set CORES 1 } -if {![info exists _CHIPNAME]} { - set _CHIPNAME aarch64 +if {![info exists CHIPNAME]} { + set CHIPNAME aarch64 +} +if {[info exists ACCESSPORT]} { + set _APNUM "-ap-num $ACCESSPORT" + if { $ACCESSPORT > 0xff } { + set _DAP6 "-adiv6" + } else { + set _DAP6 "-adiv5" + } +} else { + set _APNUM "" } -set _TARGETNAME $_CHIPNAME.cpu -set _CTINAME $_CHIPNAME.cti -set DBGBASE {0x80810000 0x80910000} -set CTIBASE {0x80820000 0x80920000} +set _TARGETNAME $CHIPNAME.cpu +set _CTINAME $CHIPNAME.cti +set _DAPNAME $CHIPNAME.dap -dap create $_CHIPNAME.dap -chain-position $_TARGETNAME -$_CHIPNAME.dap apsel 1 +dap create $_DAPNAME $_DAP6 -chain-position $_TARGETNAME -for { set _core 0 } { $_core < $_CORES } { incr _core } \ +for { set _core 0 } { $_core < $CORES } { incr _core } \ { - cti create $_CTINAME.$_core -dap $_CHIPNAME.dap -ap-num 1 -baseaddr [lindex $CTIBASE $_core] - set _command "target create $_TARGETNAME.$_core aarch64 -dap $_CHIPNAME.dap \ - -dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core -coreid $_core" + set _cmd "cti create $_CTINAME.$_core -dap $_DAPNAME $_APNUM -baseaddr [lindex $CTIBASE $_core]" + eval $_cmd + set _cmd "target create $_TARGETNAME.$_core aarch64 -dap $_DAPNAME $_APNUM -dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core -coreid $_core" if { $_core != 0 } { # non-boot core examination may fail - set _command "$_command -defer-examine" - set _smp_command "$_smp_command $_TARGETNAME.$_core" + set _cmd "$_cmd -defer-examine" + set _smp_cmd "$_smp_cmd $_TARGETNAME.$_core" } else { - set _smp_command "target smp $_TARGETNAME.$_core" + set _smp_cmd "target smp $_TARGETNAME.$_core" } - eval $_command + eval $_cmd } -eval $_smp_command +eval $_smp_cmd -# default target is core 0 -targets $_TARGETNAME.0 +set _TARGETCUR $_TARGETNAME.0 +targets $_TARGETCUR diff --git a/tcl/target/vd_cortex_m.cfg b/tcl/target/vd_cortex_m.cfg index 4d7b0df267..7db9d3aba4 100644 --- a/tcl/target/vd_cortex_m.cfg +++ b/tcl/target/vd_cortex_m.cfg @@ -2,11 +2,12 @@ # Cadence virtual debug interface # ARM Cortex M -if {![info exists _CHIPNAME]} { - set _CHIPNAME cortex_m +if {![info exists CHIPNAME]} { + set CHIPNAME cortex_m } -set _TARGETNAME $_CHIPNAME.cpu +set _TARGETNAME $CHIPNAME.cpu +set _DAPNAME $CHIPNAME.dap -dap create $_CHIPNAME.dap -chain-position $_TARGETNAME +dap create $_DAPNAME -chain-position $_TARGETNAME -target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap +target create $_TARGETNAME cortex_m -dap $_DAPNAME From 3d3f82392045384e4cfe81bf19140a60312a47e8 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Thu, 18 Jan 2024 16:10:26 -0800 Subject: [PATCH 0728/1312] target/xtensa: add dual-core support - Example for configuring multiple non-SMP Xtensa cores e.g. for heterogeneous debug - JTAG only at this time; DAP out of scope - Dual-Xtensa Palladium example via VDebug - Update Xtensa core config examples Signed-off-by: Ian Thompson Change-Id: I6d2b3d13fa8075416dcd383cf256a3e8582ee1c1 Reviewed-on: https://review.openocd.org/c/openocd/+/8078 Tested-by: jenkins Reviewed-by: Jacek Wuwer Reviewed-by: Antonio Borneo --- tcl/board/xtensa-palladium-vdebug-dual.cfg | 33 ++ tcl/board/xtensa-palladium-vdebug.cfg | 16 +- tcl/target/xtensa-core-nxp_rt600.cfg | 456 +++++++++++---------- tcl/target/xtensa-core-xt8.cfg | 297 +++++++------- tcl/target/xtensa.cfg | 25 +- 5 files changed, 455 insertions(+), 372 deletions(-) create mode 100644 tcl/board/xtensa-palladium-vdebug-dual.cfg diff --git a/tcl/board/xtensa-palladium-vdebug-dual.cfg b/tcl/board/xtensa-palladium-vdebug-dual.cfg new file mode 100644 index 0000000000..447bc1fa0c --- /dev/null +++ b/tcl/board/xtensa-palladium-vdebug-dual.cfg @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# for Palladium emulation systems +# + +source [find interface/vdebug.cfg] + +# vdebug select JTAG transport +transport select jtag + +# JTAG reset config, frequency and reset delay +reset_config trst_and_srst +adapter speed 50000 +adapter srst delay 5 + +# Future improvement: Enable backdoor memory access +# set _MEMSTART 0x00000000 +# set _MEMSIZE 0x100000 + +# BFM hierarchical path and input clk period +vdebug bfm_path Testbench.VJTAG 10ns + +# DMA Memories to access backdoor (up to 4) +# vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $_MEMSTART $_MEMSIZE + +# Configure dual-core TAP chain +set XTENSA_NUM_CORES 2 + +# Create Xtensa target first +source [find target/xtensa.cfg] + +# Configure Xtensa core parameters next +# Generate [xtensa-core-XXX.cfg] via "xt-gdb --dump-oocd-config" diff --git a/tcl/board/xtensa-palladium-vdebug.cfg b/tcl/board/xtensa-palladium-vdebug.cfg index d4a700e36d..f14d92da86 100644 --- a/tcl/board/xtensa-palladium-vdebug.cfg +++ b/tcl/board/xtensa-palladium-vdebug.cfg @@ -13,4 +13,18 @@ reset_config trst_and_srst adapter speed 50000 adapter srst delay 5 -source [find target/vd_xtensa_jtag.cfg] +# Future improvement: Enable backdoor memory access +# set _MEMSTART 0x00000000 +# set _MEMSIZE 0x100000 + +# BFM hierarchical path and input clk period +vdebug bfm_path Testbench.VJTAG 10ns + +# DMA Memories to access backdoor (up to 4) +# vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $_MEMSTART $_MEMSIZE + +# Create Xtensa target first +source [find target/xtensa.cfg] + +# Configure Xtensa core parameters next +# Generate [xtensa-core-XXX.cfg] via "xt-gdb --dump-oocd-config" diff --git a/tcl/target/xtensa-core-nxp_rt600.cfg b/tcl/target/xtensa-core-nxp_rt600.cfg index abd961e4f5..ca7fd68480 100644 --- a/tcl/target/xtensa-core-nxp_rt600.cfg +++ b/tcl/target/xtensa-core-nxp_rt600.cfg @@ -2,246 +2,254 @@ # OpenOCD configuration file for Xtensa HiFi DSP in NXP RT600 target +# Core instance default definition +if { [info exists XTNAME] } { + set _XTNAME $XTNAME +} else { + set _XTNAME xtensa.cpu +} + + # Core definition and ABI -xtensa xtdef LX -xtensa xtopt arnum 32 -xtensa xtopt windowed 1 +$_XTNAME xtensa xtdef LX +$_XTNAME xtensa xtopt arnum 32 +$_XTNAME xtensa xtopt windowed 1 # Exception/Interrupt Options -xtensa xtopt exceptions 1 -xtensa xtopt hipriints 1 -xtensa xtopt intlevels 4 -xtensa xtopt excmlevel 2 +$_XTNAME xtensa xtopt exceptions 1 +$_XTNAME xtensa xtopt hipriints 1 +$_XTNAME xtensa xtopt intlevels 4 +$_XTNAME xtensa xtopt excmlevel 2 # Cache Options -xtensa xtmem icache 256 32768 4 -xtensa xtmem dcache 256 65536 4 1 +$_XTNAME xtensa xtmem icache 256 32768 4 +$_XTNAME xtensa xtmem dcache 256 65536 4 1 # Memory Options -xtensa xtmem iram 0x24020000 65536 -xtensa xtmem dram 0x24000000 65536 -xtensa xtmem sram 0x00000000 603979776 +$_XTNAME xtensa xtmem iram 0x24020000 65536 +$_XTNAME xtensa xtmem dram 0x24000000 65536 +$_XTNAME xtensa xtmem sram 0x00000000 603979776 # Memory Protection/Translation Options # Debug Options -xtensa xtopt debuglevel 4 -xtensa xtopt ibreaknum 2 -xtensa xtopt dbreaknum 2 +$_XTNAME xtensa xtopt debuglevel 4 +$_XTNAME xtensa xtopt ibreaknum 2 +$_XTNAME xtensa xtopt dbreaknum 2 # Core Registers -xtensa xtregs 208 -xtensa xtreg pc 0x0020 -xtensa xtreg ar0 0x0100 -xtensa xtreg ar1 0x0101 -xtensa xtreg ar2 0x0102 -xtensa xtreg ar3 0x0103 -xtensa xtreg ar4 0x0104 -xtensa xtreg ar5 0x0105 -xtensa xtreg ar6 0x0106 -xtensa xtreg ar7 0x0107 -xtensa xtreg ar8 0x0108 -xtensa xtreg ar9 0x0109 -xtensa xtreg ar10 0x010a -xtensa xtreg ar11 0x010b -xtensa xtreg ar12 0x010c -xtensa xtreg ar13 0x010d -xtensa xtreg ar14 0x010e -xtensa xtreg ar15 0x010f -xtensa xtreg ar16 0x0110 -xtensa xtreg ar17 0x0111 -xtensa xtreg ar18 0x0112 -xtensa xtreg ar19 0x0113 -xtensa xtreg ar20 0x0114 -xtensa xtreg ar21 0x0115 -xtensa xtreg ar22 0x0116 -xtensa xtreg ar23 0x0117 -xtensa xtreg ar24 0x0118 -xtensa xtreg ar25 0x0119 -xtensa xtreg ar26 0x011a -xtensa xtreg ar27 0x011b -xtensa xtreg ar28 0x011c -xtensa xtreg ar29 0x011d -xtensa xtreg ar30 0x011e -xtensa xtreg ar31 0x011f -xtensa xtreg lbeg 0x0200 -xtensa xtreg lend 0x0201 -xtensa xtreg lcount 0x0202 -xtensa xtreg sar 0x0203 -xtensa xtreg prefctl 0x0228 -xtensa xtreg windowbase 0x0248 -xtensa xtreg windowstart 0x0249 -xtensa xtreg configid0 0x02b0 -xtensa xtreg configid1 0x02d0 -xtensa xtreg ps 0x02e6 -xtensa xtreg threadptr 0x03e7 -xtensa xtreg br 0x0204 -xtensa xtreg scompare1 0x020c -xtensa xtreg acclo 0x0210 -xtensa xtreg acchi 0x0211 -xtensa xtreg m0 0x0220 -xtensa xtreg m1 0x0221 -xtensa xtreg m2 0x0222 -xtensa xtreg m3 0x0223 -xtensa xtreg expstate 0x03e6 -xtensa xtreg f64r_lo 0x03ea -xtensa xtreg f64r_hi 0x03eb -xtensa xtreg f64s 0x03ec -xtensa xtreg ae_ovf_sar 0x03f0 -xtensa xtreg ae_bithead 0x03f1 -xtensa xtreg ae_ts_fts_bu_bp 0x03f2 -xtensa xtreg ae_cw_sd_no 0x03f3 -xtensa xtreg ae_cbegin0 0x03f6 -xtensa xtreg ae_cend0 0x03f7 -xtensa xtreg ae_cbegin1 0x03f8 -xtensa xtreg ae_cend1 0x03f9 -xtensa xtreg aed0 0x1010 -xtensa xtreg aed1 0x1011 -xtensa xtreg aed2 0x1012 -xtensa xtreg aed3 0x1013 -xtensa xtreg aed4 0x1014 -xtensa xtreg aed5 0x1015 -xtensa xtreg aed6 0x1016 -xtensa xtreg aed7 0x1017 -xtensa xtreg aed8 0x1018 -xtensa xtreg aed9 0x1019 -xtensa xtreg aed10 0x101a -xtensa xtreg aed11 0x101b -xtensa xtreg aed12 0x101c -xtensa xtreg aed13 0x101d -xtensa xtreg aed14 0x101e -xtensa xtreg aed15 0x101f -xtensa xtreg u0 0x1020 -xtensa xtreg u1 0x1021 -xtensa xtreg u2 0x1022 -xtensa xtreg u3 0x1023 -xtensa xtreg aep0 0x1024 -xtensa xtreg aep1 0x1025 -xtensa xtreg aep2 0x1026 -xtensa xtreg aep3 0x1027 -xtensa xtreg fcr_fsr 0x1029 -xtensa xtreg mmid 0x0259 -xtensa xtreg ibreakenable 0x0260 -xtensa xtreg memctl 0x0261 -xtensa xtreg atomctl 0x0263 -xtensa xtreg ddr 0x0268 -xtensa xtreg ibreaka0 0x0280 -xtensa xtreg ibreaka1 0x0281 -xtensa xtreg dbreaka0 0x0290 -xtensa xtreg dbreaka1 0x0291 -xtensa xtreg dbreakc0 0x02a0 -xtensa xtreg dbreakc1 0x02a1 -xtensa xtreg epc1 0x02b1 -xtensa xtreg epc2 0x02b2 -xtensa xtreg epc3 0x02b3 -xtensa xtreg epc4 0x02b4 -xtensa xtreg epc5 0x02b5 -xtensa xtreg depc 0x02c0 -xtensa xtreg eps2 0x02c2 -xtensa xtreg eps3 0x02c3 -xtensa xtreg eps4 0x02c4 -xtensa xtreg eps5 0x02c5 -xtensa xtreg excsave1 0x02d1 -xtensa xtreg excsave2 0x02d2 -xtensa xtreg excsave3 0x02d3 -xtensa xtreg excsave4 0x02d4 -xtensa xtreg excsave5 0x02d5 -xtensa xtreg cpenable 0x02e0 -xtensa xtreg interrupt 0x02e2 -xtensa xtreg intset 0x02e2 -xtensa xtreg intclear 0x02e3 -xtensa xtreg intenable 0x02e4 -xtensa xtreg vecbase 0x02e7 -xtensa xtreg exccause 0x02e8 -xtensa xtreg debugcause 0x02e9 -xtensa xtreg ccount 0x02ea -xtensa xtreg prid 0x02eb -xtensa xtreg icount 0x02ec -xtensa xtreg icountlevel 0x02ed -xtensa xtreg excvaddr 0x02ee -xtensa xtreg ccompare0 0x02f0 -xtensa xtreg ccompare1 0x02f1 -xtensa xtreg misc0 0x02f4 -xtensa xtreg misc1 0x02f5 -xtensa xtreg pwrctl 0x2024 -xtensa xtreg pwrstat 0x2025 -xtensa xtreg eristat 0x2026 -xtensa xtreg cs_itctrl 0x2027 -xtensa xtreg cs_claimset 0x2028 -xtensa xtreg cs_claimclr 0x2029 -xtensa xtreg cs_lockaccess 0x202a -xtensa xtreg cs_lockstatus 0x202b -xtensa xtreg cs_authstatus 0x202c -xtensa xtreg pmg 0x203b -xtensa xtreg pmpc 0x203c -xtensa xtreg pm0 0x203d -xtensa xtreg pm1 0x203e -xtensa xtreg pmctrl0 0x203f -xtensa xtreg pmctrl1 0x2040 -xtensa xtreg pmstat0 0x2041 -xtensa xtreg pmstat1 0x2042 -xtensa xtreg ocdid 0x2043 -xtensa xtreg ocd_dcrclr 0x2044 -xtensa xtreg ocd_dcrset 0x2045 -xtensa xtreg ocd_dsr 0x2046 -xtensa xtreg a0 0x0000 -xtensa xtreg a1 0x0001 -xtensa xtreg a2 0x0002 -xtensa xtreg a3 0x0003 -xtensa xtreg a4 0x0004 -xtensa xtreg a5 0x0005 -xtensa xtreg a6 0x0006 -xtensa xtreg a7 0x0007 -xtensa xtreg a8 0x0008 -xtensa xtreg a9 0x0009 -xtensa xtreg a10 0x000a -xtensa xtreg a11 0x000b -xtensa xtreg a12 0x000c -xtensa xtreg a13 0x000d -xtensa xtreg a14 0x000e -xtensa xtreg a15 0x000f -xtensa xtreg b0 0x0010 -xtensa xtreg b1 0x0011 -xtensa xtreg b2 0x0012 -xtensa xtreg b3 0x0013 -xtensa xtreg b4 0x0014 -xtensa xtreg b5 0x0015 -xtensa xtreg b6 0x0016 -xtensa xtreg b7 0x0017 -xtensa xtreg b8 0x0018 -xtensa xtreg b9 0x0019 -xtensa xtreg b10 0x001a -xtensa xtreg b11 0x001b -xtensa xtreg b12 0x001c -xtensa xtreg b13 0x001d -xtensa xtreg b14 0x001e -xtensa xtreg b15 0x001f -xtensa xtreg psintlevel 0x2006 -xtensa xtreg psum 0x2007 -xtensa xtreg pswoe 0x2008 -xtensa xtreg psexcm 0x2009 -xtensa xtreg pscallinc 0x200a -xtensa xtreg psowb 0x200b -xtensa xtreg acc 0x200c -xtensa xtreg dbnum 0x2011 -xtensa xtreg ae_overflow 0x2014 -xtensa xtreg ae_sar 0x2015 -xtensa xtreg ae_cwrap 0x2016 -xtensa xtreg ae_bitptr 0x2017 -xtensa xtreg ae_bitsused 0x2018 -xtensa xtreg ae_tablesize 0x2019 -xtensa xtreg ae_first_ts 0x201a -xtensa xtreg ae_nextoffset 0x201b -xtensa xtreg ae_searchdone 0x201c -xtensa xtreg roundmode 0x201d -xtensa xtreg invalidflag 0x201e -xtensa xtreg divzeroflag 0x201f -xtensa xtreg overflowflag 0x2020 -xtensa xtreg underflowflag 0x2021 -xtensa xtreg inexactflag 0x2022 +$_XTNAME xtensa xtregs 208 +$_XTNAME xtensa xtreg pc 0x0020 +$_XTNAME xtensa xtreg ar0 0x0100 +$_XTNAME xtensa xtreg ar1 0x0101 +$_XTNAME xtensa xtreg ar2 0x0102 +$_XTNAME xtensa xtreg ar3 0x0103 +$_XTNAME xtensa xtreg ar4 0x0104 +$_XTNAME xtensa xtreg ar5 0x0105 +$_XTNAME xtensa xtreg ar6 0x0106 +$_XTNAME xtensa xtreg ar7 0x0107 +$_XTNAME xtensa xtreg ar8 0x0108 +$_XTNAME xtensa xtreg ar9 0x0109 +$_XTNAME xtensa xtreg ar10 0x010a +$_XTNAME xtensa xtreg ar11 0x010b +$_XTNAME xtensa xtreg ar12 0x010c +$_XTNAME xtensa xtreg ar13 0x010d +$_XTNAME xtensa xtreg ar14 0x010e +$_XTNAME xtensa xtreg ar15 0x010f +$_XTNAME xtensa xtreg ar16 0x0110 +$_XTNAME xtensa xtreg ar17 0x0111 +$_XTNAME xtensa xtreg ar18 0x0112 +$_XTNAME xtensa xtreg ar19 0x0113 +$_XTNAME xtensa xtreg ar20 0x0114 +$_XTNAME xtensa xtreg ar21 0x0115 +$_XTNAME xtensa xtreg ar22 0x0116 +$_XTNAME xtensa xtreg ar23 0x0117 +$_XTNAME xtensa xtreg ar24 0x0118 +$_XTNAME xtensa xtreg ar25 0x0119 +$_XTNAME xtensa xtreg ar26 0x011a +$_XTNAME xtensa xtreg ar27 0x011b +$_XTNAME xtensa xtreg ar28 0x011c +$_XTNAME xtensa xtreg ar29 0x011d +$_XTNAME xtensa xtreg ar30 0x011e +$_XTNAME xtensa xtreg ar31 0x011f +$_XTNAME xtensa xtreg lbeg 0x0200 +$_XTNAME xtensa xtreg lend 0x0201 +$_XTNAME xtensa xtreg lcount 0x0202 +$_XTNAME xtensa xtreg sar 0x0203 +$_XTNAME xtensa xtreg prefctl 0x0228 +$_XTNAME xtensa xtreg windowbase 0x0248 +$_XTNAME xtensa xtreg windowstart 0x0249 +$_XTNAME xtensa xtreg configid0 0x02b0 +$_XTNAME xtensa xtreg configid1 0x02d0 +$_XTNAME xtensa xtreg ps 0x02e6 +$_XTNAME xtensa xtreg threadptr 0x03e7 +$_XTNAME xtensa xtreg br 0x0204 +$_XTNAME xtensa xtreg scompare1 0x020c +$_XTNAME xtensa xtreg acclo 0x0210 +$_XTNAME xtensa xtreg acchi 0x0211 +$_XTNAME xtensa xtreg m0 0x0220 +$_XTNAME xtensa xtreg m1 0x0221 +$_XTNAME xtensa xtreg m2 0x0222 +$_XTNAME xtensa xtreg m3 0x0223 +$_XTNAME xtensa xtreg expstate 0x03e6 +$_XTNAME xtensa xtreg f64r_lo 0x03ea +$_XTNAME xtensa xtreg f64r_hi 0x03eb +$_XTNAME xtensa xtreg f64s 0x03ec +$_XTNAME xtensa xtreg ae_ovf_sar 0x03f0 +$_XTNAME xtensa xtreg ae_bithead 0x03f1 +$_XTNAME xtensa xtreg ae_ts_fts_bu_bp 0x03f2 +$_XTNAME xtensa xtreg ae_cw_sd_no 0x03f3 +$_XTNAME xtensa xtreg ae_cbegin0 0x03f6 +$_XTNAME xtensa xtreg ae_cend0 0x03f7 +$_XTNAME xtensa xtreg ae_cbegin1 0x03f8 +$_XTNAME xtensa xtreg ae_cend1 0x03f9 +$_XTNAME xtensa xtreg aed0 0x1010 +$_XTNAME xtensa xtreg aed1 0x1011 +$_XTNAME xtensa xtreg aed2 0x1012 +$_XTNAME xtensa xtreg aed3 0x1013 +$_XTNAME xtensa xtreg aed4 0x1014 +$_XTNAME xtensa xtreg aed5 0x1015 +$_XTNAME xtensa xtreg aed6 0x1016 +$_XTNAME xtensa xtreg aed7 0x1017 +$_XTNAME xtensa xtreg aed8 0x1018 +$_XTNAME xtensa xtreg aed9 0x1019 +$_XTNAME xtensa xtreg aed10 0x101a +$_XTNAME xtensa xtreg aed11 0x101b +$_XTNAME xtensa xtreg aed12 0x101c +$_XTNAME xtensa xtreg aed13 0x101d +$_XTNAME xtensa xtreg aed14 0x101e +$_XTNAME xtensa xtreg aed15 0x101f +$_XTNAME xtensa xtreg u0 0x1020 +$_XTNAME xtensa xtreg u1 0x1021 +$_XTNAME xtensa xtreg u2 0x1022 +$_XTNAME xtensa xtreg u3 0x1023 +$_XTNAME xtensa xtreg aep0 0x1024 +$_XTNAME xtensa xtreg aep1 0x1025 +$_XTNAME xtensa xtreg aep2 0x1026 +$_XTNAME xtensa xtreg aep3 0x1027 +$_XTNAME xtensa xtreg fcr_fsr 0x1029 +$_XTNAME xtensa xtreg mmid 0x0259 +$_XTNAME xtensa xtreg ibreakenable 0x0260 +$_XTNAME xtensa xtreg memctl 0x0261 +$_XTNAME xtensa xtreg atomctl 0x0263 +$_XTNAME xtensa xtreg ddr 0x0268 +$_XTNAME xtensa xtreg ibreaka0 0x0280 +$_XTNAME xtensa xtreg ibreaka1 0x0281 +$_XTNAME xtensa xtreg dbreaka0 0x0290 +$_XTNAME xtensa xtreg dbreaka1 0x0291 +$_XTNAME xtensa xtreg dbreakc0 0x02a0 +$_XTNAME xtensa xtreg dbreakc1 0x02a1 +$_XTNAME xtensa xtreg epc1 0x02b1 +$_XTNAME xtensa xtreg epc2 0x02b2 +$_XTNAME xtensa xtreg epc3 0x02b3 +$_XTNAME xtensa xtreg epc4 0x02b4 +$_XTNAME xtensa xtreg epc5 0x02b5 +$_XTNAME xtensa xtreg depc 0x02c0 +$_XTNAME xtensa xtreg eps2 0x02c2 +$_XTNAME xtensa xtreg eps3 0x02c3 +$_XTNAME xtensa xtreg eps4 0x02c4 +$_XTNAME xtensa xtreg eps5 0x02c5 +$_XTNAME xtensa xtreg excsave1 0x02d1 +$_XTNAME xtensa xtreg excsave2 0x02d2 +$_XTNAME xtensa xtreg excsave3 0x02d3 +$_XTNAME xtensa xtreg excsave4 0x02d4 +$_XTNAME xtensa xtreg excsave5 0x02d5 +$_XTNAME xtensa xtreg cpenable 0x02e0 +$_XTNAME xtensa xtreg interrupt 0x02e2 +$_XTNAME xtensa xtreg intset 0x02e2 +$_XTNAME xtensa xtreg intclear 0x02e3 +$_XTNAME xtensa xtreg intenable 0x02e4 +$_XTNAME xtensa xtreg vecbase 0x02e7 +$_XTNAME xtensa xtreg exccause 0x02e8 +$_XTNAME xtensa xtreg debugcause 0x02e9 +$_XTNAME xtensa xtreg ccount 0x02ea +$_XTNAME xtensa xtreg prid 0x02eb +$_XTNAME xtensa xtreg icount 0x02ec +$_XTNAME xtensa xtreg icountlevel 0x02ed +$_XTNAME xtensa xtreg excvaddr 0x02ee +$_XTNAME xtensa xtreg ccompare0 0x02f0 +$_XTNAME xtensa xtreg ccompare1 0x02f1 +$_XTNAME xtensa xtreg misc0 0x02f4 +$_XTNAME xtensa xtreg misc1 0x02f5 +$_XTNAME xtensa xtreg pwrctl 0x2024 +$_XTNAME xtensa xtreg pwrstat 0x2025 +$_XTNAME xtensa xtreg eristat 0x2026 +$_XTNAME xtensa xtreg cs_itctrl 0x2027 +$_XTNAME xtensa xtreg cs_claimset 0x2028 +$_XTNAME xtensa xtreg cs_claimclr 0x2029 +$_XTNAME xtensa xtreg cs_lockaccess 0x202a +$_XTNAME xtensa xtreg cs_lockstatus 0x202b +$_XTNAME xtensa xtreg cs_authstatus 0x202c +$_XTNAME xtensa xtreg pmg 0x203b +$_XTNAME xtensa xtreg pmpc 0x203c +$_XTNAME xtensa xtreg pm0 0x203d +$_XTNAME xtensa xtreg pm1 0x203e +$_XTNAME xtensa xtreg pmctrl0 0x203f +$_XTNAME xtensa xtreg pmctrl1 0x2040 +$_XTNAME xtensa xtreg pmstat0 0x2041 +$_XTNAME xtensa xtreg pmstat1 0x2042 +$_XTNAME xtensa xtreg ocdid 0x2043 +$_XTNAME xtensa xtreg ocd_dcrclr 0x2044 +$_XTNAME xtensa xtreg ocd_dcrset 0x2045 +$_XTNAME xtensa xtreg ocd_dsr 0x2046 +$_XTNAME xtensa xtreg a0 0x0000 +$_XTNAME xtensa xtreg a1 0x0001 +$_XTNAME xtensa xtreg a2 0x0002 +$_XTNAME xtensa xtreg a3 0x0003 +$_XTNAME xtensa xtreg a4 0x0004 +$_XTNAME xtensa xtreg a5 0x0005 +$_XTNAME xtensa xtreg a6 0x0006 +$_XTNAME xtensa xtreg a7 0x0007 +$_XTNAME xtensa xtreg a8 0x0008 +$_XTNAME xtensa xtreg a9 0x0009 +$_XTNAME xtensa xtreg a10 0x000a +$_XTNAME xtensa xtreg a11 0x000b +$_XTNAME xtensa xtreg a12 0x000c +$_XTNAME xtensa xtreg a13 0x000d +$_XTNAME xtensa xtreg a14 0x000e +$_XTNAME xtensa xtreg a15 0x000f +$_XTNAME xtensa xtreg b0 0x0010 +$_XTNAME xtensa xtreg b1 0x0011 +$_XTNAME xtensa xtreg b2 0x0012 +$_XTNAME xtensa xtreg b3 0x0013 +$_XTNAME xtensa xtreg b4 0x0014 +$_XTNAME xtensa xtreg b5 0x0015 +$_XTNAME xtensa xtreg b6 0x0016 +$_XTNAME xtensa xtreg b7 0x0017 +$_XTNAME xtensa xtreg b8 0x0018 +$_XTNAME xtensa xtreg b9 0x0019 +$_XTNAME xtensa xtreg b10 0x001a +$_XTNAME xtensa xtreg b11 0x001b +$_XTNAME xtensa xtreg b12 0x001c +$_XTNAME xtensa xtreg b13 0x001d +$_XTNAME xtensa xtreg b14 0x001e +$_XTNAME xtensa xtreg b15 0x001f +$_XTNAME xtensa xtreg psintlevel 0x2006 +$_XTNAME xtensa xtreg psum 0x2007 +$_XTNAME xtensa xtreg pswoe 0x2008 +$_XTNAME xtensa xtreg psexcm 0x2009 +$_XTNAME xtensa xtreg pscallinc 0x200a +$_XTNAME xtensa xtreg psowb 0x200b +$_XTNAME xtensa xtreg acc 0x200c +$_XTNAME xtensa xtreg dbnum 0x2011 +$_XTNAME xtensa xtreg ae_overflow 0x2014 +$_XTNAME xtensa xtreg ae_sar 0x2015 +$_XTNAME xtensa xtreg ae_cwrap 0x2016 +$_XTNAME xtensa xtreg ae_bitptr 0x2017 +$_XTNAME xtensa xtreg ae_bitsused 0x2018 +$_XTNAME xtensa xtreg ae_tablesize 0x2019 +$_XTNAME xtensa xtreg ae_first_ts 0x201a +$_XTNAME xtensa xtreg ae_nextoffset 0x201b +$_XTNAME xtensa xtreg ae_searchdone 0x201c +$_XTNAME xtensa xtreg roundmode 0x201d +$_XTNAME xtensa xtreg invalidflag 0x201e +$_XTNAME xtensa xtreg divzeroflag 0x201f +$_XTNAME xtensa xtreg overflowflag 0x2020 +$_XTNAME xtensa xtreg underflowflag 0x2021 +$_XTNAME xtensa xtreg inexactflag 0x2022 diff --git a/tcl/target/xtensa-core-xt8.cfg b/tcl/target/xtensa-core-xt8.cfg index e544d7854f..523dc74e1f 100644 --- a/tcl/target/xtensa-core-xt8.cfg +++ b/tcl/target/xtensa-core-xt8.cfg @@ -1,166 +1,175 @@ # SPDX-License-Identifier: GPL-2.0-or-later # OpenOCD configuration file for Xtensa xt8 target + +# Core instance default definition +if { [info exists XTNAME] } { + set _XTNAME $XTNAME +} else { + set _XTNAME xtensa +} + + # Core definition and ABI -xtensa xtdef LX -xtensa xtopt arnum 32 -xtensa xtopt windowed 1 +$_XTNAME xtensa xtdef LX +$_XTNAME xtensa xtopt arnum 32 +$_XTNAME xtensa xtopt windowed 1 # Exception/Interrupt Options -xtensa xtopt exceptions 1 -xtensa xtopt hipriints 1 -xtensa xtopt intlevels 3 -xtensa xtopt excmlevel 1 +$_XTNAME xtensa xtopt exceptions 1 +$_XTNAME xtensa xtopt hipriints 1 +$_XTNAME xtensa xtopt intlevels 3 +$_XTNAME xtensa xtopt excmlevel 1 # Cache Options -xtensa xtmem icache 16 1024 1 -xtensa xtmem dcache 16 1024 1 1 +$_XTNAME xtensa xtmem icache 16 1024 1 +$_XTNAME xtensa xtmem dcache 16 1024 1 1 # Memory Options -xtensa xtmem iram 0x40000000 1048576 -xtensa xtmem dram 0x3ff00000 262144 -xtensa xtmem srom 0x50000000 131072 -xtensa xtmem sram 0x60000000 4194304 +$_XTNAME xtensa xtmem iram 0x40000000 1048576 +$_XTNAME xtensa xtmem dram 0x3ff00000 262144 +$_XTNAME xtensa xtmem srom 0x50000000 131072 +$_XTNAME xtensa xtmem sram 0x60000000 4194304 # Memory Protection/Translation Options # Debug Options -xtensa xtopt debuglevel 3 -xtensa xtopt ibreaknum 2 -xtensa xtopt dbreaknum 2 +$_XTNAME xtensa xtopt debuglevel 3 +$_XTNAME xtensa xtopt ibreaknum 2 +$_XTNAME xtensa xtopt dbreaknum 2 # Core Registers -xtensa xtregs 127 -xtensa xtreg a0 0x0000 -xtensa xtreg a1 0x0001 -xtensa xtreg a2 0x0002 -xtensa xtreg a3 0x0003 -xtensa xtreg a4 0x0004 -xtensa xtreg a5 0x0005 -xtensa xtreg a6 0x0006 -xtensa xtreg a7 0x0007 -xtensa xtreg a8 0x0008 -xtensa xtreg a9 0x0009 -xtensa xtreg a10 0x000a -xtensa xtreg a11 0x000b -xtensa xtreg a12 0x000c -xtensa xtreg a13 0x000d -xtensa xtreg a14 0x000e -xtensa xtreg a15 0x000f -xtensa xtreg pc 0x0020 -xtensa xtreg ar0 0x0100 -xtensa xtreg ar1 0x0101 -xtensa xtreg ar2 0x0102 -xtensa xtreg ar3 0x0103 -xtensa xtreg ar4 0x0104 -xtensa xtreg ar5 0x0105 -xtensa xtreg ar6 0x0106 -xtensa xtreg ar7 0x0107 -xtensa xtreg ar8 0x0108 -xtensa xtreg ar9 0x0109 -xtensa xtreg ar10 0x010a -xtensa xtreg ar11 0x010b -xtensa xtreg ar12 0x010c -xtensa xtreg ar13 0x010d -xtensa xtreg ar14 0x010e -xtensa xtreg ar15 0x010f -xtensa xtreg ar16 0x0110 -xtensa xtreg ar17 0x0111 -xtensa xtreg ar18 0x0112 -xtensa xtreg ar19 0x0113 -xtensa xtreg ar20 0x0114 -xtensa xtreg ar21 0x0115 -xtensa xtreg ar22 0x0116 -xtensa xtreg ar23 0x0117 -xtensa xtreg ar24 0x0118 -xtensa xtreg ar25 0x0119 -xtensa xtreg ar26 0x011a -xtensa xtreg ar27 0x011b -xtensa xtreg ar28 0x011c -xtensa xtreg ar29 0x011d -xtensa xtreg ar30 0x011e -xtensa xtreg ar31 0x011f -xtensa xtreg lbeg 0x0200 -xtensa xtreg lend 0x0201 -xtensa xtreg lcount 0x0202 -xtensa xtreg sar 0x0203 -xtensa xtreg windowbase 0x0248 -xtensa xtreg windowstart 0x0249 -xtensa xtreg configid0 0x02b0 -xtensa xtreg configid1 0x02d0 -xtensa xtreg ps 0x02e6 -xtensa xtreg expstate 0x03e6 -xtensa xtreg mmid 0x0259 -xtensa xtreg ibreakenable 0x0260 -xtensa xtreg ddr 0x0268 -xtensa xtreg ibreaka0 0x0280 -xtensa xtreg ibreaka1 0x0281 -xtensa xtreg dbreaka0 0x0290 -xtensa xtreg dbreaka1 0x0291 -xtensa xtreg dbreakc0 0x02a0 -xtensa xtreg dbreakc1 0x02a1 -xtensa xtreg epc1 0x02b1 -xtensa xtreg epc2 0x02b2 -xtensa xtreg epc3 0x02b3 -xtensa xtreg depc 0x02c0 -xtensa xtreg eps2 0x02c2 -xtensa xtreg eps3 0x02c3 -xtensa xtreg excsave1 0x02d1 -xtensa xtreg excsave2 0x02d2 -xtensa xtreg excsave3 0x02d3 -xtensa xtreg interrupt 0x02e2 -xtensa xtreg intset 0x02e2 -xtensa xtreg intclear 0x02e3 -xtensa xtreg intenable 0x02e4 -xtensa xtreg exccause 0x02e8 -xtensa xtreg debugcause 0x02e9 -xtensa xtreg ccount 0x02ea -xtensa xtreg icount 0x02ec -xtensa xtreg icountlevel 0x02ed -xtensa xtreg excvaddr 0x02ee -xtensa xtreg ccompare0 0x02f0 -xtensa xtreg ccompare1 0x02f1 -xtensa xtreg pwrctl 0x200f -xtensa xtreg pwrstat 0x2010 -xtensa xtreg eristat 0x2011 -xtensa xtreg cs_itctrl 0x2012 -xtensa xtreg cs_claimset 0x2013 -xtensa xtreg cs_claimclr 0x2014 -xtensa xtreg cs_lockaccess 0x2015 -xtensa xtreg cs_lockstatus 0x2016 -xtensa xtreg cs_authstatus 0x2017 -xtensa xtreg fault_info 0x2026 -xtensa xtreg trax_id 0x2027 -xtensa xtreg trax_control 0x2028 -xtensa xtreg trax_status 0x2029 -xtensa xtreg trax_data 0x202a -xtensa xtreg trax_address 0x202b -xtensa xtreg trax_pctrigger 0x202c -xtensa xtreg trax_pcmatch 0x202d -xtensa xtreg trax_delay 0x202e -xtensa xtreg trax_memstart 0x202f -xtensa xtreg trax_memend 0x2030 -xtensa xtreg pmg 0x203e -xtensa xtreg pmpc 0x203f -xtensa xtreg pm0 0x2040 -xtensa xtreg pm1 0x2041 -xtensa xtreg pmctrl0 0x2042 -xtensa xtreg pmctrl1 0x2043 -xtensa xtreg pmstat0 0x2044 -xtensa xtreg pmstat1 0x2045 -xtensa xtreg ocdid 0x2046 -xtensa xtreg ocd_dcrclr 0x2047 -xtensa xtreg ocd_dcrset 0x2048 -xtensa xtreg ocd_dsr 0x2049 -xtensa xtreg psintlevel 0x2003 -xtensa xtreg psum 0x2004 -xtensa xtreg pswoe 0x2005 -xtensa xtreg psexcm 0x2006 -xtensa xtreg pscallinc 0x2007 -xtensa xtreg psowb 0x2008 +$_XTNAME xtensa xtregs 127 +$_XTNAME xtensa xtreg a0 0x0000 +$_XTNAME xtensa xtreg a1 0x0001 +$_XTNAME xtensa xtreg a2 0x0002 +$_XTNAME xtensa xtreg a3 0x0003 +$_XTNAME xtensa xtreg a4 0x0004 +$_XTNAME xtensa xtreg a5 0x0005 +$_XTNAME xtensa xtreg a6 0x0006 +$_XTNAME xtensa xtreg a7 0x0007 +$_XTNAME xtensa xtreg a8 0x0008 +$_XTNAME xtensa xtreg a9 0x0009 +$_XTNAME xtensa xtreg a10 0x000a +$_XTNAME xtensa xtreg a11 0x000b +$_XTNAME xtensa xtreg a12 0x000c +$_XTNAME xtensa xtreg a13 0x000d +$_XTNAME xtensa xtreg a14 0x000e +$_XTNAME xtensa xtreg a15 0x000f +$_XTNAME xtensa xtreg pc 0x0020 +$_XTNAME xtensa xtreg ar0 0x0100 +$_XTNAME xtensa xtreg ar1 0x0101 +$_XTNAME xtensa xtreg ar2 0x0102 +$_XTNAME xtensa xtreg ar3 0x0103 +$_XTNAME xtensa xtreg ar4 0x0104 +$_XTNAME xtensa xtreg ar5 0x0105 +$_XTNAME xtensa xtreg ar6 0x0106 +$_XTNAME xtensa xtreg ar7 0x0107 +$_XTNAME xtensa xtreg ar8 0x0108 +$_XTNAME xtensa xtreg ar9 0x0109 +$_XTNAME xtensa xtreg ar10 0x010a +$_XTNAME xtensa xtreg ar11 0x010b +$_XTNAME xtensa xtreg ar12 0x010c +$_XTNAME xtensa xtreg ar13 0x010d +$_XTNAME xtensa xtreg ar14 0x010e +$_XTNAME xtensa xtreg ar15 0x010f +$_XTNAME xtensa xtreg ar16 0x0110 +$_XTNAME xtensa xtreg ar17 0x0111 +$_XTNAME xtensa xtreg ar18 0x0112 +$_XTNAME xtensa xtreg ar19 0x0113 +$_XTNAME xtensa xtreg ar20 0x0114 +$_XTNAME xtensa xtreg ar21 0x0115 +$_XTNAME xtensa xtreg ar22 0x0116 +$_XTNAME xtensa xtreg ar23 0x0117 +$_XTNAME xtensa xtreg ar24 0x0118 +$_XTNAME xtensa xtreg ar25 0x0119 +$_XTNAME xtensa xtreg ar26 0x011a +$_XTNAME xtensa xtreg ar27 0x011b +$_XTNAME xtensa xtreg ar28 0x011c +$_XTNAME xtensa xtreg ar29 0x011d +$_XTNAME xtensa xtreg ar30 0x011e +$_XTNAME xtensa xtreg ar31 0x011f +$_XTNAME xtensa xtreg lbeg 0x0200 +$_XTNAME xtensa xtreg lend 0x0201 +$_XTNAME xtensa xtreg lcount 0x0202 +$_XTNAME xtensa xtreg sar 0x0203 +$_XTNAME xtensa xtreg windowbase 0x0248 +$_XTNAME xtensa xtreg windowstart 0x0249 +$_XTNAME xtensa xtreg configid0 0x02b0 +$_XTNAME xtensa xtreg configid1 0x02d0 +$_XTNAME xtensa xtreg ps 0x02e6 +$_XTNAME xtensa xtreg expstate 0x03e6 +$_XTNAME xtensa xtreg mmid 0x0259 +$_XTNAME xtensa xtreg ibreakenable 0x0260 +$_XTNAME xtensa xtreg ddr 0x0268 +$_XTNAME xtensa xtreg ibreaka0 0x0280 +$_XTNAME xtensa xtreg ibreaka1 0x0281 +$_XTNAME xtensa xtreg dbreaka0 0x0290 +$_XTNAME xtensa xtreg dbreaka1 0x0291 +$_XTNAME xtensa xtreg dbreakc0 0x02a0 +$_XTNAME xtensa xtreg dbreakc1 0x02a1 +$_XTNAME xtensa xtreg epc1 0x02b1 +$_XTNAME xtensa xtreg epc2 0x02b2 +$_XTNAME xtensa xtreg epc3 0x02b3 +$_XTNAME xtensa xtreg depc 0x02c0 +$_XTNAME xtensa xtreg eps2 0x02c2 +$_XTNAME xtensa xtreg eps3 0x02c3 +$_XTNAME xtensa xtreg excsave1 0x02d1 +$_XTNAME xtensa xtreg excsave2 0x02d2 +$_XTNAME xtensa xtreg excsave3 0x02d3 +$_XTNAME xtensa xtreg interrupt 0x02e2 +$_XTNAME xtensa xtreg intset 0x02e2 +$_XTNAME xtensa xtreg intclear 0x02e3 +$_XTNAME xtensa xtreg intenable 0x02e4 +$_XTNAME xtensa xtreg exccause 0x02e8 +$_XTNAME xtensa xtreg debugcause 0x02e9 +$_XTNAME xtensa xtreg ccount 0x02ea +$_XTNAME xtensa xtreg icount 0x02ec +$_XTNAME xtensa xtreg icountlevel 0x02ed +$_XTNAME xtensa xtreg excvaddr 0x02ee +$_XTNAME xtensa xtreg ccompare0 0x02f0 +$_XTNAME xtensa xtreg ccompare1 0x02f1 +$_XTNAME xtensa xtreg pwrctl 0x200f +$_XTNAME xtensa xtreg pwrstat 0x2010 +$_XTNAME xtensa xtreg eristat 0x2011 +$_XTNAME xtensa xtreg cs_itctrl 0x2012 +$_XTNAME xtensa xtreg cs_claimset 0x2013 +$_XTNAME xtensa xtreg cs_claimclr 0x2014 +$_XTNAME xtensa xtreg cs_lockaccess 0x2015 +$_XTNAME xtensa xtreg cs_lockstatus 0x2016 +$_XTNAME xtensa xtreg cs_authstatus 0x2017 +$_XTNAME xtensa xtreg fault_info 0x2026 +$_XTNAME xtensa xtreg trax_id 0x2027 +$_XTNAME xtensa xtreg trax_control 0x2028 +$_XTNAME xtensa xtreg trax_status 0x2029 +$_XTNAME xtensa xtreg trax_data 0x202a +$_XTNAME xtensa xtreg trax_address 0x202b +$_XTNAME xtensa xtreg trax_pctrigger 0x202c +$_XTNAME xtensa xtreg trax_pcmatch 0x202d +$_XTNAME xtensa xtreg trax_delay 0x202e +$_XTNAME xtensa xtreg trax_memstart 0x202f +$_XTNAME xtensa xtreg trax_memend 0x2030 +$_XTNAME xtensa xtreg pmg 0x203e +$_XTNAME xtensa xtreg pmpc 0x203f +$_XTNAME xtensa xtreg pm0 0x2040 +$_XTNAME xtensa xtreg pm1 0x2041 +$_XTNAME xtensa xtreg pmctrl0 0x2042 +$_XTNAME xtensa xtreg pmctrl1 0x2043 +$_XTNAME xtensa xtreg pmstat0 0x2044 +$_XTNAME xtensa xtreg pmstat1 0x2045 +$_XTNAME xtensa xtreg ocdid 0x2046 +$_XTNAME xtensa xtreg ocd_dcrclr 0x2047 +$_XTNAME xtensa xtreg ocd_dcrset 0x2048 +$_XTNAME xtensa xtreg ocd_dsr 0x2049 +$_XTNAME xtensa xtreg psintlevel 0x2003 +$_XTNAME xtensa xtreg psum 0x2004 +$_XTNAME xtensa xtreg pswoe 0x2005 +$_XTNAME xtensa xtreg psexcm 0x2006 +$_XTNAME xtensa xtreg pscallinc 0x2007 +$_XTNAME xtensa xtreg psowb 0x2008 diff --git a/tcl/target/xtensa.cfg b/tcl/target/xtensa.cfg index 101e13546f..561131d842 100644 --- a/tcl/target/xtensa.cfg +++ b/tcl/target/xtensa.cfg @@ -5,7 +5,7 @@ set xtensa_ids { 0x120034e5 0x120134e5 0x209034e5 0x209134e5 0x209234e5 0x209334e5 0x209434e5 0x209534e5 0x209634e5 0x209734e5 0x20a034e5 0x20a134e5 0x20a234e5 0x20a334e5 0x20a434e5 0x20a534e5 0x20a634e5 0x20a734e5 0x20a834e5 - 0x20b034e5 } + 0x20b034e5 0x20b33ac5 0x20b33ac7 } set expected_xtensa_ids {} foreach i $xtensa_ids { lappend expected_xtensa_ids -expected-id $i @@ -23,6 +23,12 @@ if { [info exists CPUTAPID] } { set _CPUTAPARGLIST [join $expected_xtensa_ids] } +if { [info exists XTENSA_NUM_CORES] } { + set _XTENSA_NUM_CORES $XTENSA_NUM_CORES +} else { + set _XTENSA_NUM_CORES 1 +} + set _TARGETNAME $_CHIPNAME set _CPU0NAME cpu set _TAPNAME $_CHIPNAME.$_CPU0NAME @@ -40,12 +46,25 @@ if { [info exists XTENSA_DAP] } { } else { target create $_TARGETNAME xtensa -dap $_CHIPNAME.dap } -} else { +} elseif { $_XTENSA_NUM_CORES > 1 } { # JTAG direct (without DAP) + for {set i 0} {$i < $_XTENSA_NUM_CORES} {incr i} { + set _LCPUNAME $_CPU0NAME$i + set _LTAPNAME $_CHIPNAME.$_LCPUNAME + eval jtag newtap $_CHIPNAME $_LCPUNAME -irlen 5 $_CPUTAPARGLIST + target create $_LTAPNAME xtensa -chain-position $_LTAPNAME -coreid $i + + $_LTAPNAME configure -event reset-assert-post { soft_reset_halt } + } +} else { + # JTAG direct (without DAP) - for legacy xtensa-config-XXX.cfg format eval jtag newtap $_CHIPNAME $_CPU0NAME -irlen 5 $_CPUTAPARGLIST target create $_TARGETNAME xtensa -chain-position $_TAPNAME } -$_TARGETNAME configure -event reset-assert-post { soft_reset_halt } +if { $_XTENSA_NUM_CORES == 1 } { + # DAP and single-core legacy JTAG + $_TARGETNAME configure -event reset-assert-post { soft_reset_halt } +} gdb_report_register_access_error enable From 67675323e1ea09b5d1a4250bf58163103c85b844 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Thu, 11 Jan 2024 14:02:28 +0300 Subject: [PATCH 0729/1312] target: pass target to observers via const pointer There are quite a lot of "getters" in target interface. They do not change target structure, nevertheless the structure is passed to these functions via a plain pointer. The intention is to clarify the purpouse of these functions by passing the `target` structure as a pointer to constant data. Change-Id: Ida4a798da94938753b86a293a308d93b091d1bf3 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8092 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 10 +++++----- src/target/target.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 920511e963..a411270e22 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -244,7 +244,7 @@ static const struct nvp nvp_reset_modes[] = { { .name = NULL, .value = -1 }, }; -const char *debug_reason_name(struct target *t) +const char *debug_reason_name(const struct target *t) { const char *cp; @@ -257,7 +257,7 @@ const char *debug_reason_name(struct target *t) return cp; } -const char *target_state_name(struct target *t) +const char *target_state_name(const struct target *t) { const char *cp; cp = nvp_value2name(nvp_target_state, t->state)->name; @@ -733,7 +733,7 @@ int target_examine(void) return retval; } -const char *target_type_name(struct target *target) +const char *target_type_name(const struct target *target) { return target->type->name; } @@ -1398,7 +1398,7 @@ int target_get_gdb_reg_list_noread(struct target *target, return target_get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } -bool target_supports_gdb_connection(struct target *target) +bool target_supports_gdb_connection(const struct target *target) { /* * exclude all the targets that don't provide get_gdb_reg_list @@ -4851,7 +4851,7 @@ static int target_jim_set_reg(Jim_Interp *interp, int argc, /** * Returns true only if the target has a handler for the specified event. */ -bool target_has_event_action(struct target *target, enum target_event event) +bool target_has_event_action(const struct target *target, enum target_event event) { struct target_event_action *teap; diff --git a/src/target/target.h b/src/target/target.h index f69ee77ac4..bd01f5eb68 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -222,19 +222,19 @@ struct gdb_fileio_info { }; /** Returns a description of the endianness for the specified target. */ -static inline const char *target_endianness(struct target *target) +static inline const char *target_endianness(const struct target *target) { return (target->endianness == TARGET_ENDIAN_UNKNOWN) ? "unknown" : (target->endianness == TARGET_BIG_ENDIAN) ? "big endian" : "little endian"; } /** Returns the instance-specific name of the specified target. */ -static inline const char *target_name(struct target *target) +static inline const char *target_name(const struct target *target) { return target->cmd_name; } -const char *debug_reason_name(struct target *t); +const char *debug_reason_name(const struct target *t); enum target_event { @@ -301,7 +301,7 @@ struct target_event_action { struct target_event_action *next; }; -bool target_has_event_action(struct target *target, enum target_event event); +bool target_has_event_action(const struct target *target, enum target_event event); struct target_event_callback { int (*callback)(struct target *target, enum target_event event, void *priv); @@ -421,7 +421,7 @@ struct target *get_target(const char *id); * This routine is a wrapper for the target->type->name field. * Note that this is not an instance-specific name for his target. */ -const char *target_type_name(struct target *target); +const char *target_type_name(const struct target *target); /** * Examine the specified @a target, letting it perform any @@ -432,7 +432,7 @@ const char *target_type_name(struct target *target); int target_examine_one(struct target *target); /** @returns @c true if target_set_examined() has been called. */ -static inline bool target_was_examined(struct target *target) +static inline bool target_was_examined(const struct target *target) { return target->examined; } @@ -527,7 +527,7 @@ int target_get_gdb_reg_list_noread(struct target *target, * * Some target do not implement the necessary code required by GDB. */ -bool target_supports_gdb_connection(struct target *target); +bool target_supports_gdb_connection(const struct target *target); /** * Step the target. @@ -694,7 +694,7 @@ unsigned target_address_bits(struct target *target); unsigned int target_data_bits(struct target *target); /** Return the *name* of this targets current state */ -const char *target_state_name(struct target *target); +const char *target_state_name(const struct target *target); /** Return the *name* of a target event enumeration value */ const char *target_event_name(enum target_event event); From 1b0ffa97ea90c09e96b068450644e462102c10ae Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 12 Jan 2024 16:29:32 +0300 Subject: [PATCH 0730/1312] target: get_gdb_arch() accepts target via const pointer The function in question does not need to change target state. It is a target-type-dependant function, however, IMHO, it is safe to assume that any target type would not need to change type-independant state of a target to figure out the arch. Change-Id: I607cb3aee6529cd5a97bc1200a0226cf6ef43caf Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8093 Tested-by: jenkins Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo --- src/target/arm.h | 6 +++--- src/target/armv4_5.c | 2 +- src/target/armv8.c | 2 +- src/target/esirisc.c | 2 +- src/target/esirisc.h | 2 +- src/target/mem_ap.c | 2 +- src/target/riscv/riscv.c | 2 +- src/target/stm8.c | 2 +- src/target/target.c | 2 +- src/target/target.h | 2 +- src/target/target_type.h | 2 +- src/target/xtensa/xtensa.c | 2 +- src/target/xtensa/xtensa.h | 2 +- 13 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/target/arm.h b/src/target/arm.h index d5053afb81..486666b5c6 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -257,7 +257,7 @@ struct arm { }; /** Convert target handle to generic ARM target state handle. */ -static inline struct arm *target_to_arm(struct target *target) +static inline struct arm *target_to_arm(const struct target *target) { assert(target); return target->arch_info; @@ -293,11 +293,11 @@ extern const struct command_registration arm_command_handlers[]; extern const struct command_registration arm_all_profiles_command_handlers[]; int arm_arch_state(struct target *target); -const char *arm_get_gdb_arch(struct target *target); +const char *arm_get_gdb_arch(const struct target *target); int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); -const char *armv8_get_gdb_arch(struct target *target); +const char *armv8_get_gdb_arch(const struct target *target); int armv8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 7debb94984..1886d5e1f6 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1264,7 +1264,7 @@ const struct command_registration arm_command_handlers[] = { * same way as a gdb for arm. This can be changed later on. User can still * set the specific architecture variant with the gdb command. */ -const char *arm_get_gdb_arch(struct target *target) +const char *arm_get_gdb_arch(const struct target *target) { return "arm"; } diff --git a/src/target/armv8.c b/src/target/armv8.c index daf1ffca38..bf582ff801 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1865,7 +1865,7 @@ const struct command_registration armv8_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -const char *armv8_get_gdb_arch(struct target *target) +const char *armv8_get_gdb_arch(const struct target *target) { struct arm *arm = target_to_arm(target); return arm->core_state == ARM_STATE_AARCH64 ? "aarch64" : "arm"; diff --git a/src/target/esirisc.c b/src/target/esirisc.c index 561edb255a..c9ac1d606c 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -1248,7 +1248,7 @@ static int esirisc_arch_state(struct target *target) return ERROR_OK; } -static const char *esirisc_get_gdb_arch(struct target *target) +static const char *esirisc_get_gdb_arch(const struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); diff --git a/src/target/esirisc.h b/src/target/esirisc.h index 7496b1eda7..6f8cd14722 100644 --- a/src/target/esirisc.h +++ b/src/target/esirisc.h @@ -106,7 +106,7 @@ struct esirisc_reg { int (*write)(struct reg *reg); }; -static inline struct esirisc_common *target_to_esirisc(struct target *target) +static inline struct esirisc_common *target_to_esirisc(const struct target *target) { return (struct esirisc_common *)target->arch_info; } diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 50dc91c7b7..5c81e3a75f 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -182,7 +182,7 @@ static struct reg_arch_type mem_ap_reg_arch_type = { .set = mem_ap_reg_set, }; -static const char *mem_ap_get_gdb_arch(struct target *target) +static const char *mem_ap_get_gdb_arch(const struct target *target) { return "arm"; } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index cb8d04f201..d895ca3726 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1744,7 +1744,7 @@ static int riscv_write_memory(struct target *target, target_addr_t address, return tt->write_memory(target, address, size, count, buffer); } -static const char *riscv_get_gdb_arch(struct target *target) +static const char *riscv_get_gdb_arch(const struct target *target) { switch (riscv_xlen(target)) { case 32: diff --git a/src/target/stm8.c b/src/target/stm8.c index ad4a452981..227101b6f0 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -1158,7 +1158,7 @@ static int stm8_write_core_reg(struct target *target, unsigned int num) return ERROR_OK; } -static const char *stm8_get_gdb_arch(struct target *target) +static const char *stm8_get_gdb_arch(const struct target *target) { return "stm8"; } diff --git a/src/target/target.c b/src/target/target.c index a411270e22..45698a66c5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1358,7 +1358,7 @@ int target_hit_watchpoint(struct target *target, return target->type->hit_watchpoint(target, hit_watchpoint); } -const char *target_get_gdb_arch(struct target *target) +const char *target_get_gdb_arch(const struct target *target) { if (!target->type->get_gdb_arch) return NULL; diff --git a/src/target/target.h b/src/target/target.h index bd01f5eb68..1713448ce8 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -501,7 +501,7 @@ int target_hit_watchpoint(struct target *target, * * This routine is a wrapper for target->type->get_gdb_arch. */ -const char *target_get_gdb_arch(struct target *target); +const char *target_get_gdb_arch(const struct target *target); /** * Obtain the registers for GDB. diff --git a/src/target/target_type.h b/src/target/target_type.h index 678ce0f466..bc42c2d16e 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -83,7 +83,7 @@ struct target_type { * if dynamic allocation is used for this value, it must be managed by * the target, ideally by caching the result for subsequent calls. */ - const char *(*get_gdb_arch)(struct target *target); + const char *(*get_gdb_arch)(const struct target *target); /** * Target register access for GDB. Do @b not call this function diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index b516c17ab8..fb7748aa2d 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3442,7 +3442,7 @@ void xtensa_target_deinit(struct target *target) free(xtensa->core_config); } -const char *xtensa_get_gdb_arch(struct target *target) +const char *xtensa_get_gdb_arch(const struct target *target) { return "xtensa"; } diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index f799208f0b..a220021a68 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -422,7 +422,7 @@ int xtensa_run_algorithm(struct target *target, target_addr_t entry_point, target_addr_t exit_point, unsigned int timeout_ms, void *arch_info); void xtensa_set_permissive_mode(struct target *target, bool state); -const char *xtensa_get_gdb_arch(struct target *target); +const char *xtensa_get_gdb_arch(const struct target *target); int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p); COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa); From 9659a9b5e28dc615dfb508d301fdd8fa426c191b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jan 2024 17:51:41 +0100 Subject: [PATCH 0731/1312] target/esirisc: free memory at OpenOCD exit The target esirisc does not free the allocated memory resources, causing memory leaks at OpenOCD exit. Add esirisc_free_reg_cache() and esirisc_deinit_target() and use them to free all the allocated resources. Change-Id: I17b8ebff54906fa25a37f2d96c01d010a98cffbd Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8094 Tested-by: jenkins Reviewed-by: Steven Stallion --- src/target/esirisc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/target/esirisc.c b/src/target/esirisc.c index c9ac1d606c..0f76b5982e 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -1486,6 +1486,32 @@ static struct reg_cache *esirisc_build_reg_cache(struct target *target) return cache; } +static void esirisc_free_reg_cache(struct target *target) +{ + struct esirisc_common *esirisc = target_to_esirisc(target); + struct reg_cache *cache = esirisc->reg_cache; + struct reg *reg_list = cache->reg_list; + + for (int i = 0; i < esirisc->num_regs; ++i) { + struct reg *reg = reg_list + esirisc_regs[i].number; + + free(reg->arch_info); + free(reg->value); + free(reg->reg_data_type); + } + + for (size_t i = 0; i < ARRAY_SIZE(esirisc_csrs); ++i) { + struct reg *reg = reg_list + esirisc_csrs[i].number; + + free(reg->arch_info); + free(reg->value); + free(reg->reg_data_type); + } + + free(reg_list); + free(cache); +} + static int esirisc_identify(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); @@ -1584,6 +1610,19 @@ static int esirisc_init_target(struct command_context *cmd_ctx, struct target *t return ERROR_OK; } +static void esirisc_deinit_target(struct target *target) +{ + struct esirisc_common *esirisc = target_to_esirisc(target); + + if (!target_was_examined(target)) + return; + + esirisc_free_reg_cache(target); + + free(esirisc->gdb_arch); + free(esirisc); +} + static int esirisc_examine(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); @@ -1822,5 +1861,6 @@ struct target_type esirisc_target = { .target_create = esirisc_target_create, .init_target = esirisc_init_target, + .deinit_target = esirisc_deinit_target, .examine = esirisc_examine, }; From 4593c75f0b45ebb1bf10350c26c0163d0676f81a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 21:25:59 +0100 Subject: [PATCH 0732/1312] jtag/drivers/jlink: make jlink quiet polling target in -d 3 Jlink driver floods the debug log by a message per one poll interval. Avoid annoying messages, change their logging level to LOG_DEBUG_IO Signed-off-by: Tomas Vanek Change-Id: I84ea6aa9cdfd44b5985c5393519d1efb7de9530a Reviewed-on: https://review.openocd.org/c/openocd/+/8116 Reviewed-by: zapb Tested-by: jenkins --- src/jtag/drivers/jlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 5743d8d6eb..97dc351fdf 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -2108,7 +2108,7 @@ static int jlink_swd_switch_seq(enum swd_special_seq seq) switch (seq) { case LINE_RESET: - LOG_DEBUG("SWD line reset"); + LOG_DEBUG_IO("SWD line reset"); s = swd_seq_line_reset; s_len = swd_seq_line_reset_len; break; @@ -2157,7 +2157,7 @@ static int jlink_swd_run_queue(void) int i; int ret; - LOG_DEBUG("Executing %d queued transactions", pending_scan_results_length); + LOG_DEBUG_IO("Executing %d queued transactions", pending_scan_results_length); if (queued_retval != ERROR_OK) { LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); From 0d3d4c981ac77b600ce95c9ea6f1cdb280127342 Mon Sep 17 00:00:00 2001 From: Vincent Fazio Date: Wed, 31 Jan 2024 09:06:20 -0600 Subject: [PATCH 0733/1312] jtag/adapter: retype adapter_gpio_config.{gpio,chip}_num Previously, the gpio_num and chip_num members of adapter_gpio_config were typed as 'int' and a sentinel value of -1 was used to denote unconfigured values. Now, these members are typed as 'unsigned int' to better reflect their expected value range. The sentinel value now maps to UINT_MAX as all adapters either define an upper bound for these members or, in the case of bcm2835gpio, only operate on a specific chip, in which case the value doesn't matter. Format specifiers have been left as %d since, when configured, valid values are within the positive range of 'int'. This allows unconfigured values to display as a more readable value of -1 instead of UINT_MAX. Change-Id: Ieb20e5327b2e2e443a8e43d8689cb29538a5c9c1 Signed-off-by: Vincent Fazio Reviewed-on: https://review.openocd.org/c/openocd/+/8124 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/adapter.c | 22 ++++++++++++---------- src/jtag/adapter.h | 7 +++++-- src/jtag/drivers/am335xgpio.c | 15 ++++++++------- src/jtag/drivers/bcm2835gpio.c | 16 ++++++++-------- src/jtag/drivers/linuxgpiod.c | 4 +--- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index e70f4a1e80..bbf1cb3d2e 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -94,8 +94,9 @@ static void adapter_driver_gpios_init(void) return; for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) { - adapter_config.gpios[i].gpio_num = -1; - adapter_config.gpios[i].chip_num = -1; + /* Use ADAPTER_GPIO_NOT_SET as the sentinel 'unset' value. */ + adapter_config.gpios[i].gpio_num = ADAPTER_GPIO_NOT_SET; + adapter_config.gpios[i].chip_num = ADAPTER_GPIO_NOT_SET; if (gpio_map[i].direction == ADAPTER_GPIO_DIRECTION_INPUT) adapter_config.gpios[i].init_state = ADAPTER_GPIO_INIT_STATE_INPUT; } @@ -848,6 +849,11 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config const char *pull = ""; const char *init_state = ""; + if (gpio_config->gpio_num == ADAPTER_GPIO_NOT_SET) { + command_print(CMD, "adapter gpio %s: not configured", gpio_map[gpio_idx].name); + return ERROR_OK; + } + switch (gpio_map[gpio_idx].direction) { case ADAPTER_GPIO_DIRECTION_INPUT: dir = "input"; @@ -900,8 +906,8 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config } } - command_print(CMD, "adapter gpio %s (%s): num %d, chip %d, active-%s%s%s%s", - gpio_map[gpio_idx].name, dir, gpio_config->gpio_num, gpio_config->chip_num, active_state, + command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, active-%s%s%s%s", + gpio_map[gpio_idx].name, dir, gpio_config->gpio_num, (int)gpio_config->chip_num, active_state, drive, pull, init_state); return ERROR_OK; @@ -942,9 +948,7 @@ COMMAND_HANDLER(adapter_gpio_config_handler) LOG_DEBUG("Processing %s", CMD_ARGV[i]); if (isdigit(*CMD_ARGV[i])) { - int gpio_num; /* Use a meaningful output parameter for more helpful error messages */ - COMMAND_PARSE_NUMBER(int, CMD_ARGV[i], gpio_num); - gpio_config->gpio_num = gpio_num; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[i], gpio_config->gpio_num); ++i; continue; } @@ -955,9 +959,7 @@ COMMAND_HANDLER(adapter_gpio_config_handler) return ERROR_FAIL; } LOG_DEBUG("-chip arg is %s", CMD_ARGV[i + 1]); - int chip_num; /* Use a meaningful output parameter for more helpful error messages */ - COMMAND_PARSE_NUMBER(int, CMD_ARGV[i + 1], chip_num); - gpio_config->chip_num = chip_num; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[i + 1], gpio_config->chip_num); i += 2; continue; } diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h index 682fc10aea..23ffe2cc51 100644 --- a/src/jtag/adapter.h +++ b/src/jtag/adapter.h @@ -10,6 +10,7 @@ #include #include #include +#include /** Supported output drive modes for adaptor GPIO */ enum adapter_gpio_drive_mode { @@ -56,8 +57,8 @@ enum adapter_gpio_config_index { /** Configuration options for a single GPIO */ struct adapter_gpio_config { - int gpio_num; - int chip_num; + unsigned int gpio_num; + unsigned int chip_num; enum adapter_gpio_drive_mode drive; /* For outputs only */ enum adapter_gpio_init_state init_state; bool active_low; @@ -121,4 +122,6 @@ const char *adapter_gpio_get_name(enum adapter_gpio_config_index idx); */ const struct adapter_gpio_config *adapter_gpio_get_config(void); +#define ADAPTER_GPIO_NOT_SET UINT_MAX + #endif /* OPENOCD_JTAG_ADAPTER_H */ diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index 29d410118e..cfe41c3be5 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -86,9 +86,7 @@ static const struct adapter_gpio_config *adapter_gpio_config; static bool is_gpio_config_valid(const struct adapter_gpio_config *gpio_config) { - return gpio_config->chip_num >= 0 - && gpio_config->chip_num < AM335XGPIO_NUM_GPIO_CHIPS - && gpio_config->gpio_num >= 0 + return gpio_config->chip_num < AM335XGPIO_NUM_GPIO_CHIPS && gpio_config->gpio_num < AM335XGPIO_NUM_GPIO_PER_CHIP; } @@ -249,10 +247,13 @@ static int am335xgpio_reset(int trst, int srst) if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST])) set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST], trst); - LOG_DEBUG("am335xgpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d", - trst, srst, - adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num, - adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num); + LOG_DEBUG("trst %d gpio: %d %d, srst %d gpio: %d %d", + trst, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num, + srst, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num); return ERROR_OK; } diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 7fd7f38940..ff10b0a78c 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -84,10 +84,7 @@ static inline void bcm2835_delay(void) static bool is_gpio_config_valid(enum adapter_gpio_config_index idx) { /* Only chip 0 is supported, accept unset value (-1) too */ - return adapter_gpio_config[idx].chip_num >= -1 - && adapter_gpio_config[idx].chip_num <= 0 - && adapter_gpio_config[idx].gpio_num >= 0 - && adapter_gpio_config[idx].gpio_num <= 31; + return adapter_gpio_config[idx].gpio_num <= 31; } static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value) @@ -243,10 +240,13 @@ static int bcm2835gpio_reset(int trst, int srst) if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST)) set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST], trst); - LOG_DEBUG("BCM2835 GPIO: bcm2835gpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d", - trst, srst, - adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num, - adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num); + LOG_DEBUG("trst %d gpio: %d %d, srst %d gpio: %d %d", + trst, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num, + srst, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num, + (int)adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num); return ERROR_OK; } diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index d1a88c88d3..9428837883 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -37,9 +37,7 @@ static const struct adapter_gpio_config *adapter_gpio_config; */ static bool is_gpio_config_valid(enum adapter_gpio_config_index idx) { - return adapter_gpio_config[idx].chip_num >= 0 - && adapter_gpio_config[idx].chip_num < 1000 - && adapter_gpio_config[idx].gpio_num >= 0 + return adapter_gpio_config[idx].chip_num < 1000 && adapter_gpio_config[idx].gpio_num < 10000; } From 38616990744b2bac7026f0d41da9247b42494379 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 10:15:07 +0100 Subject: [PATCH 0734/1312] target/cortex_m: prevent asserting reset if examine is deferred In a corner case when debug_ap is not available, cortex_m_assert_reset() asserts reset to restore communication with the target. Prevent to do so on targets with defer_examine, as such targets need some special handling to enable them after reset anyway. The change makes possible to handle a multicore Cortex-M SoC with an auxiliary Cortex-M core(s) switched of by default even with 'reset_config srst_gates_jtag' Change-Id: I8cec7a816423e588d5e2e4f7904c81c776eddc42 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8097 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 6a29a5fd4c..8bb852f4f8 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1625,7 +1625,8 @@ static int cortex_m_assert_reset(struct target *target) bool srst_asserted = false; if ((jtag_reset_config & RESET_HAS_SRST) && - ((jtag_reset_config & RESET_SRST_NO_GATING) || !armv7m->debug_ap)) { + ((jtag_reset_config & RESET_SRST_NO_GATING) + || (!armv7m->debug_ap && !target->defer_examine))) { /* If we have no debug_ap, asserting SRST is the only thing * we can do now */ adapter_assert_reset(); From 226085065bdfdfd44bfadbfb2973971ff154eb22 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 12:05:35 +0100 Subject: [PATCH 0735/1312] target/cortex_m: drop useless target_halt() call In 2008 the commit 182936125371 ("define resetting the target into the halted or running state as an atomic operation.") introduced the target_halt() call to the end of cortex_m3_assert_reset(), Checkpatch-ignore: GIT_COMMIT_ID A year later the commit ed36a8d15dfd ("... Updated halt handling for cortex_m3") prevented cortex_m3_halt() take any action in case of TARGET_RESET state. This narrowed the target_halt() called from cortex_m3_assert_reset() to setting target->halt_issued and storing a time stamp. Introducing ocd_process_reset(_inner) made the setting of halt_issued and halt_issued_time useless. The Tcl function waits for halt of all targets if applicable. cortex_m_halt() and also target_halt() does not work as expected if the cached target state is TARGET_RESET (although the core could be out of reset and ready to be halted, just have not been polled). Explicit Tcl arp_poll must be issued in many scenarios. Remove the useless hack. Also remove the explicit error return from cortex_m_halt_one() in case of RESET_SRST_PULLS_TRST and asserted srst. If the communication with the target is gated by any reset, cortex_m_write_debug_halt_mask() fails. Propagate the error return of this call instead. Change-Id: I0da05b87f43c3d0facb78e54d8f00c1728fe7c46 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8098 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 8bb852f4f8..fb1794af22 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1106,6 +1106,7 @@ static int cortex_m_poll(struct target *target) static int cortex_m_halt_one(struct target *target) { + int retval; LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { @@ -1116,22 +1117,8 @@ static int cortex_m_halt_one(struct target *target) if (target->state == TARGET_UNKNOWN) LOG_TARGET_WARNING(target, "target was in unknown state when halt was requested"); - if (target->state == TARGET_RESET) { - if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { - LOG_TARGET_ERROR(target, "can't request a halt while in reset if nSRST pulls nTRST"); - return ERROR_TARGET_FAILURE; - } else { - /* we came here in a reset_halt or reset_init sequence - * debug entry was already prepared in cortex_m3_assert_reset() - */ - target->debug_reason = DBG_REASON_DBGRQ; - - return ERROR_OK; - } - } - /* Write to Debug Halting Control and Status Register */ - cortex_m_write_debug_halt_mask(target, C_HALT, 0); + retval = cortex_m_write_debug_halt_mask(target, C_HALT, 0); /* Do this really early to minimize the window where the MASKINTS erratum * can pile up pending interrupts. */ @@ -1139,7 +1126,7 @@ static int cortex_m_halt_one(struct target *target) target->debug_reason = DBG_REASON_DBGRQ; - return ERROR_OK; + return retval; } static int cortex_m_halt(struct target *target) @@ -1755,17 +1742,7 @@ static int cortex_m_assert_reset(struct target *target) register_cache_invalidate(cortex_m->armv7m.arm.core_cache); - /* now return stored error code if any */ - if (retval != ERROR_OK) - return retval; - - if (target->reset_halt && target_was_examined(target)) { - retval = target_halt(target); - if (retval != ERROR_OK) - return retval; - } - - return ERROR_OK; + return retval; } static int cortex_m_deassert_reset(struct target *target) From 79f519bb633e0d37a9b9ce4b7a1dc16aa14014cd Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 12:29:14 +0100 Subject: [PATCH 0736/1312] target/cortex_m: fix couple of comments Fix obsoleted references to Cortex-M3 from the time when M3 was the only supported Cortex. Fix typo. Signed-off-by: Tomas Vanek Change-Id: I6f93265f1b9328fec063fecd819210deb28aaf2c Reviewed-on: https://review.openocd.org/c/openocd/+/8099 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index fb1794af22..4894cabf8b 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1607,7 +1607,7 @@ static int cortex_m_assert_reset(struct target *target) } /* some cores support connecting while srst is asserted - * use that mode is it has been configured */ + * use that mode if it has been configured */ bool srst_asserted = false; @@ -1693,9 +1693,8 @@ static int cortex_m_assert_reset(struct target *target) /* srst is asserted, ignore AP access errors */ retval = ERROR_OK; } else { - /* Use a standard Cortex-M3 software reset mechanism. - * We default to using VECTRESET as it is supported on all current cores - * (except Cortex-M0, M0+ and M1 which support SYSRESETREQ only!) + /* Use a standard Cortex-M software reset mechanism. + * We default to using VECTRESET. * This has the disadvantage of not resetting the peripherals, so a * reset-init event handler is needed to perform any peripheral resets. */ @@ -2785,7 +2784,7 @@ static int cortex_m_init_arch_info(struct target *target, armv7m_init_arch_info(target, armv7m); /* default reset mode is to use srst if fitted - * if not it will use CORTEX_M3_RESET_VECTRESET */ + * if not it will use CORTEX_M_RESET_VECTRESET */ cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET; armv7m->arm.dap = dap; @@ -2842,8 +2841,7 @@ static int cortex_m_verify_pointer(struct command_invocation *cmd, /* * Only stuff below this line should need to verify that its target - * is a Cortex-M3. Everything else should have indirected through the - * cortexm3_target structure, which is only used with CM3 targets. + * is a Cortex-M with available DAP access (not a HLA adapter). */ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) @@ -2902,7 +2900,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) break; } if (i == ARRAY_SIZE(vec_ids)) { - LOG_TARGET_ERROR(target, "No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]); + LOG_TARGET_ERROR(target, "No Cortex-M vector '%s'", CMD_ARGV[CMD_ARGC]); return ERROR_COMMAND_SYNTAX_ERROR; } } From 3b5ef1726a4e5da657080d640e16f1f4d9dc6071 Mon Sep 17 00:00:00 2001 From: N S Date: Sun, 21 Jan 2024 17:45:06 -0800 Subject: [PATCH 0737/1312] jtag/drivers: Add vid_pid command to OpenJTAG Enable support for USB vid and pid combinations other than 0x0403/0x6001 on OpenJTAG adapters. Change-Id: Ibb5fb14a6f33abbc011dbf3179df20d79ed74a7a Signed-off-by: N S Reviewed-on: https://review.openocd.org/c/openocd/+/8100 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 9 +++++++++ src/jtag/drivers/openjtag.c | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index e4d4dc5d68..a4e7c6aaa3 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3445,6 +3445,15 @@ Currently valid @var{variant} values include: The USB device description string of the adapter. This value is only used with the standard variant. @end deffn + +@deffn {Config Command} {openjtag vid_pid} vid pid +The USB vendor ID and product ID of the adapter. If not specified, default +0x0403:0x6001 is used. +This value is only used with the standard variant. +@example +openjtag vid_pid 0x403 0x6014 +@end example +@end deffn @end deffn diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index dca27b0a64..45064fe6a2 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -861,6 +861,17 @@ COMMAND_HANDLER(openjtag_handle_variant_command) return ERROR_OK; } +COMMAND_HANDLER(openjtag_handle_vid_pid_command) +{ + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], openjtag_vid); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], openjtag_pid); + + return ERROR_OK; +} + static const struct command_registration openjtag_subcommand_handlers[] = { { .name = "device_desc", @@ -876,6 +887,13 @@ static const struct command_registration openjtag_subcommand_handlers[] = { .help = "set the OpenJTAG variant", .usage = "variant-string", }, + { + .name = "vid_pid", + .handler = openjtag_handle_vid_pid_command, + .mode = COMMAND_CONFIG, + .help = "USB VID and PID of the adapter", + .usage = "vid pid", + }, COMMAND_REGISTRATION_DONE }; From 50be4bd2672916f9262df31108d4611c2b0fbf44 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Mon, 10 Jul 2023 16:30:07 +0300 Subject: [PATCH 0738/1312] jtag/mpsse: mpsse_flush should not treat LIBUSB_ERROR_INTERRUPTED as an error LIBUSB_ERROR_INTERRUPTED can happen when (among other things) OpenOCD process receives a signal like SIGHUP or SIGINT during a call to libusb. Such situations are expected and should not be treated as an error - the affected request should just be restarted. Without this patch applied if a signal arrives during FTDI initialization procedure we can easily end up (if JTAG speed is low) in situations like https://review.openocd.org/c/openocd/+/4767. This happens because fpsse_flush fails due to LIBUSB_ERROR_INTERRUPTED . It should be noted that the current usage of mpsse_flush should be revised since it seems that we don't always process error codes returned by the function. Change-Id: Ifa063ce828068f8d0371e1c2a864bb6174649848 Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/7769 Reviewed-by: Tim Newsome Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/mpsse.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index fad91dde2f..41a8b6e33f 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -880,20 +880,6 @@ int mpsse_flush(struct mpsse_ctx *ctx) retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL); keep_alive(); - if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED) - break; - - if (retval != LIBUSB_SUCCESS) { - libusb_cancel_transfer(write_transfer); - if (read_transfer) - libusb_cancel_transfer(read_transfer); - while (!write_result.done || !read_result.done) { - retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, - &timeout_usb, NULL); - if (retval != LIBUSB_SUCCESS) - break; - } - } int64_t now = timeval_ms(); if (now - start > warn_after) { @@ -901,6 +887,15 @@ int mpsse_flush(struct mpsse_ctx *ctx) "ms.", now - start); warn_after *= 2; } + + if (retval == LIBUSB_ERROR_INTERRUPTED) + continue; + + if (retval != LIBUSB_SUCCESS) { + libusb_cancel_transfer(write_transfer); + if (read_transfer) + libusb_cancel_transfer(read_transfer); + } } error_check: From d0548940f289fbb6c3ce61106799aa56ec20f188 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Wed, 10 Jan 2024 19:23:53 +0300 Subject: [PATCH 0739/1312] helper/log: report the file in `log_output` command Prior to the change when calling `log_output` without any arguments it was unclear where the log was redirected. Change-Id: Iaa3ecea8166f9c7ec8aad7adf5bd412799f719a1 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8071 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 7 ++++--- src/helper/log.c | 39 ++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index a4e7c6aaa3..38c8970456 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9035,9 +9035,10 @@ echo "Downloading kernel -- please wait" @end example @end deffn -@deffn {Command} {log_output} [filename | "default"] -Redirect logging to @var{filename} or set it back to default output; -the default log output channel is stderr. +@deffn {Command} {log_output} [filename | 'default'] +Redirect logging to @var{filename}. If used without an argument or +@var{filename} is set to 'default' log output channel is set to +stderr. @end deffn @deffn {Command} {add_script_search_dir} [directory] diff --git a/src/helper/log.c b/src/helper/log.c index a4fc53d4b5..471069adee 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -214,31 +214,28 @@ COMMAND_HANDLER(handle_debug_level_command) COMMAND_HANDLER(handle_log_output_command) { - if (CMD_ARGC == 0 || (CMD_ARGC == 1 && strcmp(CMD_ARGV[0], "default") == 0)) { - if (log_output != stderr && log_output) { - /* Close previous log file, if it was open and wasn't stderr. */ - fclose(log_output); - } - log_output = stderr; - LOG_DEBUG("set log_output to default"); - return ERROR_OK; - } - if (CMD_ARGC == 1) { - FILE *file = fopen(CMD_ARGV[0], "w"); + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + FILE *file; + if (CMD_ARGC == 1 && strcmp(CMD_ARGV[0], "default") != 0) { + file = fopen(CMD_ARGV[0], "w"); if (!file) { - LOG_ERROR("failed to open output log '%s'", CMD_ARGV[0]); + command_print(CMD, "failed to open output log \"%s\"", CMD_ARGV[0]); return ERROR_FAIL; } - if (log_output != stderr && log_output) { - /* Close previous log file, if it was open and wasn't stderr. */ - fclose(log_output); - } - log_output = file; - LOG_DEBUG("set log_output to \"%s\"", CMD_ARGV[0]); - return ERROR_OK; + command_print(CMD, "set log_output to \"%s\"", CMD_ARGV[0]); + } else { + file = stderr; + command_print(CMD, "set log_output to default"); } - return ERROR_COMMAND_SYNTAX_ERROR; + if (log_output != stderr && log_output) { + /* Close previous log file, if it was open and wasn't stderr. */ + fclose(log_output); + } + log_output = file; + return ERROR_OK; } static const struct command_registration log_command_handlers[] = { @@ -247,7 +244,7 @@ static const struct command_registration log_command_handlers[] = { .handler = handle_log_output_command, .mode = COMMAND_ANY, .help = "redirect logging to a file (default: stderr)", - .usage = "[file_name | \"default\"]", + .usage = "[file_name | 'default']", }, { .name = "debug_level", From 81a50d3e9050eed8f4d95622f2b326054a200b93 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 1 Feb 2024 10:55:51 +0100 Subject: [PATCH 0740/1312] jtag: fix jtag configure command containing events Commit ea2e26f7d521 ("jtag: rewrite jim_jtag_configure() as COMMAND_HANDLER") breaks the option -event if it is the last of the command line. This can be tested, even without any device connected, through: #> openocd -f board/ti_cc26x0_launchpad.cfg wrong # args: should be "-event " Fix the check on available arguments after -event. Change-Id: Iec1522238f906d61a888a09a7685acd9ac6442a7 Signed-off-by: Antonio Borneo Reported-by: Lorenz Brun Fixes: ea2e26f7d521 ("jtag: rewrite jim_jtag_configure() as COMMAND_HANDLER") Reviewed-on: https://review.openocd.org/c/openocd/+/8125 Tested-by: jenkins Reviewed-by: Lorenz Brun --- src/jtag/tcl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 163edfa19e..7995529018 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -315,7 +315,7 @@ __COMMAND_HANDLER(handle_jtag_configure) const struct nvp *n = nvp_name2value(nvp_config_opts, CMD_ARGV[i]); switch (n->value) { case JCFG_EVENT: - if (i + (is_configure ? 3 : 2) >= CMD_ARGC) { + if (i + (is_configure ? 2 : 1) >= CMD_ARGC) { command_print(CMD, "wrong # args: should be \"-event %s\"", is_configure ? " " : ""); return ERROR_COMMAND_ARGUMENT_INVALID; From 7295ddc15c0516a64c9996d2b351accb50175803 Mon Sep 17 00:00:00 2001 From: N S Date: Sun, 22 Jan 2023 21:34:16 -0800 Subject: [PATCH 0741/1312] jtag/drivers: OpenJTAG standard variant perf improvement Calculate exact size of response expected from OpenJTAG device so that openjtag_buf_read_standard doesn't spend 5 retry cycles waiting for data that isn't coming. Change-Id: Icd010d1fa4453d6592a1f9aed93fb1f01e0a19da Signed-off-by: N S Reviewed-on: https://review.openocd.org/c/openocd/+/8101 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/openjtag.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 45064fe6a2..1c79a2c9b6 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -530,9 +530,20 @@ static int openjtag_quit(void) static void openjtag_write_tap_buffer(void) { uint32_t written; + uint32_t rx_expected = 0; + + /* calculate expected number of return bytes */ + for (int tx_offs = 0; tx_offs < usb_tx_buf_offs; tx_offs++) { + if ((usb_tx_buf[tx_offs] & 0x0F) == 6) { + rx_expected++; + tx_offs++; + } else if ((usb_tx_buf[tx_offs] & 0x0F) == 2) { + rx_expected++; + } + } openjtag_buf_write(usb_tx_buf, usb_tx_buf_offs, &written); - openjtag_buf_read(usb_rx_buf, usb_tx_buf_offs, &usb_rx_buf_len); + openjtag_buf_read(usb_rx_buf, rx_expected, &usb_rx_buf_len); usb_tx_buf_offs = 0; } From c6e7e48b053c281ef4a9dd50f2d94fa12184a956 Mon Sep 17 00:00:00 2001 From: N S Date: Mon, 22 Jan 2024 21:47:34 -0800 Subject: [PATCH 0742/1312] jtag/drivers: fix reset logic handling in OpenJTAG The OpenJTAG driver behaviour always forces a system reset on jtag_init. The driver was incorrectly assuming that when execute_reset is called with trst set to 1 - perform a software TAP reset, otherwise perform a system reset when trst is 0. The set_state call assumes the that OpenJTAG hardware will perform a software TLR reset if the target state is TAP_RESET. This is not the case: the published VHDL will simply find the shortest path to TLR and not perform a fixed 5 cycle operation with TMS held high. Fix the code to only perform system resets when srst is 1 in execute_reset and to force a software TAP reset operation in set_state when the target state is TAP_RESET. Change-Id: I7e0f76f8491efefff1ccaeb4b1ae16e722d76df4 Signed-off-by: N S Reviewed-on: https://review.openocd.org/c/openocd/+/8121 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/openjtag.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 1c79a2c9b6..086a411d6b 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -671,14 +671,12 @@ static void openjtag_execute_reset(struct jtag_command *cmd) uint8_t buf = 0x00; - if (cmd->cmd.reset->trst) { - buf = 0x03; - } else { + /* Pull SRST low for 5 TCLK cycles */ + if (cmd->cmd.reset->srst) { buf |= 0x04; buf |= 0x05 << 4; + openjtag_add_byte(buf); } - - openjtag_add_byte(buf); } static void openjtag_execute_sleep(struct jtag_command *cmd) @@ -691,8 +689,14 @@ static void openjtag_set_state(uint8_t openocd_state) uint8_t state = openjtag_get_tap_state(openocd_state); uint8_t buf = 0; - buf = 0x01; - buf |= state << 4; + + if (state != OPENJTAG_TAP_RESET) { + buf = 0x01; + buf |= state << 4; + } else { + /* Force software TLR */ + buf = 0x03; + } openjtag_add_byte(buf); } From 847f1209d644fb1db45f7a385d9592eba76ab688 Mon Sep 17 00:00:00 2001 From: Evan Hunter Date: Wed, 31 Oct 2012 17:51:45 +1100 Subject: [PATCH 0743/1312] jtag interfaces: Reduce usage of global for jtag queue Makes driver interface slightly more flexible. Change-Id: I2c7f5cb6d014e94a0e6122cbe2f4002c77fbabb9 Signed-off-by: Evan Hunter Signed-off-by: David Ryskalczyk Reviewed-on: https://review.openocd.org/c/openocd/+/945 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/commands.c | 7 ++++++- src/jtag/commands.h | 4 +--- src/jtag/core.c | 4 ++-- src/jtag/drivers/amt_jtagaccel.c | 4 ++-- src/jtag/drivers/angie.c | 6 +++--- src/jtag/drivers/arm-jtag-ew.c | 4 ++-- src/jtag/drivers/bitbang.c | 5 +++-- src/jtag/drivers/bitbang.h | 3 ++- src/jtag/drivers/bitq.c | 6 +++--- src/jtag/drivers/bitq.h | 2 +- src/jtag/drivers/buspirate.c | 6 +++--- src/jtag/drivers/cmsis_dap.c | 4 ++-- src/jtag/drivers/ft232r.c | 4 ++-- src/jtag/drivers/ftdi.c | 4 ++-- src/jtag/drivers/gw16012.c | 4 ++-- src/jtag/drivers/jlink.c | 4 ++-- src/jtag/drivers/jtag_dpi.c | 4 ++-- src/jtag/drivers/jtag_vpi.c | 4 ++-- src/jtag/drivers/opendous.c | 6 +++--- src/jtag/drivers/openjtag.c | 4 ++-- src/jtag/drivers/osbdm.c | 4 ++-- src/jtag/drivers/remote_bitbang.c | 4 ++-- src/jtag/drivers/rlink.c | 4 ++-- src/jtag/drivers/ulink.c | 6 +++--- src/jtag/drivers/usb_blaster/usb_blaster.c | 4 ++-- src/jtag/drivers/usbprog.c | 4 ++-- src/jtag/drivers/vdebug.c | 4 ++-- src/jtag/drivers/vsllink.c | 4 ++-- src/jtag/drivers/xds110.c | 4 ++-- src/jtag/drivers/xlnx-pcie-xvc.c | 4 ++-- src/jtag/interface.h | 6 ++++-- 31 files changed, 72 insertions(+), 65 deletions(-) diff --git a/src/jtag/commands.c b/src/jtag/commands.c index 43cda8ad4e..c36c219233 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -33,7 +33,7 @@ struct cmd_queue_page { static struct cmd_queue_page *cmd_queue_pages; static struct cmd_queue_page *cmd_queue_pages_tail; -struct jtag_command *jtag_command_queue; +static struct jtag_command *jtag_command_queue; static struct jtag_command **next_command_pointer = &jtag_command_queue; void jtag_queue_command(struct jtag_command *cmd) @@ -147,6 +147,11 @@ void jtag_command_queue_reset(void) next_command_pointer = &jtag_command_queue; } +struct jtag_command *jtag_command_queue_get(void) +{ + return jtag_command_queue; +} + /** * Copy a struct scan_field for insertion into the queue. * diff --git a/src/jtag/commands.h b/src/jtag/commands.h index a8c7ffdc66..a1096daa77 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -149,13 +149,11 @@ struct jtag_command { struct jtag_command *next; }; -/** The current queue of jtag_command_s structures. */ -extern struct jtag_command *jtag_command_queue; - void *cmd_queue_alloc(size_t size); void jtag_queue_command(struct jtag_command *cmd); void jtag_command_queue_reset(void); +struct jtag_command *jtag_command_queue_get(void); void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src); enum scan_type jtag_scan_type(const struct scan_command *cmd); diff --git a/src/jtag/core.c b/src/jtag/core.c index e2af6c53d9..c84d5aa3d3 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -951,9 +951,9 @@ int default_interface_jtag_execute_queue(void) return ERROR_OK; } - int result = adapter_driver->jtag_ops->execute_queue(); + struct jtag_command *cmd = jtag_command_queue_get(); + int result = adapter_driver->jtag_ops->execute_queue(cmd); - struct jtag_command *cmd = jtag_command_queue; while (debug_level >= LOG_LVL_DEBUG_IO && cmd) { switch (cmd->type) { case JTAG_SCAN: diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index a4c8f32122..b28ce62ffb 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -317,9 +317,9 @@ static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffe tap_set_state(tap_get_end_state()); } -static int amt_jtagaccel_execute_queue(void) +static int amt_jtagaccel_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 62079f0156..c024667bdb 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -233,7 +233,7 @@ static int angie_post_process_scan(struct angie_cmd *angie_cmd); static int angie_post_process_queue(struct angie *device); /* adapter driver functions */ -static int angie_execute_queue(void); +static int angie_execute_queue(struct jtag_command *cmd_queue); static int angie_khz(int khz, int *jtag_speed); static int angie_speed(int speed); static int angie_speed_div(int speed, int *khz); @@ -2037,9 +2037,9 @@ static int angie_post_process_queue(struct angie *device) * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ -static int angie_execute_queue(void) +static int angie_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int ret; while (cmd) { diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index eada67f45c..4c50c54c9b 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -85,9 +85,9 @@ static struct armjtagew *armjtagew_handle; /************************************************************************** * External interface implementation */ -static int armjtagew_execute_queue(void) +static int armjtagew_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 186d2098af..8df51764b7 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -15,6 +15,7 @@ #include "config.h" #endif +#include /* Added to avoid include loop in commands.h */ #include "bitbang.h" #include #include @@ -287,9 +288,9 @@ static void bitbang_sleep(unsigned int microseconds) } } -int bitbang_execute_queue(void) +int bitbang_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 097a5c0d12..dc941796e2 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -12,6 +12,7 @@ #define OPENOCD_JTAG_DRIVERS_BITBANG_H #include +#include typedef enum { BB_LOW, @@ -64,7 +65,7 @@ struct bitbang_interface { extern const struct swd_driver bitbang_swd; -int bitbang_execute_queue(void); +int bitbang_execute_queue(struct jtag_command *cmd_queue); extern struct bitbang_interface *bitbang_interface; diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c index 59e4f3574c..2e5cca2a49 100644 --- a/src/jtag/drivers/bitq.c +++ b/src/jtag/drivers/bitq.c @@ -203,11 +203,11 @@ static void bitq_scan(struct scan_command *cmd) bitq_scan_field(&cmd->fields[i], 1); } -int bitq_execute_queue(void) +int bitq_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ - bitq_in_state.cmd = jtag_command_queue; + bitq_in_state.cmd = cmd_queue; bitq_in_state.field_idx = 0; bitq_in_state.bit_pos = 0; bitq_in_state.status = ERROR_OK; diff --git a/src/jtag/drivers/bitq.h b/src/jtag/drivers/bitq.h index 8e06fcf737..3ed182da4c 100644 --- a/src/jtag/drivers/bitq.h +++ b/src/jtag/drivers/bitq.h @@ -27,7 +27,7 @@ struct bitq_interface { extern struct bitq_interface *bitq_interface; -int bitq_execute_queue(void); +int bitq_execute_queue(struct jtag_command *cmd_queue); void bitq_cleanup(void); diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index 03b48e68b2..3b03337c94 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -20,7 +20,7 @@ #undef DEBUG_SERIAL /*#define DEBUG_SERIAL */ -static int buspirate_execute_queue(void); +static int buspirate_execute_queue(struct jtag_command *cmd_queue); static int buspirate_init(void); static int buspirate_quit(void); static int buspirate_reset(int trst, int srst); @@ -151,10 +151,10 @@ static int buspirate_serial_read(int fd, uint8_t *buf, int size); static void buspirate_serial_close(int fd); static void buspirate_print_buffer(uint8_t *buf, int size); -static int buspirate_execute_queue(void) +static int buspirate_execute_queue(struct jtag_command *cmd_queue) { /* currently processed command */ - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index caacc9b916..341d35cdfa 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -1954,9 +1954,9 @@ static void cmsis_dap_execute_command(struct jtag_command *cmd) } } -static int cmsis_dap_execute_queue(void) +static int cmsis_dap_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; while (cmd) { cmsis_dap_execute_command(cmd); diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index 2d9d9ef34d..766f6ddb5d 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -803,9 +803,9 @@ static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int } } -static int syncbb_execute_queue(void) +static int syncbb_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index da5911ac99..2bde93169e 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -625,14 +625,14 @@ static void ftdi_execute_command(struct jtag_command *cmd) } } -static int ftdi_execute_queue(void) +static int ftdi_execute_queue(struct jtag_command *cmd_queue) { /* blink, if the current layout has that feature */ struct signal *led = find_signal_by_name("LED"); if (led) ftdi_set_signal(led, '1'); - for (struct jtag_command *cmd = jtag_command_queue; cmd; cmd = cmd->next) { + for (struct jtag_command *cmd = cmd_queue; cmd; cmd = cmd->next) { /* fill the write buffer with the desired command */ ftdi_execute_command(cmd); } diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index 592e170992..a4c6fd0f00 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -270,9 +270,9 @@ static void gw16012_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int } } -static int gw16012_execute_queue(void) +static int gw16012_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 97dc351fdf..1874557dcd 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -276,10 +276,10 @@ static int jlink_execute_command(struct jtag_command *cmd) return ERROR_OK; } -static int jlink_execute_queue(void) +static int jlink_execute_queue(struct jtag_command *cmd_queue) { int ret; - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; while (cmd) { ret = jlink_execute_command(cmd); diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c index 2a36331efc..285f96e4bf 100644 --- a/src/jtag/drivers/jtag_dpi.c +++ b/src/jtag/drivers/jtag_dpi.c @@ -222,12 +222,12 @@ static int jtag_dpi_stableclocks(int cycles) return jtag_dpi_runtest(cycles); } -static int jtag_dpi_execute_queue(void) +static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue) { struct jtag_command *cmd; int ret = ERROR_OK; - for (cmd = jtag_command_queue; ret == ERROR_OK && cmd; + for (cmd = cmd_queue; ret == ERROR_OK && cmd; cmd = cmd->next) { switch (cmd->type) { case JTAG_RUNTEST: diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index c2b3b08083..9dec0d19df 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -480,12 +480,12 @@ static int jtag_vpi_stableclocks(int cycles) return ERROR_OK; } -static int jtag_vpi_execute_queue(void) +static int jtag_vpi_execute_queue(struct jtag_command *cmd_queue) { struct jtag_command *cmd; int retval = ERROR_OK; - for (cmd = jtag_command_queue; retval == ERROR_OK && cmd; + for (cmd = cmd_queue; retval == ERROR_OK && cmd; cmd = cmd->next) { switch (cmd->type) { case JTAG_RESET: diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index 4d9fd998a7..81b74d40ec 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -99,7 +99,7 @@ static char *opendous_type; static const struct opendous_probe *opendous_probe; /* External interface functions */ -static int opendous_execute_queue(void); +static int opendous_execute_queue(struct jtag_command *cmd_queue); static int opendous_init(void); static int opendous_quit(void); @@ -238,9 +238,9 @@ struct adapter_driver opendous_adapter_driver = { .jtag_ops = &opendous_interface, }; -static int opendous_execute_queue(void) +static int opendous_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 086a411d6b..ea78ca8fd6 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -805,9 +805,9 @@ static void openjtag_execute_command(struct jtag_command *cmd) } } -static int openjtag_execute_queue(void) +static int openjtag_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; while (cmd) { openjtag_execute_command(cmd); diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index 84f2fd66a0..8d4fc90d88 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -628,7 +628,7 @@ static int osbdm_execute_command( return retval; } -static int osbdm_execute_queue(void) +static int osbdm_execute_queue(struct jtag_command *cmd_queue) { int retval = ERROR_OK; @@ -637,7 +637,7 @@ static int osbdm_execute_queue(void) LOG_ERROR("BUG: can't allocate bit queue"); retval = ERROR_FAIL; } else { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; while (retval == ERROR_OK && cmd) { retval = osbdm_execute_command(&osbdm_context, queue, cmd); diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 6d0fba2e40..c97b6b6abe 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -456,14 +456,14 @@ static const struct command_registration remote_bitbang_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static int remote_bitbang_execute_queue(void) +static int remote_bitbang_execute_queue(struct jtag_command *cmd_queue) { /* safety: the send buffer must be empty, no leftover characters from * previous transactions */ assert(remote_bitbang_send_buf_used == 0); /* process the JTAG command queue */ - int ret = bitbang_execute_queue(); + int ret = bitbang_execute_queue(cmd_queue); if (ret != ERROR_OK) return ret; diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index a28e76e013..1b1f2e4de6 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -1262,9 +1262,9 @@ static int rlink_scan(struct jtag_command *cmd, enum scan_type type, return 0; } -static int rlink_execute_queue(void) +static int rlink_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index fd29f126e2..4f23c6c7fa 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -227,7 +227,7 @@ static int ulink_post_process_scan(struct ulink_cmd *ulink_cmd); static int ulink_post_process_queue(struct ulink *device); /* adapter driver functions */ -static int ulink_execute_queue(void); +static int ulink_execute_queue(struct jtag_command *cmd_queue); static int ulink_khz(int khz, int *jtag_speed); static int ulink_speed(int speed); static int ulink_speed_div(int speed, int *khz); @@ -1905,9 +1905,9 @@ static int ulink_post_process_queue(struct ulink *device) * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ -static int ulink_execute_queue(void) +static int ulink_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int ret; while (cmd) { diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 8c37048144..c84055c4a1 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -765,7 +765,7 @@ static void ublast_initial_wipeout(void) tap_set_state(TAP_RESET); } -static int ublast_execute_queue(void) +static int ublast_execute_queue(struct jtag_command *cmd_queue) { struct jtag_command *cmd; static int first_call = 1; @@ -776,7 +776,7 @@ static int ublast_execute_queue(void) ublast_initial_wipeout(); } - for (cmd = jtag_command_queue; ret == ERROR_OK && cmd; + for (cmd = cmd_queue; ret == ERROR_OK && cmd; cmd = cmd->next) { switch (cmd->type) { case JTAG_RESET: diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index aa655ed7e6..2d666d0728 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -83,9 +83,9 @@ static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag, unsigned static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag, int bit, int value); /* static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit); */ -static int usbprog_execute_queue(void) +static int usbprog_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + struct jtag_command *cmd = cmd_queue; /* currently processed command */ int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index 6d9016e9c6..f1fc4535f3 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -1046,11 +1046,11 @@ static int vdebug_jtag_div(int speed, int *khz) return ERROR_OK; } -static int vdebug_jtag_execute_queue(void) +static int vdebug_jtag_execute_queue(struct jtag_command *cmd_queue) { int rc = ERROR_OK; - for (struct jtag_command *cmd = jtag_command_queue; rc == ERROR_OK && cmd; cmd = cmd->next) { + for (struct jtag_command *cmd = cmd_queue; rc == ERROR_OK && cmd; cmd = cmd->next) { switch (cmd->type) { case JTAG_RUNTEST: rc = vdebug_jtag_runtest(cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state, !cmd->next); diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 255ff88a2f..34525d5468 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -84,9 +84,9 @@ static bool swd_mode; static struct vsllink *vsllink_handle; -static int vsllink_execute_queue(void) +static int vsllink_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int scan_size; enum scan_type type; uint8_t *buffer; diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index 717295c73c..11fbaaab2a 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -1840,9 +1840,9 @@ static void xds110_execute_command(struct jtag_command *cmd) } } -static int xds110_execute_queue(void) +static int xds110_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; while (cmd) { xds110_execute_command(cmd); diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index 6ad0255e71..233ade3f88 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -362,9 +362,9 @@ static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd) return ERROR_OK; } -static int xlnx_pcie_xvc_execute_queue(void) +static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue) { - struct jtag_command *cmd = jtag_command_queue; + struct jtag_command *cmd = cmd_queue; int ret; while (cmd) { diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 3df424086d..28c1458cb0 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -187,10 +187,12 @@ struct jtag_interface { #define DEBUG_CAP_TMS_SEQ (1 << 0) /** - * Execute queued commands. + * Execute commands in the supplied queue + * @param cmd_queue - a linked list of commands to execute * @returns ERROR_OK on success, or an error code on failure. */ - int (*execute_queue)(void); + + int (*execute_queue)(struct jtag_command *cmd_queue); }; /** From efdd5e09b1108e3bd35898a684817c01dc95cd93 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 6 Feb 2024 22:20:06 +0100 Subject: [PATCH 0744/1312] jep106: update to revision JEP106BI January 2024 The original documents from Jedec since JEP106BG, do not report the entry for "21 NXP (Philips)", replaced by "c". It's clearly a typo. Keep the line from JEP106BF.01 for "NXP (Philips)". Change-Id: I293173c4527c2eabebdc33a94cd23d3a557a4618 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8132 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/jep106.inc | 58 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index bcf354c916..958dc4ea4d 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -2,13 +2,13 @@ /* * The manufacturer's standard identification code list appears in JEP106. - * Copyright (c) 2023 JEDEC. All rights reserved. + * Copyright (c) 2024 JEDEC. All rights reserved. * * JEP106 is regularly updated. For the current manufacturer's standard * identification code list, please visit the JEDEC website at www.jedec.org . */ -/* This file is aligned to revision JEP106BH September 2023. */ +/* This file is aligned to revision JEP106BI January 2024. */ /* "NXP (Philips)" is reported below, while missing since JEP106BG */ @@ -1621,7 +1621,7 @@ [12][0x5f - 1] = "Sitrus Technology", [12][0x60 - 1] = "AnHui Conner Storage Co Ltd", [12][0x61 - 1] = "Rochester Electronics", -[12][0x62 - 1] = "Wuxi Petabyte Technologies Co Ltd", +[12][0x62 - 1] = "Wuxi Smart Memories Technologies Co", [12][0x63 - 1] = "Star Memory", [12][0x64 - 1] = "Agile Memory Technology Co Ltd", [12][0x65 - 1] = "MEJEC", @@ -1864,7 +1864,7 @@ [14][0x56 - 1] = "Exacta Technologies Ltd", [14][0x57 - 1] = "Synology", [14][0x58 - 1] = "Trium Elektronik Bilgi Islem San Ve Dis", -[14][0x59 - 1] = "Shenzhen Hippstor Technology Co Ltd", +[14][0x59 - 1] = "Wuxi HippStor Technology Co Ltd", [14][0x5a - 1] = "SSCT", [14][0x5b - 1] = "Sichuan Heentai Semiconductor Co Ltd", [14][0x5c - 1] = "Zhejiang University", @@ -1888,4 +1888,54 @@ [14][0x6e - 1] = "Chemgdu EG Technology Co Ltd", [14][0x6f - 1] = "AGI Technology", [14][0x70 - 1] = "Syntiant", +[14][0x71 - 1] = "AOC", +[14][0x72 - 1] = "GamePP", +[14][0x73 - 1] = "Yibai Electronic Technologies", +[14][0x74 - 1] = "Hangzhou Rencheng Trading Co Ltd", +[14][0x75 - 1] = "HOGE Technology Co Ltd", +[14][0x76 - 1] = "United Micro Technology (Shenzhen) Co", +[14][0x77 - 1] = "Fabric of Truth Inc", +[14][0x78 - 1] = "Epitech", +[14][0x79 - 1] = "Elitestek", +[14][0x7a - 1] = "Cornelis Networks Inc", +[14][0x7b - 1] = "WingSemi Technologies Co Ltd", +[14][0x7c - 1] = "ForwardEdge ASIC", +[14][0x7d - 1] = "Beijing Future Imprint Technology Co Ltd", +[14][0x7e - 1] = "Fine Made Microelectronics Group Co Ltd", +[15][0x01 - 1] = "Changxin Memory Technology (Shanghai)", +[15][0x02 - 1] = "Synconv", +[15][0x03 - 1] = "MULTIUNIT", +[15][0x04 - 1] = "Zero ASIC Corporation", +[15][0x05 - 1] = "NTT Innovative Devices Corporation", +[15][0x06 - 1] = "Xbstor", +[15][0x07 - 1] = "Shenzhen South Electron Co Ltd", +[15][0x08 - 1] = "Iontra Inc", +[15][0x09 - 1] = "SIEFFI Inc", +[15][0x0a - 1] = "HK Winston Electronics Co Limited", +[15][0x0b - 1] = "Anhui SunChip Semiconductor Technology", +[15][0x0c - 1] = "HaiLa Technologies Inc", +[15][0x0d - 1] = "AUTOTALKS", +[15][0x0e - 1] = "Shenzhen Ranshuo Technology Co Limited", +[15][0x0f - 1] = "ScaleFlux", +[15][0x10 - 1] = "XC Memory", +[15][0x11 - 1] = "Guangzhou Beimu Technology Co., Ltd", +[15][0x12 - 1] = "Rays Semiconductor Nanjing Co Ltd", +[15][0x13 - 1] = "Milli-Centi Intelligence Technology Jiangsu", +[15][0x14 - 1] = "Zilia Technologioes", +[15][0x15 - 1] = "Incore Semiconductors", +[15][0x16 - 1] = "Kinetic Technologies", +[15][0x17 - 1] = "Nanjing Houmo Technology Co Ltd", +[15][0x18 - 1] = "Suzhou Yige Technology Co Ltd", +[15][0x19 - 1] = "Shenzhen Techwinsemi Technology Co Ltd", +[15][0x1a - 1] = "Pure Array Technology (Shanghai) Co. Ltd", +[15][0x1b - 1] = "Shenzhen Techwinsemi Technology Udstore", +[15][0x1c - 1] = "RISE MODE", +[15][0x1d - 1] = "NEWREESTAR", +[15][0x1e - 1] = "Hangzhou Hualan Microeletronique Co Ltd", +[15][0x1f - 1] = "Senscomm Semiconductor Co Ltd", +[15][0x20 - 1] = "Holt Integrated Circuits", +[15][0x21 - 1] = "Tenstorrent Inc", +[15][0x22 - 1] = "SkyeChip", +[15][0x23 - 1] = "Guangzhou Kaishile Trading Co Ltd", +[15][0x24 - 1] = "Jing Pai Digital Technology (Shenzhen) Co", /* EOF */ From 7145b984a9852a0494e2e63df2f61aa36f877377 Mon Sep 17 00:00:00 2001 From: Sevan Janiyan Date: Sun, 28 Jan 2024 20:34:41 +0000 Subject: [PATCH 0745/1312] portability fix: Switch binary literals to hex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows build with legacy toolchains which do not support C23 nor GCC extension for binary literals. Change-Id: I742d3a8a86bf16f81421d11c59d3cb155ee17aed Signed-off-by: Sevan Janiyan Reviewed-on: https://review.openocd.org/c/openocd/+/8123 Tested-by: jenkins Reviewed-by: Jörg Wunsch Reviewed-by: Tomas Vanek --- src/flash/nor/xcf.c | 6 +- src/target/armv8_dpm.c | 2 +- src/target/armv8_opcodes.h | 134 ++++++++++++++++++------------------- 3 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/flash/nor/xcf.c b/src/flash/nor/xcf.c index c253b2264b..1d67b09430 100644 --- a/src/flash/nor/xcf.c +++ b/src/flash/nor/xcf.c @@ -130,8 +130,8 @@ static struct xcf_status read_status(struct flash_bank *bank) jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); jtag_execute_queue(); - ret.isc_error = ((irdata[0] >> 7) & 3) == 0b01; - ret.prog_error = ((irdata[0] >> 5) & 3) == 0b01; + ret.isc_error = ((irdata[0] >> 7) & 3) == 1; + ret.prog_error = ((irdata[0] >> 5) & 3) == 1; ret.prog_busy = ((irdata[0] >> 4) & 1) == 0; ret.isc_mode = ((irdata[0] >> 3) & 1) == 1; @@ -528,7 +528,7 @@ static int isc_program_single_revision_btc(struct flash_bank *bank) { uint8_t buf[4]; uint32_t btc = 0xFFFFFFFF; - btc &= ~0b1111; + btc &= ~0xF; btc |= ((bank->num_sectors - 1) << 2); btc &= ~(1 << 4); h_u32_to_le(buf, btc); diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 552bcfa024..8bb24f225b 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -46,7 +46,7 @@ enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm) dpm->last_el = el; /* In Debug state, each bit gives the current Execution state of each EL */ - if ((rw >> el) & 0b1) + if ((rw >> el) & 1) return ARM_STATE_AARCH64; return ARM_STATE_ARM; diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index ddb0f9b073..9200dac723 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -26,80 +26,80 @@ #define SYSTEM_AAR64_MODE_EL3T 0xC #define SYSTEM_AAR64_MODE_EL3H 0xd -#define SYSTEM_DAIF 0b1101101000010001 +#define SYSTEM_DAIF 0xDA11 #define SYSTEM_DAIF_MASK 0x3C0 #define SYSTEM_DAIF_SHIFT 6 -#define SYSTEM_ELR_EL1 0b1100001000000001 -#define SYSTEM_ELR_EL2 0b1110001000000001 -#define SYSTEM_ELR_EL3 0b1111001000000001 - -#define SYSTEM_SCTLR_EL1 0b1100000010000000 -#define SYSTEM_SCTLR_EL2 0b1110000010000000 -#define SYSTEM_SCTLR_EL3 0b1111000010000000 - -#define SYSTEM_FPCR 0b1101101000100000 -#define SYSTEM_FPSR 0b1101101000100001 -#define SYSTEM_DAIF 0b1101101000010001 -#define SYSTEM_NZCV 0b1101101000010000 -#define SYSTEM_SP_EL0 0b1100001000001000 -#define SYSTEM_SP_EL1 0b1110001000001000 -#define SYSTEM_SP_EL2 0b1111001000001000 -#define SYSTEM_SP_SEL 0b1100001000010000 -#define SYSTEM_SPSR_ABT 0b1110001000011001 -#define SYSTEM_SPSR_FIQ 0b1110001000011011 -#define SYSTEM_SPSR_IRQ 0b1110001000011000 -#define SYSTEM_SPSR_UND 0b1110001000011010 - -#define SYSTEM_SPSR_EL1 0b1100001000000000 -#define SYSTEM_SPSR_EL2 0b1110001000000000 -#define SYSTEM_SPSR_EL3 0b1111001000000000 - -#define SYSTEM_ISR_EL1 0b1100011000001000 - -#define SYSTEM_DBG_DSPSR_EL0 0b1101101000101000 -#define SYSTEM_DBG_DLR_EL0 0b1101101000101001 -#define SYSTEM_DBG_DTRRX_EL0 0b1001100000101000 -#define SYSTEM_DBG_DTRTX_EL0 0b1001100000101000 -#define SYSTEM_DBG_DBGDTR_EL0 0b1001100000100000 - -#define SYSTEM_CCSIDR 0b1100100000000000 -#define SYSTEM_CLIDR 0b1100100000000001 -#define SYSTEM_CSSELR 0b1101000000000000 -#define SYSTEM_CTYPE 0b1101100000000001 -#define SYSTEM_CTR 0b1101100000000001 - -#define SYSTEM_DCCISW 0b0100001111110010 -#define SYSTEM_DCCSW 0b0100001111010010 -#define SYSTEM_ICIVAU 0b0101101110101001 -#define SYSTEM_DCCVAU 0b0101101111011001 -#define SYSTEM_DCCIVAC 0b0101101111110001 - -#define SYSTEM_MPIDR 0b1100000000000101 - -#define SYSTEM_TCR_EL1 0b1100000100000010 -#define SYSTEM_TCR_EL2 0b1110000100000010 -#define SYSTEM_TCR_EL3 0b1111000100000010 - -#define SYSTEM_TTBR0_EL1 0b1100000100000000 -#define SYSTEM_TTBR0_EL2 0b1110000100000000 -#define SYSTEM_TTBR0_EL3 0b1111000100000000 -#define SYSTEM_TTBR1_EL1 0b1100000100000001 +#define SYSTEM_ELR_EL1 0xC201 +#define SYSTEM_ELR_EL2 0xE201 +#define SYSTEM_ELR_EL3 0xF201 + +#define SYSTEM_SCTLR_EL1 0xC080 +#define SYSTEM_SCTLR_EL2 0xE080 +#define SYSTEM_SCTLR_EL3 0xF080 + +#define SYSTEM_FPCR 0xDA20 +#define SYSTEM_FPSR 0xDA21 +#define SYSTEM_DAIF 0xDA11 +#define SYSTEM_NZCV 0xDA10 +#define SYSTEM_SP_EL0 0xC208 +#define SYSTEM_SP_EL1 0xE208 +#define SYSTEM_SP_EL2 0xF208 +#define SYSTEM_SP_SEL 0xC210 +#define SYSTEM_SPSR_ABT 0xE219 +#define SYSTEM_SPSR_FIQ 0xE21B +#define SYSTEM_SPSR_IRQ 0xE218 +#define SYSTEM_SPSR_UND 0xE21A + +#define SYSTEM_SPSR_EL1 0xC200 +#define SYSTEM_SPSR_EL2 0xE200 +#define SYSTEM_SPSR_EL3 0xF200 + +#define SYSTEM_ISR_EL1 0xC608 + +#define SYSTEM_DBG_DSPSR_EL0 0xDA28 +#define SYSTEM_DBG_DLR_EL0 0xDA29 +#define SYSTEM_DBG_DTRRX_EL0 0x9828 +#define SYSTEM_DBG_DTRTX_EL0 0x9828 +#define SYSTEM_DBG_DBGDTR_EL0 0x9820 + +#define SYSTEM_CCSIDR 0xC800 +#define SYSTEM_CLIDR 0xC801 +#define SYSTEM_CSSELR 0xD000 +#define SYSTEM_CTYPE 0xD801 +#define SYSTEM_CTR 0xD801 + +#define SYSTEM_DCCISW 0x43F2 +#define SYSTEM_DCCSW 0x43D2 +#define SYSTEM_ICIVAU 0x5BA9 +#define SYSTEM_DCCVAU 0x5BD9 +#define SYSTEM_DCCIVAC 0x5BF1 + +#define SYSTEM_MPIDR 0xC005 + +#define SYSTEM_TCR_EL1 0xC102 +#define SYSTEM_TCR_EL2 0xE102 +#define SYSTEM_TCR_EL3 0xF102 + +#define SYSTEM_TTBR0_EL1 0xC100 +#define SYSTEM_TTBR0_EL2 0xE100 +#define SYSTEM_TTBR0_EL3 0xF100 +#define SYSTEM_TTBR1_EL1 0xC101 /* ARMv8 address translation */ -#define SYSTEM_PAR_EL1 0b1100001110100000 -#define SYSTEM_ATS12E0R 0b0110001111000110 -#define SYSTEM_ATS12E1R 0b0110001111000100 -#define SYSTEM_ATS1E2R 0b0110001111000000 -#define SYSTEM_ATS1E3R 0b0111001111000000 +#define SYSTEM_PAR_EL1 0xC3A0 +#define SYSTEM_ATS12E0R 0x63C6 +#define SYSTEM_ATS12E1R 0x63C4 +#define SYSTEM_ATS1E2R 0x63C0 +#define SYSTEM_ATS1E3R 0x73C0 /* fault status and fault address */ -#define SYSTEM_FAR_EL1 0b1100001100000000 -#define SYSTEM_FAR_EL2 0b1110001100000000 -#define SYSTEM_FAR_EL3 0b1111001100000000 -#define SYSTEM_ESR_EL1 0b1100001010010000 -#define SYSTEM_ESR_EL2 0b1110001010010000 -#define SYSTEM_ESR_EL3 0b1111001010010000 +#define SYSTEM_FAR_EL1 0xC300 +#define SYSTEM_FAR_EL2 0xE300 +#define SYSTEM_FAR_EL3 0xF300 +#define SYSTEM_ESR_EL1 0xC290 +#define SYSTEM_ESR_EL2 0xE290 +#define SYSTEM_ESR_EL3 0xF290 #define ARMV8_MRS_DSPSR(rt) (0xd53b4500 | (rt)) #define ARMV8_MSR_DSPSR(rt) (0xd51b4500 | (rt)) From 9d5117a23e21fd0eba4662a7068e4e2ffb09b784 Mon Sep 17 00:00:00 2001 From: wangyanwen Date: Mon, 9 Oct 2023 14:08:59 +0800 Subject: [PATCH 0746/1312] server/gdb-server: fix type error. Fix flash operation error when addr-width > 32bit on any 32-bit OS and some 64-bit OS (windows). Change-Id: I199f1cc5128c45bd0bb155e37acb2fb6325dff88 Signed-off-by: wangyanwen Reviewed-on: https://review.openocd.org/c/openocd/+/8095 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/server/gdb_server.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index d1bcfb5406..13bc233957 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3286,7 +3286,7 @@ static int gdb_v_packet(struct connection *connection, } if (strncmp(packet, "vFlashErase:", 12) == 0) { - unsigned long addr; + target_addr_t addr; unsigned long length; char const *parse = packet + 12; @@ -3295,7 +3295,7 @@ static int gdb_v_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - addr = strtoul(parse, (char **)&parse, 16); + addr = strtoull(parse, (char **)&parse, 16); if (*(parse++) != ',' || *parse == '\0') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); @@ -3343,7 +3343,7 @@ static int gdb_v_packet(struct connection *connection, if (strncmp(packet, "vFlashWrite:", 12) == 0) { int retval; - unsigned long addr; + target_addr_t addr; unsigned long length; char const *parse = packet + 12; @@ -3351,7 +3351,8 @@ static int gdb_v_packet(struct connection *connection, LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; } - addr = strtoul(parse, (char **)&parse, 16); + + addr = strtoull(parse, (char **)&parse, 16); if (*(parse++) != ':') { LOG_ERROR("incomplete vFlashErase packet received, dropping connection"); return ERROR_SERVER_REMOTE_CLOSED; From b6ee13720688a9860f3397bb89ea171b0fc5ccce Mon Sep 17 00:00:00 2001 From: Kirill Radkin Date: Fri, 16 Jun 2023 12:09:32 +0300 Subject: [PATCH 0747/1312] driver: Add additional check for count of BYPASS devices At least one TAP shouldn't be in BYPASS mode Change-Id: Ic882acbfc9b6a9f4b0c3bb4741a49f3981503c8c Signed-off-by: Kirill Radkin Reviewed-on: https://review.openocd.org/c/openocd/+/7741 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index fae2aad229..e52816d3ab 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -116,12 +116,21 @@ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, /* count devices in bypass */ size_t bypass_devices = 0; + size_t all_devices = 0; for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) { + all_devices++; + if (tap->bypass) bypass_devices++; } + if (all_devices == bypass_devices) { + LOG_ERROR("At least one TAP shouldn't be in BYPASS mode"); + + return ERROR_FAIL; + } + struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command)); struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field)); From 33573cda4aa5685b32c44a81b1f2d84a28d78810 Mon Sep 17 00:00:00 2001 From: Sevan Janiyan Date: Sat, 27 Jan 2024 21:53:11 +0000 Subject: [PATCH 0748/1312] src/target/riscv: Help older compilers find members of a union, nested in struct. Allows file to be compiled with GCC 4.0 Signed-off-by: Sevan Janiyan Change-Id: Ied68668d3b5f811573a20e11e83aceff268963eb Reviewed-on: https://review.openocd.org/c/openocd/+/8120 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/riscv/riscv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index d895ca3726..9cd4922d20 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -3851,7 +3851,7 @@ int riscv_init_registers(struct target *target) .type = REG_TYPE_ARCH_DEFINED, .id = "FPU_FD", .type_class = REG_TYPE_CLASS_UNION, - .reg_type_union = &single_double_union + { .reg_type_union = &single_double_union } }; static struct reg_data_type type_uint8 = { .type = REG_TYPE_UINT8, .id = "uint8" }; static struct reg_data_type type_uint16 = { .type = REG_TYPE_UINT16, .id = "uint16" }; From 179169268ca1bbac092324f597fbea090d75355e Mon Sep 17 00:00:00 2001 From: SydMontague Date: Fri, 2 Feb 2024 12:12:48 +0100 Subject: [PATCH 0749/1312] jtag/commands: fixed buffer overflow When performing a command queue allocation larger than the default page size of 1MiB any subsequent allocations will run into an integer under- flow when checking for the remaining memory left in the current page. Causing the function returning a pointer past the end of the buffer and thus creating a buffer overflow. This has been observed to cause some transfers to Efinix FPGAs to fail, because another buffer can get corrupted in the process, causing its respective free() to fail. Change-Id: Ic5a0e1774e2dbd58f1a05127f14816c8251a7d9c Signed-off-by: SydMontague Reviewed-on: https://review.openocd.org/c/openocd/+/8126 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/commands.c b/src/jtag/commands.c index c36c219233..a60684c880 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -103,7 +103,7 @@ void *cmd_queue_alloc(size_t size) if (*p_page) { p_page = &cmd_queue_pages_tail; - if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size) + if (CMD_QUEUE_PAGE_SIZE < (*p_page)->used + size) p_page = &((*p_page)->next); } From 56a7925a1d2d890adbb5dbd76542bfe901620103 Mon Sep 17 00:00:00 2001 From: Luca Rufer Date: Thu, 8 Feb 2024 21:59:47 +0100 Subject: [PATCH 0750/1312] src/jtag/drivers/mpsse: Add support for new FTDI chip types. The new FTDI ICs with USB-C Support have different bcdDevice identifiers. The added bcdDevice identifiers are taken from the chips datasheet, respectively. The patch was tested with a FT4232HP IC. The used bcdDevice IDs can be found in Section 8.1 of the respective Datasheets: https://ftdichip.com/wp-content/uploads/2023/09/DS_FT233HP-v1.4.pdf https://ftdichip.com/wp-content/uploads/2023/09/DS_FT2233HP-v1.4.pdf https://ftdichip.com/wp-content/uploads/2023/09/DS_FT4233HP-v1.5.pdf Change-Id: I701083cb72030e398ce1c74310676e13895a77ff Signed-off-by: Luca Rufer Reviewed-on: https://review.openocd.org/c/openocd/+/8134 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/jtag/drivers/mpsse.c | 18 ++++++++++++++++++ src/jtag/drivers/mpsse.h | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 41a8b6e33f..f3499e3864 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -265,6 +265,24 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t vids[], c case 0x900: ctx->type = TYPE_FT232H; break; + case 0x2800: + ctx->type = TYPE_FT2233HP; + break; + case 0x2900: + ctx->type = TYPE_FT4233HP; + break; + case 0x3000: + ctx->type = TYPE_FT2232HP; + break; + case 0x3100: + ctx->type = TYPE_FT4232HP; + break; + case 0x3200: + ctx->type = TYPE_FT233HP; + break; + case 0x3300: + ctx->type = TYPE_FT232HP; + break; default: LOG_ERROR("unsupported FTDI chip type: 0x%04x", desc.bcdDevice); goto error; diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index a017aff002..e92a9bb56f 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -24,6 +24,12 @@ enum ftdi_chip_type { TYPE_FT2232H, TYPE_FT4232H, TYPE_FT232H, + TYPE_FT2233HP, + TYPE_FT4233HP, + TYPE_FT2232HP, + TYPE_FT4232HP, + TYPE_FT233HP, + TYPE_FT232HP, }; struct mpsse_ctx; From 271c4e5253abcd2ec617d5fb5e1a374d2b6a543d Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Sat, 24 Feb 2024 20:29:41 +0100 Subject: [PATCH 0751/1312] target/esp_xtensa_smp: don't use coreid as an SMP index For the sake of https://review.openocd.org/c/openocd/+/7957 Instead of "coreid", 'target smp' command call order used as an index Signed-off-by: Erhan Kurubas Change-Id: Iab86b81868d37c0bf8663707ee11367c41f6b96d Reviewed-on: https://review.openocd.org/c/openocd/+/8162 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/espressif/esp_xtensa_smp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c index f883b1ce76..c49146d787 100644 --- a/src/target/espressif/esp_xtensa_smp.c +++ b/src/target/espressif/esp_xtensa_smp.c @@ -94,8 +94,11 @@ int esp_xtensa_smp_soft_reset_halt(struct target *target) LOG_TARGET_DEBUG(target, "begin"); /* in SMP mode we need to ensure that at first we reset SOC on PRO-CPU and then call xtensa_assert_reset() for all cores */ - if (target->smp && target->coreid != 0) - return ERROR_OK; + if (target->smp) { + head = list_first_entry(target->smp_targets, struct target_list, lh); + if (head->target != target) + return ERROR_OK; + } /* Reset the SoC first */ if (esp_xtensa_smp->chip_ops->reset) { res = esp_xtensa_smp->chip_ops->reset(target); From 07141132a7d787005c0829618a60b4a842be7847 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 Dec 2021 00:48:23 +0100 Subject: [PATCH 0752/1312] gdb_server: don't send unrequested ACK at connection On 2008-03-05, before git's age, commit 6d9501467441 adds sending an ACK ('+' char) at GDB connection, before receiving any GDB remote command that requires to be ACK'ed. Neither the text added in the commit message ("added ACK upon connection (send +)") nor in the associated comment ("send ACK to GDB for debug request") provide an exhaustive explanation for sending this unsolicited ACK. This code has never been touched since its introduction. Analysis of GDB code doesn't show it's required, including old GDB code. Running gdbserver (from GDB package) and attaching it with "nc" shows that gdbserver does not send any ACK to a new connection. Same for lldb-server. Drop it! Change-Id: Id68c352ce44dd85a1ea3d67446e17e2a241ef058 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6768 Tested-by: jenkins Reviewed-by: Jan Matyas Reviewed-by: Anatoly P Reviewed-by: Tomas Vanek --- src/server/gdb_server.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 13bc233957..b140689417 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1001,9 +1001,6 @@ static int gdb_new_connection(struct connection *connection) gdb_connection->output_flag = GDB_OUTPUT_NO; gdb_connection->unique_index = next_unique_id++; - /* send ACK to GDB for debug request */ - gdb_write(connection, "+", 1); - /* output goes through gdb connection */ command_set_output_handler(connection->cmd_ctx, gdb_output, connection); From 46ae39c6236ec04f7e518d876b3cd9dafb6eb878 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 15:40:37 +0100 Subject: [PATCH 0753/1312] flash/nor/nrf5: drop unused part of HWIDs table While on it update table comment and drop not working URLs. Change-Id: I9e21c72aa75a908c644460e43c148d3240c49b2d Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8102 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/nrf5.c | 48 +++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index d5de4a4644..001843d39e 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -42,7 +42,10 @@ enum nrf5_ficr_registers { NRF51_FICR_SIZERAMBLOCK2 = NRF5_FICR_REG(0x040), NRF51_FICR_SIZERAMBLOCK3 = NRF5_FICR_REG(0x044), + /* CONFIGID is documented on nRF51 series only. + * On nRF52 is present but not documented */ NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C), + NRF5_FICR_DEVICEID0 = NRF5_FICR_REG(0x060), NRF5_FICR_DEVICEID1 = NRF5_FICR_REG(0x064), NRF5_FICR_ER0 = NRF5_FICR_REG(0x080), @@ -164,26 +167,20 @@ struct nrf5_info { .features = NRF5_FEATURE_SERIES_51, \ } -#define NRF5_DEVICE_DEF(id, pt, var, bcode, fsize, features) \ -{ \ -.hwid = (id), \ -.part = pt, \ -.variant = var, \ -.build_code = bcode, \ -.flash_size_kb = (fsize), \ -.features = features, \ -} - -/* The known devices table below is derived from the "nRF5x series - * compatibility matrix" documents, which can be found in the "DocLib" of - * nordic: +/* + * The table maps known HWIDs to the part numbers, variant + * build code and some other info. For nRF51 rev 1 and 2 devices + * this is the only way how to get the part number and variant. * - * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51422_ic_revision_overview - * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51822_ic_revision_overview - * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF51/latest/COMP/nrf51/nRF51824_ic_revision_overview - * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52810/latest/COMP/nrf52810/nRF52810_ic_revision_overview - * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52832/latest/COMP/nrf52832/ic_revision_overview - * https://www.nordicsemi.com/DocLib/Content/Comp_Matrix/nRF52840/latest/COMP/nrf52840/nRF52840_ic_revision_overview + * All tested nRF51 rev 3 devices have FICR INFO fields + * but the fields are not documented in RM so we keep HWIDs in + * this table. + * + * nRF52 and newer devices have FICR INFO documented, the autodetection + * can rely on it and HWIDs table is not used. + * + * The known devices table below is derived from the "nRF5x series + * compatibility matrix" documents. * * Up to date with Matrix v2.0, plus some additional HWIDs. * @@ -248,19 +245,6 @@ static const struct nrf5_device_spec nrf5_known_devices_table[] = { /* The driver fully autodetects nRF52 series devices by FICR INFO, * no need for nRF52xxx HWIDs in this table */ -#if 0 - /* nRF52810 Devices */ - NRF5_DEVICE_DEF(0x0142, "52810", "QFAA", "B0", 192, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT), - NRF5_DEVICE_DEF(0x0143, "52810", "QCAA", "C0", 192, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT), - - /* nRF52832 Devices */ - NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT), - NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0", 512, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT), - NRF5_DEVICE_DEF(0x00E3, "52832", "CIAA", "B0", 512, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_BPROT), - - /* nRF52840 Devices */ - NRF5_DEVICE_DEF(0x0150, "52840", "QIAA", "C0", 1024, NRF5_FEATURE_SERIES_52 | NRF5_FEATURE_ACL_PROT), -#endif }; struct nrf5_device_package { From 1354ff7adfeff5d0c1024c2f2e9a9cd714a753d8 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 15:55:37 +0100 Subject: [PATCH 0754/1312] flash/nor/nrf5, target/nrf51: deprecate nrf51 flash driver Use the newer driver name 'nrf5' instead. While on it set the unused parameters of flash bank creation to zero. While on it remove 2 empty comments. Change-Id: I9cf0eadc5b696e6c8b7e6aec0ea3345967523e87 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8103 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/nrf5.c | 3 +++ tcl/target/nrf51.cfg | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 001843d39e..18efae5c6d 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -1144,6 +1144,9 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) struct nrf5_info *chip; struct nrf5_bank *nbank = NULL; + if (bank->driver == &nrf51_flash) + LOG_WARNING("Flash driver 'nrf51' is deprecated! Use 'nrf5' instead."); + switch (bank->base) { case NRF5_FLASH_BASE: case NRF5_UICR_BASE: diff --git a/tcl/target/nrf51.cfg b/tcl/target/nrf51.cfg index 48c2715d10..53ac3069fb 100644 --- a/tcl/target/nrf51.cfg +++ b/tcl/target/nrf51.cfg @@ -45,13 +45,11 @@ if {![using_hla]} { cortex_m reset_config sysresetreq } -flash bank $_CHIPNAME.flash nrf51 0x00000000 0 1 1 $_TARGETNAME -flash bank $_CHIPNAME.uicr nrf51 0x10001000 0 1 1 $_TARGETNAME +flash bank $_CHIPNAME.flash nrf5 0x00000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.uicr nrf5 0x10001000 0 0 0 $_TARGETNAME -# # The chip should start up from internal 16Mhz RC, so setting adapter # clock to 1Mhz should be OK -# adapter speed 1000 proc enable_all_ram {} { From 19ef6634f021f545c2154cdd6d011608f1249308 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 16:01:00 +0100 Subject: [PATCH 0755/1312] target/nrf51: use PAN #16 workaround in reset-init only After 'reset run' or 'reset halt' the loaded application is expected to manipulate RAMON register to workaround the known silicon errata. Moreover, writing to RAMON register from 'reset-end' event after 'reset run' may collide with application intentions. Use the workaround in 'reset-init' event only to ensure correct function of target algorithms. Change-Id: I7d2d92e6805a05a83676edb46b3163ef39b9a7e4 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8104 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/nrf51.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcl/target/nrf51.cfg b/tcl/target/nrf51.cfg index 53ac3069fb..3781eccb50 100644 --- a/tcl/target/nrf51.cfg +++ b/tcl/target/nrf51.cfg @@ -58,4 +58,4 @@ proc enable_all_ram {} { # resetting we enable all banks via the RAMON register mww 0x40000524 0xF } -$_TARGETNAME configure -event reset-end { enable_all_ram } +$_TARGETNAME configure -event reset-init { enable_all_ram } From 85bc3289699a23dfb66bd10927aa1a6330e3668c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 18:00:06 +0100 Subject: [PATCH 0756/1312] flash/nor/nrf5: add missing package codes from Product Specification of nRF52805, 810, 811 820, 833 and 840. While on it, rename the table to make sure the codes are valid for nRF52 series only. Change-Id: Id8f78fd214c5d345d1769378ae546a6be5a183ba Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8105 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 18efae5c6d..b6d712d3f2 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -254,11 +254,16 @@ struct nrf5_device_package { /* Newer devices have FICR INFO.PACKAGE. * This table converts its value to two character code */ -static const struct nrf5_device_package nrf5_packages_table[] = { +static const struct nrf5_device_package nrf52_packages_table[] = { { 0x2000, "QF" }, { 0x2001, "CH" }, { 0x2002, "CI" }, + { 0x2003, "QC" }, + { 0x2004, "QI/CA" }, /* differs nRF52805, 810, 811: CA, nRF52833, 840: QI */ { 0x2005, "CK" }, + { 0x2007, "QD" }, + { 0x2008, "CJ" }, + { 0x2009, "CF" }, }; const struct flash_driver nrf5_flash, nrf51_flash; @@ -591,9 +596,9 @@ static bool nrf5_info_variant_to_str(uint32_t variant, char *bf) static const char *nrf5_decode_info_package(uint32_t package) { - for (size_t i = 0; i < ARRAY_SIZE(nrf5_packages_table); i++) { - if (nrf5_packages_table[i].package == package) - return nrf5_packages_table[i].code; + for (size_t i = 0; i < ARRAY_SIZE(nrf52_packages_table); i++) { + if (nrf52_packages_table[i].package == package) + return nrf52_packages_table[i].code; } return "xx"; } From 42e4f26a3da8203d8f28c3edc490968273b1d904 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 18:08:33 +0100 Subject: [PATCH 0757/1312] flash/nor/nrf5: add missing device types from nRF52 family. Change-Id: I6d2b4586700bb4014c0b77dbf4ea26d1b5dc9715 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8106 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/nrf5.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index b6d712d3f2..4446b3081b 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -665,11 +665,15 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip) chip->features = NRF5_FEATURE_SERIES_52; switch (chip->ficr_info.part) { + case 0x52805: case 0x52810: + case 0x52811: case 0x52832: chip->features |= NRF5_FEATURE_BPROT; break; + case 0x52820: + case 0x52833: case 0x52840: chip->features |= NRF5_FEATURE_ACL_PROT; break; From 2db325f5395fa24aefbf137584e5fdeedf390e97 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 18:14:14 +0100 Subject: [PATCH 0758/1312] flash/nor/nrf5: drop nrf5_get_probed_chip_if_halted() nrf5_get_probed_chip_if_halted() was somewhat bizarre combination of functions: - test if the target is halted is appropriate for flash erase/write only, certainly not for getting chip info - getting chip pointer takes place more frequently and using one temporary variable for dereference makes no harm - probing chip is useless at all as the flash infrastructure always calls auto_probe() before entering a flash operation Replace the function by ordinary and readable code. Change-Id: Ic31f4e33d8b7b36687be3f40bfd0fe913d17b75f Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8107 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 97 ++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 4446b3081b..7bc1f0cfed 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -271,28 +271,10 @@ const struct flash_driver nrf5_flash, nrf51_flash; static bool nrf5_bank_is_probed(const struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); return nbank->probed; } -static int nrf5_probe(struct flash_bank *bank); - -static int nrf5_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf5_info **chip) -{ - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - struct nrf5_bank *nbank = bank->driver_priv; - *chip = nbank->chip; - - if (nrf5_bank_is_probed(bank)) - return ERROR_OK; - - return nrf5_probe(bank); -} static int nrf5_wait_for_nvmc(struct nrf5_info *chip) { @@ -420,9 +402,10 @@ static int nrf5_protect_check_clenr0(struct flash_bank *bank) { int res; uint32_t clenr0; + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); res = target_read_u32(chip->target, NRF51_FICR_CLENR0, @@ -451,8 +434,8 @@ static int nrf5_protect_check_clenr0(struct flash_bank *bank) static int nrf5_protect_check_bprot(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 }; @@ -482,8 +465,8 @@ static int nrf5_protect_check(struct flash_bank *bank) return ERROR_OK; struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); if (chip->features & NRF5_FEATURE_BPROT) @@ -501,8 +484,11 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int fi { int res; uint32_t clenr0, ppfc; + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; + assert(chip); if (first != 0) { LOG_ERROR("Code region 0 must start at the beginning of the bank"); @@ -559,18 +545,21 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int fi static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { - int res; - struct nrf5_info *chip; - /* UICR cannot be write protected so just bail out early */ if (bank->base == NRF5_UICR_BASE) { LOG_ERROR("UICR page does not support protection"); return ERROR_FLASH_OPER_UNSUPPORTED; } - res = nrf5_get_probed_chip_if_halted(bank, &chip); - if (res != ERROR_OK) - return res; + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); if (chip->features & NRF5_FEATURE_SERIES_51) return nrf5_protect_clenr0(bank, set, first, last); @@ -631,7 +620,9 @@ static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, unsig static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) { struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; + assert(chip); char chip_type_str[256]; if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) @@ -748,8 +739,11 @@ static int nrf5_get_ram_size(struct target *target, uint32_t *ram_size) static int nrf5_probe(struct flash_bank *bank) { int res; + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; + assert(chip); struct target *target = chip->target; uint32_t configid; @@ -1017,11 +1011,17 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t address, const u static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { - struct nrf5_info *chip; + int res; - int res = nrf5_get_probed_chip_if_halted(bank, &chip); - if (res != ERROR_OK) - return res; + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); assert(offset % 4 == 0); assert(count % 4 == 0); @@ -1074,11 +1074,16 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, unsigned int last) { int res; - struct nrf5_info *chip; - res = nrf5_get_probed_chip_if_halted(bank, &chip); - if (res != ERROR_OK) - return res; + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); /* UICR CLENR0 based protection used on nRF51 prevents erase * absolutely silently. NVMC has no flag to indicate the protection @@ -1115,6 +1120,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, static void nrf5_free_driver_priv(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); struct nrf5_info *chip = nbank->chip; if (!chip) return; @@ -1206,11 +1212,15 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) assert(bank); - struct nrf5_info *chip; + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } - res = nrf5_get_probed_chip_if_halted(bank, &chip); - if (res != ERROR_OK) - return res; + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); if (chip->features & NRF5_FEATURE_SERIES_51) { uint32_t ppfc; @@ -1253,11 +1263,10 @@ COMMAND_HANDLER(nrf5_handle_info_command) assert(bank); - struct nrf5_info *chip; - - res = nrf5_get_probed_chip_if_halted(bank, &chip); - if (res != ERROR_OK) - return res; + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); static struct { const uint32_t address; From cdc569ce3a0d76a638378b7d97ae9f5f1bcbd3c6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 23:34:30 +0100 Subject: [PATCH 0759/1312] flash/nor/nrf5: drop nrf5 info command The command substantially complicates support of nRF53/91 series. It was not even properly ported to nRF52. The informative value is disputable. Who wants to see e.g. override trim values for radio or unique device ID? Drop it and simplify the driver. Change-Id: Ia7fb20ce2ebf16065705c5d18deaf934e58db426 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8108 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 4 -- src/flash/nor/nrf5.c | 166 ------------------------------------------- 2 files changed, 170 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 38c8970456..4297258d9f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7319,10 +7319,6 @@ works only for chips that do not have factory pre-programmed region 0 code. @end deffn -@deffn {Command} {nrf5 info} -Decodes and shows information from FICR and UICR registers. -@end deffn - @end deffn @deffn {Flash Driver} {ocl} diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 7bc1f0cfed..35fa6d1429 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -46,32 +46,6 @@ enum nrf5_ficr_registers { * On nRF52 is present but not documented */ NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C), - NRF5_FICR_DEVICEID0 = NRF5_FICR_REG(0x060), - NRF5_FICR_DEVICEID1 = NRF5_FICR_REG(0x064), - NRF5_FICR_ER0 = NRF5_FICR_REG(0x080), - NRF5_FICR_ER1 = NRF5_FICR_REG(0x084), - NRF5_FICR_ER2 = NRF5_FICR_REG(0x088), - NRF5_FICR_ER3 = NRF5_FICR_REG(0x08C), - NRF5_FICR_IR0 = NRF5_FICR_REG(0x090), - NRF5_FICR_IR1 = NRF5_FICR_REG(0x094), - NRF5_FICR_IR2 = NRF5_FICR_REG(0x098), - NRF5_FICR_IR3 = NRF5_FICR_REG(0x09C), - NRF5_FICR_DEVICEADDRTYPE = NRF5_FICR_REG(0x0A0), - NRF5_FICR_DEVICEADDR0 = NRF5_FICR_REG(0x0A4), - NRF5_FICR_DEVICEADDR1 = NRF5_FICR_REG(0x0A8), - - NRF51_FICR_OVERRIDEN = NRF5_FICR_REG(0x0AC), - NRF51_FICR_NRF_1MBIT0 = NRF5_FICR_REG(0x0B0), - NRF51_FICR_NRF_1MBIT1 = NRF5_FICR_REG(0x0B4), - NRF51_FICR_NRF_1MBIT2 = NRF5_FICR_REG(0x0B8), - NRF51_FICR_NRF_1MBIT3 = NRF5_FICR_REG(0x0BC), - NRF51_FICR_NRF_1MBIT4 = NRF5_FICR_REG(0x0C0), - NRF51_FICR_BLE_1MBIT0 = NRF5_FICR_REG(0x0EC), - NRF51_FICR_BLE_1MBIT1 = NRF5_FICR_REG(0x0F0), - NRF51_FICR_BLE_1MBIT2 = NRF5_FICR_REG(0x0F4), - NRF51_FICR_BLE_1MBIT3 = NRF5_FICR_REG(0x0F8), - NRF51_FICR_BLE_1MBIT4 = NRF5_FICR_REG(0x0FC), - /* Following registers are available on nRF52 and on nRF51 since rev 3 */ NRF5_FICR_INFO_PART = NRF5_FICR_REG(0x100), NRF5_FICR_INFO_VARIANT = NRF5_FICR_REG(0x104), @@ -87,9 +61,6 @@ enum nrf5_uicr_registers { #define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset) NRF51_UICR_CLENR0 = NRF5_UICR_REG(0x000), - NRF51_UICR_RBPCONF = NRF5_UICR_REG(0x004), - NRF51_UICR_XTALFREQ = NRF5_UICR_REG(0x008), - NRF51_UICR_FWID = NRF5_UICR_REG(0x010), }; enum nrf5_nvmc_registers { @@ -1251,136 +1222,6 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) return res; } -COMMAND_HANDLER(nrf5_handle_info_command) -{ - int res; - struct flash_bank *bank = NULL; - struct target *target = get_current_target(CMD_CTX); - - res = get_flash_bank_by_addr(target, NRF5_FLASH_BASE, true, &bank); - if (res != ERROR_OK) - return res; - - assert(bank); - - struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); - struct nrf5_info *chip = nbank->chip; - assert(chip); - - static struct { - const uint32_t address; - uint32_t value; - } ficr[] = { - { .address = NRF5_FICR_CODEPAGESIZE }, - { .address = NRF5_FICR_CODESIZE }, - { .address = NRF51_FICR_CLENR0 }, - { .address = NRF51_FICR_PPFC }, - { .address = NRF51_FICR_NUMRAMBLOCK }, - { .address = NRF51_FICR_SIZERAMBLOCK0 }, - { .address = NRF51_FICR_SIZERAMBLOCK1 }, - { .address = NRF51_FICR_SIZERAMBLOCK2 }, - { .address = NRF51_FICR_SIZERAMBLOCK3 }, - { .address = NRF5_FICR_CONFIGID }, - { .address = NRF5_FICR_DEVICEID0 }, - { .address = NRF5_FICR_DEVICEID1 }, - { .address = NRF5_FICR_ER0 }, - { .address = NRF5_FICR_ER1 }, - { .address = NRF5_FICR_ER2 }, - { .address = NRF5_FICR_ER3 }, - { .address = NRF5_FICR_IR0 }, - { .address = NRF5_FICR_IR1 }, - { .address = NRF5_FICR_IR2 }, - { .address = NRF5_FICR_IR3 }, - { .address = NRF5_FICR_DEVICEADDRTYPE }, - { .address = NRF5_FICR_DEVICEADDR0 }, - { .address = NRF5_FICR_DEVICEADDR1 }, - { .address = NRF51_FICR_OVERRIDEN }, - { .address = NRF51_FICR_NRF_1MBIT0 }, - { .address = NRF51_FICR_NRF_1MBIT1 }, - { .address = NRF51_FICR_NRF_1MBIT2 }, - { .address = NRF51_FICR_NRF_1MBIT3 }, - { .address = NRF51_FICR_NRF_1MBIT4 }, - { .address = NRF51_FICR_BLE_1MBIT0 }, - { .address = NRF51_FICR_BLE_1MBIT1 }, - { .address = NRF51_FICR_BLE_1MBIT2 }, - { .address = NRF51_FICR_BLE_1MBIT3 }, - { .address = NRF51_FICR_BLE_1MBIT4 }, - }, uicr[] = { - { .address = NRF51_UICR_CLENR0, }, - { .address = NRF51_UICR_RBPCONF }, - { .address = NRF51_UICR_XTALFREQ }, - { .address = NRF51_UICR_FWID }, - }; - - for (size_t i = 0; i < ARRAY_SIZE(ficr); i++) { - res = target_read_u32(chip->target, ficr[i].address, - &ficr[i].value); - if (res != ERROR_OK) { - LOG_ERROR("Couldn't read %" PRIx32, ficr[i].address); - return res; - } - } - - for (size_t i = 0; i < ARRAY_SIZE(uicr); i++) { - res = target_read_u32(chip->target, uicr[i].address, - &uicr[i].value); - if (res != ERROR_OK) { - LOG_ERROR("Couldn't read %" PRIx32, uicr[i].address); - return res; - } - } - - command_print(CMD, - "\n[factory information control block]\n\n" - "code page size: %"PRIu32"B\n" - "code memory size: %"PRIu32"kB\n" - "code region 0 size: %"PRIu32"kB\n" - "pre-programmed code: %s\n" - "number of ram blocks: %"PRIu32"\n" - "ram block 0 size: %"PRIu32"B\n" - "ram block 1 size: %"PRIu32"B\n" - "ram block 2 size: %"PRIu32"B\n" - "ram block 3 size: %"PRIu32 "B\n" - "config id: %" PRIx32 "\n" - "device id: 0x%"PRIx32"%08"PRIx32"\n" - "encryption root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n" - "identity root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n" - "device address type: 0x%"PRIx32"\n" - "device address: 0x%"PRIx32"%08"PRIx32"\n" - "override enable: %"PRIx32"\n" - "NRF_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n" - "BLE_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n" - "\n[user information control block]\n\n" - "code region 0 size: %"PRIu32"kB\n" - "read back protection configuration: %"PRIx32"\n" - "reset value for XTALFREQ: %"PRIx32"\n" - "firmware id: 0x%04"PRIx32, - ficr[0].value, - (ficr[1].value * ficr[0].value) / 1024, - (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024, - ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present", - ficr[4].value, - ficr[5].value, - (ficr[6].value == 0xFFFFFFFF) ? 0 : ficr[6].value, - (ficr[7].value == 0xFFFFFFFF) ? 0 : ficr[7].value, - (ficr[8].value == 0xFFFFFFFF) ? 0 : ficr[8].value, - ficr[9].value, - ficr[10].value, ficr[11].value, - ficr[12].value, ficr[13].value, ficr[14].value, ficr[15].value, - ficr[16].value, ficr[17].value, ficr[18].value, ficr[19].value, - ficr[20].value, - ficr[21].value, ficr[22].value, - ficr[23].value, - ficr[24].value, ficr[25].value, ficr[26].value, ficr[27].value, ficr[28].value, - ficr[29].value, ficr[30].value, ficr[31].value, ficr[32].value, ficr[33].value, - (uicr[0].value == 0xFFFFFFFF) ? 0 : uicr[0].value / 1024, - uicr[1].value & 0xFFFF, - uicr[2].value & 0xFF, - uicr[3].value & 0xFFFF); - - return ERROR_OK; -} static const struct command_registration nrf5_exec_command_handlers[] = { { @@ -1390,13 +1231,6 @@ static const struct command_registration nrf5_exec_command_handlers[] = { .help = "Erase all flash contents of the chip.", .usage = "", }, - { - .name = "info", - .handler = nrf5_handle_info_command, - .mode = COMMAND_EXEC, - .help = "Show FICR and UICR info.", - .usage = "", - }, COMMAND_REGISTRATION_DONE }; From 61e19349b2b83f844e9729a76ad5698e6c77c686 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 12:13:46 +0100 Subject: [PATCH 0760/1312] flash/nor/nrf5: use BIT() instead of << operator for features flags. Change-Id: I8bff0f5fac41c50180c847f36c6d2a075eca32ca Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8109 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/nrf5.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 35fa6d1429..3f451a76c4 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -17,6 +17,7 @@ #include #include #include +#include /* Both those values are constant across the current spectrum ofr nRF5 devices */ #define WATCHDOG_REFRESH_REGISTER 0x40010600 @@ -94,10 +95,10 @@ struct nrf52_ficr_info { }; enum nrf5_features { - NRF5_FEATURE_SERIES_51 = 1 << 0, - NRF5_FEATURE_SERIES_52 = 1 << 1, - NRF5_FEATURE_BPROT = 1 << 2, - NRF5_FEATURE_ACL_PROT = 1 << 3, + NRF5_FEATURE_SERIES_51 = BIT(0), + NRF5_FEATURE_SERIES_52 = BIT(1), + NRF5_FEATURE_BPROT = BIT(2), + NRF5_FEATURE_ACL_PROT = BIT(3), }; struct nrf5_device_spec { From 5c395fdef42a5750852ea0fc0abd944cf303a39b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Feb 2024 12:22:44 +0100 Subject: [PATCH 0761/1312] mem_ap: fix GDB connections After commit d9b2607ca094 ("gdb_server: support sparse register maps"), GDB crashes while requesting the value of 'cpsr' because the fake register is tagged as not existing. Change the logic and set all register as existing, while still limiting the list for the initial GDB request at connect. Change-Id: I1c4e274c06147683db2a59a8920ae5ccd863e15c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8163 Tested-by: jenkins --- src/target/mem_ap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 5c81e3a75f..61a9475e64 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -194,11 +194,11 @@ static const char *mem_ap_get_gdb_arch(const struct target *target) * reg[24]: 32 bits, fps * reg[25]: 32 bits, cpsr * - * Set 'exist' only to reg[0..15], so initial response to GDB is correct + * GDB requires only reg[0..15] */ #define NUM_REGS 26 +#define NUM_GDB_REGS 16 #define MAX_REG_SIZE 96 -#define REG_EXIST(n) ((n) < 16) #define REG_SIZE(n) ((((n) >= 16) && ((n) < 24)) ? 96 : 32) struct mem_ap_alloc_reg_list { @@ -218,14 +218,14 @@ static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[ } *reg_list = mem_ap_alloc->reg_list; - *reg_list_size = NUM_REGS; + *reg_list_size = (reg_class == REG_CLASS_ALL) ? NUM_REGS : NUM_GDB_REGS; struct reg *regs = mem_ap_alloc->regs; for (int i = 0; i < NUM_REGS; i++) { regs[i].number = i; regs[i].value = mem_ap_alloc->regs_value; regs[i].size = REG_SIZE(i); - regs[i].exist = REG_EXIST(i); + regs[i].exist = true; regs[i].type = &mem_ap_reg_arch_type; (*reg_list)[i] = ®s[i]; } From fcda9f1561bfc413e3723e5b4552bc7e91eb4a8d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Feb 2024 18:36:47 +0100 Subject: [PATCH 0762/1312] gdb_server: fix segfault with GDB command 'flash-erase' Running the GDB command 'flash-erase' triggers sending the remote GDB commands 'vFlashErase' (one per flash bank) followed by one single 'vFlashDone', with no 'vFlashWrite' commands in between. This causes the field 'gdb_connection->vflash_image' to be NULL during the execution of 'vFlashDone', triggering a segmentation fault in OpenOCD. While parsing 'vFlashDone', check if any image to flash has been received. Change-Id: I443021c7a531255b60f2c44c2685e52e3c34b5c8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8164 Tested-by: jenkins --- src/server/gdb_server.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index b140689417..ae288de1cf 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3376,6 +3376,13 @@ static int gdb_v_packet(struct connection *connection, if (strncmp(packet, "vFlashDone", 10) == 0) { uint32_t written; + /* GDB command 'flash-erase' does not send a vFlashWrite, + * so nothing to write here. */ + if (!gdb_connection->vflash_image) { + gdb_put_packet(connection, "OK", 2); + return ERROR_OK; + } + /* process the flashing buffer. No need to erase as GDB * always issues a vFlashErase first. */ target_call_event_callbacks(target, From 561ea48d83ae4b83ff823888a80cbcc282b61333 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Fri, 17 Nov 2023 11:27:56 +0800 Subject: [PATCH 0763/1312] target/mips32: add dsp access support Add access to dsp registers and a command for dsp related operations. Checkpatch-ignore: MACRO_ARG_REUSE Change-Id: I30aec0b9e4984896965edb1663f74216ad41101e Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7867 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- doc/openocd.texi | 5 + src/target/mips32.c | 428 ++++++++++++++++++++++++++++++++++++++++++++ src/target/mips32.h | 20 ++- 3 files changed, 452 insertions(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 4297258d9f..bf4e0ad65c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11070,6 +11070,11 @@ EJTAG Register Specification could be found in MIPS Document MD00047F, for core specific EJTAG Register definition, please check Core Specific SUM manual. @end deffn +@deffn {Command} {mips32 dsp} [[register_name] [value]] +Displays all DSP registers' contents or get/set value by register name. Will display +an error if current CPU does not support DSP. +@end deffn + @section RISC-V Architecture @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG diff --git a/src/target/mips32.c b/src/target/mips32.c index 5b94e6c894..ec2bfb7d0c 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -161,6 +161,67 @@ static const struct { #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) + +#define zero 0 + +#define AT 1 + +#define v0 2 +#define v1 3 + +#define a0 4 +#define a1 5 +#define a2 6 +#define a3 7 +#define t0 8 +#define t1 9 +#define t2 10 +#define t3 11 +#define t4 12 +#define t5 13 +#define t6 14 +#define t7 15 +#define ta0 12 /* alias for $t4 */ +#define ta1 13 /* alias for $t5 */ +#define ta2 14 /* alias for $t6 */ +#define ta3 15 /* alias for $t7 */ + +#define s0 16 +#define s1 17 +#define s2 18 +#define s3 19 +#define s4 20 +#define s5 21 +#define s6 22 +#define s7 23 +#define s8 30 /* == fp */ + +#define t8 24 +#define t9 25 +#define k0 26 +#define k1 27 + +#define gp 28 + +#define sp 29 +#define fp 30 +#define ra 31 + + +static const struct { + const char *name; +} mips32_dsp_regs[MIPS32NUMDSPREGS] = { + { "hi0"}, + { "hi1"}, + { "hi2"}, + { "hi3"}, + { "lo0"}, + { "lo1"}, + { "lo2"}, + { "lo3"}, + { "control"}, +}; + static int mips32_get_core_reg(struct reg *reg) { int retval; @@ -1544,6 +1605,204 @@ COMMAND_HANDLER(mips32_handle_cp0_command) return retval; } +/** + * mips32_dsp_enable - Enable access to DSP registers + * @param[in] ctx: Context information for the pracc queue + * @param[in] isa: Instruction Set Architecture identifier + * + * @brief Enables access to DSP registers by modifying the status register. + * + * This function adds instructions to the context queue for enabling + * access to DSP registers by modifying the status register. + */ +static void mips32_dsp_enable(struct pracc_queue_info *ctx, int isa) +{ + /* Save Status Register */ + /* move status to $9 (t1) 2*/ + pracc_add(ctx, 0, MIPS32_MFC0(isa, 9, 12, 0)); + + /* Read it again in order to modify it */ + /* move status to $0 (t0) 3*/ + pracc_add(ctx, 0, MIPS32_MFC0(isa, 8, 12, 0)); + + /* Enable access to DSP registers by setting MX bit in status register */ + /* $15 = MIPS32_PRACC_STACK 4/5/6*/ + pracc_add(ctx, 0, MIPS32_LUI(isa, 15, UPPER16(MIPS32_DSP_ENABLE))); + pracc_add(ctx, 0, MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_DSP_ENABLE))); + pracc_add(ctx, 0, MIPS32_ISA_OR(8, 8, 15)); + /* Enable DSP - update status registers 7*/ + pracc_add(ctx, 0, MIPS32_MTC0(isa, 8, 12, 0)); +} + +/** + * mips32_dsp_restore - Restore DSP status registers to the previous setting + * @param[in] ctx: Context information pracc queue + * @param[in] isa: isa identifier + * + * @brief Restores the DSP status registers to their previous setting. + * + * This function adds instructions to the context queue for restoring the DSP + * status registers to their values before the operation. + */ +static void mips32_dsp_restore(struct pracc_queue_info *ctx, int isa) +{ + pracc_add(ctx, 0, MIPS32_MTC0(isa, 9, 12, 0)); /* Restore status registers to previous setting */ + pracc_add(ctx, 0, MIPS32_NOP); /* nop */ +} + +/** + * mips32_pracc_read_dsp_reg - Read a value from a MIPS32 DSP register + * @param[in] ejtag_info: EJTAG information structure + * @param[out] val: Pointer to store the read value + * @param[in] reg: Index of the DSP register to read + * + * @brief Reads the value from the specified MIPS32 DSP register using EJTAG access. + * + * This function initiates a sequence of instructions to read the value from the + * specified DSP register. It will enable dsp module if its not enabled + * and restoring the status registers after the read operation. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_pracc_read_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t reg) +{ + int isa = 0; + + struct pracc_queue_info ctx = { + .max_code = 48, + .ejtag_info = ejtag_info + }; + + uint32_t dsp_read_code[] = { + MIPS32_MFHI(isa, t0), /* mfhi t0 ($ac0) - OPCODE - 0x00004010 */ + MIPS32_DSP_MFHI(t0, 1), /* mfhi t0,$ac1 - OPCODE - 0x00204010 */ + MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ + MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ + MIPS32_MFLO(isa, t0), /* mflo t0 ($ac0) - OPCODE - 0x00004012 */ + MIPS32_DSP_MFLO(t0, 1), /* mflo t0,$ac1 - OPCODE - 0x00204012 */ + MIPS32_DSP_MFLO(t0, 2), /* mflo t0,$ac2 - OPCODE - 0x00404012 */ + MIPS32_DSP_MFLO(t0, 3), /* mflo t0,$ac3 - OPCODE - 0x00604012 */ + MIPS32_DSP_RDDSP(t0, 0x3F), /* rddsp t0, 0x3f (DSPCtl) - OPCODE - 0x7c3f44b8 */ + }; + + /* Check status register to determine if dsp register access is enabled */ + /* Get status register so it can be restored later */ + + ctx.pracc_list = NULL; + + /* Init context queue */ + pracc_queue_init(&ctx); + + if (ctx.retval != ERROR_OK) + goto exit; + + /* Enables DSP whether its already enabled or not */ + mips32_dsp_enable(&ctx, isa); + + /* move AC or Control to $8 (t0) 8*/ + pracc_add(&ctx, 0, dsp_read_code[reg]); + /* Restore status registers to previous setting */ + mips32_dsp_restore(&ctx, isa); + + /* $15 = MIPS32_PRACC_BASE_ADDR 1*/ + pracc_add(&ctx, 0, MIPS32_LUI(isa, 15, PRACC_UPPER_BASE_ADDR)); + /* store $8 to pracc_out 10*/ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(isa, 8, PRACC_OUT_OFFSET, 15)); + /* move COP0 DeSave to $15 11*/ + pracc_add(&ctx, 0, MIPS32_MFC0(isa, 15, 31, 0)); + /* restore upper 16 of $8 12*/ + pracc_add(&ctx, 0, MIPS32_LUI(isa, 8, UPPER16(ejtag_info->reg8))); + /* restore lower 16 of $8 13*/ + pracc_add(&ctx, 0, MIPS32_ORI(isa, 8, 8, LOWER16(ejtag_info->reg8))); + /* restore upper 16 of $9 14*/ + pracc_add(&ctx, 0, MIPS32_LUI(isa, 9, UPPER16(ejtag_info->reg9))); + pracc_add(&ctx, 0, MIPS32_SYNC(isa)); + /* jump to start 18*/ + pracc_add(&ctx, 0, MIPS32_B(isa, NEG16(ctx.code_count + 1))); + /* restore lower 16 of $9 15*/ + pracc_add(&ctx, 0, MIPS32_ORI(isa, 9, 9, LOWER16(ejtag_info->reg9))); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1); +exit: + pracc_queue_free(&ctx); + return ctx.retval; +} + +/** + * mips32_pracc_write_dsp_reg - Write a value to a MIPS32 DSP register + * @param[in] ejtag_info: EJTAG information structure + * @param[in] val: Value to be written to the register + * @param[in] reg: Index of the DSP register to write + * + * @brief Writes the specified value to the specified MIPS32 DSP register. + * + * This function initiates a sequence of instructions to write the given value to the + * specified DSP register. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_pracc_write_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t reg) +{ + int isa = 0; + + struct pracc_queue_info ctx = { + .max_code = 48, + .ejtag_info = ejtag_info + }; + + uint32_t dsp_write_code[] = { + MIPS32_MTHI(isa, t0), /* mthi t0 ($ac0) - OPCODE - 0x01000011 */ + MIPS32_DSP_MTHI(t0, 1), /* mthi t0, $ac1 - OPCODE - 0x01000811 */ + MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ + MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ + MIPS32_MTLO(isa, t0), /* mtlo t0 ($ac0) - OPCODE - 0x01000013 */ + MIPS32_DSP_MTLO(t0, 1), /* mtlo t0, $ac1 - OPCODE - 0x01000813 */ + MIPS32_DSP_MTLO(t0, 2), /* mtlo t0, $ac2 - OPCODE - 0x01001013 */ + MIPS32_DSP_MTLO(t0, 3), /* mtlo t0, $ac3 - OPCODE - 0x01001813 */ + MIPS32_DSP_WRDSP(t0, 0x1F), /* wrdsp t0, 0x1f (DSPCtl) - OPCODE - 0x7d00fcf8*/ + }; + + /* Init context queue */ + pracc_queue_init(&ctx); + if (ctx.retval != ERROR_OK) + goto exit; + + /* Enables DSP whether its already enabled or not */ + mips32_dsp_enable(&ctx, isa); + + /* Load val to $8 (t0) */ + pracc_add(&ctx, 0, MIPS32_LUI(isa, 8, UPPER16(val))); + pracc_add(&ctx, 0, MIPS32_ORI(isa, 8, 8, LOWER16(val))); + + /* move AC or Control to $8 (t0) */ + pracc_add(&ctx, 0, dsp_write_code[reg]); + + /* nop, delay in order to ensure write */ + pracc_add(&ctx, 0, MIPS32_NOP); + /* Restore status registers to previous setting */ + mips32_dsp_restore(&ctx, isa); + + /* move COP0 DeSave to $15 */ + pracc_add(&ctx, 0, MIPS32_MFC0(isa, 15, 31, 0)); + + /* restore $8 */ + pracc_add(&ctx, 0, MIPS32_LUI(isa, 8, UPPER16(ejtag_info->reg8))); + pracc_add(&ctx, 0, MIPS32_ORI(isa, 8, 8, LOWER16(ejtag_info->reg8))); + + /* restore upper 16 of $9 */ + pracc_add(&ctx, 0, MIPS32_LUI(isa, 9, UPPER16(ejtag_info->reg9))); + + /* jump to start */ + pracc_add(&ctx, 0, MIPS32_B(isa, NEG16(ctx.code_count + 1))); + /* restore lower 16 of $9 */ + pracc_add(&ctx, 0, MIPS32_ORI(isa, 9, 9, LOWER16(ejtag_info->reg9))); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); +exit: + pracc_queue_free(&ctx); + return ctx.retval; +} + /** * mips32_handle_cpuinfo_command - Handles the 'cpuinfo' command. * @param[in] cmd: Command invocation context. @@ -1746,6 +2005,167 @@ COMMAND_HANDLER(mips32_handle_cpuinfo_command) return ERROR_OK; } +/** + * mips32_dsp_find_register_by_name - Find DSP register index by name + * @param[in] reg_name: Name of the DSP register to find + * + * @brief Searches for a DSP register by name and returns its index. + * If no match is found, it returns MIPS32NUMDSPREGS. + * + * @return Index of the found register or MIPS32NUMDSPREGS if not found. + */ +static int mips32_dsp_find_register_by_name(const char *reg_name) +{ + if (reg_name) + for (int i = 0; i < MIPS32NUMDSPREGS; i++) { + if (strcmp(mips32_dsp_regs[i].name, reg_name) == 0) + return i; + } + return MIPS32NUMDSPREGS; +} + +/** + * mips32_dsp_get_all_regs - Get values of all MIPS32 DSP registers + * @param[in] cmd: Command invocation context + * @param[in] ejtag_info: EJTAG information structure + * + * @brief This function iterates through all DSP registers, reads their values, + * and prints each register name along with its corresponding value. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +{ + uint32_t value; + for (int i = 0; i < MIPS32NUMDSPREGS; i++) { + int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i); + if (retval != ERROR_OK) { + command_print(CMD, "couldn't access reg %s", mips32_dsp_regs[i].name); + return retval; + } + command_print(CMD, "%*s: 0x%8.8x", 7, mips32_dsp_regs[i].name, value); + } + return ERROR_OK; +} + +/** + * mips32_dsp_get_register - Get the value of a MIPS32 DSP register + * @param[in] cmd: Command invocation context + * @param[in] ejtag_info: EJTAG information structure + * + * @brief Retrieves the value of a specified MIPS32 DSP register. + * If the register is found, it reads the register value and prints the result. + * If the register is not found, it prints an error message. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +{ + uint32_t value; + int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); + if (index == MIPS32NUMDSPREGS) { + command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, index); + if (retval != ERROR_OK) + command_print(CMD, "ERROR: Could not access dsp register %s", CMD_ARGV[0]); + else + command_print(CMD, "0x%8.8x", value); + + return retval; +} + +/** + * mips32_dsp_set_register - Set the value of a MIPS32 DSP register + * @param[in] cmd: Command invocation context + * @param[in] ejtag_info: EJTAG information structure + * + * @brief Sets the value of a specified MIPS32 DSP register. + * If the register is found, it writes provided value to the register. + * If the register is not found or there is an error in writing the value, + * it prints an error message. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +{ + uint32_t value; + int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); + if (index == MIPS32NUMDSPREGS) { + command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + + int retval = mips32_pracc_write_dsp_reg(ejtag_info, value, index); + if (retval != ERROR_OK) + command_print(CMD, "Error: could not write to dsp register %s", CMD_ARGV[0]); + + return retval; +} + +/** + * mips32_handle_dsp_command - Handles mips dsp related command + * @param[in] cmd: Command invocation context + * + * @brief Reads or sets the content of each dsp register. + * + * @return ERROR_OK on success; error code on failure. +*/ +COMMAND_HANDLER(mips32_handle_dsp_command) +{ + int retval, tmp; + struct target *target = get_current_target(CMD_CTX); + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + retval = mips32_verify_pointer(CMD, mips32); + if (retval != ERROR_OK) + return retval; + + if (target->state != TARGET_HALTED) { + command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME); + return ERROR_OK; + } + + /* Check for too many command args */ + if (CMD_ARGC >= 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* Check if DSP access supported or not */ + if (!mips32->dsp_imp) { + /* Issue Error Message */ + command_print(CMD, "DSP not implemented by this processor"); + return ERROR_OK; + } + + switch (CMD_ARGC) { + case 0: + retval = mips32_dsp_get_all_regs(CMD, ejtag_info); + break; + case 1: + retval = mips32_dsp_get_register(CMD, ejtag_info); + break; + case 2: + tmp = *CMD_ARGV[0]; + if (isdigit(tmp)) { + command_print(CMD, "Error: invalid dsp command format"); + retval = ERROR_COMMAND_ARGUMENT_INVALID; + } else { + retval = mips32_dsp_set_register(CMD, ejtag_info); + } + break; + default: + command_print(CMD, "Error: invalid argument format, required 0-2, given %d", CMD_ARGC); + retval = ERROR_COMMAND_ARGUMENT_INVALID; + break; + } + return retval; +} + /** * mips32_handle_ejtag_reg_command - Handler commands related to EJTAG * @param[in] cmd: Command invocation context @@ -1847,6 +2267,14 @@ static const struct command_registration mips32_exec_command_handlers[] = { .help = "display CPU information", .usage = "", }, + { + .name = "dsp", + .handler = mips32_handle_dsp_command, + .mode = COMMAND_EXEC, + .help = "display or set DSP register; " + "with no arguments, displays all registers and their values", + .usage = "[[register_name] [value]]", + }, { .name = "scan_delay", .handler = mips32_handle_scan_delay_command, diff --git a/src/target/mips32.h b/src/target/mips32.h index 208c9da174..d512e49709 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -69,7 +69,7 @@ #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 -#define MIPS32_NUM_DSPREGS 9 +#define MIPS32NUMDSPREGS 9 /* Bit Mask indicating CP0 register supported by this core */ #define MIPS_CP0_MK4 0x0001 @@ -734,6 +734,24 @@ struct mips32_algorithm { /* ejtag specific instructions */ #define MICRO_MIPS32_SDBBP 0x000046C0 #define MICRO_MIPS_SDBBP 0x46C0 +#define MIPS32_DSP_ENABLE 0x1000000 + +#define MIPS32_S_INST(rs, rac, opcode) \ + (((rs) << 21) | ((rac) << 11) | (opcode)) + +#define MIPS32_DSP_R_INST(rt, immd, opcode, extrw) \ + ((0x1F << 26) | ((immd) << 16) | ((rt) << 11) | ((opcode) << 6) | (extrw)) +#define MIPS32_DSP_W_INST(rs, immd, opcode, extrw) \ + ((0x1F << 26) | ((rs) << 21) | ((immd) << 11) | ((opcode) << 6) | (extrw)) + +#define MIPS32_DSP_MFHI(reg, ac) MIPS32_R_INST(0, ac, 0, reg, 0, MIPS32_OP_MFHI) +#define MIPS32_DSP_MFLO(reg, ac) MIPS32_R_INST(0, ac, 0, reg, 0, MIPS32_OP_MFLO) +#define MIPS32_DSP_MTLO(reg, ac) MIPS32_S_INST(reg, ac, MIPS32_OP_MTLO) +#define MIPS32_DSP_MTHI(reg, ac) MIPS32_S_INST(reg, ac, MIPS32_OP_MTHI) +#define MIPS32_DSP_RDDSP(rt, mask) MIPS32_DSP_R_INST(rt, mask, 0x12, 0x38) +#define MIPS32_DSP_WRDSP(rs, mask) MIPS32_DSP_W_INST(rs, mask, 0x13, 0x38) + + /* * MIPS32 Config1 Register (CP0 Register 16, Select 1) */ From 12ff36bd19e4f25dd7505c46a77d9f2c47dc350a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 10 Mar 2024 12:12:55 +0100 Subject: [PATCH 0764/1312] flash/nor/nrf5: drop useless for cycle condition Commit [1] added a break on error to the nrf5_erase() sector loop and the checking of the res value became useless in the for loop condition. Removing nrf5_get_probed_chip_if_halted() later in [2] dropped res initialization and clang static analyser complains "The left operand of '==' is a garbage value" Drop the useless test! Fixes: [1] commit 491636c8b832 ("flash/nor/nrf5: check protection before flash erase/write on nRF51") Fixes: [2] commit 2db325f5395f ("flash/nor/nrf5: drop nrf5_get_probed_chip_if_halted()") Signed-off-by: Tomas Vanek Change-Id: Ife6071c509719f8d7dc312fe9a780bdcf2575f69 Reviewed-on: https://review.openocd.org/c/openocd/+/8174 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 3f451a76c4..bf8c9da5fe 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -1071,7 +1071,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, } /* For each sector to be erased */ - for (unsigned int s = first; s <= last && res == ERROR_OK; s++) { + for (unsigned int s = first; s <= last; s++) { if (chip->features & NRF5_FEATURE_SERIES_51 && bank->sectors[s].is_protected == 1) { From 348b79aafe6826734921167397190c9032a6039e Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 9 Feb 2024 07:35:42 +0100 Subject: [PATCH 0765/1312] drivers/cmsis_dap, kitprog: use helper to derive err code from ack Unify the error codes returned by adapter drivers in the case of the received SWD ACK field differs from OK. Signed-off-by: Tomas Vanek Change-Id: I29e478390b4b30408054a090ac6a7fac3415ae71 Reviewed-on: https://review.openocd.org/c/openocd/+/8137 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/cmsis_dap.c | 2 +- src/jtag/drivers/kitprog.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 341d35cdfa..d7367d8137 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -944,7 +944,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo if (ack != SWD_ACK_OK) { LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count, ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); - queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; + queued_retval = swd_ack_to_error_code(ack); /* TODO: use results of transfers completed before the error occurred? */ goto skip; } diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c index c0d2adc100..98b0d16681 100644 --- a/src/jtag/drivers/kitprog.c +++ b/src/jtag/drivers/kitprog.c @@ -782,7 +782,7 @@ static int kitprog_swd_run_queue(void) if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) { LOG_DEBUG("SWD ack not OK: %d %s", i, ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); - queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; + queued_retval = swd_ack_to_error_code(ack); break; } read_index++; From 263dbc1472efa5f24e636e95f8c71a6f83b4097a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 11 Feb 2024 17:22:38 +0100 Subject: [PATCH 0766/1312] target/arm_adi_v5: introduce adiv5_jim_configure_ext() Allow direct pointer to struct adiv5_private_config for targets with adiv5_private_config inside of a bigger private config container. Use it instead of the private_config pointer toggling hack in aarch64.c Allow optional use of -dap parameter and use it instead of the static variable hack in xtensa_chip.c Signed-off-by: Tomas Vanek Change-Id: I7260c79332940adfa49d57b45cae39325cdaf432 Reviewed-on: https://review.openocd.org/c/openocd/+/8138 Tested-by: jenkins Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo --- src/target/aarch64.c | 7 +------ src/target/arm_adi_v5.c | 27 ++++++++++++++++++--------- src/target/arm_adi_v5.h | 9 +++++++++ src/target/xtensa/xtensa_chip.c | 12 +----------- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 1c056a015e..36bcddc31c 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2891,13 +2891,8 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info * * options, JIM_OK if it correctly parsed the topmost option * and JIM_ERR if an error occurred during parameter evaluation. * For JIM_CONTINUE, we check our own params. - * - * adiv5_jim_configure() assumes 'private_config' to point to - * 'struct adiv5_private_config'. Override 'private_config'! */ - target->private_config = &pc->adiv5_config; - e = adiv5_jim_configure(target, goi); - target->private_config = pc; + e = adiv5_jim_configure_ext(target, goi, &pc->adiv5_config, ADI_CONFIGURE_DAP_COMPULSORY); if (e != JIM_CONTINUE) return e; diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index ff12658c83..9129acecf9 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -2424,23 +2424,26 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, return JIM_ERR; } -int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi) +int adiv5_jim_configure_ext(struct target *target, struct jim_getopt_info *goi, + struct adiv5_private_config *pc, enum adiv5_configure_dap_optional optional) { - struct adiv5_private_config *pc; int e; - pc = (struct adiv5_private_config *)target->private_config; if (!pc) { - pc = calloc(1, sizeof(struct adiv5_private_config)); + pc = (struct adiv5_private_config *)target->private_config; if (!pc) { - LOG_ERROR("Out of memory"); - return JIM_ERR; + 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; } - pc->ap_num = DP_APSEL_INVALID; - target->private_config = pc; } - target->has_dap = true; + if (optional == ADI_CONFIGURE_DAP_COMPULSORY) + target->has_dap = true; e = adiv5_jim_spot_configure(goi, &pc->dap, &pc->ap_num, NULL); if (e != JIM_OK) @@ -2455,11 +2458,17 @@ int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi) } target->tap = pc->dap->tap; target->dap_configured = true; + target->has_dap = true; } return JIM_OK; } +int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi) +{ + return adiv5_jim_configure_ext(target, goi, NULL, ADI_CONFIGURE_DAP_COMPULSORY); +} + int adiv5_verify_config(struct adiv5_private_config *pc) { if (!pc) diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 60c161f3ca..92c3dbc3a6 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -788,6 +788,15 @@ struct adiv5_private_config { }; extern int adiv5_verify_config(struct adiv5_private_config *pc); + +enum adiv5_configure_dap_optional { + ADI_CONFIGURE_DAP_COMPULSORY = false, + ADI_CONFIGURE_DAP_OPTIONAL = true +}; + +extern int adiv5_jim_configure_ext(struct target *target, struct jim_getopt_info *goi, + struct adiv5_private_config *pc, + enum adiv5_configure_dap_optional optional); extern int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi); struct adiv5_mem_ap_spot { diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index ac758ed830..ac4a49ccf4 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -144,17 +144,7 @@ static int xtensa_chip_examine(struct target *target) static int xtensa_chip_jim_configure(struct target *target, struct jim_getopt_info *goi) { - static bool dap_configured; - int ret = adiv5_jim_configure(target, goi); - if (ret == JIM_OK) { - LOG_DEBUG("xtensa '-dap' target option found"); - dap_configured = true; - } - if (!dap_configured) { - LOG_DEBUG("xtensa '-dap' target option not yet found, assuming JTAG..."); - target->has_dap = false; - } - return ret; + return adiv5_jim_configure_ext(target, goi, NULL, ADI_CONFIGURE_DAP_OPTIONAL); } /** Methods for generic example of Xtensa-based chip-level targets. */ From b63e065f23807cdf6da44d03def4c416686695f5 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 16 Feb 2024 17:40:22 +0100 Subject: [PATCH 0767/1312] helper/log: add LOG_CUSTOM_LEVEL() macro Allow logging at a changeable level. Add an example of usage in ftdi driver. Log SWD commands with not OK response at debug level (3). For commands which responded OK use debug io level (4) not to flood the log. Signed-off-by: Tomas Vanek Change-Id: I67a472b293f7ed9ee84cadb7c081803e9eeb1ad0 Reviewed-on: https://review.openocd.org/c/openocd/+/8151 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/helper/log.h | 9 +++++++++ src/jtag/drivers/ftdi.c | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/helper/log.h b/src/helper/log.h index ee71bf03f0..818716a9df 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -114,6 +114,15 @@ extern int debug_level; expr); \ } while (0) +#define LOG_CUSTOM_LEVEL(level, expr ...) \ + do { \ + enum log_levels _level = level; \ + if (debug_level >= _level) \ + log_printf_lf(_level, \ + __FILE__, __LINE__, __func__, \ + expr); \ + } while (0) + #define LOG_INFO(expr ...) \ log_printf_lf(LOG_LVL_INFO, __FILE__, __LINE__, __func__, expr) diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 2bde93169e..58f83af592 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -1088,7 +1088,8 @@ static int ftdi_swd_run_queue(void) /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ bool check_ack = swd_cmd_returns_ack(swd_cmd_queue[i].cmd); - LOG_DEBUG_IO("%s%s %s %s reg %X = %08"PRIx32, + LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK) ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO, + "%s%s %s %s reg %X = %08" PRIx32, check_ack ? "" : "ack ignored ", ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", swd_cmd_queue[i].cmd & SWD_CMD_APNDP ? "AP" : "DP", From f7f4fa84f1466036ebec80b3143fdd32ce181344 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 17 Feb 2024 12:48:46 +0100 Subject: [PATCH 0768/1312] jtag/drivers/bitbang: use LOG_CUSTOM_LEVEL() macro for SWD Log SWD commands with not OK response but WAIT retries at debug level. For commands responded OK and WAIT retries use debug io level not to flood the log. Signed-off-by: Tomas Vanek Change-Id: Idf658e82ed970061c155945df55d06908ed25e09 Reviewed-on: https://review.openocd.org/c/openocd/+/8152 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/bitbang.c | 56 ++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 8df51764b7..f0236848b3 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -474,7 +474,7 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay return; } - for (;;) { + for (unsigned int retry = 0;; retry++) { uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; cmd |= SWD_CMD_START | SWD_CMD_PARK; @@ -488,16 +488,22 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32); int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1); - LOG_DEBUG_IO("%s %s read reg %X = %08" PRIx32, - ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", - cmd & SWD_CMD_APNDP ? "AP" : "DP", - (cmd & SWD_CMD_A32) >> 1, - data); + LOG_CUSTOM_LEVEL((ack != SWD_ACK_OK && (retry == 0 || ack != SWD_ACK_WAIT)) + ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO, + "%s %s read reg %X = %08" PRIx32, + ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", + cmd & SWD_CMD_APNDP ? "AP" : "DP", + (cmd & SWD_CMD_A32) >> 1, + data); if (ack == SWD_ACK_WAIT) { swd_clear_sticky_errors(); continue; - } else if (ack != SWD_ACK_OK) { + } + if (retry > 1) + LOG_DEBUG("SWD WAIT: retried %u times", retry); + + if (ack != SWD_ACK_OK) { queued_retval = swd_ack_to_error_code(ack); return; } @@ -529,7 +535,7 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay /* 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 (;;) { + for (unsigned int retry = 0;; retry++) { 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)); @@ -554,22 +560,26 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1); int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3); + LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK && (retry == 0 || ack != SWD_ACK_WAIT)) + ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO, + "%s%s %s write reg %X = %08" PRIx32, + check_ack ? "" : "ack ignored ", + ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", + cmd & SWD_CMD_APNDP ? "AP" : "DP", + (cmd & SWD_CMD_A32) >> 1, + buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32)); + + if (check_ack && ack == SWD_ACK_WAIT) { + swd_clear_sticky_errors(); + continue; + } - LOG_DEBUG_IO("%s%s %s write reg %X = %08" PRIx32, - check_ack ? "" : "ack ignored ", - ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", - cmd & SWD_CMD_APNDP ? "AP" : "DP", - (cmd & SWD_CMD_A32) >> 1, - buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32)); - - if (check_ack) { - if (ack == SWD_ACK_WAIT) { - swd_clear_sticky_errors(); - continue; - } else if (ack != SWD_ACK_OK) { - queued_retval = swd_ack_to_error_code(ack); - return; - } + if (retry > 1) + LOG_DEBUG("SWD WAIT: retried %u times", retry); + + if (check_ack && ack != SWD_ACK_OK) { + queued_retval = swd_ack_to_error_code(ack); + return; } if (cmd & SWD_CMD_APNDP) From 31af18e9d1807d442885d0254ff5b13a66ea3a65 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 17 Feb 2024 13:14:01 +0100 Subject: [PATCH 0769/1312] jtag/drivers/bitbang: limit SWD WAIT retries by timeout The bitbang driver kept retrying a SWD command as long as the debugged device had been responding by SWD WAIT. If the DP stalled in WAIT permanently, OpenOCD hanged. Check 0.5 sec timeout in WAIT retry loop. While on it insert a short alive_sleep() if the command is retried 20 or more times. Signed-off-by: Tomas Vanek Change-Id: I744e56e21a5a2dc2c4494cc0d7bbcb4be14ddb23 Reviewed-on: https://review.openocd.org/c/openocd/+/8153 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/bitbang.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index f0236848b3..3d839e65de 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -20,6 +20,11 @@ #include #include +#include + +/* Timeout for retrying on SWD WAIT in msec */ +#define SWD_WAIT_TIMEOUT 500 + /** * Function bitbang_stableclocks * issues a number of clock cycles while staying in a stable state. @@ -474,6 +479,7 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay return; } + int64_t timeout = timeval_ms() + SWD_WAIT_TIMEOUT; for (unsigned int retry = 0;; retry++) { uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)]; @@ -496,8 +502,11 @@ static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay (cmd & SWD_CMD_A32) >> 1, data); - if (ack == SWD_ACK_WAIT) { + if (ack == SWD_ACK_WAIT && timeval_ms() <= timeout) { swd_clear_sticky_errors(); + if (retry > 20) + alive_sleep(1); + continue; } if (retry > 1) @@ -530,6 +539,8 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay return; } + int64_t timeout = timeval_ms() + SWD_WAIT_TIMEOUT; + /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */ bool check_ack = swd_cmd_returns_ack(cmd); @@ -569,8 +580,11 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay (cmd & SWD_CMD_A32) >> 1, buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32)); - if (check_ack && ack == SWD_ACK_WAIT) { + if (check_ack && ack == SWD_ACK_WAIT && timeval_ms() <= timeout) { swd_clear_sticky_errors(); + if (retry > 20) + alive_sleep(1); + continue; } From 4c0a2cf42ea0a0b48a948be1ff825629265bbf21 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 15 Feb 2024 10:05:21 +0100 Subject: [PATCH 0770/1312] target/adi_v5_swd: fix DP registers banking ADIv6 brought more complicated rules for DP reg 0 banking. Neither the original implementation [1] nor the later modification [2] respected that the DP reg 0 is banked for read only, not for write. Enforcing of an useless SELECT write before a write to ABORT register may trigger FAULT (CTRL/STAT bits ORUNDETECT and STICKYORUN are set) or WAIT (DP is stalled by an outstanding previous operation) and therefore make ABORT register virtually unusable on some adapters (bitbang, CMSIS-DAP). There are DP ABORT specific functions swd_queue_ap_abort() and swd_clear_sticky_errors() which worked around the problem using the lowest level swd->write_reg(). Using a specific write procedure for a single DP register was error prone (there are other DP_ABORT writes using swd_queue_dp_write_inner()) and also the Tcl command 'xx.dap dpreg 0 value' suffered from unwanted SELECT write. Other smaller discords in DP banking probably do not influence normal DP operation however they may complicate debugging in corner cases. Adhere strictly to the DP banking rules for both ADI versions. Fixes: [1] commit 72fb88613f02 ("adiv6: add low level swd transport") Fixes: [2] commit ee3fb5a0eacb ("target/arm_adi_v5: fix DP SELECT logic") Signed-off-by: Tomas Vanek Change-Id: I3328748c1c3e0661c5ecd6eb070ac519b190ace2 Reviewed-on: https://review.openocd.org/c/openocd/+/8154 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/adi_v5_swd.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 6d6f287b05..67706f35b0 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -105,14 +105,13 @@ static inline int check_sync(struct adiv5_dap *dap) static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg) { /* Only register address 0 (ADIv6 only) and 4 are banked. */ - if ((reg & 0xf) > 4) + if (is_adiv6(dap) ? (reg & 0xf) > 4 : (reg & 0xf) != 4) return ERROR_OK; uint32_t sel = (reg >> 4) & DP_SELECT_DPBANK; - /* DP register 0 is not mapped according to ADIv5 - * whereas ADIv6 ensures DPBANKSEL = 0 after line reset */ - if ((dap->select_valid || ((reg & 0xf) == 0 && dap->select_dpbanksel_valid)) + /* ADIv6 ensures DPBANKSEL = 0 after line reset */ + if ((dap->select_valid || (is_adiv6(dap) && dap->select_dpbanksel_valid)) && (sel == (dap->select & DP_SELECT_DPBANK))) return ERROR_OK; @@ -146,7 +145,7 @@ static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg, static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { - int retval; + int retval = ERROR_OK; const struct swd_driver *swd = adiv5_dap_swd_driver(dap); assert(swd); @@ -167,7 +166,11 @@ static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, if (reg == DP_SELECT1) dap->select = ((uint64_t)data << 32) | (dap->select & 0xffffffffull); - retval = swd_queue_dp_bankselect(dap, reg); + /* DP_ABORT write is not banked. + * Prevent writing DP_SELECT before as it would fail on locked up DP */ + if (reg != DP_ABORT) + retval = swd_queue_dp_bankselect(dap, reg); + if (retval == ERROR_OK) { swd->write_reg(swd_cmd(false, false, reg), data, 0); From e9df8a5102106de5a13956759ae52eb72ff68113 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 28 Feb 2024 13:41:34 +0100 Subject: [PATCH 0771/1312] target: aarch64: add support for 32 bit MON mode Extend the existing code to support Monitor mode in AArch32. Change-Id: Ia43df98d1497baac48aea67b92d81344c24f0635 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8169 Tested-by: jenkins --- src/target/aarch64.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 36bcddc31c..2e4d0b5c03 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -93,6 +93,7 @@ static int aarch64_restore_system_control_reg(struct target *target) case ARM_MODE_HYP: case ARM_MODE_UND: case ARM_MODE_SYS: + case ARM_MODE_MON: instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0); break; @@ -172,6 +173,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) case ARM_MODE_HYP: case ARM_MODE_UND: case ARM_MODE_SYS: + case ARM_MODE_MON: instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0); break; @@ -1043,6 +1045,7 @@ static int aarch64_post_debug_entry(struct target *target) case ARM_MODE_HYP: case ARM_MODE_UND: case ARM_MODE_SYS: + case ARM_MODE_MON: instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0); break; From 1d076d6ce1908d5c154bfc6ee2ccd8a629853ef1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Mar 2024 14:01:07 +0100 Subject: [PATCH 0772/1312] openocd: dump full command line in the debug log When receiving an OpenOCD debug log to investigate about errors or issues, the first question is often about providing the complete command line to better understand the use context. Plus, when OpenOCD is lunched by an IDE, its command line is kept hidden inside the IDE, adding troubles to the user to recover it. Add the full command line directly inside the debug log. It could have been useful to also search and add in the log the full path of the OpenOCD executable, but this is not an immediate task due to portability among OS's. See, for example: https://stackoverflow.com/questions/933850 This part could be handled in a future change, if really needed. Change-Id: Ia6c5b838b9b7208bf1ecac7f95b5efc319aeabf5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8170 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/helper/options.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helper/options.c b/src/helper/options.c index 05cde6709f..61a1014697 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -341,6 +341,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) exit(0); } + /* dump full command line */ + for (int i = 0; i < argc; i++) + LOG_DEBUG("ARGV[%d] = \"%s\"", i, argv[i]); + /* paths specified on the command line take precedence over these * built-in paths */ From 7a77355a3ea574dc5b7fc0a6ea8be413589ef847 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Mon, 1 Jan 2024 16:05:07 +0100 Subject: [PATCH 0773/1312] ipdbg: split ipdbg command into multiple commands To simplify the ipdbg start/stop command and be able to add additional commands in the future, we introduce the concept of a hub which has to be created before a ipdbg server can be started. The hub was created on the fly in previous versions. Change-Id: I55f317542d01a7324990b2cacd496a41fa5ff875 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7979 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 75 ++++-- src/jtag/startup.tcl | 128 ++++++++++ src/server/ipdbg.c | 416 ++++++++++++++++++++----------- src/server/ipdbg.h | 1 + src/server/server.c | 2 + tcl/board/bemicro_cycloneiii.cfg | 3 +- tcl/board/digilent_cmod_s7.cfg | 3 +- tcl/board/ecp5_evaluation.cfg | 3 +- tcl/board/gowin_runber.cfg | 3 +- tcl/board/trion_t20_bga256.cfg | 3 +- 10 files changed, 470 insertions(+), 167 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index bf4e0ad65c..651cc53bb3 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -12116,55 +12116,84 @@ waveform generator. These are synthesize-able hardware descriptions of logic circuits in addition to software for control, visualization and further analysis. In a session using JTAG for its transport protocol, OpenOCD supports the function of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the -control-software. For more details see @url{http://ipdbg.org}. +control-software. The JTAG-Hub is the circuit which transfers the data from JTAG to the +different tools connected to the Hub. Hub implementations for most major FPGA vendors/families +are provided. For more details see @url{http://ipdbg.org}. -@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] [@option{-port @var{number}}] [@option{-tool @var{number}}] -Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order. +@deffn {Command} {ipdbg create-hub} @var{hub_name} @option{-tap @var{tapname}} @option{-ir @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] +@deffnx {Command} {ipdbg create-hub} @var{hub_name} @option{-pld @var{pld_name} [@var{user}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] +Creates a IPDBG JTAG Hub. The created hub is later used to start, stop and configure IPDBG JTAG Host servers. +The first argument @var{hub_name} is the name of the created hub. It can be used later as a reference. + +The pld drivers are able to provide the tap and ir_value for the IPDBG JTAG-Host server. This will be used with the second variant with option @option{-pld}. Command options: @itemize @bullet -@item @option{-start|-stop} starts or stops a IPDBG JTAG-Host server (default: start). +@item @var{hub_name} the name of the IPDBG hub. +This name is also used to create the object's command, referred to here +as @command{$hub_name}, and in other places where the Hub needs to be identified. + @item @option{-tap @var{tapname}} targeting the TAP @var{tapname}. -@item @option{-hub @var{ir_value}} states that the JTAG hub is -reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}. -@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given. -@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given. -@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is reachable if there is a -specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an + +@item @option{-ir @var{ir_value}} states that the JTAG hub is +reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}. Also known as @verb{|USERx|} instructions. +The optional @var{dr_length} is the length of the dr. +Current JTAG-Hub implementation only supports dr_length=13, which is also the default value. + +@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} To support more Hubs than USER registers in a single FPGA it is possible to +use a mechanism known as virtual-ir where the user data-register is reachable if there is a specific value in a second dr. +This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to shift data through vir can be configured. + +@item @option{-pld @var{pld_name} [@var{user}]} The defined driver for the pld @var{pld_name} is used to get the tap and user instruction. +The pld devices names can be shown by the command @command{pld devices}. With [@var{user}] one can select a different @verb{|USERx|}-Instruction. +If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate. +The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor. +So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. +If your device/vendor is not supported you have to use the first variant. + @end itemize + @end deffn -or -@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{name} [@var{user}]} [@option{-port @var{number}}] [@option{-tool @var{number}}] -Also starts or stops a IPDBG JTAG-Host server. The pld drivers are able to provide the tap and hub/IR for the IPDBG JTAG-Host server. -With the @option{-pld @var{name} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required. -The defined driver for the pld @var{name} gets selected. (The pld devices names can be shown by the command @command{pld devices}). -The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor. -So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. If your device/vendor is not supported you have to use the previous command. +@deffn {Command} {$hub_name ipdbg start} @option{-tool @var{number}} @option{-port @var{number}} +Starts a IPDBG JTAG-Host server. The remaining arguments can be specified in any order. -With [@var{user}] one can select a different @verb{|USERx|}-Instruction. If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate. +Command options: +@itemize @bullet +@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given. +@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given. +@end itemize +@end deffn -The remaining options are described in the previous command. +@deffn {Command} {$hub_name ipdbg stop} @option{-tool @var{number}} +Stops a IPDBG JTAG-Host server. +Command options: +@itemize @bullet +@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given. +@end itemize @end deffn Examples: @example -ipdbg -start -tap xc6s.tap -hub 0x02 -port 4242 -tool 4 +ipdbg create-hub xc6s.ipdbghub -tap xc6s.tap -hub 0x02 +xc6s.ipdbghub ipdbg start -port 4242 -tool 4 @end example -Starts a server listening on tcp-port 4242 which connects to tool 4. +Creates a IPDBG Hub and starts a server listening on tcp-port 4242 which connects to tool 4. The connection is through the TAP of a Xilinx Spartan 6 on USER1 instruction (tested with a papillion pro board). @example -ipdbg -start -tap 10m50.tap -hub 0x00C -vir -port 60000 -tool 1 +ipdbg create-hub max10m50.ipdbghub -tap max10m50.tap -hub 0x00C -vir +max10m50.ipdbghub ipdbg start -tool 1 -port 60000 @end example Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1). The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5). @example -ipdbg -start -pld xc7.pld -port 5555 -tool 0 +ipdbg create-hub xc7.ipdbghub -pld xc7.pld +xc7.ipdbghub ipdbg start -port 5555 -tool 0 @end example Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0). The TAP and ir value used to reach the JTAG Hub is given by the pld driver. diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 4eca67771d..41db38e4ac 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -1146,4 +1146,132 @@ proc "pld device" {driver tap_name {opt 0}} { } } +lappend _telnet_autocomplete_skip "ipdbg -start" +proc "ipdbg -start" {args} { + echo "DEPRECATED! use 'ipdbg create-hub' and 'chip.ipdbghub ipdbg start ...', not 'ipdbg -start ...'" + set tap_name "" + set pld_name "" + set tool_num "1" + set port_num "4242" + set idx 0 + set num_args [llength $args] + while {$idx < $num_args} { + set arg [lindex $args $idx] + switch -- $arg { + "-tap" { + incr idx + if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} { + echo "no TAP name given" + return + } + set tap_name [lindex $args $idx] + } + "-pld" { + incr idx + if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} { + echo "no PLD name given" + return + } + set pld_name [lindex $args $idx] + } + "-tool" { + if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} { + set tool_num [lindex $args [expr {$idx + 1}]] + set args [lreplace $args [expr {$idx + 1}] [expr {$idx + 1}]] + incr num_args -1 + } + set args [lreplace $args $idx $idx] + incr num_args -1 + incr idx -1 + } + "-port" { + if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} { + set port_num [lindex $args [expr {$idx + 1}]] + set args [lreplace $args [expr {$idx + 1}] [expr {$idx + 1}]] + incr num_args -1 + } + set args [lreplace $args $idx $idx] + incr num_args -1 + incr idx -1 + } + "-hub" { + set args [lreplace $args $idx $idx "-ir" ] + } + default { +# don't touch remaining arguments + } + } + incr idx + } + + set hub_name "" + if {$tap_name != ""} { + set hub_name [lindex [split $tap_name .] 0].ipdbghub + } elseif {$pld_name != ""} { + set hub_name [lindex [split $pld_name .] 0].ipdbghub + } else { + echo "parsing arguments failed: no tap and no pld given." + return + } + + echo "name: $hub_name" + echo "ipdbg create-hub $hub_name $args" + + catch {eval ipdbg create-hub $hub_name $args} + + eval $hub_name ipdbg start -tool $tool_num -port $port_num +} + +lappend _telnet_autocomplete_skip "ipdbg -stop" +proc "ipdbg -stop" {args} { + echo "DEPRECATED! use 'chip.ipdbghub ipdbg stop ...', not 'ipdbg -stop ...'" + set tap_name "" + set pld_name "" + set tool_num "1" + set idx 0 + set num_args [llength $args] + while {$idx < $num_args} { + set arg [lindex $args $idx] + switch -- $arg { + "-tap" { + incr idx + if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} { + echo "no TAP name given" + return + } + set tap_name [lindex $args $idx] + } + "-pld" { + incr idx + if {$idx >= $num_args || [string index [lindex $args $idx] 0] == "-"} { + echo "no PLD name given" + return + } + set pld_name [lindex $args $idx] + } + "-tool" { + if {[expr {$idx + 1}] < $num_args && [string index [lindex $args [expr {$idx + 1}]] 0] != "-"} { + set tool_num [lindex $args [expr {$idx + 1}]] + } + } + default { +# don't touch remaining arguments + } + } + incr idx + } + + set hub_name "" + if {$tap_name != ""} { + set hub_name [lindex [split $tap_name .] 0].ipdbghub + } elseif {$pld_name != ""} { + set hub_name [lindex [split $pld_name .] 0].ipdbghub + } else { + echo "parsing arguments failed: no tap and no pld given." + return + } + + eval $hub_name ipdbg stop -tool $tool_num +} + # END MIGRATION AIDS diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index 0733230322..e218b82443 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -15,8 +15,10 @@ #include "ipdbg.h" #define IPDBG_BUFFER_SIZE 16384 -#define IPDBG_MIN_NUM_OF_OPTIONS 2 -#define IPDBG_MAX_NUM_OF_OPTIONS 14 +#define IPDBG_MIN_NUM_OF_CREATE_OPTIONS 3 +#define IPDBG_MAX_NUM_OF_CREATE_OPTIONS 10 +#define IPDBG_NUM_OF_START_OPTIONS 4 +#define IPDBG_NUM_OF_STOP_OPTIONS 2 #define IPDBG_MIN_DR_LENGTH 11 #define IPDBG_MAX_DR_LENGTH 13 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6 @@ -75,6 +77,7 @@ struct ipdbg_hub { uint32_t xoff_mask; uint32_t tool_mask; uint32_t last_dn_tool; + char *name; struct ipdbg_hub *next; struct jtag_tap *tap; struct connection **connections; @@ -247,59 +250,27 @@ static void ipdbg_add_hub(struct ipdbg_hub *hub) for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) ; ihub->next = hub; - } else + } else { ipdbg_first_hub = hub; + } } -static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length, - struct ipdbg_virtual_ir_info *virtual_ir, struct ipdbg_hub **hub) +static int ipdbg_remove_hub(struct ipdbg_hub *hub) { - *hub = NULL; - struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub)); - if (!new_hub) - goto mem_err_hub; - - const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8); - new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length); - - new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size); - new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size); - new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field)); - new_hub->connections = calloc(new_hub->max_tools, sizeof(struct connection *)); - - if (virtual_ir) - new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8)); - - if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals || - !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) || - !new_hub->connections) - goto mem_err2; - - if (virtual_ir) - buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value); - - new_hub->tap = tap; - new_hub->user_instruction = user_instruction; - new_hub->data_register_length = data_register_length; - new_hub->valid_mask = BIT(data_register_length - 1); - new_hub->xoff_mask = BIT(data_register_length - 2); - new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8; - new_hub->last_dn_tool = new_hub->tool_mask; - new_hub->virtual_ir = virtual_ir; + if (!ipdbg_first_hub) + return ERROR_FAIL; + if (hub == ipdbg_first_hub) { + ipdbg_first_hub = ipdbg_first_hub->next; + return ERROR_OK; + } - *hub = new_hub; - return ERROR_OK; + for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) { + if (hub == ihub->next) { + ihub->next = hub->next; + return ERROR_OK; + } + } -mem_err2: - free(new_hub->scratch_memory.vir_out_val); - free(new_hub->connections); - free(new_hub->scratch_memory.fields); - free(new_hub->scratch_memory.dr_in_vals); - free(new_hub->scratch_memory.dr_out_vals); - free(new_hub); -mem_err_hub: - free(virtual_ir); - LOG_ERROR("Out of memory"); return ERROR_FAIL; } @@ -309,6 +280,7 @@ static void ipdbg_free_hub(struct ipdbg_hub *hub) return; free(hub->connections); free(hub->virtual_ir); + free(hub->name); free(hub->scratch_memory.dr_out_vals); free(hub->scratch_memory.dr_in_vals); free(hub->scratch_memory.fields); @@ -316,23 +288,42 @@ static void ipdbg_free_hub(struct ipdbg_hub *hub) free(hub); } -static int ipdbg_remove_hub(struct ipdbg_hub *hub) +static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, + const char *name) { - if (!ipdbg_first_hub) - return ERROR_FAIL; - if (hub == ipdbg_first_hub) { - ipdbg_first_hub = ipdbg_first_hub->next; - return ERROR_OK; + struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub)); + if (!new_hub) { + LOG_ERROR("Out of memory"); + return NULL; } - for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) { - if (hub == ihub->next) { - ihub->next = hub->next; - return ERROR_OK; - } + new_hub->name = strdup(name); + if (!new_hub->name) { + free(new_hub); + LOG_ERROR("Out of memory"); + return NULL; } - return ERROR_FAIL; + const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8); + uint32_t max_tools = ipdbg_max_tools_from_data_register_length(data_register_length); + + new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size); + new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size); + new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field)); + new_hub->connections = calloc(max_tools, sizeof(struct connection *)); + + if (virtual_ir) + new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8)); + + if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals || + !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) || + !new_hub->connections) { + ipdbg_free_hub(new_hub); + LOG_ERROR("Out of memory"); + return NULL; + } + + return new_hub; } static void ipdbg_init_scan_field(struct scan_field *fields, uint8_t *in_value, int num_bits, const uint8_t *out_value) @@ -760,23 +751,62 @@ static const struct service_driver ipdbg_service_driver = { .keep_client_alive_handler = NULL, }; -static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instruction, - uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool) +static struct ipdbg_hub *ipdbg_get_hub_by_name(const char *name) { - LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool); + struct ipdbg_hub *hub = NULL; + for (hub = ipdbg_first_hub; hub; hub = hub->next) { + if (strcmp(hub->name, name) == 0) + break; + } + return hub; +}; - struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir); - if (hub) { - free(virtual_ir); - if (hub->data_register_length != data_register_length) { - LOG_DEBUG("hub must have the same data_register_length for all tools"); - return ERROR_FAIL; +static int ipdbg_stop_service(struct ipdbg_service *service) +{ + int retval = ipdbg_remove_service(service); + if (retval != ERROR_OK) { + LOG_ERROR("BUG: ipdbg_remove_service failed"); + return retval; + } + + char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH]; + snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", service->port); + retval = remove_service("ipdbg", port_str_buffer); + /* The ipdbg_service structure is freed by server.c:remove_service(). + There the "priv" pointer is freed.*/ + if (retval != ERROR_OK) { + LOG_ERROR("BUG: remove_service failed"); + return retval; + } + return ERROR_OK; +} + +int ipdbg_server_free(void) +{ + int retval = ERROR_OK; + for (struct ipdbg_hub *hub = ipdbg_first_hub; hub;) { + for (uint8_t tool = 0; tool < hub->max_tools; ++tool) { + struct ipdbg_service *service = ipdbg_find_service(hub, tool); + if (service) { + int new_retval = ipdbg_stop_service(service); + if (new_retval != ERROR_OK) + retval = new_retval; + hub->active_services--; + } } - } else { - int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub); - if (retval != ERROR_OK) - return retval; + struct ipdbg_hub *next_hub = hub->next; + int new_retval = ipdbg_remove_hub(hub); + if (new_retval != ERROR_OK) + retval = new_retval; + ipdbg_free_hub(hub); + hub = next_hub; } + return retval; +} + +static int ipdbg_start(struct ipdbg_hub *hub, uint16_t port, uint8_t tool) +{ + LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool); struct ipdbg_service *service = NULL; int retval = ipdbg_create_service(hub, tool, &service, port); @@ -790,82 +820,181 @@ static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instru char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH]; snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port); retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service); - if (retval == ERROR_OK) { - ipdbg_add_service(service); - if (hub->active_services == 0 && hub->active_connections == 0) - ipdbg_add_hub(hub); - hub->active_services++; - } else { - if (hub->active_services == 0 && hub->active_connections == 0) - ipdbg_free_hub(hub); + if (retval != ERROR_OK) { free(service); + return retval; } + ipdbg_add_service(service); + hub->active_services++; + return ERROR_OK; +} +COMMAND_HANDLER(handle_ipdbg_start_command) +{ + struct ipdbg_hub *hub = CMD_DATA; + + uint16_t port = 4242; + uint8_t tool = 1; + + if (CMD_ARGC > IPDBG_NUM_OF_START_OPTIONS) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int i = 0; i < CMD_ARGC; ++i) { + if (strcmp(CMD_ARGV[i], "-port") == 0) { + COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number"); + } else if (strcmp(CMD_ARGV[i], "-tool") == 0) { + COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool"); + } else { + command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]); + return ERROR_FAIL; + } + } + + return ipdbg_start(hub, port, tool); +} + +static int ipdbg_stop(struct ipdbg_hub *hub, uint8_t tool) +{ + struct ipdbg_service *service = ipdbg_find_service(hub, tool); + if (!service) { + LOG_ERROR("No service for hub '%s'/tool %d found", hub->name, tool); + return ERROR_FAIL; + } + + int retval = ipdbg_stop_service(service); + hub->active_services--; + + LOG_INFO("stopped ipdbg service for tool %d", tool); return retval; } -static int ipdbg_stop(struct jtag_tap *tap, uint32_t user_instruction, - struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool) +COMMAND_HANDLER(handle_ipdbg_stop_command) { - struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir); - free(virtual_ir); - if (!hub) + struct ipdbg_hub *hub = CMD_DATA; + + uint8_t tool = 1; + + if (CMD_ARGC > IPDBG_NUM_OF_STOP_OPTIONS) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int i = 0; i < CMD_ARGC; ++i) { + if (strcmp(CMD_ARGV[i], "-tool") == 0) { + COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool"); + } else { + command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]); + return ERROR_FAIL; + } + } + + return ipdbg_stop(hub, tool); +} + +static const struct command_registration ipdbg_hostserver_subcommand_handlers[] = { + { + .name = "start", + .mode = COMMAND_EXEC, + .handler = handle_ipdbg_start_command, + .help = "Starts a IPDBG Host server.", + .usage = "-tool number -port port" + }, { + .name = "stop", + .mode = COMMAND_EXEC, + .handler = handle_ipdbg_stop_command, + .help = "Stops a IPDBG Host server.", + .usage = "-tool number" + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration ipdbg_hub_subcommand_handlers[] = { + { + .name = "ipdbg", + .mode = COMMAND_EXEC, + .help = "IPDBG Hub commands.", + .usage = "", + .chain = ipdbg_hostserver_subcommand_handlers + }, + COMMAND_REGISTRATION_DONE +}; + +static int ipdbg_register_hub_command(struct ipdbg_hub *hub, struct command_invocation *cmd) +{ + Jim_Interp *interp = CMD_CTX->interp; + + /* does this command exist? */ + Jim_Cmd *jcmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, hub->name, -1), JIM_NONE); + if (jcmd) { + LOG_ERROR("cannot create Hub because a command with name '%s' already exists", hub->name); return ERROR_FAIL; + } - struct ipdbg_service *service = ipdbg_find_service(hub, tool); - if (!service) + const struct command_registration obj_commands[] = { + { + .name = hub->name, + .mode = COMMAND_EXEC, + .help = "IPDBG Hub command group.", + .usage = "", + .chain = ipdbg_hub_subcommand_handlers + }, + COMMAND_REGISTRATION_DONE + }; + + return register_commands_with_data(CMD_CTX, NULL, obj_commands, hub); +} + +static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length, + struct ipdbg_virtual_ir_info *virtual_ir, const char *name, struct command_invocation *cmd) +{ + struct ipdbg_hub *new_hub = ipdbg_allocate_hub(data_register_length, virtual_ir, name); + if (!new_hub) return ERROR_FAIL; - int retval = ipdbg_remove_service(service); - if (retval != ERROR_OK) { - LOG_ERROR("BUG: ipdbg_remove_service failed"); - return retval; - } + if (virtual_ir) + buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value); + new_hub->tap = tap; + new_hub->user_instruction = user_instruction; + new_hub->data_register_length = data_register_length; + new_hub->valid_mask = BIT(data_register_length - 1); + new_hub->xoff_mask = BIT(data_register_length - 2); + new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8; + new_hub->last_dn_tool = new_hub->tool_mask; + new_hub->virtual_ir = virtual_ir; + new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length); - char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH]; - snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", service->port); - retval = remove_service("ipdbg", port_str_buffer); - /* The ipdbg_service structure is freed by server.c:remove_service(). - There the "priv" pointer is freed.*/ + int retval = ipdbg_register_hub_command(new_hub, cmd); if (retval != ERROR_OK) { - LOG_ERROR("BUG: remove_service failed"); - return retval; - } - hub->active_services--; - if (hub->active_connections == 0 && hub->active_services == 0) { - retval = ipdbg_remove_hub(hub); - if (retval != ERROR_OK) { - LOG_ERROR("BUG: ipdbg_remove_hub failed"); - return retval; - } - ipdbg_free_hub(hub); + LOG_ERROR("Creating hub failed"); + ipdbg_free_hub(new_hub); + return ERROR_FAIL; } + + ipdbg_add_hub(new_hub); + return ERROR_OK; } -COMMAND_HANDLER(handle_ipdbg_command) +COMMAND_HANDLER(handle_ipdbg_create_hub_command) { struct jtag_tap *tap = NULL; - uint16_t port = 4242; - uint8_t tool = 1; uint32_t user_instruction = 0x00; uint8_t data_register_length = IPDBG_MAX_DR_LENGTH; - bool start = true; - bool hub_configured = false; bool has_virtual_ir = false; uint32_t virtual_ir_instruction = 0x00e; uint32_t virtual_ir_length = 5; uint32_t virtual_ir_value = 0x11; struct ipdbg_virtual_ir_info *virtual_ir = NULL; int user_num = 1; + bool hub_configured = false; - if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS)) + if (CMD_ARGC < IPDBG_MIN_NUM_OF_CREATE_OPTIONS || CMD_ARGC > IPDBG_MAX_NUM_OF_CREATE_OPTIONS) return ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned int i = 0; i < CMD_ARGC; ++i) { + const char *hub_name = CMD_ARGV[0]; + + for (unsigned int i = 1; i < CMD_ARGC; ++i) { if (strcmp(CMD_ARGV[i], "-tap") == 0) { if (i + 1 >= CMD_ARGC || CMD_ARGV[i + 1][0] == '-') { - command_print(CMD, "no TAP given"); + command_print(CMD, "no TAP name given"); return ERROR_FAIL; } tap = jtag_tap_by_string(CMD_ARGV[i + 1]); @@ -874,7 +1003,7 @@ COMMAND_HANDLER(handle_ipdbg_command) return ERROR_FAIL; } ++i; - } else if (strcmp(CMD_ARGV[i], "-hub") == 0) { + } else if (strcmp(CMD_ARGV[i], "-ir") == 0) { COMMAND_PARSE_ADDITIONAL_NUMBER(u32, i, user_instruction, "ir_value to select hub"); hub_configured = true; COMMAND_PARSE_OPTIONAL_NUMBER(u8, i, data_register_length); @@ -917,20 +1046,11 @@ COMMAND_HANDLER(handle_ipdbg_command) COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length); COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_instruction); has_virtual_ir = true; - } else if (strcmp(CMD_ARGV[i], "-port") == 0) { - COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number"); - } else if (strcmp(CMD_ARGV[i], "-tool") == 0) { - COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool"); - } else if (strcmp(CMD_ARGV[i], "-stop") == 0) { - start = false; - } else if (strcmp(CMD_ARGV[i], "-start") == 0) { - start = true; } else { command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]); return ERROR_FAIL; } } - if (!tap) { command_print(CMD, "no valid tap selected"); return ERROR_FAIL; @@ -941,8 +1061,8 @@ COMMAND_HANDLER(handle_ipdbg_command) return ERROR_FAIL; } - if (tool >= ipdbg_max_tools_from_data_register_length(data_register_length)) { - command_print(CMD, "Tool: %d is invalid", tool); + if (ipdbg_get_hub_by_name(hub_name)) { + LOG_ERROR("IPDBG hub with name '%s' already exists", hub_name); return ERROR_FAIL; } @@ -957,20 +1077,38 @@ COMMAND_HANDLER(handle_ipdbg_command) virtual_ir->value = virtual_ir_value; } - if (start) - return ipdbg_start(port, tap, user_instruction, data_register_length, virtual_ir, tool); - else - return ipdbg_stop(tap, user_instruction, virtual_ir, tool); + if (ipdbg_find_hub(tap, user_instruction, virtual_ir)) { + LOG_ERROR("IPDBG hub for given TAP and user-instruction already exists"); + free(virtual_ir); + return ERROR_FAIL; + } + + int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd); + if (retval != ERROR_OK) + free(virtual_ir); + + return retval; } +static const struct command_registration ipdbg_config_command_handlers[] = { + { + .name = "create-hub", + .mode = COMMAND_ANY, + .handler = handle_ipdbg_create_hub_command, + .help = "create a IPDBG Hub", + .usage = "name.ipdbghub (-tap device.tap -ir ir_value [dr_length] |" + " -pld name.pld [user]) [-vir [vir_value [length [instr_code]]]]", + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration ipdbg_command_handlers[] = { { .name = "ipdbg", - .handler = handle_ipdbg_command, - .mode = COMMAND_EXEC, - .help = "Starts or stops an IPDBG JTAG-Host server.", - .usage = "[-start|-stop] -tap device.tap -hub ir_value [dr_length]" - " [-port number] [-tool number] [-vir [vir_value [length [instr_code]]]]", + .mode = COMMAND_ANY, + .help = "IPDBG Hub/Host commands.", + .usage = "", + .chain = ipdbg_config_command_handlers, }, COMMAND_REGISTRATION_DONE }; diff --git a/src/server/ipdbg.h b/src/server/ipdbg.h index 6b70545845..1f4156b7ac 100644 --- a/src/server/ipdbg.h +++ b/src/server/ipdbg.h @@ -7,5 +7,6 @@ #include int ipdbg_register_commands(struct command_context *cmd_ctx); +int ipdbg_server_free(void); #endif /* OPENOCD_IPDBG_IPDBG_H */ diff --git a/src/server/server.c b/src/server/server.c index 2be90451f7..0649ec942b 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -23,6 +23,7 @@ #include "openocd.h" #include "tcl_server.h" #include "telnet_server.h" +#include "ipdbg.h" #include @@ -714,6 +715,7 @@ void server_free(void) tcl_service_free(); telnet_service_free(); jsp_service_free(); + ipdbg_server_free(); free(bindto_name); } diff --git a/tcl/board/bemicro_cycloneiii.cfg b/tcl/board/bemicro_cycloneiii.cfg index bd1459adc4..3c92b500c1 100644 --- a/tcl/board/bemicro_cycloneiii.cfg +++ b/tcl/board/bemicro_cycloneiii.cfg @@ -17,7 +17,8 @@ source [find fpga/altera-cycloneiii.cfg] #quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf #openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load cycloneiii.pld cycloneiii_blinker.rbf" -# "ipdbg -start -tap cycloneiii.tap -hub 0x00e -tool 0 -port 5555" +# "ipdbg create-hub cycloneiii.ipdbghub -tap cycloneiii.tap -ir 0x00e" +# "cycloneiii.ipdbghub ipdbg start -tool 0 -port 5555" set JTAGSPI_CHAIN_ID cycloneiii.pld diff --git a/tcl/board/digilent_cmod_s7.cfg b/tcl/board/digilent_cmod_s7.cfg index c52ee9505b..4fa45a17a7 100644 --- a/tcl/board/digilent_cmod_s7.cfg +++ b/tcl/board/digilent_cmod_s7.cfg @@ -15,7 +15,8 @@ adapter speed 10000 source [find cpld/xilinx-xc7.cfg] -# "ipdbg -start -tap xc7.tap -hub 0x02 -tool 0 -port 5555" +# "ipdbg create-hub xc7.ipdbghub -tap xc7.tap -ir 0x02" +# "xc7.ipdbghub ipdbg start -tool 0 -port 5555" #openocd -f board/digilent_cmod_s7.cfg -c "init" -c "pld load xc7.pld shared_folder/cmod_s7_fast.bit" set JTAGSPI_CHAIN_ID xc7.pld diff --git a/tcl/board/ecp5_evaluation.cfg b/tcl/board/ecp5_evaluation.cfg index dd663f79d8..71769f6074 100644 --- a/tcl/board/ecp5_evaluation.cfg +++ b/tcl/board/ecp5_evaluation.cfg @@ -16,7 +16,8 @@ adapter speed 6000 source [find fpga/lattice_ecp5.cfg] #openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load ecp5.pld shared_folder/ecp5_blinker_impl1.bit" -#ipdbg -start -tap ecp5.tap -hub 0x32 -port 5555 -tool 0 +#ipdbg create-hub ecp5.ipdbghub -tap ecp5.tap -ir 0x32 +#ecp5.ipdbghub ipdbg start -tool 0 -port 5555 set JTAGSPI_CHAIN_ID ecp5.pld source [find cpld/jtagspi.cfg] diff --git a/tcl/board/gowin_runber.cfg b/tcl/board/gowin_runber.cfg index 9496c6f008..6cb07362b9 100644 --- a/tcl/board/gowin_runber.cfg +++ b/tcl/board/gowin_runber.cfg @@ -16,4 +16,5 @@ source [find fpga/gowin_gw1n.cfg] #openocd -f board/gowin_runber.cfg -c "init" -c "pld load 0 impl/pnr/gw1n_blinker.fs" -#ipdbg -start -tap gw1n.tap -hub 0x42 -port 5555 -tool 0 +#ipdbg create-hub gw1n.ipdbghub -tap gw1n.tap -ir 0x42 +#gw1n.ipdbghubipdbg start -tool 0 -port 5555 diff --git a/tcl/board/trion_t20_bga256.cfg b/tcl/board/trion_t20_bga256.cfg index dc76d39104..ca44f0b8ce 100644 --- a/tcl/board/trion_t20_bga256.cfg +++ b/tcl/board/trion_t20_bga256.cfg @@ -20,7 +20,8 @@ adapter speed 6000 source [find fpga/efinix_trion.cfg] #openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load trion.pld outflow/trion_blinker.bit" -#ipdbg -start -tap trion.tap -hub 0x8 -port 5555 -tool 0 +#ipdbg create-hub trion.ipdbghub -tap trion.tap -ir 0x8 +#trion.ipdbghub ipdbg start -tool 0 -port 5555 set JTAGSPI_CHAIN_ID trion.pld source [find cpld/jtagspi.cfg] From a88db9b1211ea71b5795b91d11d94fb0f37cc905 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Mon, 1 Jan 2024 16:05:07 +0100 Subject: [PATCH 0774/1312] ipdbg: configurable queue size used between JTAG-Host and JTAG-Hub Change-Id: I7941de02a968ccab730bfebd3483b8c3b84d7e53 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7980 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 14 ++++++++++ src/server/ipdbg.c | 68 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 651cc53bb3..6b71fe869d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -12198,6 +12198,20 @@ xc7.ipdbghub ipdbg start -port 5555 -tool 0 Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0). The TAP and ir value used to reach the JTAG Hub is given by the pld driver. +@deffn {Command} {$hub_name queuing} @option{-size @var{size}} +Configure the queuing between IPDBG JTAG-Host and Hub. +The maximum possible queue size is 1024 which is also the default. + +@itemize @bullet +@item @option{-size @var{size}} max number of transfers in the queue. +@end itemize +@end deffn + +@example +bitbang.ibdbghub queuing -size 32 +@end example +Send a maximum of 32 transfers to the queue before executing them. + @node Utility Commands @chapter Utility Commands diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index e218b82443..e7eb96e13c 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -19,20 +19,11 @@ #define IPDBG_MAX_NUM_OF_CREATE_OPTIONS 10 #define IPDBG_NUM_OF_START_OPTIONS 4 #define IPDBG_NUM_OF_STOP_OPTIONS 2 +#define IPDBG_NUM_OF_QUEUE_OPTIONS 2 #define IPDBG_MIN_DR_LENGTH 11 #define IPDBG_MAX_DR_LENGTH 13 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6 #define IPDBG_SCRATCH_MEMORY_SIZE 1024 -#define IPDBG_EMPTY_DOWN_TRANSFERS 1024 -#define IPDBG_CONSECUTIVE_UP_TRANSFERS 1024 - -#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_EMPTY_DOWN_TRANSFERS -#error "scratch Memory must be at least IPDBG_EMPTY_DOWN_TRANSFERS" -#endif - -#if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_CONSECUTIVE_UP_TRANSFERS -#error "scratch Memory must be at least IPDBG_CONSECUTIVE_UP_TRANSFERS" -#endif /* private connection data for IPDBG */ struct ipdbg_fifo { @@ -78,6 +69,7 @@ struct ipdbg_hub { uint32_t tool_mask; uint32_t last_dn_tool; char *name; + size_t using_queue_size; struct ipdbg_hub *next; struct jtag_tap *tap; struct connection **connections; @@ -461,7 +453,7 @@ static int ipdbg_shift_empty_data(struct ipdbg_hub *hub) const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8); memset(hub->scratch_memory.dr_out_vals, 0, dreg_buffer_size); - for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) { + for (size_t i = 0; i < hub->using_queue_size; ++i) { ipdbg_init_scan_field(hub->scratch_memory.fields + i, hub->scratch_memory.dr_in_vals + i * dreg_buffer_size, hub->data_register_length, @@ -473,7 +465,7 @@ static int ipdbg_shift_empty_data(struct ipdbg_hub *hub) if (retval == ERROR_OK) { uint32_t up_data; - for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) { + for (size_t i = 0; i < hub->using_queue_size; ++i) { up_data = buf_get_u32(hub->scratch_memory.dr_in_vals + i * dreg_buffer_size, 0, hub->data_register_length); @@ -522,8 +514,8 @@ static int ipdbg_jtag_transfer_bytes(struct ipdbg_hub *hub, return ERROR_FAIL; const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8); - size_t num_tx = (connection->dn_fifo.count < IPDBG_CONSECUTIVE_UP_TRANSFERS) ? - connection->dn_fifo.count : IPDBG_CONSECUTIVE_UP_TRANSFERS; + size_t num_tx = (connection->dn_fifo.count < hub->using_queue_size) ? + connection->dn_fifo.count : hub->using_queue_size; for (size_t i = 0; i < num_tx; ++i) { uint32_t dn_data = hub->valid_mask | ((tool & hub->tool_mask) << 8) | @@ -906,6 +898,46 @@ static const struct command_registration ipdbg_hostserver_subcommand_handlers[] COMMAND_REGISTRATION_DONE }; +static COMMAND_HELPER(ipdbg_config_queuing, struct ipdbg_hub *hub, unsigned int size) +{ + if (!hub) + return ERROR_FAIL; + + if (hub->active_connections) { + command_print(CMD, "Configuration change not allowed when hub has active connections"); + return ERROR_FAIL; + } + + if (size == 0 || size > IPDBG_SCRATCH_MEMORY_SIZE) { + command_print(CMD, "queuing size out of range! Must be 0 < size <= %d", IPDBG_SCRATCH_MEMORY_SIZE); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + hub->using_queue_size = size; + return ERROR_OK; +} + +COMMAND_HANDLER(handle_ipdbg_cfg_queuing_command) +{ + struct ipdbg_hub *hub = CMD_DATA; + + unsigned int size; + + if (CMD_ARGC != IPDBG_NUM_OF_QUEUE_OPTIONS) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int i = 0; i < CMD_ARGC; ++i) { + if (strcmp(CMD_ARGV[i], "-size") == 0) { + COMMAND_PARSE_ADDITIONAL_NUMBER(uint, i, size, "size"); + } else { + command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]); + return ERROR_FAIL; + } + } + + return CALL_COMMAND_HANDLER(ipdbg_config_queuing, hub, size); +} + static const struct command_registration ipdbg_hub_subcommand_handlers[] = { { .name = "ipdbg", @@ -914,6 +946,13 @@ static const struct command_registration ipdbg_hub_subcommand_handlers[] = { .usage = "", .chain = ipdbg_hostserver_subcommand_handlers }, + { + .name = "queuing", + .handler = handle_ipdbg_cfg_queuing_command, + .mode = COMMAND_ANY, + .help = "configures queuing between IPDBG Host and Hub.", + .usage = "-size size", + }, COMMAND_REGISTRATION_DONE }; @@ -960,6 +999,7 @@ static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uin new_hub->last_dn_tool = new_hub->tool_mask; new_hub->virtual_ir = virtual_ir; new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length); + new_hub->using_queue_size = IPDBG_SCRATCH_MEMORY_SIZE; int retval = ipdbg_register_hub_command(new_hub, cmd); if (retval != ERROR_OK) { From 01a797af143398c6f3aa1eb6f8949deff4ccf044 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Fri, 17 Nov 2023 16:46:55 +0800 Subject: [PATCH 0775/1312] target/mips32: add fpu access support Add access to fpr and cp1 registers. GDB can now check the FPRs with `info reg f` and change them. Checkpatch-ignore: MACRO_ARG_REUSE Change-Id: I63896ab6f6737054d8108db105a13a58e1446fbc Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/7866 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- src/target/mips32.c | 95 ++++++++++++++++++++++++++++++---- src/target/mips32.h | 41 +++++++++++++++ src/target/mips32_pracc.c | 106 +++++++++++++++++++++++++++++++++++++- src/target/mips32_pracc.h | 15 ++++++ 4 files changed, 245 insertions(+), 12 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index ec2bfb7d0c..6bbf71bd82 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -262,6 +262,61 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_OK; } +/** + * mips32_set_all_fpr_width - Set the width of all floating-point registers + * @param[in] mips32: MIPS32 common structure + * @param[in] fp64: Flag indicating whether to set the width to 64 bits (double precision) + * + * @brief Sets the width of all floating-point registers based on the specified flag. + */ +static void mips32_set_all_fpr_width(struct mips32_common *mips32, bool fp64) +{ + struct reg_cache *cache = mips32->core_cache; + struct reg *reg_list = cache->reg_list; + int i; + + for (i = MIPS32_REGLIST_FP_INDEX; i < (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT); i++) { + reg_list[i].size = fp64 ? 64 : 32; + reg_list[i].reg_data_type->type = fp64 ? REG_TYPE_IEEE_DOUBLE : REG_TYPE_IEEE_SINGLE; + } +} + +/** + * mips32_detect_fpr_mode_change - Detect changes in floating-point register mode + * @param[in] mips32: MIPS32 common structure + * @param[in] cp0_status: Value of the CP0 status register + * + * @brief Detects changes in the floating-point register mode based on the CP0 status register. + * If changes are detected, it updates the internal state + * and logs a warning message indicating the mode change. + */ +static void mips32_detect_fpr_mode_change(struct mips32_common *mips32, uint32_t cp0_status) +{ + if (!mips32->fp_imp) + return; + + /* CP0.Status.FR indicates the working mode of floating-point register. + * When FP = 0, fpr can contain any 32bit data type, + * 64bit data types are stored in even-odd register pairs. + * When FP = 1, fpr can contain any data types.*/ + bool fpu_in_64bit = ((cp0_status & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); + + /* CP0.Status.CU1 indicated whether CoProcessor1(which is FPU) is present. */ + bool fp_enabled = ((cp0_status & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + + if (mips32->fpu_in_64bit != fpu_in_64bit) { + mips32->fpu_in_64bit = fpu_in_64bit; + mips32_set_all_fpr_width(mips32, fpu_in_64bit); + LOG_WARNING("** FP mode changed to %sbit, you must reconnect GDB **", fpu_in_64bit ? "64" : "32"); + } + + if (mips32->fpu_enabled != fp_enabled) { + mips32->fpu_enabled = fp_enabled; + const char *s = fp_enabled ? "enabled" : "disabled"; + LOG_WARNING("** FP is %s, register update %s **", s, s); + } +} + static int mips32_read_core_reg(struct target *target, unsigned int num) { unsigned int cnum; @@ -278,6 +333,8 @@ static int mips32_read_core_reg(struct target *target, unsigned int num) cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = mips32->core_regs.cp0[cnum]; buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); + if (cnum == MIPS32_REG_C0_STATUS_INDEX) + mips32_detect_fpr_mode_change(mips32, reg_value); } else if (num >= MIPS32_REGLIST_FPC_INDEX) { /* FPCR */ cnum = num - MIPS32_REGLIST_FPC_INDEX; @@ -319,6 +376,8 @@ static int mips32_write_core_reg(struct target *target, unsigned int num) cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); mips32->core_regs.cp0[cnum] = (uint32_t)reg_value; + if (cnum == MIPS32_REG_C0_STATUS_INDEX) + mips32_detect_fpr_mode_change(mips32, reg_value); } else if (num >= MIPS32_REGLIST_FPC_INDEX) { /* FPCR */ cnum = num - MIPS32_REGLIST_FPC_INDEX; @@ -987,8 +1046,8 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta mips32->fp_imp = MIPS32_FP_IMP_NONE; return ERROR_OK; } - uint32_t status_value; - bool status_fr, status_cu1; + uint32_t fir_value, status_value; + bool fpu_in_64bit, fp_enabled; retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0); if (retval != ERROR_OK) { @@ -996,20 +1055,34 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta return retval; } - status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1; - status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1; - if (status_cu1) { - /* TODO: read fpu(cp1) config register for current operating mode. - * Now its set to 32 bits by default. */ - snprintf(buf, sizeof(buf), "yes"); - fp_imp = MIPS32_FP_IMP_32; + fpu_in_64bit = (status_value & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0; + fp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0; + if (fp_enabled) { + retval = mips32_cp1_control_read(ejtag_info, &fir_value, 0); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read cp1 FIR register"); + return retval; + } + + if ((fir_value >> MIPS32_CP1_FIR_F64_SHIFT) & 0x1) + fp_imp++; } else { + /* This is the only condition that writes to buf */ snprintf(buf, sizeof(buf), "yes, disabled"); fp_imp = MIPS32_FP_IMP_UNKNOWN; } - mips32->fpu_in_64bit = status_fr; - mips32->fpu_enabled = status_cu1; + mips32->fpu_in_64bit = fpu_in_64bit; + mips32->fpu_enabled = fp_enabled; + + mips32_set_all_fpr_width(mips32, fpu_in_64bit); + + /* If fpu is not disabled, print out more information */ + if (!buf[0]) + snprintf(buf, sizeof(buf), "yes, %sbit (%s, working in %sbit)", + fp_imp == MIPS32_FP_IMP_64 ? "64" : "32", + fp_enabled ? "enabled" : "disabled", + fpu_in_64bit ? "64" : "32"); LOG_USER("FPU implemented: %s", buf); mips32->fp_imp = fp_imp; diff --git a/src/target/mips32.h b/src/target/mips32.h index d512e49709..a557f31172 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -459,10 +459,13 @@ struct mips32_algorithm { #define MIPS32_OP_AND 0x24u #define MIPS32_OP_CACHE 0x2Fu #define MIPS32_OP_COP0 0x10u +#define MIPS32_OP_COP1 0x11u #define MIPS32_OP_J 0x02u #define MIPS32_OP_JR 0x08u #define MIPS32_OP_LUI 0x0Fu #define MIPS32_OP_LW 0x23u +#define MIPS32_OP_LWC1 0x31u +#define MIPS32_OP_LDC1 0x35u #define MIPS32_OP_LB 0x20u #define MIPS32_OP_LBU 0x24u #define MIPS32_OP_LHU 0x25u @@ -470,6 +473,7 @@ struct mips32_algorithm { #define MIPS32_OP_MTHI 0x11u #define MIPS32_OP_MFLO 0x12u #define MIPS32_OP_MTLO 0x13u +#define MIPS32_OP_MUL 0x02u #define MIPS32_OP_RDHWR 0x3Bu #define MIPS32_OP_SB 0x28u #define MIPS32_OP_SH 0x29u @@ -485,6 +489,8 @@ struct mips32_algorithm { #define MIPS32_OP_SLLV 0x04u #define MIPS32_OP_SLTI 0x0Au #define MIPS32_OP_MOVN 0x0Bu +#define MIPS32_OP_SWC1 0x39u +#define MIPS32_OP_SDC1 0x3Du #define MIPS32_OP_REGIMM 0x01u #define MIPS32_OP_SDBBP 0x3Fu @@ -517,6 +523,7 @@ struct mips32_algorithm { #define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) #define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) #define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) +#define MIPS32_ISA_CFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_CF, gpr, cpr, 0, 0) #define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) #define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) #define MIPS32_ISA_JRHB(reg) MIPS32_R_INST(0, reg, 0, 0, 0x10, MIPS32_OP_JR) @@ -526,9 +533,15 @@ struct mips32_algorithm { #define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) #define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) #define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) +#define MIPS32_ISA_LWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LWC1, base, reg, off) +#define MIPS32_ISA_LDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LDC1, base, reg, off) #define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MF, gpr, cpr, 0, sel) #define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MT, gpr, cpr, 0, sel) +#define MIPS32_ISA_MFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MF, gpr, cpr, 0, 0) +#define MIPS32_ISA_MFHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MFH, gpr, cpr, 0, 0) +#define MIPS32_ISA_MTC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MT, gpr, cpr, 0, 0) +#define MIPS32_ISA_MTHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MTH, gpr, cpr, 0, 0) #define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) #define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) #define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) @@ -542,6 +555,8 @@ struct mips32_algorithm { #define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) #define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) #define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) +#define MIPS32_ISA_SWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SWC1, base, reg, off) +#define MIPS32_ISA_SDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SDC1, base, reg, off) #define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) #define MIPS32_ISA_SLLV(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLLV) @@ -588,6 +603,7 @@ struct mips32_algorithm { #define MMIPS32_OP_BGTZ 0x06u #define MMIPS32_OP_BNE 0x2Du #define MMIPS32_OP_CACHE 0x06u +#define MMIPS32_OP_CFC1 0x40u #define MMIPS32_OP_J 0x35u #define MMIPS32_OP_JALR 0x03Cu #define MMIPS32_OP_JALRHB 0x07Cu @@ -596,8 +612,14 @@ struct mips32_algorithm { #define MMIPS32_OP_LHU 0x0Du #define MMIPS32_OP_LUI 0x0Du #define MMIPS32_OP_LW 0x3Fu +#define MMIPS32_OP_LWC1 0x27u +#define MMIPS32_OP_LDC1 0x2Fu #define MMIPS32_OP_MFC0 0x03u +#define MMIPS32_OP_MFC1 0x80u +#define MMIPS32_OP_MFHC1 0xC0u #define MMIPS32_OP_MTC0 0x0Bu +#define MMIPS32_OP_MTC1 0xA0u +#define MMIPS32_OP_MTHC1 0xE0u #define MMIPS32_OP_MFLO 0x075u #define MMIPS32_OP_MFHI 0x035u #define MMIPS32_OP_MTLO 0x0F5u @@ -608,6 +630,8 @@ struct mips32_algorithm { #define MMIPS32_OP_SB 0x06u #define MMIPS32_OP_SH 0x0Eu #define MMIPS32_OP_SW 0x3Eu +#define MMIPS32_OP_SWC1 0x26u +#define MMIPS32_OP_SDC1 0x2Eu #define MMIPS32_OP_SLTU 0x390u #define MMIPS32_OP_SLL 0x000u #define MMIPS32_OP_SLTI 0x24u @@ -627,6 +651,7 @@ struct mips32_algorithm { #define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_BGTZ, reg, off) #define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) #define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(MMIPS32_POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) +#define MMIPS32_CFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_CFC1, MMIPS32_POOL32FXF) #define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) #define MMIPS32_JR(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALR, MMIPS32_POOL32AXF) @@ -636,13 +661,19 @@ struct mips32_algorithm { #define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off) #define MMIPS32_LUI(reg, val) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_LUI, reg, val) #define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off) +#define MMIPS32_LWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LWC1, reg, base, off) +#define MMIPS32_LDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LDC1, reg, base, off) #define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ MMIPS32_OP_MFC0, MMIPS32_POOL32AXF) +#define MMIPS32_MFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFC1, MMIPS32_POOL32FXF) +#define MMIPS32_MFHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFHC1, MMIPS32_POOL32FXF) #define MMIPS32_MFLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, MMIPS32_POOL32AXF) #define MMIPS32_MFHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, MMIPS32_POOL32AXF) #define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ MMIPS32_OP_MTC0, MMIPS32_POOL32AXF) +#define MMIPS32_MTC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTC1, MMIPS32_POOL32FXF) +#define MMIPS32_MTHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTHC1, MMIPS32_POOL32FXF) #define MMIPS32_MTLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, MMIPS32_POOL32AXF) #define MMIPS32_MTHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, MMIPS32_POOL32AXF) @@ -653,6 +684,8 @@ struct mips32_algorithm { #define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off) #define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off) #define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off) +#define MMIPS32_SWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SWC1, reg, base, off) +#define MMIPS32_SDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SDC1, reg, base, off) #define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(MMIPS32_POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) #define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) @@ -686,6 +719,7 @@ struct mips32_algorithm { #define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off)) #define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off)) #define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base)) +#define MIPS32_CFC1(isa, gpr, cpr) (isa ? MMIPS32_CFC1(gpr, cpr) : MIPS32_ISA_CFC1(gpr, cpr)) #define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) #define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) @@ -694,10 +728,15 @@ struct mips32_algorithm { #define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) #define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) #define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base)) +#define MIPS32_LWC1(isa, reg, off, base) (isa ? MMIPS32_LWC1(reg, off, base) : MIPS32_ISA_LWC1(reg, off, base)) #define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val)) #define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel)) #define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel)) +#define MIPS32_MFC1(isa, gpr, cpr) (isa ? MMIPS32_MFC1(gpr, cpr) : MIPS32_ISA_MFC1(gpr, cpr)) +#define MIPS32_MFHC1(isa, gpr, cpr) (isa ? MMIPS32_MFHC1(gpr, cpr) : MIPS32_ISA_MFHC1(gpr, cpr)) +#define MIPS32_MTC1(isa, gpr, cpr) (isa ? MMIPS32_MTC1(gpr, cpr) : MIPS32_ISA_MTC1(gpr, cpr)) +#define MIPS32_MTHC1(isa, gpr, cpr) (isa ? MMIPS32_MTHC1(gpr, cpr) : MIPS32_ISA_MTHC1(gpr, cpr)) #define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg)) #define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg)) #define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) @@ -710,6 +749,8 @@ struct mips32_algorithm { #define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base)) #define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base)) #define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) +#define MIPS32_SWC1(isa, reg, off, base) (isa ? MMIPS32_SWC1(reg, off, base) : MIPS32_ISA_SWC1(reg, off, base)) +#define MIPS32_SDC1(isa, reg, off, base) (isa ? MMIPS32_SDC1(reg, off, base) : MIPS32_ISA_SDC1(reg, off, base)) #define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) #define MIPS32_EHB(isa) (isa ? MMIPS32_SLL(0, 0, 3) : MIPS32_ISA_SLL(0, 0, 3)) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 22edf6a410..aaf3875fb7 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -588,6 +588,26 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r return ctx.retval; } +int mips32_cp1_control_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp1_c_reg) +{ + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; + pracc_queue_init(&ctx); + + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, cp1_c_reg)); /* move cp1c reg to $8 */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1); + pracc_queue_free(&ctx); + return ctx.retval; +} + /** * \b mips32_pracc_sync_cache * @@ -856,6 +876,9 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; uint32_t *gprs = mips32->core_regs.gpr; uint32_t *c0rs = mips32->core_regs.cp0; + bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); + bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; pracc_queue_init(&ctx); @@ -895,6 +918,31 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) if (mips32_cpu_support_hazard_barrier(ejtag_info)) pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + + /* store FPRs */ + if (mips32->fp_imp && fp_enabled) { + uint64_t *fprs = mips32->core_regs.fpr; + if (fpu_in_64bit) { + for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) { + uint32_t fp_lo = fprs[i] & 0xffffffff; + uint32_t fp_hi = (fprs[i] >> 32) & 0xffffffff; + pracc_add_li32(&ctx, 2, fp_lo, 0); + pracc_add_li32(&ctx, 3, fp_hi, 0); + pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i)); + pracc_add(&ctx, 0, MIPS32_MTHC1(ctx.isa, 3, i)); + } + } else { + for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) { + uint32_t fp_lo = fprs[i] & 0xffffffff; + pracc_add_li32(&ctx, 2, fp_lo, 0); + pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i)); + } + } + + if (rel > MIPS32_RELEASE_1) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + } + /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, gprs[i], 1); @@ -1014,6 +1062,9 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) struct mips32_core_regs *core_regs = &mips32->core_regs; unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs; unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs; + unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs; + unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs; + bool fp_enabled; /* * This procedure has to be in 2 distinctive steps, because we can @@ -1040,11 +1091,64 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) ejtag_info->reg8 = mips32->core_regs.gpr[8]; ejtag_info->reg9 = mips32->core_regs.gpr[9]; + if (ctx.retval != ERROR_OK) + return ctx.retval; + /* we only care if FP is actually impl'd and if cp1 is enabled */ /* since we already read cp0 in the prev step */ /* now we know what's in cp0.status */ - /* TODO: Read FPRs */ + fp_enabled = (mips32->core_regs.cp0[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0; + if (mips32->fp_imp && fp_enabled) { + pracc_queue_init(&ctx); + mips32_pracc_store_regs_set_base_addr(&ctx); + + /* FCSR */ + pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 31)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr, 1)); + + /* FIR */ + pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 0)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr + 4, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr + 4, 1)); + + /* f0 to f31 */ + if (mips32->fpu_in_64bit) { + for (int i = 0; i != 32; i++) { + size_t offset = offset_fpr + (i * 8); + /* current pracc implementation (or EJTAG itself) only supports 32b access */ + /* so there is no way to use SDC1 */ + + /* lower half */ + pracc_add(&ctx, 0, MIPS32_MFC1(ctx.isa, 8, i)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset, 1)); + + /* upper half */ + pracc_add(&ctx, 0, MIPS32_MFHC1(ctx.isa, 8, i)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset + 4, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset + 4, 1)); + } + } else { + for (int i = 0; i != 32; i++) { + size_t offset = offset_fpr + (i * 8); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset, + MIPS32_SWC1(ctx.isa, i, PRACC_OUT_OFFSET + offset, 1)); + } + } + + mips32_pracc_store_regs_restore(&ctx); + + /* jump to start */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); + /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1); + + pracc_queue_free(&ctx); + } return ctx.retval; } diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 78d087213c..f78f89153f 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -103,6 +103,21 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); +/** + * mips32_cp1_control_read + * + * @brief Simulates cfc1 ASM instruction (Move Control Word From Floating Point), + * i.e. implements copro C1 Control Register read. + * + * @param[in] ejtag_info + * @param[in] val Storage to hold read value + * @param[in] cp1_c_reg Number of copro C1 control register we want to read + * + * @return ERROR_OK on Success, ERROR_FAIL otherwise + */ +int mips32_cp1_control_read(struct mips_ejtag *ejtag_info, + uint32_t *val, uint32_t cp1_c_reg); + static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) { if (ejtag_info->isa && ejtag_info->endianness) From 0c0243228cb958b7c12c2e5a81c84d35734fce25 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Feb 2024 22:55:35 +0100 Subject: [PATCH 0776/1312] gdb_server: add async-notif keep-alive during memory read/write To avoid gdb to timeout, OpenOCD implements a keep-alive mechanism that consists in sending periodically to gdb empty strings embedded in the "O" remote reply packet. The main purpose of "O" packets is to forward in the gdb console the output of the remote execution; the gdb-remote puts in the "O" packet the string that gdb will print. It's use is restricted to few "running/execution" contexts listed in http://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html and this currently limits the keep-alive capabilities of OpenOCD. Long data transfer (memory R/W) can also cause gdb to timeout if the interface is too slow. In this case the usual keep-alive based on "O" packet cannot be used and, if used, would trigger a protocol error that causes the transfer to be dropped. The slow transfer rate can be simulated by adding some delay in the main loop of mem_ap_write() and mem_ap_read(), then using the gdb commands "dump" and "restore". In the wait loop during a memory R/W, gdb drops any extra character received from the gdb-remote that is not recognized as a valid reply to the memory command. Every dropped character re-initializes the timeout counter and could be used as keep-alive. From gdb 7.0 (released 2009-10-06), an asynchronous notification can also be received from gdb-remote during a memory R/W and has the effect to reset the timeout counter, thus can be used as keep-alive. The notification would be treated as "junk" extra characters by any gdb older than 7.0, being still valid as keep-alive. Check putpkt_binary() and getpkt_sane() in gdb commit 74531fed1f2d662debc2c209b8b3faddceb55960 Currently, only one notification packet ("Stop") is recognized by gdb, and gdb documentation reports that notification packets that are not recognized should be silently dropped. Use 'set debug remote 1' in gdb to dump the received notifications and the junk extra characters. Add a new level in enum gdb_output_flag for using the asynchronous notifications. Activate this new level during memory transfers. Send a custom "oocd_keepalive" notification packet as keep_alive. While there, drop a useless return in the switch/case, already managed in case of break. After this commit, the proper calls to keep_alive() have to be added in the loops that code the memory transfers. Of course, the keep_alive() should be placed during the wait for JTAG flush, not while locally queuing the JTAG elementary transfers. Change-Id: I9ca8e78630611597d15984bd0e8634c8fc3c32b9 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8165 Tested-by: jenkins --- src/server/gdb_server.c | 52 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index ae288de1cf..00e43cfe95 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -53,6 +53,8 @@ enum gdb_output_flag { /* GDB doesn't accept 'O' packets */ GDB_OUTPUT_NO, + /* GDB doesn't accept 'O' packets but accepts notifications */ + GDB_OUTPUT_NOTIF, /* GDB accepts 'O' packets */ GDB_OUTPUT_ALL, }; @@ -1486,9 +1488,6 @@ static int gdb_error(struct connection *connection, int retval) return ERROR_OK; } -/* We don't have to worry about the default 2 second timeout for GDB packets, - * because GDB breaks up large memory reads into smaller reads. - */ static int gdb_read_memory_packet(struct connection *connection, char const *packet, int packet_size) { @@ -3477,7 +3476,7 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line, struct connection *connection = priv; struct gdb_connection *gdb_con = connection->priv; - if (gdb_con->output_flag == GDB_OUTPUT_NO) + if (gdb_con->output_flag != GDB_OUTPUT_ALL) /* No out allowed */ return; @@ -3562,10 +3561,14 @@ static int gdb_input_inner(struct connection *connection) retval = gdb_set_register_packet(connection, packet, packet_size); break; case 'm': + gdb_con->output_flag = GDB_OUTPUT_NOTIF; retval = gdb_read_memory_packet(connection, packet, packet_size); + gdb_con->output_flag = GDB_OUTPUT_NO; break; case 'M': + gdb_con->output_flag = GDB_OUTPUT_NOTIF; retval = gdb_write_memory_packet(connection, packet, packet_size); + gdb_con->output_flag = GDB_OUTPUT_NO; break; case 'z': case 'Z': @@ -3656,9 +3659,9 @@ static int gdb_input_inner(struct connection *connection) retval = gdb_detach(connection); break; case 'X': + gdb_con->output_flag = GDB_OUTPUT_NOTIF; retval = gdb_write_memory_binary_packet(connection, packet, packet_size); - if (retval != ERROR_OK) - return retval; + gdb_con->output_flag = GDB_OUTPUT_NO; break; case 'k': if (gdb_con->extended_protocol) { @@ -3754,6 +3757,39 @@ static int gdb_input(struct connection *connection) return ERROR_OK; } +/* + * Send custom notification packet as keep-alive during memory read/write. + * + * From gdb 7.0 (released 2009-10-06) an unknown notification received during + * memory read/write would be silently dropped. + * Before gdb 7.0 any character, with exclusion of "+-$", would be considered + * as junk and ignored. + * In both cases the reception will reset the timeout counter in gdb, thus + * working as a keep-alive. + * Check putpkt_binary() and getpkt_sane() in gdb commit + * 74531fed1f2d662debc2c209b8b3faddceb55960 + * + * Enable remote debug in gdb with 'set debug remote 1' to either dump the junk + * characters in gdb pre-7.0 and the notification from gdb 7.0. + */ +static void gdb_async_notif(struct connection *connection) +{ + static unsigned char count; + unsigned char checksum = 0; + char buf[22]; + + int len = sprintf(buf, "%%oocd_keepalive:%2.2x", count++); + for (int i = 1; i < len; i++) + checksum += buf[i]; + len += sprintf(buf + len, "#%2.2x", checksum); + +#ifdef _DEBUG_GDB_IO_ + LOG_DEBUG("sending packet '%s'", buf); +#endif + + gdb_write(connection, buf, len); +} + static void gdb_keep_client_alive(struct connection *connection) { struct gdb_connection *gdb_con = connection->priv; @@ -3767,6 +3803,10 @@ static void gdb_keep_client_alive(struct connection *connection) case GDB_OUTPUT_NO: /* no need for keep-alive */ break; + case GDB_OUTPUT_NOTIF: + /* send asynchronous notification */ + gdb_async_notif(connection); + break; case GDB_OUTPUT_ALL: /* send an empty O packet */ gdb_output_con(connection, ""); From 35e4c4616f5a924313e85290f56f84f7a8534801 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Feb 2024 23:03:27 +0100 Subject: [PATCH 0777/1312] gdb_server: drop useless check in gdb_keep_client_alive() OpenOCD can send it's log to gdb, and gdb replies with 'OK'. Calls to LOG_XXX() are also present in the code that communicates with gdb. This can cause infinite nested calls. OpenOCD uses the flag 'gdb_con->busy' to protect the communication with gdb and prevent nested calls. There is no reason to check for 'gdb_con->busy' in the code for keep-alive, as keep_alive() is never called in this gdb server; the flag would eventually be set if the current keep_alive() will send something to gdb. Drop the flag 'gdb_con->busy' in gdb_keep_client_alive(). While there, document the use of 'gdb_con->busy'. Change-Id: I1ea20bf96abb5d2f1fcdba1e3861df257c396bb6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8166 Tested-by: jenkins --- src/server/gdb_server.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 00e43cfe95..c1ee4aa2a1 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -73,6 +73,8 @@ struct gdb_connection { enum target_state frontend_state; struct image *vflash_image; bool closed; + /* set to prevent re-entrance from log messages during gdb_get_packet() + * and gdb_put_packet(). */ bool busy; int noack_mode; /* set flag to true if you want the next stepi to return immediately. @@ -3794,11 +3796,6 @@ static void gdb_keep_client_alive(struct connection *connection) { struct gdb_connection *gdb_con = connection->priv; - if (gdb_con->busy) { - /* do not send packets, retry asap */ - return; - } - switch (gdb_con->output_flag) { case GDB_OUTPUT_NO: /* no need for keep-alive */ From a213afad09e50402be8d02298f48757ff4e2e1cf Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Mar 2024 17:53:16 +0100 Subject: [PATCH 0778/1312] helper/list: Replace Linux code with FreeBSD one The file list.h was originally taken from the Linux kernel code, thus under license GPL-2.0-only. This locks OpenOCD to follow the same license, even if the majority of OpenOCD files are licensed as GPL-2.0-or-later. A similar file is also present in FreeBSD code base under the more permissive license BSD-2-Clause. Drop the code from Linux kernel and replace it with the code from FreeBSD 13.3.0. Adapt the code to OpenOCD coding style by fixing the majority of issues identified by checkpatch. Add the OpenOCD specific macros and comments. Unfortunately this causes the lost of all the doxygen comments. Checkpatch-ignore: MACRO_ARG_REUSE, MACRO_ARG_PRECEDENCE Change-Id: I6d86752c50158f3174c4e8c4add81e9998d01e0e Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8172 Tested-by: jenkins --- src/helper/list.h | 934 +++++++++++----------------------------------- 1 file changed, 225 insertions(+), 709 deletions(-) diff --git a/src/helper/list.h b/src/helper/list.h index c9de0569bc..eb8858e74b 100644 --- a/src/helper/list.h +++ b/src/helper/list.h @@ -1,15 +1,31 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ +/* SPDX-License-Identifier: BSD-2-Clause */ /* - * The content of this file is mainly copied/inspired from Linux kernel - * code in include/linux/list.h, include/linux/types.h - * Last aligned with kernel v5.12: - * - skip the functions hlist_unhashed_lockless() and __list_del_clearprev() - * that are relevant only in kernel; - * - Remove non-standard GCC extension "omitted conditional operand" from - * list_prepare_entry; - * - expand READ_ONCE, WRITE_ONCE, smp_load_acquire, smp_store_release; - * - make comments compatible with doxygen. + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. + * Copyright (c) 2021-2024 by Antonio Borneo + * All rights reserved. + */ + +/* + * Circular doubly linked list implementation. + * + * The content of this file is mainly copied/inspired from FreeBSD code in: + * https://cgit.freebsd.org/src/tree/ + * files: + * sys/compat/linuxkpi/common/include/linux/list.h + * sys/compat/linuxkpi/common/include/linux/types.h + * + * Last aligned with release/13.3.0: + * + * - Skip 'hlist_*' double linked lists with a single pointer list head. + * - Expand WRITE_ONCE(). + * - Use TAB for indentation. + * - Put macro arguments within parenthesis. + * - Remove blank lines after an open brace '{'. + * - Remove multiple assignment. * * There is an example of using this file in contrib/list_example.c. */ @@ -17,155 +33,64 @@ #ifndef OPENOCD_HELPER_LIST_H #define OPENOCD_HELPER_LIST_H -/* begin local changes */ -#include +/* begin OpenOCD changes */ -#define LIST_POISON1 NULL -#define LIST_POISON2 NULL +#include struct list_head { - struct list_head *next, *prev; + struct list_head *next; + struct list_head *prev; }; -/* end local changes */ - -/* - * Circular doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ +/* end OpenOCD changes */ #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) -/** - * INIT_LIST_HEAD - Initialize a list_head structure - * @param list list_head structure to be initialized. - * - * Initializes the list_head to point to itself. If it is a list header, - * the result is an empty list. - */ -static inline void INIT_LIST_HEAD(struct list_head *list) +static inline void +INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; } -#ifdef CONFIG_DEBUG_LIST -extern bool __list_add_valid(struct list_head *new, - struct list_head *prev, - struct list_head *next); -extern bool __list_del_entry_valid(struct list_head *entry); -#else -static inline bool __list_add_valid(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - return true; -} -static inline bool __list_del_entry_valid(struct list_head *entry) +static inline int +list_empty(const struct list_head *head) { - return true; + return (head->next == head); } -#endif -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - if (!__list_add_valid(new, prev, next)) - return; - - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @param new new entry to be added - * @param head list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) +static inline int +list_empty_careful(const struct list_head *head) { - __list_add(new, head, head->next); -} - + struct list_head *next = head->next; -/** - * list_add_tail - add a new entry - * @param new new entry to be added - * @param head list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); + return ((next == head) && (next == head->prev)); } -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) +static inline void +__list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } -/* Ignore kernel __list_del_clearprev() */ - -static inline void __list_del_entry(struct list_head *entry) +static inline void +__list_del_entry(struct list_head *entry) { - if (!__list_del_entry_valid(entry)) - return; - __list_del(entry->prev, entry->next); } -/** - * list_del - deletes entry from list. - * @param entry the element to delete from the list. - * Note: list_empty() on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) +static inline void +list_del(struct list_head *entry) { - __list_del_entry(entry); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; + __list_del(entry->prev, entry->next); } -/** - * list_replace - replace old entry by new one - * @param old the element to be replaced - * @param new the new element to insert - * - * If @a old was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, - struct list_head *new) +static inline void +list_replace(struct list_head *old, struct list_head *new) { new->next = old->next; new->next->prev = new; @@ -173,205 +98,189 @@ static inline void list_replace(struct list_head *old, new->prev->next = new; } -/** - * list_replace_init - replace old entry by new one and initialize the old one - * @param old the element to be replaced - * @param new the new element to insert - * - * If @a old was empty, it will be overwritten. - */ -static inline void list_replace_init(struct list_head *old, - struct list_head *new) +static inline void +list_replace_init(struct list_head *old, struct list_head *new) { list_replace(old, new); INIT_LIST_HEAD(old); } -/** - * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position - * @param entry1 the location to place entry2 - * @param entry2 the location to place entry1 - */ -static inline void list_swap(struct list_head *entry1, - struct list_head *entry2) +static inline void +linux_list_add(struct list_head *new, struct list_head *prev, + struct list_head *next) { - struct list_head *pos = entry2->prev; - - list_del(entry2); - list_replace(entry1, entry2); - if (pos == entry1) - pos = entry2; - list_add(entry1, pos); + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; } -/** - * list_del_init - deletes entry from list and reinitialize it. - * @param entry the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) +static inline void +list_del_init(struct list_head *entry) { - __list_del_entry(entry); + list_del(entry); INIT_LIST_HEAD(entry); } -/** - * list_move - delete from one list and add as another's head - * @param list the entry to move - * @param head the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) +#define list_entry(ptr, type, field) container_of(ptr, type, field) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +#define list_first_entry_or_null(ptr, type, member) \ + (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) + +#define list_next_entry(ptr, member) \ + list_entry(((ptr)->member.next), typeof(*(ptr)), member) + +#define list_safe_reset_next(ptr, n, member) \ + (n) = list_next_entry(ptr, member) + +#define list_prev_entry(ptr, member) \ + list_entry(((ptr)->member.prev), typeof(*(ptr)), member) + +#define list_for_each(p, head) \ + for (p = (head)->next; p != (head); p = (p)->next) + +#define list_for_each_safe(p, n, head) \ + for (p = (head)->next, n = (p)->next; p != (head); p = n, n = (p)->next) + +#define list_for_each_entry(p, h, field) \ + for (p = list_entry((h)->next, typeof(*p), field); &(p)->field != (h); \ + p = list_entry((p)->field.next, typeof(*p), field)) + +#define list_for_each_entry_safe(p, n, h, field) \ + for (p = list_entry((h)->next, typeof(*p), field), \ + n = list_entry((p)->field.next, typeof(*p), field); &(p)->field != (h);\ + p = n, n = list_entry(n->field.next, typeof(*n), field)) + +#define list_for_each_entry_from(p, h, field) \ + for ( ; &(p)->field != (h); \ + p = list_entry((p)->field.next, typeof(*p), field)) + +#define list_for_each_entry_continue(p, h, field) \ + for (p = list_next_entry((p), field); &(p)->field != (h); \ + p = list_next_entry((p), field)) + +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry((pos)->member.next, typeof(*pos), member); \ + &(pos)->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +#define list_for_each_entry_reverse(p, h, field) \ + for (p = list_entry((h)->prev, typeof(*p), field); &(p)->field != (h); \ + p = list_entry((p)->field.prev, typeof(*p), field)) + +#define list_for_each_entry_safe_reverse(p, n, h, field) \ + for (p = list_entry((h)->prev, typeof(*p), field), \ + n = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \ + p = n, n = list_entry(n->field.prev, typeof(*n), field)) + +#define list_for_each_entry_continue_reverse(p, h, field) \ + for (p = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \ + p = list_entry((p)->field.prev, typeof(*p), field)) + +#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev) + +#define list_for_each_entry_from_reverse(p, h, field) \ + for (; &p->field != (h); \ + p = list_prev_entry(p, field)) + +static inline void +list_add(struct list_head *new, struct list_head *head) { - __list_del_entry(list); - list_add(list, head); + linux_list_add(new, head, head->next); } -/** - * list_move_tail - delete from one list and add as another's tail - * @param list the entry to move - * @param head the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) +static inline void +list_add_tail(struct list_head *new, struct list_head *head) { - __list_del_entry(list); - list_add_tail(list, head); + linux_list_add(new, head->prev, head); } -/** - * list_bulk_move_tail - move a subsection of a list to its tail - * @param head the head that will follow our entry - * @param first the first entry to move - * @param last the last entry to move, can be the same as first - * - * Move all entries between @a first and including @a last before @a head. - * All three entries must belong to the same linked list. - */ -static inline void list_bulk_move_tail(struct list_head *head, - struct list_head *first, - struct list_head *last) +static inline void +list_move(struct list_head *list, struct list_head *head) { - first->prev->next = last->next; - last->next->prev = first->prev; - - head->prev->next = first; - first->prev = head->prev; - - last->next = head; - head->prev = last; + list_del(list); + list_add(list, head); } -/** - * list_is_first -- tests whether @a list is the first entry in list @a head - * @param list the entry to test - * @param head the head of the list - */ -static inline int list_is_first(const struct list_head *list, const struct list_head *head) +static inline void +list_move_tail(struct list_head *entry, struct list_head *head) { - return list->prev == head; + list_del(entry); + list_add_tail(entry, head); } -/** - * list_is_last - tests whether @a list is the last entry in list @a head - * @param list the entry to test - * @param head the head of the list - */ -static inline int list_is_last(const struct list_head *list, const struct list_head *head) +static inline void +list_rotate_to_front(struct list_head *entry, struct list_head *head) { - return list->next == head; + list_move_tail(entry, head); } -/** - * list_is_head - tests whether @a list is the list @a head - * @param list the entry to test - * @param head the head of the list - */ -static inline int list_is_head(const struct list_head *list, const struct list_head *head) +static inline void +list_bulk_move_tail(struct list_head *head, struct list_head *first, + struct list_head *last) { - return list == head; + first->prev->next = last->next; + last->next->prev = first->prev; + head->prev->next = first; + first->prev = head->prev; + last->next = head; + head->prev = last; } -/** - * list_empty - tests whether a list is empty - * @param head the list to test. - */ -static inline int list_empty(const struct list_head *head) +static inline void +linux_list_splice(const struct list_head *list, struct list_head *prev, + struct list_head *next) { - return head->next == head; + struct list_head *first; + struct list_head *last; + + if (list_empty(list)) + return; + first = list->next; + last = list->prev; + first->prev = prev; + prev->next = first; + last->next = next; + next->prev = last; } -/** - * list_del_init_careful - deletes entry from list and reinitialize it. - * @param entry the element to delete from the list. - * - * This is the same as list_del_init(), except designed to be used - * together with list_empty_careful() in a way to guarantee ordering - * of other memory operations. - * - * Any memory operations done before a list_del_init_careful() are - * guaranteed to be visible after a list_empty_careful() test. - */ -static inline void list_del_init_careful(struct list_head *entry) +static inline void +list_splice(const struct list_head *list, struct list_head *head) { - __list_del_entry(entry); - entry->prev = entry; - entry->next = entry; + linux_list_splice(list, head, head->next); } -/** - * list_empty_careful - tests whether a list is empty and not being modified - * @param head the list to test - * - * Description: - * tests whether a list is empty _and_ checks that no other CPU might be - * in the process of modifying either member (next or prev) - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - */ -static inline int list_empty_careful(const struct list_head *head) +static inline void +list_splice_tail(struct list_head *list, struct list_head *head) { - struct list_head *next = head->next; - return (next == head) && (next == head->prev); + linux_list_splice(list, head->prev, head); } -/** - * list_rotate_left - rotate the list to the left - * @param head the head of the list - */ -static inline void list_rotate_left(struct list_head *head) +static inline void +list_splice_init(struct list_head *list, struct list_head *head) { - struct list_head *first; - - if (!list_empty(head)) { - first = head->next; - list_move_tail(first, head); - } + linux_list_splice(list, head, head->next); + INIT_LIST_HEAD(list); } -/** - * list_rotate_to_front() - Rotate list to specific item. - * @param list The desired new front of the list. - * @param head The head of the list. - * - * Rotates list so that @a list becomes the new front of the list. - */ -static inline void list_rotate_to_front(struct list_head *list, - struct list_head *head) +static inline void +list_splice_tail_init(struct list_head *list, struct list_head *head) { - /* - * Deletes the list head from the list denoted by @a head and - * places it as the tail of @a list, this effectively rotates the - * list so that @a list is at the front. - */ - list_move_tail(head, list); + linux_list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); } -/** - * list_is_singular - tests whether a list has just one entry. - * @param head the list to test. +/* + * Double linked lists with a single pointer list head. + * IGNORED */ + static inline int list_is_singular(const struct list_head *head) { return !list_empty(head) && (head->next == head->prev); @@ -389,472 +298,79 @@ static inline void __list_cut_position(struct list_head *list, new_first->prev = head; } -/** - * list_cut_position - cut a list into two - * @param list a new list to add all removed entries - * @param head a list with entries - * @param entry an entry within head, could be the head itself - * and if so we won't cut the list - * - * This helper moves the initial part of @a head, up to and - * including @a entry, from @a head to @a list. You should - * pass on @a entry an element you know is on @a head. @a list - * should be an empty list or a list you do not care about - * losing its data. - * - */ static inline void list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry) { if (list_empty(head)) return; - if (list_is_singular(head) && !list_is_head(entry, head) && (entry != head->next)) + if (list_is_singular(head) && + (head->next != entry && head != entry)) return; - if (list_is_head(entry, head)) + if (entry == head) INIT_LIST_HEAD(list); else __list_cut_position(list, head, entry); } -/** - * list_cut_before - cut a list into two, before given entry - * @param list a new list to add all removed entries - * @param head a list with entries - * @param entry an entry within head, could be the head itself - * - * This helper moves the initial part of @a head, up to but - * excluding @a entry, from @a head to @a list. You should pass - * in @a entry an element you know is on @a head. @a list should - * be an empty list or a list you do not care about losing - * its data. - * If @a entry == @a head, all entries on @a head are moved to - * @a list. - */ -static inline void list_cut_before(struct list_head *list, - struct list_head *head, - struct list_head *entry) +static inline int list_is_first(const struct list_head *list, + const struct list_head *head) { - if (head->next == entry) { - INIT_LIST_HEAD(list); - return; - } - list->next = head->next; - list->next->prev = list; - list->prev = entry->prev; - list->prev->next = list; - head->next = entry; - entry->prev = head; + return (list->prev == head); } -static inline void __list_splice(const struct list_head *list, - struct list_head *prev, - struct list_head *next) +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) { - struct list_head *first = list->next; - struct list_head *last = list->prev; - - first->prev = prev; - prev->next = first; - - last->next = next; - next->prev = last; -} - -/** - * list_splice - join two lists, this is designed for stacks - * @param list the new list to add. - * @param head the place to add it in the first list. - */ -static inline void list_splice(const struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head, head->next); + return list->next == head; } -/** - * list_splice_tail - join two lists, each list being a queue - * @param list the new list to add. - * @param head the place to add it in the first list. - */ -static inline void list_splice_tail(struct list_head *list, - struct list_head *head) +static inline size_t +list_count_nodes(const struct list_head *list) { - if (!list_empty(list)) - __list_splice(list, head->prev, head); -} + const struct list_head *lh; + size_t count; -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @param list the new list to add. - * @param head the place to add it in the first list. - * - * The list at @a list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head, head->next); - INIT_LIST_HEAD(list); + count = 0; + list_for_each(lh, list) { + count++; } -} -/** - * list_splice_tail_init - join two lists and reinitialise the emptied list - * @param list the new list to add. - * @param head the place to add it in the first list. - * - * Each of the lists is a queue. - * The list at @a list is reinitialised - */ -static inline void list_splice_tail_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head->prev, head); - INIT_LIST_HEAD(list); - } + return (count); } -/** - * list_entry - get the struct for this entry - * @param ptr the &struct list_head pointer. - * @param type the type of the struct this is embedded in. - * @param member the name of the list_head within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_first_entry - get the first element from a list - * @param ptr the list head to take the element from. - * @param type the type of the struct this is embedded in. - * @param member the name of the list_head within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/** - * list_last_entry - get the last element from a list - * @param ptr the list head to take the element from. - * @param type the type of the struct this is embedded in. - * @param member the name of the list_head within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_last_entry(ptr, type, member) \ - list_entry((ptr)->prev, type, member) - -/** - * list_first_entry_or_null - get the first element from a list - * @param ptr the list head to take the element from. - * @param type the type of the struct this is embedded in. - * @param member the name of the list_head within the struct. - * - * Note that if the list is empty, it returns NULL. - */ -#define list_first_entry_or_null(ptr, type, member) ({ \ - struct list_head *head__ = (ptr); \ - struct list_head *pos__ = head__->next; \ - pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ -}) - -/** - * list_next_entry - get the next element in list - * @param pos the type * to cursor - * @param member the name of the list_head within the struct. - */ -#define list_next_entry(pos, member) \ - list_entry((pos)->member.next, typeof(*(pos)), member) - -/** - * list_next_entry_circular - get the next element in list - * @param pos the type * to cursor. - * @param head the list head to take the element from. - * @param member the name of the list_head within the struct. - * - * Wraparound if pos is the last element (return the first element). - * Note, that list is expected to be not empty. - */ -#define list_next_entry_circular(pos, head, member) \ - (list_is_last(&(pos)->member, head) ? \ - list_first_entry(head, typeof(*(pos)), member) : list_next_entry(pos, member)) - -/** - * list_prev_entry - get the prev element in list - * @param pos the type * to cursor - * @param member the name of the list_head within the struct. - */ -#define list_prev_entry(pos, member) \ - list_entry((pos)->member.prev, typeof(*(pos)), member) - -/** - * list_prev_entry_circular - get the prev element in list - * @param pos the type * to cursor. - * @param head the list head to take the element from. - * @param member the name of the list_head within the struct. - * - * Wraparound if pos is the first element (return the last element). - * Note, that list is expected to be not empty. - */ -#define list_prev_entry_circular(pos, head, member) \ - (list_is_first(&(pos)->member, head) ? \ - list_last_entry(head, typeof(*(pos)), member) : list_prev_entry(pos, member)) - -/** - * list_for_each - iterate over a list - * @param pos the &struct list_head to use as a loop cursor. - * @param head the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next) - -/* Ignore kernel list_for_each_rcu() */ - -/** - * list_for_each_continue - continue iteration over a list - * @param pos the &struct list_head to use as a loop cursor. - * @param head the head for your list. - * - * Continue to iterate over a list, continuing after the current position. +/* + * Double linked lists with a single pointer list head. + * IGNORED */ -#define list_for_each_continue(pos, head) \ - for (pos = pos->next; pos != (head); pos = pos->next) -/** - * list_for_each_prev - iterate over a list backwards - * @param pos the &struct list_head to use as a loop cursor. - * @param head the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); pos = pos->prev) +/* begin OpenOCD extensions */ /** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @param pos the &struct list_head to use as a loop cursor. - * @param n another &struct list_head to use as temporary storage - * @param head the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry - * @param pos the &struct list_head to use as a loop cursor. - * @param n another &struct list_head to use as temporary storage - * @param head the head for your list. + * list_for_each_entry_direction - iterate forward/backward over list of given type + * @param is_fwd the iterate direction, true for forward, false for backward. + * @param p the type * to use as a loop cursor. + * @param h the head of the list. + * @param field the name of the list_head within the struct. */ -#define list_for_each_prev_safe(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; \ - pos != (head); \ - pos = n, n = pos->prev) +#define list_for_each_entry_direction(is_fwd, p, h, field) \ + for (p = list_entry(is_fwd ? (h)->next : (h)->prev, typeof(*p), field); \ + &(p)->field != (h); \ + p = list_entry(is_fwd ? (p)->field.next : (p)->field.prev, typeof(*p), field)) /** - * list_count_nodes - count nodes in the list - * @param head the head for your list. + * list_rotate_left - rotate the list to the left + * @param h the head of the list */ -static inline size_t list_count_nodes(struct list_head *head) +static inline void list_rotate_left(struct list_head *h) { - struct list_head *pos; - size_t count = 0; - - list_for_each(pos, head) - count++; + struct list_head *first; - return count; + if (!list_empty(h)) { + first = h->next; + list_move_tail(first, h); + } } -/** - * list_entry_is_head - test if the entry points to the head of the list - * @param pos the type * to cursor - * @param head the head for your list. - * @param member the name of the list_head within the struct. - */ -#define list_entry_is_head(pos, head, member) \ - (&pos->member == (head)) - -/** - * list_for_each_entry - iterate over list of given type - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_first_entry(head, typeof(*pos), member); \ - !list_entry_is_head(pos, head, member); \ - pos = list_next_entry(pos, member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_last_entry(head, typeof(*pos), member); \ - !list_entry_is_head(pos, head, member); \ - pos = list_prev_entry(pos, member)) - -/** - * list_for_each_entry_direction - iterate forward/backward over list of given type - * @param forward the iterate direction, true for forward, false for backward. - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - */ -#define list_for_each_entry_direction(forward, pos, head, member) \ - for (pos = forward ? list_first_entry(head, typeof(*pos), member) \ - : list_last_entry(head, typeof(*pos), member); \ - !list_entry_is_head(pos, head, member); \ - pos = forward ? list_next_entry(pos, member) \ - : list_prev_entry(pos, member)) - -/** - * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() - * @param pos the type * to use as a start point - * @param head the head of the list - * @param member the name of the list_head within the struct. - * - * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? (pos) : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - continue iteration over list of given type - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_next_entry(pos, member); \ - !list_entry_is_head(pos, head, member); \ - pos = list_next_entry(pos, member)) - -/** - * list_for_each_entry_continue_reverse - iterate backwards from the given point - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Start to iterate over list of given type backwards, continuing after - * the current position. - */ -#define list_for_each_entry_continue_reverse(pos, head, member) \ - for (pos = list_prev_entry(pos, member); \ - !list_entry_is_head(pos, head, member); \ - pos = list_prev_entry(pos, member)) - -/** - * list_for_each_entry_from - iterate over list of given type from the current point - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define list_for_each_entry_from(pos, head, member) \ - for (; !list_entry_is_head(pos, head, member); \ - pos = list_next_entry(pos, member)) - -/** - * list_for_each_entry_from_reverse - iterate backwards over list of given type - * from the current point - * @param pos the type * to use as a loop cursor. - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Iterate backwards over list of given type, continuing from current position. - */ -#define list_for_each_entry_from_reverse(pos, head, member) \ - for (; !list_entry_is_head(pos, head, member); \ - pos = list_prev_entry(pos, member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @param pos the type * to use as a loop cursor. - * @param n another type * to use as temporary storage - * @param head the head for your list. - * @param member the name of the list_head within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_first_entry(head, typeof(*pos), member), \ - n = list_next_entry(pos, member); \ - !list_entry_is_head(pos, head, member); \ - pos = n, n = list_next_entry(n, member)) - -/** - * list_for_each_entry_safe_continue - continue list iteration safe against removal - * @param pos the type * to use as a loop cursor. - * @param n another type * to use as temporary storage - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define list_for_each_entry_safe_continue(pos, n, head, member) \ - for (pos = list_next_entry(pos, member), \ - n = list_next_entry(pos, member); \ - !list_entry_is_head(pos, head, member); \ - pos = n, n = list_next_entry(n, member)) - -/** - * list_for_each_entry_safe_from - iterate over list from current point safe against removal - * @param pos the type * to use as a loop cursor. - * @param n another type * to use as temporary storage - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define list_for_each_entry_safe_from(pos, n, head, member) \ - for (n = list_next_entry(pos, member); \ - !list_entry_is_head(pos, head, member); \ - pos = n, n = list_next_entry(n, member)) - -/** - * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal - * @param pos the type * to use as a loop cursor. - * @param n another type * to use as temporary storage - * @param head the head for your list. - * @param member the name of the list_head within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = list_last_entry(head, typeof(*pos), member), \ - n = list_prev_entry(pos, member); \ - !list_entry_is_head(pos, head, member); \ - pos = n, n = list_prev_entry(n, member)) - -/** - * list_safe_reset_next - reset a stale list_for_each_entry_safe loop - * @param pos the loop cursor used in the list_for_each_entry_safe loop - * @param n temporary storage used in list_for_each_entry_safe - * @param member the name of the list_head within the struct. - * - * list_safe_reset_next is not safe to use in general if the list may be - * modified concurrently (eg. the lock is dropped in the loop body). An - * exception to this is if the cursor element (pos) is pinned in the list, - * and list_safe_reset_next is called after re-taking the lock and before - * completing the current iteration of the loop body. - */ -#define list_safe_reset_next(pos, n, member) \ - n = list_next_entry(pos, member) - -/* - * Double linked lists with a single pointer list head. - * IGNORED - */ +/* end OpenOCD extensions */ #endif /* OPENOCD_HELPER_LIST_H */ From c02cf9404dc9dba2a6bc60c4db65c0287168a338 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Mar 2024 18:12:36 +0100 Subject: [PATCH 0779/1312] helper/list: include the correct header file The file 'list.h', copied from FreeBSD, does not depend from any OpenOCD specific include file, but only needs 'stddef.h' for the type 'size_t'. Let 'list.h' to include the correct header file, then fix the now broken dependencies in the other files that were incorrectly relying on 'list.h' to include 'helper/types.h' Change-Id: Idd31b5bf607e226cac44ef41b2aa335ae4dbf519 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8173 Tested-by: jenkins --- src/helper/binarybuffer.h | 3 ++- src/helper/list.h | 2 +- src/target/target.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index a8a5ef8f3f..3446296817 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -11,7 +11,8 @@ #ifndef OPENOCD_HELPER_BINARYBUFFER_H #define OPENOCD_HELPER_BINARYBUFFER_H -#include "list.h" +#include +#include /** @file * Support functions to access arbitrary bits in a byte array diff --git a/src/helper/list.h b/src/helper/list.h index eb8858e74b..47290c2602 100644 --- a/src/helper/list.h +++ b/src/helper/list.h @@ -35,7 +35,7 @@ /* begin OpenOCD changes */ -#include +#include struct list_head { struct list_head *next; diff --git a/src/target/target.h b/src/target/target.h index 1713448ce8..d5c0e0e8c7 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -23,6 +23,7 @@ #include #include "helper/replacements.h" #include "helper/system.h" +#include #include struct reg; From a35e254c5383008cdacf7838a777f7f17af5eeb1 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 16 Feb 2024 17:17:05 +0100 Subject: [PATCH 0780/1312] target/adi_v5_swd: move setting of do_reconnect one level up Move setting of do_reconnect flag from swd_run_inner() to swd_run(). Reconnect is not used at the inner level and the flag had to be cleared after swd_run_inner() to prevent recursion. Signed-off-by: Tomas Vanek Change-Id: Ib1de80bbdf10d1cbfb1dd351c6a5658e50d12af2 Reviewed-on: https://review.openocd.org/c/openocd/+/8155 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/adi_v5_swd.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 67706f35b0..1231005884 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -84,16 +84,8 @@ static void swd_clear_sticky_errors(struct adiv5_dap *dap) static int swd_run_inner(struct adiv5_dap *dap) { const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - int retval; - - retval = swd->run(); - - if (retval != ERROR_OK) { - /* fault response */ - dap->do_reconnect = true; - } - return retval; + return swd->run(); } static inline int check_sync(struct adiv5_dap *dap) @@ -288,15 +280,15 @@ static int swd_multidrop_select(struct adiv5_dap *dap) swd_multidrop_selected_dap = NULL; if (retry > 3) { LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap)); + dap->do_reconnect = true; return retval; } LOG_DEBUG("Failed to select multidrop %s, retrying...", adiv5_dap_name(dap)); - /* we going to retry localy, do not ask for full reconnect */ - dap->do_reconnect = false; } + dap->do_reconnect = false; return retval; } @@ -635,7 +627,13 @@ static int swd_run(struct adiv5_dap *dap) swd_finish_read(dap); - return swd_run_inner(dap); + retval = swd_run_inner(dap); + if (retval != ERROR_OK) { + /* fault response */ + dap->do_reconnect = true; + } + + return retval; } /** Put the SWJ-DP back to JTAG mode */ From dd1758272276e20d5b60c16146a820ec8b5bfaa1 Mon Sep 17 00:00:00 2001 From: Steven Chang Date: Sun, 11 Feb 2024 21:34:50 +0800 Subject: [PATCH 0781/1312] flash/nor/eneispif: support ENE KB1200 ispi flash Change-Id: I03bccceb1956ee121e6a3728b7d647ef1262fa23 Signed-off-by: Steven Chang Reviewed-on: https://review.openocd.org/c/openocd/+/8136 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 18 ++ src/flash/nor/Makefile.am | 1 + src/flash/nor/driver.h | 1 + src/flash/nor/drivers.c | 1 + src/flash/nor/eneispif.c | 433 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 454 insertions(+) create mode 100644 src/flash/nor/eneispif.c diff --git a/doc/openocd.texi b/doc/openocd.texi index 6b71fe869d..52a51c196f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6776,6 +6776,24 @@ Note that in order for this command to take effect, the target needs to be reset supported.} @end deffn +@deffn {Flash Driver} {eneispif} +All versions of the KB1200 microcontrollers from ENE include internal +flash. The eneispif flash driver supports the KB1200 family of devices. The driver +automatically recognizes the specific version's flash parameters and +autoconfigures itself. The flash bank starts at address 0x60000000. An optional additional +parameter sets the address of eneispif controller, with the default address is 0x50101000. + +@example + +flash bank $_FLASHNAME eneispif 0x60000000 0 0 0 $_TARGETNAME \ + 0x50101000 + +# Address defaults to 0x50101000 +flash bank $_FLASHNAME eneispif 0x60000000 0 0 0 $_TARGETNAME + +@end example +@end deffn + @deffn {Flash Driver} {esirisc} Members of the eSi-RISC family may optionally include internal flash programmed via the eSi-TSMC Flash interface. Additional parameters are required to diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 534a7a804e..afa11e7d40 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -28,6 +28,7 @@ NOR_DRIVERS = \ %D%/dsp5680xx_flash.c \ %D%/efm32.c \ %D%/em357.c \ + %D%/eneispif.c \ %D%/esirisc_flash.c \ %D%/faux.c \ %D%/fespi.c \ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index a63b72c8fa..7d6f8c5cc4 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -256,6 +256,7 @@ extern const struct flash_driver cfi_flash; extern const struct flash_driver dsp5680xx_flash; extern const struct flash_driver efm32_flash; extern const struct flash_driver em357_flash; +extern const struct flash_driver eneispif_flash; extern const struct flash_driver esirisc_flash; extern const struct flash_driver faux_flash; extern const struct flash_driver fespi_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 3157bd3292..34359889a6 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -33,6 +33,7 @@ static const struct flash_driver * const flash_drivers[] = { &dsp5680xx_flash, &efm32_flash, &em357_flash, + &eneispif_flash, &esirisc_flash, &faux_flash, &fm3_flash, diff --git a/src/flash/nor/eneispif.c b/src/flash/nor/eneispif.c new file mode 100644 index 0000000000..6572b8c25b --- /dev/null +++ b/src/flash/nor/eneispif.c @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* + * Copyright (c) 2024 ENE Technology Inc. + * steven@ene.com.tw +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#define ISPICFG 0x0000 +#define ISPISTS 0x0004 +#define ISPIADDR 0x0008 +#define ISPICMD 0x000C +#define ISPIDAT 0x0100 + +#define ISPISTS_BUSY BIT(0) +#define STATUS1_QE BIT(1) + +#define CFG_READ 0x372 +#define CFG_WRITE 0x371 + +#define ISPI_CTRL_BASE 0x50101000 + +/* name read qread page erase chip device_id page erase flash + * _cmd _cmd _prog _cmd* _erase size size* size + * _cmd _cmd + */ +struct flash_device ene_flash_device = + FLASH_ID("ISPI flash", 0x03, 0x00, 0x02, 0x20, 0x60, 0x00132085, 0x100, 0x1000, 0x80000); + +struct eneispif_flash_bank { + bool probed; + target_addr_t ctrl_base; + uint32_t dev_id; + const struct flash_device *dev; +}; + +FLASH_BANK_COMMAND_HANDLER(eneispif_flash_bank_command) +{ + struct eneispif_flash_bank *eneispif_info; + + LOG_DEBUG("%s", __func__); + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + eneispif_info = malloc(sizeof(struct eneispif_flash_bank)); + if (!eneispif_info) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + + bank->driver_priv = eneispif_info; + eneispif_info->probed = false; + eneispif_info->ctrl_base = ISPI_CTRL_BASE; + if (CMD_ARGC >= 7) { + COMMAND_PARSE_ADDRESS(CMD_ARGV[6], eneispif_info->ctrl_base); + LOG_INFO("ASSUMING ISPI device at ctrl_base = " TARGET_ADDR_FMT, + eneispif_info->ctrl_base); + } + + return ERROR_OK; +} + +static int eneispif_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address) +{ + struct target *target = bank->target; + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + + int result = target_read_u32(target, eneispif_info->ctrl_base + address, value); + if (result != ERROR_OK) { + LOG_ERROR("%s error at " TARGET_ADDR_FMT, __func__, + eneispif_info->ctrl_base + address); + return result; + } + LOG_DEBUG("Read address " TARGET_ADDR_FMT " = 0x%" PRIx32, + eneispif_info->ctrl_base + address, *value); + return ERROR_OK; +} + +static int eneispif_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value) +{ + struct target *target = bank->target; + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + + LOG_DEBUG("Write address " TARGET_ADDR_FMT " = 0x%" PRIx32, + eneispif_info->ctrl_base + address, value); + int result = target_write_u32(target, eneispif_info->ctrl_base + address, value); + if (result != ERROR_OK) { + LOG_ERROR("%s error writing 0x%" PRIx32 " to " TARGET_ADDR_FMT, __func__, + value, eneispif_info->ctrl_base + address); + return result; + } + return ERROR_OK; +} + +static int eneispif_wait(struct flash_bank *bank) +{ + int64_t start = timeval_ms(); + + while (1) { + uint32_t status; + + if (eneispif_read_reg(bank, &status, ISPISTS) != ERROR_OK) + return ERROR_FAIL; + + if (!(status & ISPISTS_BUSY)) + break; + + int64_t now = timeval_ms(); + if (now - start > 1000) { + LOG_ERROR("Busy more than 1000ms."); + return ERROR_TARGET_TIMEOUT; + } + } + + return ERROR_OK; +} + +static int eneispi_erase_sector(struct flash_bank *bank, int sector) +{ + int retval = ERROR_OK; + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + uint32_t offset; + uint32_t conf; + + retval = eneispif_read_reg(bank, &conf, ISPICFG); + if (retval != ERROR_OK) + return retval; + + offset = bank->sectors[sector].offset; + retval = eneispif_write_reg(bank, ISPIADDR, offset); /* Address */ + if (retval != ERROR_OK) + goto done; + + eneispif_write_reg(bank, ISPICFG, CFG_WRITE); /* Cmmmand enable */ + eneispif_write_reg(bank, ISPICMD, SPIFLASH_WRITE_ENABLE); /* Write enable */ + retval = eneispif_write_reg(bank, ISPICMD, eneispif_info->dev->erase_cmd); /* Erase page */ + if (retval != ERROR_OK) + goto done; + + retval = eneispif_wait(bank); + if (retval != ERROR_OK) + goto done; + +done: + eneispif_write_reg(bank, ISPICFG, conf); /* restore */ + return retval; +} + +static int eneispif_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + struct target *target = bank->target; + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + int retval = ERROR_OK; + + LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (last < first || last >= bank->num_sectors) { + LOG_ERROR("Flash sector invalid"); + return ERROR_FLASH_SECTOR_INVALID; + } + + if (!(eneispif_info->probed)) { + LOG_ERROR("Flash bank not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + for (unsigned int sector = first; sector <= last; sector++) { + if (bank->sectors[sector].is_protected) { + LOG_ERROR("Flash sector %u protected", sector); + return ERROR_FAIL; + } + } + + if (eneispif_info->dev->erase_cmd == 0x00) + return ERROR_FLASH_OPER_UNSUPPORTED; + + for (unsigned int sector = first; sector <= last; sector++) { + retval = eneispi_erase_sector(bank, sector); + if (retval != ERROR_OK) + break; + } + + return retval; +} + +static int eneispif_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) +{ + for (unsigned int sector = first; sector <= last; sector++) + bank->sectors[sector].is_protected = set; + + return ERROR_OK; +} + +static int eneispif_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, + uint32_t count) +{ + struct target *target = bank->target; + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + uint32_t page_size; + uint32_t conf; + int retval = ERROR_OK; + + LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32 " count=0x%08" PRIx32, bank->size, offset, + count); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > eneispif_info->dev->size_in_bytes) { + LOG_WARNING("Write past end of flash. Extra data discarded."); + count = eneispif_info->dev->size_in_bytes - offset; + } + + /* Check sector protection */ + for (unsigned int sector = 0; sector < bank->num_sectors; sector++) { + /* Start offset in or before this sector? */ + /* End offset in or behind this sector? */ + if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && + ((offset + count - 1) >= bank->sectors[sector].offset) && + bank->sectors[sector].is_protected) { + LOG_ERROR("Flash sector %u protected", sector); + return ERROR_FAIL; + } + } + + retval = eneispif_read_reg(bank, &conf, ISPICFG); + if (retval != ERROR_OK) + return retval; + + eneispif_write_reg(bank, ISPICFG, CFG_WRITE); // Cmmmand enable + + /* If no valid page_size, use reasonable default. */ + page_size = + eneispif_info->dev->pagesize ? eneispif_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE; + uint32_t page_offset = offset % page_size; + + while (count > 0) { + uint32_t cur_count; + + /* clip block at page boundary */ + if (page_offset + count > page_size) + cur_count = page_size - page_offset; + else + cur_count = count; + + eneispif_write_reg(bank, ISPICMD, SPIFLASH_WRITE_ENABLE); /* Write enable */ + target_write_buffer(target, eneispif_info->ctrl_base + ISPIDAT, cur_count, buffer); + eneispif_write_reg(bank, ISPIADDR, offset); + retval = eneispif_write_reg(bank, ISPICMD, + (cur_count << 16) | eneispif_info->dev->pprog_cmd); + if (retval != ERROR_OK) + goto err; + + page_offset = 0; + buffer += cur_count; + offset += cur_count; + count -= cur_count; + retval = eneispif_wait(bank); + if (retval != ERROR_OK) + goto err; + } + +err: + eneispif_write_reg(bank, ISPICFG, conf); /* restore */ + return retval; +} + +/* Return ID of flash device */ +/* On exit, SW mode is kept */ +static int eneispif_read_flash_id(struct flash_bank *bank, uint32_t *id) +{ + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + struct target *target = bank->target; + int retval; + uint32_t conf, value; + uint8_t buffer[4]; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = eneispif_read_reg(bank, &conf, ISPICFG); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("ISPCFG = (0x%08" PRIx32 ")", conf); + + /* read ID from Receive Register */ + eneispif_write_reg(bank, ISPICFG, CFG_WRITE); /* Cmmmand enable */ + retval = eneispif_write_reg(bank, ISPICMD, (3 << 16) | SPIFLASH_READ_ID); + if (retval != ERROR_OK) + goto done; + + retval = eneispif_wait(bank); + if (retval != ERROR_OK) + goto done; + + retval = target_read_buffer(target, eneispif_info->ctrl_base + ISPIDAT, 3, buffer); + if (retval != ERROR_OK) + goto done; + value = (buffer[2] << 16) | (buffer[1] << 8) | buffer[0]; + LOG_DEBUG("ISPDAT = (0x%08" PRIx32 ")", value); + + *id = value; +done: + eneispif_write_reg(bank, ISPICFG, conf); // restore + return retval; +} + +static int eneispif_probe(struct flash_bank *bank) +{ + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + struct flash_sector *sectors; + uint32_t id; + int retval; + uint32_t sectorsize; + + if (eneispif_info->probed) + free(bank->sectors); + + eneispif_info->probed = false; + + LOG_INFO("Assuming ISPI flash at address " TARGET_ADDR_FMT + " with controller at " TARGET_ADDR_FMT, + bank->base, eneispif_info->ctrl_base); + + eneispif_write_reg(bank, ISPICFG, CFG_READ); /* RAM map enable */ + + retval = eneispif_read_flash_id(bank, &id); + if (retval != ERROR_OK) + return retval; + + eneispif_info->dev_id = id; + eneispif_info->dev = &ene_flash_device; + + LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", eneispif_info->dev->name, + eneispif_info->dev_id); + + /* Set correct size value */ + bank->size = eneispif_info->dev->size_in_bytes; + + if (bank->size <= (1UL << 16)) + LOG_WARNING("device needs 2-byte addresses - not implemented"); + + /* if no sectors, treat whole bank as single sector */ + sectorsize = eneispif_info->dev->sectorsize ? eneispif_info->dev->sectorsize + : eneispif_info->dev->size_in_bytes; + + /* create and fill sectors array */ + bank->num_sectors = eneispif_info->dev->size_in_bytes / sectorsize; + sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); + if (!sectors) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + + for (unsigned int sector = 0; sector < bank->num_sectors; sector++) { + sectors[sector].offset = sector * sectorsize; + sectors[sector].size = sectorsize; + sectors[sector].is_erased = -1; + sectors[sector].is_protected = 0; + } + + bank->sectors = sectors; + eneispif_info->probed = true; + return ERROR_OK; +} + +static int eneispif_auto_probe(struct flash_bank *bank) +{ + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + if (eneispif_info->probed) + return ERROR_OK; + return eneispif_probe(bank); +} + +static int eneispif_protect_check(struct flash_bank *bank) +{ + /* Nothing to do. Protection is only handled in SW. */ + return ERROR_OK; +} + +static int get_eneispif_info(struct flash_bank *bank, struct command_invocation *cmd) +{ + struct eneispif_flash_bank *eneispif_info = bank->driver_priv; + + if (!(eneispif_info->probed)) { + command_print(cmd, "ENE ISPI flash bank not probed yet."); + return ERROR_OK; + } + + command_print(cmd, + "ENE ISPI flash information:\n" + " Device \'%s\' (ID 0x%08" PRIx32 ")", + eneispif_info->dev->name, eneispif_info->dev_id); + + return ERROR_OK; +} + +const struct flash_driver eneispif_flash = { + .name = "eneispif", + .usage = "flash bank 'eneispif' 0 0 ", + .flash_bank_command = eneispif_flash_bank_command, + .erase = eneispif_erase, + .protect = eneispif_protect, + .write = eneispif_write, + .read = default_flash_read, + .probe = eneispif_probe, + .auto_probe = eneispif_auto_probe, + .erase_check = default_flash_blank_check, + .protect_check = eneispif_protect_check, + .info = get_eneispif_info, + .free_driver_priv = default_flash_free_driver_priv, +}; From 329e983ee9bb24bfa49c59c949d5da250506b7f4 Mon Sep 17 00:00:00 2001 From: Dominik Wernberger Date: Tue, 26 Mar 2024 20:32:22 +0100 Subject: [PATCH 0782/1312] zynq_7000.cfg: Fix issue 'Error: can't read "zynq_pl": no such variable' Change-Id: Ic79ce114b60d0707a6e082a81743b378b164b4e2 Signed-off-by: Dominik Wernberger Reviewed-on: https://review.openocd.org/c/openocd/+/8190 Reviewed-by: Daniel Anselmi Reviewed-by: Tomas Vanek Tested-by: jenkins --- tcl/target/zynq_7000.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcl/target/zynq_7000.cfg b/tcl/target/zynq_7000.cfg index f5b4478ffc..5a88b6e9d5 100644 --- a/tcl/target/zynq_7000.cfg +++ b/tcl/target/zynq_7000.cfg @@ -47,7 +47,7 @@ ${_TARGETNAME}0 configure -event reset-assert-post "cortex_a dbginit" ${_TARGETNAME}1 configure -event reset-assert-post "cortex_a dbginit" pld create zynq_pl.pld virtex2 -chain-position zynq_pl.bs -no_jstart -virtex2 set_user_codes $zynq_pl.pld 0x02 0x03 0x22 0x23 +virtex2 set_user_codes zynq_pl.pld 0x02 0x03 0x22 0x23 set XC7_JSHUTDOWN 0x0d set XC7_JPROGRAM 0x0b From 74e7fcb2dd96c09f946bc8b0f59bfdf6215d8873 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 24 Mar 2024 15:53:33 +0100 Subject: [PATCH 0783/1312] configure: prevent build of linuxgpiod with libgpiod v2 The API in libgpiod v2 have changed, and current driver code for linuxgpiod does not build anymore. Prevent building the current driver linuxgpiod with the new library. Change-Id: Ie673db786dc50ae18a263d2c0a2b46b106866450 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8185 Reviewed-by: Michael Heimpold Tested-by: jenkins Reviewed-by: Tomas Vanek --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c9cf0214e3..fd7b64d150 100644 --- a/configure.ac +++ b/configure.ac @@ -669,7 +669,7 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [ PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) ]) -PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [use_libgpiod=yes], [use_libgpiod=no]) +PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [use_libgpiod=yes], [use_libgpiod=no]) PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], [use_libjaylink=yes], [use_libjaylink=no]) From e035756b22f96adc95b791aaa01de7a2c11d7f2e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 24 Mar 2024 16:17:11 +0100 Subject: [PATCH 0784/1312] jtag: linuxgpiod: fix detection for line request bias Commit 290eac04b93c ("drivers/linuxgpiod: Migrate to adapter gpio commands") introduced an incorrect check to determine if the library libgpiod declares the line request flags: GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN The names above are declared by the library inside an enum, thus cannot be used by the C preprocessor in a #ifdef. Determine in configure if the version of libgpiod provides the line request flags for "bias" and define a C macro. Use the new macro in the driver code. Change-Id: Iaa452230f4753fce4c6e9daa254299cedb7cab7f Signed-off-by: Antonio Borneo Fixes: 290eac04b93c ("drivers/linuxgpiod: Migrate to adapter gpio commands") Reviewed-on: https://review.openocd.org/c/openocd/+/8186 Tested-by: jenkins Reviewed-by: Michael Heimpold --- configure.ac | 6 +++++- src/jtag/drivers/linuxgpiod.c | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index fd7b64d150..7613848371 100644 --- a/configure.ac +++ b/configure.ac @@ -669,7 +669,11 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [ PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) ]) -PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [use_libgpiod=yes], [use_libgpiod=no]) +PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [ + use_libgpiod=yes + PKG_CHECK_EXISTS([libgpiod >= 1.5], + [AC_DEFINE([HAVE_LIBGPIOD1_FLAGS_BIAS], [1], [define if libgpiod v1 has line request flags bias])]) +], [use_libgpiod=no]) PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], [use_libjaylink=yes], [use_libjaylink=no]) diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 9428837883..3ca452357a 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -320,12 +320,12 @@ static int helper_get_line(enum adapter_gpio_config_index idx) switch (adapter_gpio_config[idx].pull) { case ADAPTER_GPIO_PULL_NONE: -#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE +#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE; #endif break; case ADAPTER_GPIO_PULL_UP: -#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP +#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP; #else LOG_WARNING("linuxgpiod: ignoring request for pull-up on %s: not supported by gpiod v%s", @@ -333,7 +333,7 @@ static int helper_get_line(enum adapter_gpio_config_index idx) #endif break; case ADAPTER_GPIO_PULL_DOWN: -#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN +#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN; #else LOG_WARNING("linuxgpiod: ignoring request for pull-down on %s: not supported by gpiod v%s", From 79b51fedab9e8023a2e72551c4dcaf4373274287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Neusch=C3=A4fer?= Date: Sat, 30 Mar 2024 13:18:43 +0100 Subject: [PATCH 0785/1312] remote_bitbang: Change sleep commands to Zz to avoid conflict with SWD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was noticed that the remote_bitbang protocol has a design issue: SWD and sleep commands cannot be implemented at the same time, because they overlap: - SWD uses d,e,f,g for setting pin state - sleep uses d,D for microsecond and millisecond sleep, respectively This has previously been reported by Marek Vrbka, but it wasn't fixed. This commit does the following to resolve the issue: - Change the sleep commands to 'Z' for 1 ms, 'z' for 1 µs - Document 'D' and 'd' as deprecated aliases - Switch the remote_bitbang driver in OpenOCD to 'Z' and 'z' Unfortunately that's a breaking change, because existing adapter-side implementations of the protocol will have to implement the new commands to keep working with future versions of OpenOCD. Fortunately, the remote sleep commands haven't been part of an OpenOCD release yet, which should limit the breakage somewhat. Reported-by: Marek Vrbka Link: https://sourceforge.net/p/openocd/mailman/openocd-devel/thread/670d28d2-75a1-45ec-afe5-541415701d7a%40codasip.com/ Fixes: e8e09b1b5 ("remote_bitbang: add use_remote_sleep option to send delays to remote") Change-Id: I04d2790a33bff9d47eb7f69b3275fd9a271625ae Signed-off-by: J. Neuschäfer Reviewed-on: https://review.openocd.org/c/openocd/+/8191 Reviewed-by: David Ryskalczyk Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Jeremy Herbert --- doc/manual/jtag/drivers/remote_bitbang.txt | 9 +++++++-- src/jtag/drivers/remote_bitbang.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/manual/jtag/drivers/remote_bitbang.txt b/doc/manual/jtag/drivers/remote_bitbang.txt index 94d6038163..8316cb0dd5 100644 --- a/doc/manual/jtag/drivers/remote_bitbang.txt +++ b/doc/manual/jtag/drivers/remote_bitbang.txt @@ -77,7 +77,12 @@ The read responses are encoded in ASCII as either digit 0 or 1. If the use_remote_sleep option is set to 'yes', two additional requests may be sent: - D - Sleep for 1 millisecond - d - Sleep for 1 microsecond + Z - Sleep for 1 millisecond + z - Sleep for 1 microsecond + +NOTE: Previously these were specified as 'D' and 'd', which conflicts with the +"SWD write 0 0" command defined above. Adapters that implement Dd for remote +sleep must be updated to work with Zz. + */ diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index c97b6b6abe..53d2151fdc 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -230,13 +230,13 @@ static int remote_bitbang_sleep(unsigned int microseconds) unsigned int us = microseconds % 1000; for (unsigned int i = 0; i < ms; i++) { - tmp = remote_bitbang_queue('D', NO_FLUSH); + tmp = remote_bitbang_queue('Z', NO_FLUSH); if (tmp != ERROR_OK) return tmp; } for (unsigned int i = 0; i < us; i++) { - tmp = remote_bitbang_queue('d', NO_FLUSH); + tmp = remote_bitbang_queue('z', NO_FLUSH); if (tmp != ERROR_OK) return tmp; } From 47d983a77aeefa511d18450d65e7111799d926a8 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Mon, 18 Mar 2024 17:24:51 +0800 Subject: [PATCH 0786/1312] target/mips32: fix clang sbuild check fail Initialized `value` variables that could only be set in a branch. Change-Id: Iec7413ade9d053c93352a58ff954ad49a6545923 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/8179 Tested-by: jenkins Reviewed-by: Oleksij Rempel Reviewed-by: Antonio Borneo --- src/target/mips32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 6bbf71bd82..81faab72da 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -2109,7 +2109,7 @@ static int mips32_dsp_find_register_by_name(const char *reg_name) */ static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) { - uint32_t value; + uint32_t value = 0; for (int i = 0; i < MIPS32NUMDSPREGS; i++) { int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i); if (retval != ERROR_OK) { @@ -2134,7 +2134,7 @@ static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_e */ static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) { - uint32_t value; + uint32_t value = 0; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); From 04154af5d6cd5fe76a2583778379bdacb5aa6fb0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 24 Mar 2024 22:57:52 +0100 Subject: [PATCH 0787/1312] jtag: linuxgpiod: drop extra parenthesis Checkpatch complains for extra parenthesis not required. Drop them. Change-Id: I311409f5732acf10a4910de5dcf0fb05f43e21b5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8187 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/jtag/drivers/linuxgpiod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 3ca452357a..2f3d644542 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -157,7 +157,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio) int retval; if (!swdio_input) { - if (!last_stored || (swdio != last_swdio)) { + if (!last_stored || swdio != last_swdio) { retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], swdio); if (retval < 0) LOG_WARNING("Fail set swdio"); @@ -165,7 +165,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio) } /* write swclk last */ - if (!last_stored || (swclk != last_swclk)) { + if (!last_stored || swclk != last_swclk) { retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWCLK], swclk); if (retval < 0) LOG_WARNING("Fail set swclk"); From 495311d2067e85ee1fb53593a4671ef0ec09c6f1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 7 Apr 2024 12:41:48 +0200 Subject: [PATCH 0788/1312] doc: style: report indentation of multi-line condition To help readability and discriminate the 'then' block from the multi-line condition, suggest to increase the indentation of the condition. Change-Id: I02e3834be3001e7ecf24349ad3cefe94b27b79c8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8199 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Oleksij Rempel --- doc/manual/style.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/manual/style.txt b/doc/manual/style.txt index 1d3ec6748d..a1e6b8f016 100644 --- a/doc/manual/style.txt +++ b/doc/manual/style.txt @@ -97,6 +97,21 @@ OpenOCD project. x = 0; } @endcode +- on if statements where the condition is split among multiple + lines, increase the indentation of the condition to prevent it to match + to the indentation of the then block due to length of 'if (' + being same of the TAB width of 4 characters. Use: + @code + if (CMD_ARGC < 3 + || CMD_ARGC > 8) + return ERROR_COMMAND_SYNTAX_ERROR; + @endcode + instead of: + @code + if (CMD_ARGC < 3 || + CMD_ARGC > 8) + return ERROR_COMMAND_SYNTAX_ERROR; + @endcode Finally, try to avoid lines of code that are longer than 72-80 columns: From a9e8ca55a6f44cf6edef7ea5ca66927fa02f3cca Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 7 Apr 2024 12:28:55 +0200 Subject: [PATCH 0789/1312] jtag: linuxgpiod: minor alignment to coding style Avoid double TAB in 'then' block by increasing indentation of the multi-line condition. Change-Id: I7f5a4437fe4f74228f1b0d98e5c5921af4fd36b8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8200 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/jtag/drivers/linuxgpiod.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 2f3d644542..1926ed9ae6 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -378,12 +378,12 @@ static int linuxgpiod_init(void) goto out_error; } - if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) - goto out_error; + if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) + goto out_error; } if (transport_is_swd()) { @@ -413,9 +413,9 @@ static int linuxgpiod_init(void) goto out_error; } - if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) - goto out_error; + if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) + goto out_error; return ERROR_OK; From ac6b00c3cae5def9c1b3f08fae68703abc494109 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 6 Apr 2024 00:26:38 +0200 Subject: [PATCH 0790/1312] target: cortex_m: fix display of DWT registers Commit 16b4b8cf5453 ("Cortex-M3: expose most DWT registers") added the DWT registers to the list of CPU registers. The commit message from 2009 reports the reason behind this odd mixing of CPU and DWT registers. This feature got broken in 2017 with the introduction of the field struct reg::exist and its further use in the code. As result, the command 'reg' on a target Cortex-M reports only the core registers and then the header line ===== Cortex-M DWT registers not anymore followed by the DWT registers. Fix it by tagging each DWT registers as existing. Change-Id: Iab026e7da8d6b8ba052514c3fd3b5cdfe301f330 Signed-off-by: Antonio Borneo Fixes: b5964191f0d2 ("register: support non-existent registers") Reviewed-on: https://review.openocd.org/c/openocd/+/8198 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/target/cortex_m.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 4894cabf8b..a26df2e5a2 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2351,6 +2351,7 @@ static void cortex_m_dwt_addreg(struct target *t, struct reg *r, const struct dw r->value = state->value; r->arch_info = state; r->type = &dwt_reg_type; + r->exist = true; } static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target) From 8667a726532604afab099881779a4b898539dabf Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 18 Nov 2023 12:48:33 +0100 Subject: [PATCH 0791/1312] target/target: Add 'debug_reason' to current target Change-Id: Ie35b13b3e06411b4866ffeada47b3262493dbf2e Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8021 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 12 ++++++++++++ src/target/target.c | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 52a51c196f..55e6e76808 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9191,6 +9191,18 @@ read_memory 0x20000000 32 2 @end example @end deffn +@deffn {Command} {debug_reason} +Displays the current debug reason: +@code{debug-request}, +@code{breakpoint}, +@code{watchpoint}, +@code{watchpoint-and-breakpoint}, +@code{single-step}, +@code{target-not-halted}, +@code{program-exit}, +@code{exception-catch} or @code{undefined}. +@end deffn + @deffn {Command} {halt} [ms] @deffnx {Command} {wait_halt} [ms] The @command{halt} command first sends a halt request to the target, diff --git a/src/target/target.c b/src/target/target.c index 45698a66c5..5168305dee 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -6736,6 +6736,13 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, + { + .name = "debug_reason", + .mode = COMMAND_EXEC, + .handler = handle_target_debug_reason, + .help = "displays the debug reason of this target", + .usage = "", + }, { .name = "reset_nag", .handler = handle_target_reset_nag, From 89d881c19ae89712652f17962b8b7d2e79e25ca3 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 8 Apr 2024 17:40:09 +0200 Subject: [PATCH 0792/1312] cortex_m: don't try to halt not-examined targets Prevent a segmentation fault by preventing to try to halt a target that has not been examined yet. Change-Id: I5d344e7fbdb5422f7c5e2c39bdd48cbc6c2a3e58 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8213 Tested-by: jenkins --- src/target/cortex_m.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index a26df2e5a2..c225b1aa9d 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1109,6 +1109,11 @@ static int cortex_m_halt_one(struct target *target) int retval; LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); + if (!target_was_examined(target)) { + LOG_TARGET_ERROR(target, "target non examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } + if (target->state == TARGET_HALTED) { LOG_TARGET_DEBUG(target, "target was already halted"); return ERROR_OK; From 42e31d75b443e369597669b5ff7901de902ad35e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 13 Apr 2024 18:46:11 +0200 Subject: [PATCH 0793/1312] target: aarch64: fix regs invalidation when -defer-examine The code for aarch64 allocates the register cache during the very first examine of the target. To prevent a segmentation fault in assert_reset(), the call to register_cache_invalidate() is guarded by target_was_examined(). But for targets with -defer-examine, the target is set as not examined in handle_target_reset() just before entering in assert_reset(). This causes registers to not be invalidated while reset a target examined but with -defer-examine. Change the condition and invalidate the register cache if it has been already allocated. Change-Id: Ie13abb0ae2cc28fc3295d678c4ad1691024eb7b8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8214 Tested-by: jenkins --- src/target/aarch64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 2e4d0b5c03..6a70b2ddf8 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1983,7 +1983,7 @@ static int aarch64_assert_reset(struct target *target) } /* registers are now invalid */ - if (target_was_examined(target)) { + if (armv8->arm.core_cache) { register_cache_invalidate(armv8->arm.core_cache); register_cache_invalidate(armv8->arm.core_cache->next); } From c72afedce794a7251fd9c822e3bfc89f870b9fc1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 13 Apr 2024 18:54:12 +0200 Subject: [PATCH 0794/1312] target: cortex_a: fix regs invalidation when -defer-examine The code for cortex_a allocates the register cache during the very first examine of the target. To prevent a segmentation fault in assert_reset(), the call to register_cache_invalidate() is guarded by target_was_examined(). But for targets with -defer-examine, the target is set as not examined in handle_target_reset() just before entering in assert_reset(). This causes registers to not be invalidated while reset a target examined but with -defer-examine. Change the condition and invalidate the register cache if it has been already allocated. Change-Id: I81ae782ddce07431d5f2c1bea3e2f19dfcd6d1ce Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8215 Tested-by: jenkins --- src/target/cortex_a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 7fa0c4e8b7..78fd4482c3 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1932,7 +1932,7 @@ static int cortex_a_assert_reset(struct target *target) } /* registers are now invalid */ - if (target_was_examined(target)) + if (armv7a->arm.core_cache) register_cache_invalidate(armv7a->arm.core_cache); target->state = TARGET_RESET; From 3eba7b53bf067508197e2455b81fc1375b1d945e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 15 Apr 2024 17:42:12 +0200 Subject: [PATCH 0795/1312] smp: fix SIGSEGV for "smp off" during target examine The gdb subsystem is initialized after the first target examine, so the field struct target::gdb_service is NULL during examine. A command "smp off" in the examine event handler causes a SIGSEGV during OpenOCD startup. Check for pointer not NULL before dereferencing it. Change-Id: Id115e28be23a957fef1b97ab66d7273f0ea0dce4 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8216 Tested-by: jenkins --- src/target/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/smp.c b/src/target/smp.c index 50b19d01a0..41ca880d43 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -119,7 +119,7 @@ COMMAND_HANDLER(default_handle_smp_command) head->target->smp = 0; /* fixes the target display to the debugger */ - if (!list_empty(target->smp_targets)) + if (!list_empty(target->smp_targets) && target->gdb_service) target->gdb_service->target = target; return ERROR_OK; From a84d1b5f5e2754680c12c1595db9d296eec7d45c Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 22 Feb 2024 12:18:36 -0500 Subject: [PATCH 0796/1312] tcl/target: Add helpers for booting Xilinx ZynqMP from JTAG Add some helpers for booting ZynqMPs over JTAG. Normally, the CSU ROM will load boot.bin from the boot medium. However, when booting from JTAG we have to do this ourselves. There are generally two parts to this. First, we need to load the PMU firmware. Xilinx's tools do this by attaching to the PMU (a Microblaze CPU) over JTAG. However, the TAP is undocumented and we don't have any microblaze support in-tree. So instead we do it the same way FSBL does it: - We ask the PMU to halt - We load the firmware into the PMU RAM - We ask the PMU to resume The second thing we need to do is start one of the APU cores. When an APU is released from reset, it starts executing at the value of its RVBARADDR. While we could load the APU firmware over the AXI target, it is faster to load it over the APU target. To do this, we put the APU into an infinite loop before halting it. As an aside, I chose to use the "APU" terminology as opposed to "core" to make it clear that these commands operate on the A53 cores and not the R5F cores. Typical usage of these commands could look something like targets uscale.axi boot_pmu /path/to/pmu-firmware.bin boot_apu /path/to/u-boot-spl.bin But of course there is always the option to call lower-level commands individually if your boot process is more unusual. Signed-off-by: Sean Anderson Change-Id: I816940c2022ccca0fabb489aa75d682edd0f6138 Reviewed-on: https://review.openocd.org/c/openocd/+/8133 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/xilinx_zynqmp.cfg | 134 +++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/tcl/target/xilinx_zynqmp.cfg b/tcl/target/xilinx_zynqmp.cfg index 9734a18376..e8224be043 100644 --- a/tcl/target/xilinx_zynqmp.cfg +++ b/tcl/target/xilinx_zynqmp.cfg @@ -104,3 +104,137 @@ proc core_up { args } { $_TARGETNAME.$core arp_examine } } + +proc BIT {n} { + return [expr {1 << $n}] +} + +set IPI_BASE 0xff300000 +set IPI_PMU_0_TRIG [expr {$IPI_BASE + 0x30000}] +set IPI_PMU_0_IER [expr {$IPI_BASE + 0x30018}] +set IPI_PMU_0 [BIT 16] + +set CRF_APB_BASE 0xfd1a0000 +set CRF_APB_RST_FPD_APU [expr {$CRF_APB_BASE + 0x104}] +set CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET [BIT 10] +set CRF_APB_RST_FPD_APU_L2_RESET [BIT 8] +set CRF_APB_RST_FPD_APU_ACPU0_RESET [BIT 0] + +set APU_BASE 0xfd5c0000 +set APU_RVBARADDR_BASE [expr {$APU_BASE + 0x40}] + +set PMU_BASE 0xffd80000 +set PMU_GLOBAL $PMU_BASE +set PMU_GLOBAL_MB_SLEEP [BIT 16] +set PMU_GLOBAL_FW_IS_PRESENT [BIT 4] +set PMU_GLOBAL_DONT_SLEEP [BIT 0] + +set PMU_RAM_BASE 0xffdc0000 + +set OCM_RAM_BASE 0xfffc0000 + +rename BIT {} + +add_help_text halt_pmu "Halt the PMU in preparation for loading new firmware.\ + This should be matched with a call to resume_pmu." +proc halt_pmu {} { + set axi $::_CHIPNAME.axi + set val [$axi read_memory $::IPI_PMU_0_IER 32 1] + $axi write_memory $::IPI_PMU_0_IER 32 [expr {$val | $::IPI_PMU_0}] + + set val [$axi read_memory $::IPI_PMU_0_TRIG 32 1] + $axi write_memory $::IPI_PMU_0_TRIG 32 [expr {$val | $::IPI_PMU_0}] + + set start [ms] + while {!([$axi read_memory $::PMU_GLOBAL 32 1] & $::PMU_GLOBAL_MB_SLEEP)} { + if {[ms] - $start > 1000} { + error "Timed out waiting for PMU to halt" + } + } +} + +add_help_text resume_pmu "Resume the PMU after loading new firmware. This\ + should be matched with a call to halt_pmu." +proc resume_pmu {} { + set axi $::_CHIPNAME.axi + set val [$axi read_memory $::PMU_GLOBAL 32 1] + $axi write_memory $::PMU_GLOBAL 32 [expr {$val | $::PMU_GLOBAL_DONT_SLEEP}] + + set start [ms] + while {!([$axi read_memory $::PMU_GLOBAL 32 1] & $::PMU_GLOBAL_FW_IS_PRESENT)} { + if {[ms] - $start > 5000} { + error "Timed out waiting for PMU firmware" + } + } +} + +add_usage_text release_apu {apu} +add_help_text release_apu "Release an APU from reset. It will start executing\ + at RVBARADDR. You probably want resume_apu or start_apu instead." +proc release_apu {apu} { + set axi $::_CHIPNAME.axi + set val [$axi read_memory $::CRF_APB_RST_FPD_APU 32 1] + set mask [expr { + (($::CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET | \ + $::CRF_APB_RST_FPD_APU_ACPU0_RESET) << $apu) | \ + $::CRF_APB_RST_FPD_APU_L2_RESET + }] + $axi write_memory $::CRF_APB_RST_FPD_APU 32 [expr {$val & ~$mask}] + + core_up $apu + $::_TARGETNAME.$apu aarch64 dbginit +} + +proc _rvbaraddr {apu} { + return [expr {$::APU_RVBARADDR_BASE + 8 * $apu}] +} + +add_usage_text resume_apu {apu addr} +add_help_text resume_apu "Resume an APU at a given address." +proc resume_apu {apu addr} { + set addrl [expr {$addr & 0xffffffff}] + set addrh [expr {$addr >> 32}] + $::_CHIPNAME.axi write_memory [_rvbaraddr $apu] 32 [list $addrl $addrh] + + release_apu $apu +} + +add_usage_text start_apu {apu} +add_help_text start_apu "Start an APU and put it into an infinite loop at\ + RVBARADDR. This can be convenient if you just want to halt the APU\ + (since it won't execute anything unusual)." +proc start_apu {apu} { + set axi $::_CHIPNAME.axi + foreach {addrl addrh} [$axi read_memory [_rvbaraddr $apu] 32 2] { + set addr [expr {($addrh << 32) | $addrl}] + } + # write the infinite loop instruction + $axi write_memory $addr 32 0x14000000 + + release_apu $apu +} + +add_usage_text boot_pmu {image} +add_help_text boot_pmu "Boot the PMU with a given firmware image, loading it\ + to the beginning of PMU RAM. The PMU ROM will jump to this location\ + after we resume it." +proc boot_pmu {image} { + halt_pmu + echo "Info : Loading PMU firmware $image to $::PMU_RAM_BASE" + load_image $image $::PMU_RAM_BASE + resume_pmu +} + +add_usage_text boot_apu "image \[apu=0 \[addr=$OCM_RAM_BASE\]\]" +add_help_text boot_apu "Boot an APU with a given firmware image. The default\ + address is the beginning of OCM RAM. Upon success, the default target\ + will be changed to the (running) apu." +proc boot_apu [list image {apu 0} [list addr $OCM_RAM_BASE]] { + start_apu $apu + targets $::_TARGETNAME.$apu + halt + + echo "Info : Loading APU$apu firmware $image to $addr" + load_image $image $addr + resume $addr +} From bc9ca5f4a82ccbbdbe07108a83f7979b53e89889 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sun, 17 Mar 2024 01:15:16 +0100 Subject: [PATCH 0797/1312] ipdbg: fix double free of virtual-ir data Fix possible double free and possible memory leak while creating an ipdbg hub. Change-Id: I6254663c27c4f38d46008c4dbff11aa27b84f399 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/8085 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/ipdbg.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index e7eb96e13c..859fdb035e 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -285,6 +285,7 @@ static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct { struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub)); if (!new_hub) { + free(virtual_ir); LOG_ERROR("Out of memory"); return NULL; } @@ -292,6 +293,7 @@ static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct new_hub->name = strdup(name); if (!new_hub->name) { free(new_hub); + free(virtual_ir); LOG_ERROR("Out of memory"); return NULL; } @@ -304,8 +306,10 @@ static struct ipdbg_hub *ipdbg_allocate_hub(uint8_t data_register_length, struct new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field)); new_hub->connections = calloc(max_tools, sizeof(struct connection *)); - if (virtual_ir) + if (virtual_ir) { + new_hub->virtual_ir = virtual_ir; new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8)); + } if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals || !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) || @@ -997,7 +1001,6 @@ static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uin new_hub->xoff_mask = BIT(data_register_length - 2); new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8; new_hub->last_dn_tool = new_hub->tool_mask; - new_hub->virtual_ir = virtual_ir; new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length); new_hub->using_queue_size = IPDBG_SCRATCH_MEMORY_SIZE; @@ -1123,11 +1126,7 @@ COMMAND_HANDLER(handle_ipdbg_create_hub_command) return ERROR_FAIL; } - int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd); - if (retval != ERROR_OK) - free(virtual_ir); - - return retval; + return ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, hub_name, cmd); } static const struct command_registration ipdbg_config_command_handlers[] = { From dbef02789fb1f30ae77020754b1468549fd16510 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 2 May 2024 15:24:57 +0200 Subject: [PATCH 0798/1312] cortex_a: drop useless cache invalidate on mem write The initial OpenOCD code for Cortex-A (ARMv7a) [1] was merged in 2009 but, due to lack of public documentation for ARMv7a, it was almost a simple copy/paste from the existing code for Cortex-M (ARMv7m). On Cortex-M the same AP provides access to both CPU debug and CPU memory. This feature is not present on ARMv7a. To still keep some communality with ARMv7m code, the change [2] splits the CPU debug access from the CPU memory access by using two independent AP; this is copied from the system architecture of TI OMAP3530 which provides to DAP a direct AHB-AP memory bus on AP#0, separated from AP#1 for the APB-AP CPU debug. But the direct memory access through the system bus breaks the coherency between memory and CPU caches, so change [3] added some cache invalidation to avoid issues. The code to allow ARMv7a CPU to really read/write in CPU memory was added by change [4] in 2011. Such still not optimized implementation was very slow, so it did not replace the access through the system bus. A selection through DAP's 'apsel" command was used to select between the two modes. Only in 2015, with change [5], the speed of CPU read/write was improved using the DCC_FAST_MODE. But the direct access to the memory through the system bus remained. Finally, with change [6] in 2018 the system bus access was dropped for good, as the new virtual target "mem_ap" could implement such access in a more clean way. Only memory access through CPU remained for ARMv7a. Nevertheless, a useless cache invalidation remained in the code, decreasing the speed of the write access. Drop the useless cache invalidate on CPU memory write and the associated comment, not anymore valid. Drop the now unused function armv7a_cache_auto_flush_on_write(). This provides a speedup of between 4 and 8, depending on adapter and JTAG/SWD speed. Link: [1] 7a93100c2dfe ("Add minimalist Cortex A8 file") Link: [2] 1d0b276c9f75 ("The rest of the Cortex-A8 support from Magnus: ...") Link: [3] d4e4d65d284f ("Cache invalidation when writing to memory") Link: [4] 05ab8bdb813a ("cortex_a9: implement read/write memory through APB-AP") Link: [5] 0228f8e8274d ("Cortex A: fix extra memory read and non-word sizes") Link: [6] fac9be64d944 ("target/cortex_a: remove buggy memory AP accesses") Change-Id: Ifa3c7ddf2698b2c87037fb48f783844034a7140e Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8229 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/target/armv7a_cache.c | 21 --------------------- src/target/armv7a_cache.h | 2 -- src/target/cortex_a.c | 3 --- 3 files changed, 26 deletions(-) diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index e1f0dfafb0..681c06affc 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -391,27 +391,6 @@ int armv7a_cache_flush_virt(struct target *target, uint32_t virt, return ERROR_OK; } -/* - * We assume that target core was chosen correctly. It means if same data - * was handled by two cores, other core will loose the changes. Since it - * is impossible to know (FIXME) which core has correct data, keep in mind - * that some kind of data lost or corruption is possible. - * Possible scenario: - * - core1 loaded and changed data on 0x12345678 - * - we halted target and modified same data on core0 - * - data on core1 will be lost. - */ -int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt, - uint32_t size) -{ - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) - return ERROR_OK; - - return armv7a_cache_flush_virt(target, virt, size); -} - COMMAND_HANDLER(arm7a_l1_cache_info_cmd) { struct target *target = get_current_target(CMD_CTX); diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h index 17ec5e6de1..3e3eae55c5 100644 --- a/src/target/armv7a_cache.h +++ b/src/target/armv7a_cache.h @@ -20,8 +20,6 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, int armv7a_l1_i_cache_inval_all(struct target *target); int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, uint32_t size); -int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt, - uint32_t size); int armv7a_cache_auto_flush_all_data(struct target *target); int armv7a_cache_flush_virt(struct target *target, uint32_t virt, uint32_t size); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 78fd4482c3..f90c02a958 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2791,9 +2791,6 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address, LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32, address, size, count); - /* memory writes bypass the caches, must flush before writing */ - armv7a_cache_auto_flush_on_write(target, address, size * count); - cortex_a_prep_memaccess(target, 0); retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); cortex_a_post_memaccess(target, 0); From caabdd4a6627a86be43cd91e09f127173eb9e692 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 May 2024 20:09:51 +0200 Subject: [PATCH 0799/1312] cortex_a: drop the command 'cache auto' The command 'cache auto' was introduced with commit cd440bd32a12 ("add armv7a_cache handlers") in 2015 to allow disabling the cache handling done automatically by OpenOCD. This was probably a way to test the cache handling when there were still the two independent accesses for APB-AP CPU debug and for AHB-AP memory bus. The handling of cache for cortex_a is robust and there is no more reason to disable it. The command 'cache auto' is not used in any upstream script. On target aarch64 this command has never been introduced as the cache is always handled automatically by OpenOCD. Drop the command 'cache auto' and add it in the deprecated list. Drop the flag 'auto_cache_enabled' by considering it as true. Rename the function 'armv7a_cache_auto_flush_all_data()' as 'armv7a_cache_flush_all_data()' and, while there, fix the error propagation in SMP case. Change-Id: I0399f1081b08c4929e0795b76f4a686630f41d56 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8230 Tested-by: jenkins Reviewed-by: Oleksij Rempel --- src/target/armv7a.c | 3 +-- src/target/armv7a.h | 2 -- src/target/armv7a_cache.c | 42 ++++++--------------------------------- src/target/armv7a_cache.h | 2 +- src/target/cortex_a.c | 8 ++------ src/target/startup.tcl | 22 ++++++++++++++++++++ 6 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 82f4be5a0b..dc3752e0b0 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -473,7 +473,7 @@ int armv7a_identify_cache(struct target *target) /* if no l2 cache initialize l1 data cache flush function function */ if (!armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache) { armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = - armv7a_cache_auto_flush_all_data; + armv7a_cache_flush_all_data; } armv7a->armv7a_mmu.armv7a_cache.info = 1; @@ -525,7 +525,6 @@ int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) armv7a->armv7a_mmu.armv7a_cache.info = -1; armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL; armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL; - armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1; return ERROR_OK; } diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 6b9c2a68f4..8943f1c697 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -65,8 +65,6 @@ struct armv7a_cache_common { struct armv7a_arch_cache arch[6]; /* cache info, L1 - L7 */ int i_cache_enabled; int d_u_cache_enabled; - int auto_cache_enabled; /* openocd automatic - * cache handling */ /* outer unified cache if some */ void *outer_cache; int (*flush_all_data_cache)(struct target *target); diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 681c06affc..f2f1097c5a 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -118,20 +118,19 @@ static int armv7a_l1_d_cache_clean_inval_all(struct target *target) return retval; } -int armv7a_cache_auto_flush_all_data(struct target *target) +int armv7a_cache_flush_all_data(struct target *target) { int retval = ERROR_FAIL; - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) - return ERROR_OK; if (target->smp) { struct target_list *head; foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - if (curr->state == TARGET_HALTED) - retval = armv7a_l1_d_cache_clean_inval_all(curr); + if (curr->state == TARGET_HALTED) { + int retval1 = armv7a_l1_d_cache_clean_inval_all(curr); + if (retval1 != ERROR_OK) + retval = retval1; + } } } else retval = armv7a_l1_d_cache_clean_inval_all(target); @@ -472,28 +471,6 @@ COMMAND_HANDLER(arm7a_l1_i_cache_inval_virt_cmd) return armv7a_l1_i_cache_inval_virt(target, virt, size); } -COMMAND_HANDLER(arm7a_cache_disable_auto_cmd) -{ - struct target *target = get_current_target(CMD_CTX); - struct armv7a_common *armv7a = target_to_armv7a(target); - - if (CMD_ARGC == 0) { - command_print(CMD, "auto cache is %s", - armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled ? "enabled" : "disabled"); - return ERROR_OK; - } - - if (CMD_ARGC == 1) { - uint32_t set; - - COMMAND_PARSE_ENABLE(CMD_ARGV[0], set); - armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = !!set; - return ERROR_OK; - } - - return ERROR_COMMAND_SYNTAX_ERROR; -} - static const struct command_registration arm7a_l1_d_cache_commands[] = { { .name = "flush_all", @@ -563,13 +540,6 @@ static const struct command_registration arm7a_l1_di_cache_group_handlers[] = { }; static const struct command_registration arm7a_cache_group_handlers[] = { - { - .name = "auto", - .handler = arm7a_cache_disable_auto_cmd, - .mode = COMMAND_ANY, - .help = "disable or enable automatic cache handling.", - .usage = "(1|0)", - }, { .name = "l1", .mode = COMMAND_ANY, diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h index 3e3eae55c5..c4637c5d30 100644 --- a/src/target/armv7a_cache.h +++ b/src/target/armv7a_cache.h @@ -20,7 +20,7 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, int armv7a_l1_i_cache_inval_all(struct target *target); int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, uint32_t size); -int armv7a_cache_auto_flush_all_data(struct target *target); +int armv7a_cache_flush_all_data(struct target *target); int armv7a_cache_flush_virt(struct target *target, uint32_t virt, uint32_t size); extern const struct command_registration arm7a_cache_command_handlers[]; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index f90c02a958..a235404632 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1362,10 +1362,8 @@ static int cortex_a_set_breakpoint(struct target *target, return retval; /* make sure data cache is cleaned & invalidated down to PoC */ - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) { - armv7a_cache_flush_virt(target, breakpoint->address, + armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length); - } retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, @@ -1600,10 +1598,8 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b } else { /* make sure data cache is cleaned & invalidated down to PoC */ - if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) { - armv7a_cache_flush_virt(target, breakpoint->address, + armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length); - } /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { diff --git a/src/target/startup.tcl b/src/target/startup.tcl index 75e0edc77d..e9646097f0 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -294,3 +294,25 @@ proc "mips_m4k smp_off" {args} { echo "DEPRECATED! use 'mips_m4k smp off' not 'mips_m4k smp_off'" eval mips_m4k smp off $args } + +lappend _telnet_autocomplete_skip _post_init_target_cortex_a_cache_auto +proc _post_init_target_cortex_a_cache_auto {} { + set cortex_a_found 0 + + foreach t [target names] { + if { [$t cget -type] != "cortex_a" } { continue } + set cortex_a_found 1 + lappend ::_telnet_autocomplete_skip "$t cache auto" + proc "$t cache auto" { enable } { + echo "DEPRECATED! Don't use anymore '[dict get [info frame 0] proc] $enable' as it's always enabled" + } + } + + if { $cortex_a_found } { + lappend ::_telnet_autocomplete_skip "cache auto" + proc "cache auto" { enable } { + echo "DEPRECATED! Don't use anymore 'cache auto $enable' as it's always enabled" + } + } +} +lappend post_init_commands _post_init_target_cortex_a_cache_auto From 126d8a0972ab6031588eb2f0e1fc3957bd3ccc6b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 May 2024 19:13:51 +0200 Subject: [PATCH 0800/1312] cortex_a: drop cortex_a_dap_write_memap_register_u32() Historically, the function cortex_a_dap_write_memap_register_u32() was used to discriminate the register write in APB-AP CPU debug against the complex memory access in AHB-AP memory bus. It has no sense to keep the function and its comment. Plus, by forcing atomic write it impacts the debug performance. Drop it! A further rework to enqueue sequence of atomic writes is needed. Change-Id: I2f5e9015f0e27fa5a6d8337a1ae25e753e2e1d26 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8231 Reviewed-by: Oleksij Rempel Tested-by: jenkins --- src/target/cortex_a.c | 91 +++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index a235404632..2de77c9602 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -314,19 +314,6 @@ static int cortex_a_exec_opcode(struct target *target, return retval; } -/* Write to memory mapped registers directly with no cache or mmu handling */ -static int cortex_a_dap_write_memap_register_u32(struct target *target, - uint32_t address, - uint32_t value) -{ - int retval; - struct armv7a_common *armv7a = target_to_armv7a(target); - - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value); - - return retval; -} - /* * Cortex-A implementation of Debug Programmer's Model * @@ -611,11 +598,11 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, LOG_DEBUG("A: bpwp enable, vr %08x cr %08x", (unsigned) vr, (unsigned) cr); - retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target, + retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, vr, addr); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target, + retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, control); return retval; } @@ -641,7 +628,7 @@ static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); /* clear control register */ - return cortex_a_dap_write_memap_register_u32(dpm->arm->target, cr, 0); + return mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, 0); } static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr) @@ -1323,13 +1310,13 @@ static int cortex_a_set_breakpoint(struct target *target, brp_list[brp_i].used = true; brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_i].control = control; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1415,13 +1402,13 @@ static int cortex_a_set_context_breakpoint(struct target *target, brp_list[brp_i].used = true; brp_list[brp_i].value = (breakpoint->asid); brp_list[brp_i].control = control; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1481,13 +1468,13 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi brp_list[brp_1].used = true; brp_list[brp_1].value = (breakpoint->asid); brp_list[brp_1].control = control_ctx; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].brpn, brp_list[brp_1].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].brpn, brp_list[brp_1].control); if (retval != ERROR_OK) return retval; @@ -1499,13 +1486,13 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi brp_list[brp_2].used = true; brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_2].control = control_iva; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].brpn, brp_list[brp_2].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].brpn, brp_list[brp_2].control); if (retval != ERROR_OK) return retval; @@ -1538,13 +1525,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_i].used = false; brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; @@ -1557,13 +1544,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_j].used = false; brp_list[brp_j].value = 0; brp_list[brp_j].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].brpn, brp_list[brp_j].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].brpn, brp_list[brp_j].value); if (retval != ERROR_OK) return retval; @@ -1582,13 +1569,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_i].used = false; brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].brpn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; @@ -1783,14 +1770,14 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat wrp_list[wrp_i].value = address; wrp_list[wrp_i].control = control; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].value); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].control); if (retval != ERROR_OK) return retval; @@ -1832,13 +1819,13 @@ static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *w wrp_list[wrp_i].used = false; wrp_list[wrp_i].value = 0; wrp_list[wrp_i].control = 0; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].control); if (retval != ERROR_OK) return retval; - retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base - + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].wrpn, wrp_list[wrp_i].value); if (retval != ERROR_OK) return retval; From 22ddf62d759b10a89e9c4c3f3929a66c9d72572d Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Fri, 3 May 2024 00:28:33 +0300 Subject: [PATCH 0801/1312] gdb_server: enable keep-alive packets for qCRC packet Change-Id: Ia384179bb83ad6b70bf385cc9d575e9ec58f76c7 Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8227 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index c1ee4aa2a1..dfd7cd5201 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2845,7 +2845,9 @@ static int gdb_query_packet(struct connection *connection, len = strtoul(separator + 1, NULL, 16); + gdb_connection->output_flag = GDB_OUTPUT_NOTIF; retval = target_checksum_memory(target, addr, len, &checksum); + gdb_connection->output_flag = GDB_OUTPUT_NO; if (retval == ERROR_OK) { snprintf(gdb_reply, 10, "C%8.8" PRIx32 "", checksum); From 2c8376b79d104a855bd3a559e59edf330309bcad Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Wed, 31 Jan 2024 15:14:25 -0800 Subject: [PATCH 0802/1312] target/xtensa: avoid IHI for writes to non-executable memory For MPU configs, determine memory access rights by probing protection TLB. Issuing IHI without execute permissions can trigger an exception. No new clang static analyzer warnings. Change-Id: Iea8eab5c2113df3f954285c3b9a79e96d41aa941 Signed-off-by: Ian Thompson Reviewed-on: https://review.openocd.org/c/openocd/+/8080 Reviewed-by: Erhan Kurubas Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/xtensa/xtensa.c | 89 ++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index fb7748aa2d..f7c82efed4 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -158,6 +158,12 @@ #define XT_INS_RFWU(X) (XT_ISBE(X) ? 0x005300 << 8 : 0x003500) #define XT_INS_RFWO_RFWU_MASK(X) (XT_ISBE(X) ? 0xFFFFFF << 8 : 0xFFFFFF) +/* Read Protection TLB Entry Info */ +#define XT_INS_PPTLB(X, S, T) _XT_INS_FORMAT_RRR(X, 0x500000, ((S) << 4) | (T), 0xD) + +#define XT_TLB1_ACC_SHIFT 8 +#define XT_TLB1_ACC_MSK 0xF + #define XT_WATCHPOINTS_NUM_MAX 2 /* Special register number macro for DDR, PS, WB, A3, A4 registers. @@ -298,6 +304,27 @@ enum xtensa_mem_region_type { XTENSA_MEM_REGS_NUM }; +/** + * Types of access rights for MPU option + * The first block is kernel RWX ARs; the second block is user rwx ARs. + */ +enum xtensa_mpu_access_type { + XTENSA_ACC_00X_000 = 0x2, + XTENSA_ACC_000_00X, + XTENSA_ACC_R00_000, + XTENSA_ACC_R0X_000, + XTENSA_ACC_RW0_000, + XTENSA_ACC_RWX_000, + XTENSA_ACC_0W0_0W0, + XTENSA_ACC_RW0_RWX, + XTENSA_ACC_RW0_R00, + XTENSA_ACC_RWX_R0X, + XTENSA_ACC_R00_R00, + XTENSA_ACC_R0X_R0X, + XTENSA_ACC_RW0_RW0, + XTENSA_ACC_RWX_RWX +}; + /* Register definition as union for list allocation */ union xtensa_reg_val_u { xtensa_reg_val_t val; @@ -521,6 +548,44 @@ static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint } } +/* NOTE: Assumes A3 has already been saved and marked dirty; A3 will be clobbered */ +static inline bool xtensa_region_ar_exec(struct target *target, target_addr_t start, target_addr_t end) +{ + struct xtensa *xtensa = target_to_xtensa(target); + if (xtensa->core_config->mpu.enabled) { + /* For cores with the MPU option, issue PPTLB on start and end addresses. + * Parse access rights field, and confirm both have execute permissions. + */ + for (int i = 0; i <= 1; i++) { + uint32_t at, acc; + uint8_t at_buf[4]; + bool exec_acc; + target_addr_t addr = i ? end : start; + xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, addr); + xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3)); + xtensa_queue_exec_ins(xtensa, XT_INS_PPTLB(xtensa, XT_REG_A3, XT_REG_A3)); + xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A3)); + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, at_buf); + int res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) + LOG_TARGET_ERROR(target, "Error queuing PPTLB: %d", res); + res = xtensa_core_status_check(target); + if (res != ERROR_OK) + LOG_TARGET_ERROR(target, "Error issuing PPTLB: %d", res); + at = buf_get_u32(at_buf, 0, 32); + acc = (at >> XT_TLB1_ACC_SHIFT) & XT_TLB1_ACC_MSK; + exec_acc = ((acc == XTENSA_ACC_00X_000) || (acc == XTENSA_ACC_R0X_000) || + (acc == XTENSA_ACC_RWX_000) || (acc == XTENSA_ACC_RWX_R0X) || + (acc == XTENSA_ACC_R0X_R0X) || (acc == XTENSA_ACC_RWX_RWX)); + LOG_TARGET_DEBUG(target, "PPTLB(" TARGET_ADDR_FMT ") -> 0x%08" PRIx32 " exec_acc %d", + addr, at, exec_acc); + if (!exec_acc) + return false; + } + } + return true; +} + static int xtensa_queue_pwr_reg_write(struct xtensa *xtensa, unsigned int reg, uint32_t data) { struct xtensa_debug_module *dm = &xtensa->dbg_mod; @@ -2176,11 +2241,13 @@ int xtensa_write_memory(struct target *target, } } else { /* Invalidate ICACHE, writeback DCACHE if present */ - uint32_t issue_ihi = xtensa_is_icacheable(xtensa, address); - uint32_t issue_dhwb = xtensa_is_dcacheable(xtensa, address); - if (issue_ihi || issue_dhwb) { + bool issue_ihi = xtensa_is_icacheable(xtensa, address) && + xtensa_region_ar_exec(target, addrstart_al, addrend_al); + bool issue_dhwbi = xtensa_is_dcacheable(xtensa, address); + LOG_TARGET_DEBUG(target, "Cache OPs: IHI %d, DHWBI %d", issue_ihi, issue_dhwbi); + if (issue_ihi || issue_dhwbi) { uint32_t ilinesize = issue_ihi ? xtensa->core_config->icache.line_size : UINT32_MAX; - uint32_t dlinesize = issue_dhwb ? xtensa->core_config->dcache.line_size : UINT32_MAX; + uint32_t dlinesize = issue_dhwbi ? xtensa->core_config->dcache.line_size : UINT32_MAX; uint32_t linesize = MIN(ilinesize, dlinesize); uint32_t off = 0; adr = addrstart_al; @@ -2193,7 +2260,7 @@ int xtensa_write_memory(struct target *target, } if (issue_ihi) xtensa_queue_exec_ins(xtensa, XT_INS_IHI(xtensa, XT_REG_A3, off)); - if (issue_dhwb) + if (issue_dhwbi) xtensa_queue_exec_ins(xtensa, XT_INS_DHWBI(xtensa, XT_REG_A3, off)); off += linesize; if (off > 1020) { @@ -2205,7 +2272,11 @@ int xtensa_write_memory(struct target *target, /* Execute cache WB/INV instructions */ res = xtensa_dm_queue_execute(&xtensa->dbg_mod); - xtensa_core_status_check(target); + if (res != ERROR_OK) + LOG_TARGET_ERROR(target, + "Error queuing cache writeback/invaldate instruction(s): %d", + res); + res = xtensa_core_status_check(target); if (res != ERROR_OK) LOG_TARGET_ERROR(target, "Error issuing cache writeback/invaldate instruction(s): %d", @@ -2367,7 +2438,8 @@ int xtensa_poll(struct target *target) static int xtensa_update_instruction(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { struct xtensa *xtensa = target_to_xtensa(target); - unsigned int issue_ihi = xtensa_is_icacheable(xtensa, address); + unsigned int issue_ihi = xtensa_is_icacheable(xtensa, address) && + xtensa_region_ar_exec(target, address, address + size); unsigned int issue_dhwbi = xtensa_is_dcacheable(xtensa, address); uint32_t icache_line_size = issue_ihi ? xtensa->core_config->icache.line_size : UINT32_MAX; uint32_t dcache_line_size = issue_dhwbi ? xtensa->core_config->dcache.line_size : UINT32_MAX; @@ -2385,7 +2457,8 @@ static int xtensa_update_instruction(struct target *target, target_addr_t addres /* Write start address to A3 and invalidate */ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, address); xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3)); - LOG_TARGET_DEBUG(target, "DHWBI, IHI for address "TARGET_ADDR_FMT, address); + LOG_TARGET_DEBUG(target, "IHI %d, DHWBI %d for address " TARGET_ADDR_FMT, + issue_ihi, issue_dhwbi, address); if (issue_dhwbi) { xtensa_queue_exec_ins(xtensa, XT_INS_DHWBI(xtensa, XT_REG_A3, 0)); if (!same_dc_line) { From 2506ccb5091504fa50bc71979852701a74246f06 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 28 Apr 2024 12:47:42 +0200 Subject: [PATCH 0803/1312] target/arm_tpiu_swo: Fix division by zero When external capturing is configured (default), the SWO pin frequency is required. Enforce this to avoid a division by zero error. While at it, ensure that the 'out_filename' variable always contains a valid string. This saves a few checks and makes the code more clean and readable. Change-Id: If8c1dae9549dd10e2f21d5b896414d47edac9fc2 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8224 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_tpiu_swo.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 5cea682ec4..128e14702c 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -153,7 +153,7 @@ static int arm_tpiu_swo_poll_trace(void *priv) } } - if (obj->out_filename && obj->out_filename[0] == ':') + if (obj->out_filename[0] == ':') list_for_each_entry(c, &obj->connections, lh) if (connection_write(c->connection, buf, size) != (int)size) LOG_ERROR("Error writing to connection"); /* FIXME: which connection? */ @@ -201,7 +201,7 @@ static void arm_tpiu_swo_close_output(struct arm_tpiu_swo_object *obj) fclose(obj->file); obj->file = NULL; } - if (obj->out_filename && obj->out_filename[0] == ':') + if (obj->out_filename[0] == ':') remove_service(TCP_SERVICE_NAME, &obj->out_filename[1]); } @@ -475,12 +475,13 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s return JIM_ERR; } } - free(obj->out_filename); - obj->out_filename = strdup(s); - if (!obj->out_filename) { + char *out_filename = strdup(s); + if (!out_filename) { LOG_ERROR("Out of memory"); return JIM_ERR; } + free(obj->out_filename); + obj->out_filename = out_filename; } else { if (goi->argc) goto err_no_params; @@ -625,9 +626,18 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) return ERROR_FAIL; } - if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) - if (!obj->swo_pin_freq) + const bool output_external = !strcmp(obj->out_filename, "external"); + + if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) { + if (!obj->swo_pin_freq) { + if (output_external) { + command_print(CMD, "SWO pin frequency required when using external capturing"); + return ERROR_FAIL; + } + LOG_DEBUG("SWO pin frequency not set, will be autodetected by the adapter"); + } + } struct target *target = get_current_target(CMD_CTX); @@ -705,7 +715,7 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) uint16_t prescaler = 1; /* dummy value */ unsigned int swo_pin_freq = obj->swo_pin_freq; /* could be replaced */ - if (obj->out_filename && strcmp(obj->out_filename, "external") && obj->out_filename[0]) { + if (!output_external) { if (obj->out_filename[0] == ':') { struct arm_tpiu_swo_priv_connection *priv = malloc(sizeof(*priv)); if (!priv) { @@ -947,6 +957,12 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const adiv5_mem_ap_spot_init(&obj->spot); obj->spot.base = TPIU_SWO_DEFAULT_BASE; obj->port_width = 1; + obj->out_filename = strdup("external"); + if (!obj->out_filename) { + LOG_ERROR("Out of memory"); + free(obj); + return JIM_ERR; + } Jim_Obj *n; jim_getopt_obj(&goi, &n); From c831758ea4f0baf6e4d1b2ee69ae3c895922fee5 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 3 May 2024 09:18:00 +0200 Subject: [PATCH 0804/1312] server/gdb: Use 'bool' data type where appropriate Change-Id: Ic23c5469334337963185b69fcabeedf70c2c7ae9 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8253 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/server/gdb_server.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index dfd7cd5201..5052bf43b2 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -128,9 +128,9 @@ static int gdb_actual_connections; /* set if we are sending a memory map to gdb * via qXfer:memory-map:read packet */ /* enabled by default*/ -static int gdb_use_memory_map = 1; +static bool gdb_use_memory_map = true; /* enabled by default*/ -static int gdb_flash_program = 1; +static bool gdb_flash_program = true; /* if set, data aborts cause an error to be reported in memory read packets * see the code in gdb_read_memory_packet() for further explanations. @@ -144,7 +144,7 @@ static int gdb_report_register_access_error; /* set if we are sending target descriptions to gdb * via qXfer:features:read packet */ /* enabled by default */ -static int gdb_use_target_description = 1; +static bool gdb_use_target_description = true; /* current processing free-run type, used by file-I/O */ static char gdb_running_type; @@ -2599,7 +2599,7 @@ static int gdb_get_target_description_chunk(struct target *target, struct target return ERROR_OK; } -static int gdb_target_description_supported(struct target *target, int *supported) +static int gdb_target_description_supported(struct target *target, bool *supported) { int retval = ERROR_OK; struct reg **reg_list = NULL; @@ -2631,9 +2631,9 @@ static int gdb_target_description_supported(struct target *target, int *supporte if (supported) { if (architecture || feature_list_size) - *supported = 1; + *supported = true; else - *supported = 0; + *supported = false; } error: @@ -2867,20 +2867,20 @@ static int gdb_query_packet(struct connection *connection, char *buffer = NULL; int pos = 0; int size = 0; - int gdb_target_desc_supported = 0; + bool gdb_target_desc_supported = false; /* we need to test that the target supports target descriptions */ retval = gdb_target_description_supported(target, &gdb_target_desc_supported); if (retval != ERROR_OK) { LOG_INFO("Failed detecting Target Description Support, disabling"); - gdb_target_desc_supported = 0; + gdb_target_desc_supported = false; } /* support may be disabled globally */ - if (gdb_use_target_description == 0) { + if (!gdb_use_target_description) { if (gdb_target_desc_supported) LOG_WARNING("Target Descriptions Supported, but disabled"); - gdb_target_desc_supported = 0; + gdb_target_desc_supported = false; } xml_printf(&retval, @@ -2889,8 +2889,8 @@ static int gdb_query_packet(struct connection *connection, &size, "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+;vContSupported+", GDB_BUFFER_SIZE, - ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-', - (gdb_target_desc_supported == 1) ? '+' : '-'); + (gdb_use_memory_map && (flash_get_bank_count() > 0)) ? '+' : '-', + gdb_target_desc_supported ? '+' : '-'); if (retval != ERROR_OK) { gdb_send_error(connection, 01); @@ -3280,7 +3280,7 @@ static int gdb_v_packet(struct connection *connection, /* if flash programming disabled - send a empty reply */ - if (gdb_flash_program == 0) { + if (!gdb_flash_program) { gdb_put_packet(connection, "", 0); return ERROR_OK; } From be1aebd8183c5b6b3bbecfc065a84b7e10bd8f8e Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 1 May 2024 12:58:18 +0200 Subject: [PATCH 0805/1312] target/arm_tpiu_swo: Handle errors in pre/post-enable events Currently, errors in pre/post-enable events are ignored and capturing is always started, even if necessary device configuration fails. This behaviour is confusing to users. Also, the TPIU must be disabled before re-configuration is possible. Start capturing and enable TPIU only if no errors in pre/post-enable events occurred. Change-Id: I422033e36ca006e38aa4504d491b7947def1237a Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8254 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/arm_tpiu_swo.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 128e14702c..340d3323d4 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -161,7 +161,7 @@ static int arm_tpiu_swo_poll_trace(void *priv) return ERROR_OK; } -static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_tpiu_swo_event event) +static int arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_tpiu_swo_event event) { for (struct arm_tpiu_swo_event_action *ea = obj->event_action; ea; ea = ea->next) { if (ea->event != event) @@ -182,7 +182,7 @@ static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_ if (retval == JIM_RETURN) retval = ea->interp->returnCode; if (retval == JIM_OK || retval == ERROR_COMMAND_CLOSE_CONNECTION) - return; + return ERROR_OK; Jim_MakeErrorMessage(ea->interp); LOG_USER("Error executing event %s on TPIU/SWO %s:\n%s", @@ -191,8 +191,10 @@ static void arm_tpiu_swo_handle_event(struct arm_tpiu_swo_object *obj, enum arm_ Jim_GetString(Jim_GetResult(ea->interp), NULL)); /* clean both error code and stacktrace before return */ Jim_Eval(ea->interp, "error \"\" \"\""); - return; + return ERROR_FAIL; } + + return ERROR_OK; } static void arm_tpiu_swo_close_output(struct arm_tpiu_swo_object *obj) @@ -674,7 +676,9 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) } /* 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 = arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_ENABLE); + if (retval != ERROR_OK) + return retval; retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_DEVID_OFFSET, &value); if (retval != ERROR_OK) { @@ -800,7 +804,9 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) if (retval != ERROR_OK) goto error_exit; - arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_ENABLE); + retval = arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_ENABLE); + if (retval != ERROR_OK) + goto error_exit; /* START_DEPRECATED_TPIU */ target_handle_event(target, TARGET_EVENT_TRACE_CONFIG); From 1a00c67e101015ba23b8213604b9cc5725bc1d52 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 5 May 2024 15:20:07 +0200 Subject: [PATCH 0806/1312] tcl/target/nrf52: Use 'error' instead of 'echo' Use 'error' instead of 'echo' for error messages. Otherwise, capturing is always started, for example with an unsupported device. While at it, make the error messages more consistent and clear. Change-Id: I83c9abfb4514e6b638c4be14651e67f768af8bad Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8255 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: --- tcl/target/nrf52.cfg | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tcl/target/nrf52.cfg b/tcl/target/nrf52.cfg index 0c82c5758a..a9121d3561 100644 --- a/tcl/target/nrf52.cfg +++ b/tcl/target/nrf52.cfg @@ -133,8 +133,7 @@ proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname _chipname} { 0x52832 { if { [$_chipname.tpiu cget -protocol] eq "sync" } { if { [$_chipname.tpiu cget -port-width] != 4 } { - echo "Error. Device only supports 4-bit sync traces." - return + error "Device only supports 4-bit sync traces" } # Set TRACECONFIG.TRACEMUX to enable synchronous trace @@ -154,12 +153,10 @@ proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname _chipname} { 0x52811 - 0x52810 - 0x52805 { - echo "Error: Device does not support TPIU" - return + error "Device does not support TPIU" } default { - echo "Error: Unknown device" - return + error "Unknown device, cannot configure TPIU" } } } From edb14a02e9b698d015696a959ca81f821d49d4e3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 5 May 2024 15:28:20 +0200 Subject: [PATCH 0807/1312] tcl/target/nrf52: Configure trace port speed Configure the TRACECONFIG.TRACEPORTSPEED register depending on the trace clock speed. Also catch invalid trace clock speeds. Change-Id: I1ece1cc59da539732d2d71f296fd55799c195387 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8256 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/nrf52.cfg | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tcl/target/nrf52.cfg b/tcl/target/nrf52.cfg index a9121d3561..0703b18862 100644 --- a/tcl/target/nrf52.cfg +++ b/tcl/target/nrf52.cfg @@ -131,6 +131,26 @@ proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname _chipname} { 0x52840 - 0x52833 - 0x52832 { + # Configuration values for all supported trace port speeds, see + # TRACECONFIG.TRACEPORTSPEED + set trace_port_speeds { + 32000000 0 + 16000000 1 + 8000000 2 + 4000000 3 + } + + # Note that trace port clock stands for what is referred to as + # TRACECLKIN in the Arm CoreSight documentation. + set trace_port_clock [$_chipname.tpiu cget -traceclk] + + if { ![dict exists $trace_port_speeds $trace_port_clock] } { + error "Trace clock speed is not supported" + } + + # Set TRACECONFIG.TRACEPORTSPEED + mmw 0x4000055C [dict get $trace_port_speeds $trace_port_clock] 0x3 + if { [$_chipname.tpiu cget -protocol] eq "sync" } { if { [$_chipname.tpiu cget -port-width] != 4 } { error "Device only supports 4-bit sync traces" From bd89b91c697d9aea97abfcd3a3b8043a95216d6d Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 1 May 2024 10:24:32 +0200 Subject: [PATCH 0808/1312] target/semihosting: Fix double free() Do not free the service in 'connection_closed_handler' because it is free'd by the server infrastructure. Checkpatch-ignore: COMMIT_LOG_LONG_LINE This error was detected with valgrind: ==272468== Invalid free() / delete / delete[] / realloc() ==272468== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==272468== by 0x1F34C7: remove_service (server.c:374) ==272468== by 0x2ED3D5: semihosting_tcp_close_cnx (semihosting_common.c:1819) ==272468== by 0x2ED3D5: handle_common_semihosting_redirect_command (semihosting_common.c:1926) ==272468== by 0x1FC703: exec_command (command.c:520) ==272468== by 0x1FC703: jim_command_dispatch (command.c:931) ==272468== by 0x36980F: JimInvokeCommand (in /home/marc/openocd/build/src/openocd) ==272468== by 0x1FFFFFFFFF: ??? ==272468== by 0x53ED09F: ??? ==272468== by 0x300000001: ??? ==272468== by 0x1FFEFFF7FF: ??? ==272468== by 0x3D3984: ??? (in /home/marc/openocd/build/src/openocd) ==272468== by 0x2: ??? ==272468== Address 0x5fff650 is 0 bytes inside a block of size 24 free'd ==272468== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==272468== by 0x2ECA42: semihosting_service_connection_closed_handler (semihosting_common.c:1807) ==272468== by 0x1F2E39: remove_connection.isra.0 (server.c:164) ==272468== by 0x1F349E: remove_connections (server.c:350) ==272468== by 0x1F349E: remove_service (server.c:364) ==272468== by 0x2ED3D5: semihosting_tcp_close_cnx (semihosting_common.c:1819) ==272468== by 0x2ED3D5: handle_common_semihosting_redirect_command (semihosting_common.c:1926) ==272468== by 0x1FC703: exec_command (command.c:520) ==272468== by 0x1FC703: jim_command_dispatch (command.c:931) ==272468== by 0x36980F: JimInvokeCommand (in /home/marc/openocd/build/src/openocd) ==272468== by 0x1FFFFFFFFF: ??? ==272468== by 0x53ED09F: ??? ==272468== by 0x300000001: ??? ==272468== by 0x1FFEFFF7FF: ??? ==272468== by 0x3D3984: ??? (in /home/marc/openocd/build/src/openocd) ==272468== Block was alloc'd at ==272468== at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==272468== by 0x2ED326: handle_common_semihosting_redirect_command (semihosting_common.c:1931) ==272468== by 0x1FC703: exec_command (command.c:520) ==272468== by 0x1FC703: jim_command_dispatch (command.c:931) ==272468== by 0x36980F: JimInvokeCommand (in /home/marc/openocd/build/src/openocd) ==272468== by 0x1FFFFFFFFF: ??? ==272468== by 0x53ED09F: ??? ==272468== by 0x400000002: ??? ==272468== by 0x1FFEFFF7FF: ??? ==272468== by 0x3D3984: ??? (in /home/marc/openocd/build/src/openocd) ==272468== by 0x2: ??? ==272468== Change-Id: I3e5323f145a98d1ff9ea7d03f87ed96140f49a18 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8257 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/semihosting_common.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index f7acc6092d..1eb195712e 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -1802,10 +1802,8 @@ static int semihosting_service_input_handler(struct connection *connection) static int semihosting_service_connection_closed_handler(struct connection *connection) { struct semihosting_tcp_service *service = connection->service->priv; - if (service) { + if (service) free(service->name); - free(service); - } return ERROR_OK; } From ccc5c1642b32ab79d5ab315e4b308e53392a77c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Rosenkr=C3=A4nzer?= Date: Thu, 9 May 2024 15:30:13 +0200 Subject: [PATCH 0809/1312] Fix build with clang even if it sets __GNUC__ to >= 4.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clang doesn't support the gnu_printf attribute that OpenOCD uses if __GNUC__ and __GNUC_MINOR__ indicates gcc >= 4.4. Most clang builds set __GNUC__/__GNUC_MINOR__ to 4.2 for historical reasons, so they don't trigger this condition; however, some builds set it to something much higher to work around code using __GNUC__ to determine if a feature that does exist in clang (but not gcc 4.2) is available, causing OpenOCD to use attribute gnu_printf. The problem can be reproduced without a special clang build by adding -fgnuc-version=14.1 to CFLAGS. Change-Id: I3c0832d4201578b116c5214203f95b6153dad30e Signed-off-by: Bernhard Rosenkränzer Reviewed-on: https://review.openocd.org/c/openocd/+/8258 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/command.h | 2 +- src/helper/log.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helper/command.h b/src/helper/command.h index dc45070420..fc26dda81a 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -21,7 +21,7 @@ /* To achieve C99 printf compatibility in MinGW, gnu_printf should be * used for __attribute__((format( ... ))), with GCC v4.4 or later */ -#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004)) +#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004)) && !defined(__clang__) #define PRINTF_ATTRIBUTE_FORMAT gnu_printf #else #define PRINTF_ATTRIBUTE_FORMAT printf diff --git a/src/helper/log.h b/src/helper/log.h index 818716a9df..d52c05f99d 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -19,7 +19,7 @@ /* To achieve C99 printf compatibility in MinGW, gnu_printf should be * used for __attribute__((format( ... ))), with GCC v4.4 or later */ -#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004)) +#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004)) && !defined(__clang__) #define PRINTF_ATTRIBUTE_FORMAT gnu_printf #else #define PRINTF_ATTRIBUTE_FORMAT printf From fbea7d5d38d0dcbdd71cb574da9bd12c78b568cf Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 9 Apr 2024 01:29:34 +0200 Subject: [PATCH 0810/1312] openocd: drop include of target_type.h Few files include target_type.h even if it is not needed. Drop the include. Other files access directly to target type's name instead of using the proper API target_type_name(). Use the API and drop the include. Change-Id: I86c0e0bbad51db93500c0efa27b7d6f1a67a02c2 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8260 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/psoc6.c | 1 - src/rtos/FreeRTOS.c | 3 +-- src/rtos/ThreadX.c | 3 +-- src/rtos/chibios.c | 7 +++---- src/rtos/chromium-ec.c | 7 +++---- src/rtos/eCos.c | 7 +++---- src/rtos/embKernel.c | 5 ++--- src/rtos/hwthread.c | 1 - src/rtos/mqx.c | 7 +++---- src/rtos/nuttx.c | 1 - src/rtos/riot.c | 3 +-- src/rtos/rtkernel.c | 3 +-- src/rtos/uCOS-III.c | 5 ++--- src/rtos/zephyr.c | 1 - src/target/arm_tpiu_swo.c | 9 ++++----- src/target/target.c | 4 ++-- 16 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index b7ba1027ed..859b3e9ec5 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -18,7 +18,6 @@ #include "target/target.h" #include "target/cortex_m.h" #include "target/breakpoints.h" -#include "target/target_type.h" #include "target/algorithm.h" /************************************************************************************************** diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index e8df030aad..20977e07e9 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -12,7 +12,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -533,7 +532,7 @@ static bool freertos_detect_rtos(struct target *target) static int freertos_create(struct target *target) { for (unsigned int i = 0; i < ARRAY_SIZE(freertos_params_list); i++) - if (strcmp(freertos_params_list[i].target_name, target->type->name) == 0) { + if (strcmp(freertos_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&freertos_params_list[i]; return 0; } diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c index 5bdd007d42..61c49264e8 100644 --- a/src/rtos/ThreadX.c +++ b/src/rtos/ThreadX.c @@ -12,7 +12,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -608,7 +607,7 @@ static int threadx_get_thread_detail(struct rtos *rtos, static int threadx_create(struct target *target) { for (unsigned int i = 0; i < ARRAY_SIZE(threadx_params_list); i++) - if (strcmp(threadx_params_list[i].target_name, target->type->name) == 0) { + if (strcmp(threadx_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&threadx_params_list[i]; target->rtos->current_thread = 0; target->rtos->thread_details = NULL; diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c index 20378274ec..c1e4e84192 100644 --- a/src/rtos/chibios.c +++ b/src/rtos/chibios.c @@ -15,7 +15,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "target/armv7m.h" #include "target/cortex_m.h" #include "rtos.h" @@ -470,7 +469,7 @@ static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, /* Update stacking if it can only be determined from runtime information */ if (!param->stacking_info && (chibios_update_stacking(rtos) != ERROR_OK)) { - LOG_ERROR("Failed to determine exact stacking for the target type %s", rtos->target->type->name); + LOG_ERROR("Failed to determine exact stacking for the target type %s", target_type_name(rtos->target)); return -1; } @@ -518,12 +517,12 @@ static bool chibios_detect_rtos(struct target *target) static int chibios_create(struct target *target) { for (unsigned int i = 0; i < ARRAY_SIZE(chibios_params_list); i++) - if (strcmp(chibios_params_list[i].target_name, target->type->name) == 0) { + if (strcmp(chibios_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&chibios_params_list[i]; return 0; } LOG_WARNING("Could not find target \"%s\" in ChibiOS compatibility " - "list", target->type->name); + "list", target_type_name(target)); return -1; } diff --git a/src/rtos/chromium-ec.c b/src/rtos/chromium-ec.c index a95969e345..dbfe3b3c68 100644 --- a/src/rtos/chromium-ec.c +++ b/src/rtos/chromium-ec.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "rtos_standard_stackings.h" @@ -120,7 +119,7 @@ static int chromium_ec_create(struct target *target) size_t t; for (t = 0; t < ARRAY_SIZE(chromium_ec_params_list); t++) - if (!strcmp(chromium_ec_params_list[t].target_name, target->type->name)) { + if (!strcmp(chromium_ec_params_list[t].target_name, target_type_name(target))) { params = malloc(sizeof(*params)); if (!params) { LOG_ERROR("Chromium-EC: out of memory"); @@ -133,11 +132,11 @@ static int chromium_ec_create(struct target *target) target->rtos->thread_details = NULL; target->rtos->thread_count = 0; - LOG_INFO("Chromium-EC: Using target: %s", target->type->name); + LOG_INFO("Chromium-EC: Using target: %s", target_type_name(target)); return ERROR_OK; } - LOG_ERROR("Chromium-EC: target not supported: %s", target->type->name); + LOG_ERROR("Chromium-EC: target not supported: %s", target_type_name(target)); return ERROR_FAIL; } diff --git a/src/rtos/eCos.c b/src/rtos/eCos.c index 10ed12809f..7048b006e0 100644 --- a/src/rtos/eCos.c +++ b/src/rtos/eCos.c @@ -10,7 +10,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "target/armv7m.h" #include "rtos.h" #include "helper/log.h" @@ -1137,7 +1136,7 @@ static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[ ARRAY_SIZE(ecos_symbol_list), sizeof(struct symbol_table_elem)); /* If the target reference was passed into this function we could limit - * the symbols we need to lookup to the target->type->name based + * the symbols we need to lookup to the target_type_name(target) based * range. For the moment we need to provide a single vector with all of * the symbols across all of the supported architectures. */ for (i = 0; i < ARRAY_SIZE(ecos_symbol_list); i++) { @@ -1189,8 +1188,8 @@ static int ecos_create(struct target *target) for (unsigned int i = 0; i < ARRAY_SIZE(ecos_params_list); i++) { const char * const *tnames = ecos_params_list[i].target_names; while (*tnames) { - if (strcmp(*tnames, target->type->name) == 0) { - /* LOG_DEBUG("eCos: matched target \"%s\"", target->type->name); */ + if (strcmp(*tnames, target_type_name(target)) == 0) { + /* LOG_DEBUG("eCos: matched target \"%s\"", target_type_name(target)); */ target->rtos->rtos_specific_params = (void *)&ecos_params_list[i]; ecos_params_list[i].flush_common = true; ecos_params_list[i].stacking_info = NULL; diff --git a/src/rtos/embKernel.c b/src/rtos/embKernel.c index a03b039e0c..7e6de7902a 100644 --- a/src/rtos/embKernel.c +++ b/src/rtos/embKernel.c @@ -12,7 +12,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -110,12 +109,12 @@ static int embkernel_create(struct target *target) { size_t i = 0; while ((i < ARRAY_SIZE(embkernel_params_list)) && - (strcmp(embkernel_params_list[i].target_name, target->type->name) != 0)) + (strcmp(embkernel_params_list[i].target_name, target_type_name(target)) != 0)) i++; if (i >= ARRAY_SIZE(embkernel_params_list)) { LOG_WARNING("Could not find target \"%s\" in embKernel compatibility " - "list", target->type->name); + "list", target_type_name(target)); return -1; } diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 895f11cfc9..937d01b874 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -7,7 +7,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "target/register.h" #include #include "rtos.h" diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c index d9b694282a..b4a1821352 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -13,7 +13,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -249,13 +248,13 @@ static int mqx_create( { /* check target name against supported architectures */ for (unsigned int i = 0; i < ARRAY_SIZE(mqx_params_list); i++) { - if (strcmp(mqx_params_list[i].target_name, target->type->name) == 0) { + if (strcmp(mqx_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&mqx_params_list[i]; - /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */ + /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target_type_name(target)); */ return 0; } } - LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target->type->name); + LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target_type_name(target)); return -1; } diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 0616af0f4c..9100148895 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -12,7 +12,6 @@ #include #include "target/target.h" -#include "target/target_type.h" #include "target/armv7m.h" #include "target/cortex_m.h" #include "rtos.h" diff --git a/src/rtos/riot.c b/src/rtos/riot.c index be5452e9e7..b90b069148 100644 --- a/src/rtos/riot.c +++ b/src/rtos/riot.c @@ -12,7 +12,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -391,7 +390,7 @@ static int riot_create(struct target *target) /* lookup if target is supported by RIOT */ while ((i < RIOT_NUM_PARAMS) && - (strcmp(riot_params_list[i].target_name, target->type->name) != 0)) { + (strcmp(riot_params_list[i].target_name, target_type_name(target)) != 0)) { i++; } if (i >= RIOT_NUM_PARAMS) { diff --git a/src/rtos/rtkernel.c b/src/rtos/rtkernel.c index ba1de25172..aebbf3d94d 100644 --- a/src/rtos/rtkernel.c +++ b/src/rtos/rtkernel.c @@ -12,7 +12,6 @@ #include #include #include "target/target.h" -#include "target/target_type.h" #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -363,7 +362,7 @@ static bool rtkernel_detect_rtos(struct target *target) static int rtkernel_create(struct target *target) { for (size_t i = 0; i < ARRAY_SIZE(rtkernel_params_list); i++) { - if (strcmp(rtkernel_params_list[i].target_name, target->type->name) == 0) { + if (strcmp(rtkernel_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&rtkernel_params_list[i]; return 0; } diff --git a/src/rtos/uCOS-III.c b/src/rtos/uCOS-III.c index 4d704a44fe..f19d06e3c0 100644 --- a/src/rtos/uCOS-III.c +++ b/src/rtos/uCOS-III.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "rtos_ucos_iii_stackings.h" @@ -253,7 +252,7 @@ static int ucos_iii_create(struct target *target) struct ucos_iii_private *params; for (size_t i = 0; i < ARRAY_SIZE(ucos_iii_params_list); i++) - if (strcmp(ucos_iii_params_list[i].target_name, target->type->name) == 0) { + if (strcmp(ucos_iii_params_list[i].target_name, target_type_name(target)) == 0) { params = calloc(1, sizeof(*params)); if (!params) { LOG_ERROR("uCOS-III: out of memory"); @@ -268,7 +267,7 @@ static int ucos_iii_create(struct target *target) return ERROR_OK; } - LOG_ERROR("uCOS-III: target not supported: %s", target->type->name); + LOG_ERROR("uCOS-III: target not supported: %s", target_type_name(target)); return ERROR_FAIL; } diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c index a4c60904b5..023db60c9e 100644 --- a/src/rtos/zephyr.c +++ b/src/rtos/zephyr.c @@ -20,7 +20,6 @@ #include "rtos.h" #include "rtos_standard_stackings.h" #include "target/target.h" -#include "target/target_type.h" #include "target/armv7m.h" #include "target/arc.h" diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 340d3323d4..b5a4882011 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -40,7 +40,6 @@ /* START_DEPRECATED_TPIU */ #include -#include #define MSG "DEPRECATED \'tpiu config\' command: " /* END_DEPRECATED_TPIU */ @@ -645,8 +644,8 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) /* START_DEPRECATED_TPIU */ if (obj->recheck_ap_cur_target) { - if (strcmp(target->type->name, "cortex_m") && - strcmp(target->type->name, "hla_target")) { + if (strcmp(target_type_name(target), "cortex_m") && + strcmp(target_type_name(target), "hla_target")) { LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA"); return ERROR_FAIL; } @@ -1043,8 +1042,8 @@ COMMAND_HANDLER(handle_tpiu_deprecated_config_command) struct arm_tpiu_swo_object *obj = NULL; int retval; - if (strcmp(target->type->name, "cortex_m") && - strcmp(target->type->name, "hla_target")) { + if (strcmp(target_type_name(target), "cortex_m") && + strcmp(target_type_name(target), "hla_target")) { LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA"); return ERROR_FAIL; } diff --git a/src/target/target.c b/src/target/target.c index 5168305dee..efc168903b 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1498,7 +1498,7 @@ static int target_init_one(struct command_context *cmd_ctx, */ if (type->mmu) { if (!type->virt2phys) { - LOG_ERROR("type '%s' is missing virt2phys", type->name); + LOG_ERROR("type '%s' is missing virt2phys", target_name(target)); type->virt2phys = identity_virt2phys; } } else { @@ -1507,7 +1507,7 @@ static int target_init_one(struct command_context *cmd_ctx, * ensure that virt2phys() is always an identity mapping. */ if (type->write_phys_memory || type->read_phys_memory || type->virt2phys) - LOG_WARNING("type '%s' has bad MMU hooks", type->name); + LOG_WARNING("type '%s' has bad MMU hooks", target_name(target)); type->mmu = no_mmu; type->write_phys_memory = type->write_memory; From 1fba7d53bb92fca82336f6615324bc597ab0a6c4 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 21 Apr 2024 22:58:21 +0200 Subject: [PATCH 0811/1312] configure.ac: show the dummy adapter in the configuration summary The dummy adapter now uses the same config logic as most adapters. Its name has changed from "dummy port driver" to "Dummy Adapter". Change-Id: Ic9ee617aab1f54215835d4d8db03f6637b797082 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/7340 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 7613848371..becc531b0d 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,11 @@ m4_define([PCIE_ADAPTERS], m4_define([SERIAL_PORT_ADAPTERS], [[[buspirate], [Bus Pirate], [BUS_PIRATE]]]) +# The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter +# because there is an M4 macro called 'adapter'. +m4_define([DUMMY_ADAPTER], + [[[dummy], [Dummy Adapter], [DUMMY]]]) + m4_define([OPTIONAL_LIBRARIES], [[[capstone], [Use Capstone disassembly framework], []]]) @@ -234,10 +239,6 @@ AS_IF([test "x$debug_malloc" = "xyes"], [ AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging]) ]) -AC_ARG_ENABLE([dummy], - AS_HELP_STRING([--enable-dummy], [Enable building the dummy port driver]), - [build_dummy=$enableval], [build_dummy=no]) - AC_ARG_ENABLE([rshim], AS_HELP_STRING([--enable-rshim], [Enable building the rshim driver]), [build_rshim=$enableval], [build_rshim=no]) @@ -266,6 +267,8 @@ AC_ARG_ADAPTERS([ LIBJAYLINK_ADAPTERS ],[auto]) +AC_ARG_ADAPTERS([DUMMY_ADAPTER],[no]) + AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), [build_parport=$enableval], [build_parport=no]) @@ -492,11 +495,8 @@ AS_IF([test "x$build_dmem" = "xyes"], [ AC_DEFINE([BUILD_DMEM], [0], [0 if you don't want to debug via Direct Mem.]) ]) -AS_IF([test "x$build_dummy" = "xyes"], [ +AS_IF([test "x$ADAPTER_VAR([dummy])" = "xyes"], [ build_bitbang=yes - AC_DEFINE([BUILD_DUMMY], [1], [1 if you want dummy driver.]) -], [ - AC_DEFINE([BUILD_DUMMY], [0], [0 if you don't want dummy driver.]) ]) AS_IF([test "x$build_ep93xx" = "xyes"], [ @@ -678,6 +678,11 @@ PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [ PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], [use_libjaylink=yes], [use_libjaylink=no]) +# Arg $1: The adapter name, used to derive option and variable names for the adapter. +# Arg $2: Whether the adapter can be enabled, for example, because +# its prerequisites are installed in the system. +# Arg $3: What prerequisites are missing, to be shown in an error message +# if the adapter was requested but cannot be enabled. m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ AS_IF([test $2], [ @@ -704,6 +709,7 @@ PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x]) PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [libgpiod]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) +PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ build_bitbang=yes @@ -743,7 +749,6 @@ AS_IF([test "x$enable_esp_usb_jtag" != "xno"], [ AM_CONDITIONAL([RELEASE], [test "x$build_release" = "xyes"]) AM_CONDITIONAL([PARPORT], [test "x$build_parport" = "xyes"]) -AM_CONDITIONAL([DUMMY], [test "x$build_dummy" = "xyes"]) AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"]) AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "xyes"]) AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"]) @@ -852,6 +857,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, + DUMMY_ADAPTER, OPTIONAL_LIBRARIES], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) AS_CASE([$ADAPTER_VAR([adapter])], From cf48bf6d3d1a76ed418ad4e5ef62fb578741e79a Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 12 May 2024 20:50:34 +0200 Subject: [PATCH 0812/1312] ChangeLog: fix warning "Wide character in print" from git2cl Change-Id: Iaefd989413753fb59642c3887807abd6ddac4b53 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8262 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- Makefile.am | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 1313d151b5..647b571cfa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -114,9 +114,14 @@ TCL_PATH = tcl TCL_FILES = find $(srcdir)/$(TCL_PATH) -name '*.cfg' -o -name '*.tcl' -o -name '*.txt' | \ sed -e 's,^$(srcdir)/$(TCL_PATH),,' +# Without the PERL_UNICODE="IO" workaround below when running git2cl, you get several +# "Wide character" warnings and you also risk an invalid character encoding in +# the generated ChangeLog file. For more information, see this bug report: +# Warning "Wide character in print" +# https://savannah.nongnu.org/bugs/?65689 dist-hook: if test -d $(srcdir)/.git -a \( ! -e $(distdir)/ChangeLog -o -w $(distdir)/ChangeLog \) ; then \ - git --git-dir $(srcdir)/.git log | $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \ + git --git-dir $(srcdir)/.git log | PERL_UNICODE="IO" $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \ fi for i in $$($(TCL_FILES)); do \ j="$(distdir)/$(TCL_PATH)/$$i" && \ From 7c4ddfb5467b096156e7e12ec7e2ad114e88d648 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 12 May 2024 22:03:08 +0200 Subject: [PATCH 0813/1312] Documentation: Fix 2 warnings "Underfull \hbox (badness 10000)" The link to product GW16042 was broken, so it has been reduced to the manufacturer's website, which fixes the warning as a side effect. The link to Raisonance RLink was broken, and the new one is shorter, which fixes the warning as a side effect. Change-Id: I4df9acf2d994d51cd8f375bdac6c803270029506 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8264 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- doc/openocd.texi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 55e6e76808..32697f86d0 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -399,8 +399,7 @@ to be available anymore as of April 2012. @* Link @url{http://www.distortec.com/jtag-lock-pick-tiny-2} FT232H-based @item @b{GW16042} -@* Link: @url{http://shop.gateworks.com/index.php?route=product/product&path=70_80&product_id=64} -FT2232H-based +@* Link: @url{https://www.gateworks.com/} FT2232H-based @end itemize @section USB-JTAG / Altera USB-Blaster compatibles @@ -442,7 +441,7 @@ SWD and not JTAG, thus not supported. @itemize @bullet @item @b{Raisonance RLink} -@* Link: @url{http://www.mcu-raisonance.com/~rlink-debugger-programmer__@/microcontrollers__tool~tool__T018:4cn9ziz4bnx6.html} +@* Link: @url{https://www.raisonance.com/rlink.html} @item @b{STM32 Primer} @* Link: @url{http://www.stm32circle.com/resources/stm32primer.php} @item @b{STM32 Primer2} From 437dde701c13e707e5fd912ef6403e09052e4d9b Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 12 May 2024 18:45:16 +0200 Subject: [PATCH 0814/1312] Documentation: fix warning "unbalanced square brackets" Change-Id: I17b716533f5c9371600f0d932bf9b81c95c349e7 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8261 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 32697f86d0..5eef81e40f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9371,7 +9371,7 @@ Loads an image stored in memory by @command{fast_load_image} to the current target. Must be preceded by fast_load_image. @end deffn -@deffn {Command} {fast_load_image} filename [address [@option{bin}|@option{ihex}|@option{elf}|@option{s19} [@option{min_addr} [@option{max_length}]]]]]] +@deffn {Command} {fast_load_image} filename [address [@option{bin}|@option{ihex}|@option{elf}|@option{s19} [@option{min_addr} [@option{max_length}]]]] Normally you should be using @command{load_image} or GDB load. However, for testing purposes or when I/O overhead is significant(OpenOCD running on an embedded host), storing the image in memory and uploading the image to the target From 71013521d7b195022616284aabc5e072a60c52bf Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 3 May 2024 23:04:46 +0200 Subject: [PATCH 0815/1312] server: gdb: respect command gdb_report_register_access_error Commit 236c54c94a53 ("server/gdb_server.c: support unavailable registers") correctly returns a string of 'x' when the register is not available in the current target. While implementing this, it incorrectly drops the pre-existing feature of optionally ignoring errors while reading a register. This feature has a real use case documented in the OpenOCD manual in chapter 'Using GDB as a non-intrusive memory inspector', where GDB attaches to a target without halting it. For targets that need to be halted to read its registers, we need to hack the values of the registers returned to GDB; either returning 'xxxx' or an error causes GDB to drop the connection. Re-add the check on 'gdb_report_register_access_error' to keep the pre-existing behavior when a register error has to be ignored: - return a string of '0'; - drop a debug message. Change-Id: Ie65c92f259f92502e688914f334655b635874179 Signed-off-by: Antonio Borneo Fixes: 236c54c94a53 ("server/gdb_server.c: support unavailable registers") Reviewed-on: https://review.openocd.org/c/openocd/+/8228 Tested-by: jenkins --- src/server/gdb_server.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 5052bf43b2..7c2f41e41a 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1233,6 +1233,8 @@ static int gdb_get_reg_value_as_str(struct target *target, char *tstr, struct re tstr[len] = '\0'; return ERROR_OK; } + memset(tstr, '0', len); + tstr[len] = '\0'; return ERROR_FAIL; } @@ -1277,7 +1279,9 @@ static int gdb_get_registers_packet(struct connection *connection, for (i = 0; i < reg_list_size; i++) { if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) continue; - if (gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]) != ERROR_OK) { + retval = gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]); + if (retval != ERROR_OK && gdb_report_register_access_error) { + LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name); free(reg_packet); free(reg_list); return gdb_error(connection, retval); @@ -1395,7 +1399,9 @@ static int gdb_get_register_packet(struct connection *connection, reg_packet = calloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1, 1); /* plus one for string termination null */ - if (gdb_get_reg_value_as_str(target, reg_packet, reg_list[reg_num]) != ERROR_OK) { + retval = gdb_get_reg_value_as_str(target, reg_packet, reg_list[reg_num]); + if (retval != ERROR_OK && gdb_report_register_access_error) { + LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name); free(reg_packet); free(reg_list); return gdb_error(connection, retval); From c7c4d4d48c63c1048414779f633641ea4e9657c8 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 20 May 2024 11:32:19 +0200 Subject: [PATCH 0816/1312] contrib: Drop 'coresight-trace.txt' This document is outdated and has broken text formatting. It also provides no useful information to users nor developers, at worst it causes confusion. For that reason, drop this file. Change-Id: Id5ee1f6e74d1a641c60d897f114bb97f5fd48e5b Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8292 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/coresight-trace.txt | 68 ------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 contrib/coresight-trace.txt diff --git a/contrib/coresight-trace.txt b/contrib/coresight-trace.txt deleted file mode 100644 index 517119b6f6..0000000000 --- a/contrib/coresight-trace.txt +++ /dev/null @@ -1,68 +0,0 @@ -+OpenOCD and CoreSight Tracing -+ -Many recent ARM chips (Using e..g. Cortex-M3 and -Cortex-M4 cores) support CoreSight debug/trace. -This note sketches an approach currently planned for those cores -with OpenOCD. - - This tracing data can help debug and tune ARM software, but not -all cores support tracing. Some support more extensive tracing -other cores with trace support +should be able to use the same -approach and maybe some of the same analysis code. - -+the Cortex-M3 is assumed here to be the -+core in use, for simplicity and to reflect current OpenOCD users. - - -This note summarizes a software model to generate, collect, and -analyze such trace data . That is not fully implemented as of early -January 2011, +and thus is not *yet* usable. -+ -+ -+Some microcontroller cores support a low pin-count Single-wire trace, -with a mode where +trace data is emitted (usually to a UART. To use -this mode, +SWD must be in use. -+At this writing, OpenOCD SWD support is not yet complete either. - -(There are also multi-wire trace ports requiring more complex debug -adapters than OpenOCD currently supports, and offering richer data. -+ -+ -+* ENABLING involves activating SWD and (single wire) trace. -+ -+current expectations are that OpenOCD itself will handle enabling; -activating single wire trace involves a debug adapter interaction, and -collecting that trace data requires particular (re)wiring. -+ -+* CONFIGURATION involves setting up ITM and/or ETM modules to emit the -+desired data from the Cortex core. (This might include dumping -+event counters printf-style messages; code profiling; and more. Not all -+cores offer the same trace capabilities. -+ -+current expectations are that Tcl scripts will be used to configure these -+modules for the desired tracing, by direct writes to registers. In some -+cases (as with RTOS event tracking and similar messaging, this might -+be augmented or replaced by user code running on the ARM core. -+ -+COLLECTION involves reading that trace data, probably through UART, and -+saving it in a useful format to analyse For now, deferred analysis modes -are assumed, not than real-time or interactive ones. -+ -+ -+current expectations are to to dump data in text using contrib/itmdump.c -+or derived tools, and to post-process it into reports. Such reports might -+include program messaging (such as application data streams via ITM, maybe -+using printf type messaging; code coverage analysis or so forth. Recent -+versions of CMSIS software reserve some ITM codespace for RTOS event -tracing and include ITM messaging support. -Clearly some of that data would be valuable for interactive debugging. -+ -+Should someone get ambitious, GUI reports should be possible. GNU tools -+for simpler reports like gprof may be simpler to support at first. -+In any case, OpenOCD is not currently GUI-oriented. Accordingly, we now -+expect any such graphics to come from postprocessing. - - measurements for RTOS event timings should also be easy to collect. -+Examples include context and message switch times, as well as times -for application interactions. -+ From eecba412cd8a6d515c925d87fe53e79881305517 Mon Sep 17 00:00:00 2001 From: Noah Moroze Date: Wed, 15 May 2024 22:39:12 -0400 Subject: [PATCH 0817/1312] tcl/memory: fix syntax errors Using a command in an expression requires a bracketed command substitution. These syntax errors were caught by tclint v0.2.5 (https://github.com/nmoroze/tclint): ``` tclint tcl/memory.tcl | grep "syntax error" ``` Change-Id: I510d46222f4fb02d6ef73121b231d5b2df77e5c0 Signed-off-by: Noah Moroze Reviewed-on: https://review.openocd.org/c/openocd/+/8279 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/memory.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/memory.tcl b/tcl/memory.tcl index b111749954..8b93b515eb 100644 --- a/tcl/memory.tcl +++ b/tcl/memory.tcl @@ -66,10 +66,10 @@ proc iswithin { ADDRESS BASE LEN } { proc address_info { ADDRESS } { foreach WHERE { FLASH RAM MMREGS XMEM UNKNOWN } { - if { info exists $WHERE } { + if { [info exists $WHERE] } { set lmt [set N_[set WHERE]] for { set region 0 } { $region < $lmt } { incr region } { - if { iswithin $ADDRESS $WHERE($region,BASE) $WHERE($region,LEN) } { + if { [iswithin $ADDRESS $WHERE($region,BASE) $WHERE($region,LEN)] } { return "$WHERE $region"; } } From 223e3d8fe76d86f01111bbe37f83a19d719ac81a Mon Sep 17 00:00:00 2001 From: Noah Moroze Date: Wed, 15 May 2024 22:47:53 -0400 Subject: [PATCH 0818/1312] tcl/target/c100helper: fix syntax errors Fixes: 64d89d5ee1a5 ("tcl: [3/3] prepare for jimtcl 0.81 'expr' syntax change") These syntax errors were caught by tclint v0.2.5 (https://github.com/nmoroze/tclint): ``` tclint tcl/target/c100helper.tcl | grep "syntax error" ``` Change-Id: I511c54353c4853560adca6b4852d48df2aade283 Signed-off-by: Noah Moroze Reviewed-on: https://review.openocd.org/c/openocd/+/8280 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/c100helper.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/target/c100helper.tcl b/tcl/target/c100helper.tcl index d1d3f258bc..ba0e4fe0af 100644 --- a/tcl/target/c100helper.tcl +++ b/tcl/target/c100helper.tcl @@ -176,7 +176,7 @@ proc setupAmbaClk {} { mmw $CLKCORE_AHB_CLK_CNTRL [expr {($x << 16) + ($w << 8) + $y}] 0x0 # wait for PLL to lock echo "Waiting for Amba PLL to lock" - while {[expr {[mrw $CLKCORE_PLL_STATUS] & $AHBCLK_PLL_LOCK]} == 0} { sleep 1 } + while {[mrw $CLKCORE_PLL_STATUS] & $AHBCLK_PLL_LOCK == 0} { sleep 1 } # remove the internal PLL bypass mmw $CLKCORE_AHB_CLK_CNTRL 0x0 $AHB_PLL_BY_CTRL # remove PLL from BYPASS mode using MUX @@ -250,7 +250,7 @@ proc setupArmClk {} { mmw $CLKCORE_ARM_CLK_CNTRL [expr {($x << 16) + ($w << 8) + $y}] 0x0 # wait for PLL to lock echo "Waiting for Amba PLL to lock" - while {[expr {[mrw $CLKCORE_PLL_STATUS] & $FCLK_PLL_LOCK]} == 0} { sleep 1 } + while {[mrw $CLKCORE_PLL_STATUS] & $FCLK_PLL_LOCK == 0} { sleep 1 } # remove the internal PLL bypass mmw $CLKCORE_ARM_CLK_CNTRL 0x0 $ARM_PLL_BY_CTRL # remove PLL from BYPASS mode using MUX From 7050cade9dcea77dd9882669ea97fddc6a8084d4 Mon Sep 17 00:00:00 2001 From: Noah Moroze Date: Wed, 15 May 2024 22:49:23 -0400 Subject: [PATCH 0819/1312] tcl/chip/st/spear: fix syntax errors While the current jimtcl does not consider this an error, the Tcl dodekalogue states that strings terminate at the second double quote character (see https://www.tcl.tk/man/tcl/TclCmd/Tcl.htm#M8). These syntax errors were caught by tclint v0.2.5 (https://github.com/nmoroze/tclint): ``` tclint tcl/chip/st/spear/spear3xx_ddr.tcl | grep "syntax error" ``` Change-Id: I2763d93095e3db7590644652f16b7b24939d6cae Signed-off-by: Noah Moroze Reviewed-on: https://review.openocd.org/c/openocd/+/8281 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- tcl/chip/st/spear/spear3xx_ddr.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/chip/st/spear/spear3xx_ddr.tcl b/tcl/chip/st/spear/spear3xx_ddr.tcl index 59925672dc..06962215b2 100644 --- a/tcl/chip/st/spear/spear3xx_ddr.tcl +++ b/tcl/chip/st/spear/spear3xx_ddr.tcl @@ -10,7 +10,7 @@ proc sp3xx_ddr_init {ddr_type {ddr_chips 1}} { if { $ddr_chips != 1 && $ddr_chips != 2 } { - error "Only 1 or 2 DDR chips permitted. Wrong value "$ddr_chips + error "Only 1 or 2 DDR chips permitted. Wrong value $ddr_chips" } if { $ddr_type == "mt47h64m16_3_333_cl5_async" } { @@ -21,7 +21,7 @@ proc sp3xx_ddr_init {ddr_type {ddr_chips 1}} { # ????? $ddr_chips # set ddr_size 0x????? } else { - error "sp3xx_ddr_init: unrecognized DDR type "$ddr_type + error "sp3xx_ddr_init: unrecognized DDR type $ddr_type" } # MPMC START From b5e7118048250a4ffc589fd8b82a11de05132d23 Mon Sep 17 00:00:00 2001 From: Noah Moroze Date: Wed, 15 May 2024 22:50:58 -0400 Subject: [PATCH 0820/1312] src/helper/startup: fix syntax errors The missing closing brackets were caught by tclint v0.2.5 (https://github.com/nmoroze/tclint): ``` tclint src/helper/startup.tcl | grep "syntax error" ``` The improperly escaped backslash was caught by manual inspection during code review. Change-Id: I8cd44e58040d4627f6b2fc8b88ca8a930cda0ba6 Signed-off-by: Noah Moroze Reviewed-on: https://review.openocd.org/c/openocd/+/8282 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/startup.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl index 5a0d479f5e..e6e76e68fd 100644 --- a/src/helper/startup.tcl +++ b/src/helper/startup.tcl @@ -11,10 +11,10 @@ proc find {filename} { if {[catch {ocd_find $filename} t]==0} { return $t } - if {[catch {ocd_find [string map {\ /} $filename} t]==0} { + if {[catch {ocd_find [string map {\\ /} $filename]} t]==0} { return $t } - if {[catch {ocd_find [string map {/ \\} $filename} t]==0} { + if {[catch {ocd_find [string map {/ \\} $filename]} t]==0} { return $t } # make sure error message matches original input string From 72b39088ee1772a65e74004fdc096db09edf8c0c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 8 Apr 2024 17:42:52 +0200 Subject: [PATCH 0821/1312] target: reset examine after assert_reset For some target, the API assert_reset() checks if the target has been examined, with target_was_examined(), to perform conditional operations like: - assert adapter's srst; - write some register to catch the reset vector; - invalidate the register cache. Targets created with -defer-examine gets the examine flag reset right before entering in their assert_reset(), disrupting the actions above. For targets created with -defer-examine, move the reset examine after the assert_reset(). Change-Id: If96e7876dcace8905165115292deb93a3e45cb36 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8293 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/target.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index efc168903b..7d4947a6ef 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5365,17 +5365,19 @@ COMMAND_HANDLER(handle_target_reset) return ERROR_FAIL; } - if (target->defer_examine) - target_reset_examined(target); - /* determine if we should halt or not. */ target->reset_halt = (a != 0); /* When this happens - all workareas are invalid. */ target_free_all_working_areas_restore(target, 0); /* do the assert */ - if (n->value == NVP_ASSERT) - return target->type->assert_reset(target); + if (n->value == NVP_ASSERT) { + int retval = target->type->assert_reset(target); + if (target->defer_examine) + target_reset_examined(target); + return retval; + } + return target->type->deassert_reset(target); } From 9623069e8090fbbf80250836e82feaecdb65233e Mon Sep 17 00:00:00 2001 From: Mark Featherston Date: Thu, 23 May 2024 13:24:32 -0700 Subject: [PATCH 0822/1312] jtag/drivers/ftdi: Use command_print instead of LOG_USER for get_signal LOG_USER only outputs to user interfaces, but leaves no way to get the FTDI inputs over the RPC interface. Switch to command_print so this string goes to both logs and the RPC interface. Change-Id: I99024194b6687b88d354ef278aa25f372c862c22 Signed-off-by: Mark Featherston Reviewed-on: https://review.openocd.org/c/openocd/+/8294 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: zapb --- src/jtag/drivers/ftdi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 58f83af592..661300506c 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -852,7 +852,7 @@ COMMAND_HANDLER(ftdi_handle_get_signal_command) uint16_t sig_data = 0; sig = find_signal_by_name(CMD_ARGV[0]); if (!sig) { - LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV[0]); + command_print(CMD, "interface configuration doesn't define signal '%s'", CMD_ARGV[0]); return ERROR_FAIL; } @@ -860,7 +860,7 @@ COMMAND_HANDLER(ftdi_handle_get_signal_command) if (ret != ERROR_OK) return ret; - LOG_USER("Signal %s = %#06x", sig->name, sig_data); + command_print(CMD, "%#06x", sig_data); return ERROR_OK; } From 2f8bb252ffb89cb2019f634230bc17b4dfccc75a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 21 Sep 2020 14:10:27 -0700 Subject: [PATCH 0823/1312] doc: Minimally describe the BSCAN tunnel interface. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add minimal documentation for the BSCAN tunnel interface. This is based on Tim Newsome 's work on the RISC-V fork. Change-Id: I5e0cd6972cb90649670249765e9bb30c2847eea6 Signed-off-by: Tim Newsome Signed-off-by: Bernhard Rosenkränzer Reviewed-on: https://review.openocd.org/c/openocd/+/8297 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 5eef81e40f..87e3650b46 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11279,8 +11279,22 @@ and DBUS registers, respectively. @end deffn @deffn {Command} {riscv use_bscan_tunnel} value -Enable or disable use of a BSCAN tunnel to reach DM. Supply the width of -the DM transport TAP's instruction register to enable. Supply a value of 0 to disable. +Enable or disable use of a BSCAN tunnel to reach the Debug Module. Supply the +width of the DM transport TAP's instruction register to enable. Supply a +value of 0 to disable. + +This BSCAN tunnel interface is specific to SiFive IP. Anybody may implement +it, but currently there is no good documentation on it. In a nutshell, this +feature scans USER4 into a Xilinx TAP to select the tunnel device (assuming +hardware is present and it is hooked up to the Xilinx USER4 IR) and +encapsulates a tunneled scan directive into a DR scan into the Xilinx TAP. A +tunneled DR scan consists of: +@enumerate +@item 1 bit that selects IR when 0, or DR when 1 +@item 7 bits that encode the width of the desired tunneled scan +@item A width+1 stream of bits for the tunneled TDI. The plus one is because there is a one-clock skew between TDI of Xilinx chain and TDO from tunneled chain. +@item 3 bits of zero that the tunnel uses to go back to idle state. +@end enumerate @end deffn @deffn {Command} {riscv set_ebreakm} on|off From d382c95d57c0ad9ed2dcc83c95404babb7647708 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Thu, 22 Jun 2023 19:28:52 +0300 Subject: [PATCH 0824/1312] target/riscv: support for smp group manipulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this functionality allows to query if a target belongs to some smp group and to dynamically turn on/off smp-specific behavior Change-Id: I67bafb1817c621a38ae4a2f55e12e4143e992c4e Signed-off-by: Parshintsev Anatoly Signed-off-by: Bernhard Rosenkränzer Reviewed-on: https://review.openocd.org/c/openocd/+/8296 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 12 ++++++++++++ src/target/riscv/riscv.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 87e3650b46..b782e0ba92 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11278,6 +11278,18 @@ When utilizing version 0.11 of the RISC-V Debug Specification, and DBUS registers, respectively. @end deffn +@deffn {Command} {riscv smp} [on|off] +Display, enable or disable SMP handling mode. This command is needed only if +user wants to temporary @b{disable} SMP handling for an existing SMP group +(see @code{aarch64 smp} for additional information). To define an SMP +group the command @code{target smp} should be used. +@end deffn + +@deffn {Command} {riscv smp_gdb} [core_id] +Display/set the current core displayed in GDB. This is needed only if +@code{riscv smp} was used. +@end deffn + @deffn {Command} {riscv use_bscan_tunnel} value Enable or disable use of a BSCAN tunnel to reach the Debug Module. Supply the width of the DM transport TAP's instruction register to enable. Supply a diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 9cd4922d20..511a3c6c32 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -3049,6 +3049,9 @@ static const struct command_registration riscv_command_handlers[] = { .usage = "", .chain = semihosting_common_handlers }, + { + .chain = smp_command_handlers + }, COMMAND_REGISTRATION_DONE }; From 84126893ff9305060b7d481ebf50e8c7405d7eae Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 25 May 2024 18:55:23 +0200 Subject: [PATCH 0825/1312] tcl/board: Add config for NXP FRDM-KV11Z Change-Id: I9cd497a085f8f9c7854ae3b96e60a73b3b050d0e Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8298 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/nxp/frdm-kv11z-jlink.cfg | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tcl/board/nxp/frdm-kv11z-jlink.cfg diff --git a/tcl/board/nxp/frdm-kv11z-jlink.cfg b/tcl/board/nxp/frdm-kv11z-jlink.cfg new file mode 100644 index 0000000000..725a37b9e6 --- /dev/null +++ b/tcl/board/nxp/frdm-kv11z-jlink.cfg @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Configuration file for NXP FRDM-KV11Z development boards. +# +# This configuration file is only for FRDM-KV11Z development boards with the +# SEGGER J-Link OpenSDA firmware, see: +# https://www.segger.com/products/debug-probes/j-link/models/other-j-links/opensda-sda-v2/ + +source [find interface/jlink.cfg] + +# Set working area size to 16 KiB. +set WORKAREASIZE 0x4000 + +# Set the chip name. +set CHIPNAME kv11z + +transport select swd + +source [find target/kx.cfg] + +reset_config srst_only From 0a3217b8ff34043e6c59850e5d7667edf97ec447 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 25 May 2024 18:57:10 +0200 Subject: [PATCH 0826/1312] tcl/board: Add config for NXP FRDM-KV31F Change-Id: I4d7cd1bcadd8159e4830107c2788708aef02add0 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8299 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/nxp/frdm-kv31f-jlink.cfg | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tcl/board/nxp/frdm-kv31f-jlink.cfg diff --git a/tcl/board/nxp/frdm-kv31f-jlink.cfg b/tcl/board/nxp/frdm-kv31f-jlink.cfg new file mode 100644 index 0000000000..e55a01cd70 --- /dev/null +++ b/tcl/board/nxp/frdm-kv31f-jlink.cfg @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Configuration file for NXP FRDM-KV31F development boards. +# +# This configuration file is only for FRDM-KV31F development boards with the +# SEGGER J-Link OpenSDA firmware, see: +# https://www.segger.com/products/debug-probes/j-link/models/other-j-links/opensda-sda-v2/ + +source [find interface/jlink.cfg] + +# Set working area size to 32 KiB. +set WORKAREASIZE 0x8000 + +# Set the chip name. +set CHIPNAME kv31f + +transport select swd + +source [find target/kx.cfg] + +reset_config srst_only From 1fba55a9b62118ac102c161bb8efcd2ceed379a1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 1 Jun 2024 10:41:29 +0200 Subject: [PATCH 0827/1312] flash/nor/tcl: Fix memory leak of flash bank name Change-Id: I54cd1ee479a0570ae849a71be47c82eebd1ae454 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8303 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/tcl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 720fb60a1b..6ac932be7f 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1298,6 +1298,7 @@ COMMAND_HANDLER(handle_flash_bank_command) if (retval != ERROR_OK) { LOG_ERROR("'%s' driver rejected flash bank at " TARGET_ADDR_FMT "; usage: %s", driver_name, c->base, driver->usage); + free(c->name); free(c); return retval; } From ed9203f4aaf3b4a28d5e28da2cdb1a52d9f7c408 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 25 Apr 2024 14:33:07 +0300 Subject: [PATCH 0828/1312] gdb_server: do not start multiple instances on "pipe" For configurations which include multiple targets and the "pipe" mode is requested only the first gdb_server instance should be enabled, otherwise GDB gets confusing replies, goes out of sync and the session fails in weird ways. Compile-tested only. Signed-off-by: Paul Fertser Change-Id: If8f13aa7b58e9b0dc6d5ae88cf75538b34cc1218 Reviewed-on: https://review.openocd.org/c/openocd/+/8222 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 7c2f41e41a..0ded8e4404 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3879,7 +3879,7 @@ static int gdb_target_add_one(struct target *target) return gdb_target_start(target, target->gdb_port_override); } - if (strcmp(gdb_port, "disabled") == 0) { + if (strcmp(gdb_port_next, "disabled") == 0) { LOG_INFO("gdb port disabled"); return ERROR_OK; } @@ -3908,6 +3908,8 @@ static int gdb_target_add_one(struct target *target) gdb_port_next = strdup("0"); } } + } else if (strcmp(gdb_port_next, "pipe") == 0) { + gdb_port_next = "disabled"; } } return retval; From 37f9485cef8b98aaed739c8140b3674441dc5876 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Jan 2024 23:25:13 +0100 Subject: [PATCH 0829/1312] flash/nor/nrf5: introduce address maps Preparatory change before extending support to nRF53 and 91. While on it, rename nRF51 and 52 specific routines and constants. Change-Id: I46bc496cef5cbde46d6755a4b908c875351f6612 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8110 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 237 +++++++++++++++++++++++++++---------------- 1 file changed, 152 insertions(+), 85 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index bf8c9da5fe..b4a8e979e8 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -19,8 +19,7 @@ #include #include -/* Both those values are constant across the current spectrum ofr nRF5 devices */ -#define WATCHDOG_REFRESH_REGISTER 0x40010600 +/* The refresh code is constant across the current spectrum of nRF5 devices */ #define WATCHDOG_REFRESH_VALUE 0x6e524635 enum { @@ -28,12 +27,9 @@ enum { }; enum nrf5_ficr_registers { - NRF5_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */ + NRF51_52_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */ -#define NRF5_FICR_REG(offset) (NRF5_FICR_BASE + offset) - - NRF5_FICR_CODEPAGESIZE = NRF5_FICR_REG(0x010), - NRF5_FICR_CODESIZE = NRF5_FICR_REG(0x014), +#define NRF5_FICR_REG(offset) (NRF51_52_FICR_BASE + (offset)) NRF51_FICR_CLENR0 = NRF5_FICR_REG(0x028), NRF51_FICR_PPFC = NRF5_FICR_REG(0x02C), @@ -42,39 +38,23 @@ enum nrf5_ficr_registers { NRF51_FICR_SIZERAMBLOCK1 = NRF5_FICR_REG(0x03C), NRF51_FICR_SIZERAMBLOCK2 = NRF5_FICR_REG(0x040), NRF51_FICR_SIZERAMBLOCK3 = NRF5_FICR_REG(0x044), - - /* CONFIGID is documented on nRF51 series only. - * On nRF52 is present but not documented */ - NRF5_FICR_CONFIGID = NRF5_FICR_REG(0x05C), - - /* Following registers are available on nRF52 and on nRF51 since rev 3 */ - NRF5_FICR_INFO_PART = NRF5_FICR_REG(0x100), - NRF5_FICR_INFO_VARIANT = NRF5_FICR_REG(0x104), - NRF5_FICR_INFO_PACKAGE = NRF5_FICR_REG(0x108), - NRF5_FICR_INFO_RAM = NRF5_FICR_REG(0x10C), - NRF5_FICR_INFO_FLASH = NRF5_FICR_REG(0x110), }; enum nrf5_uicr_registers { - NRF5_UICR_BASE = 0x10001000, /* User Information + NRF51_52_UICR_BASE = 0x10001000, /* User Information * Configuration Registers */ -#define NRF5_UICR_REG(offset) (NRF5_UICR_BASE + offset) +#define NRF5_UICR_REG(offset) (NRF51_52_UICR_BASE + (offset)) NRF51_UICR_CLENR0 = NRF5_UICR_REG(0x000), }; enum nrf5_nvmc_registers { - NRF5_NVMC_BASE = 0x4001E000, /* Non-Volatile Memory - * Controller Registers */ - -#define NRF5_NVMC_REG(offset) (NRF5_NVMC_BASE + offset) - - NRF5_NVMC_READY = NRF5_NVMC_REG(0x400), - NRF5_NVMC_CONFIG = NRF5_NVMC_REG(0x504), - NRF5_NVMC_ERASEPAGE = NRF5_NVMC_REG(0x508), - NRF5_NVMC_ERASEALL = NRF5_NVMC_REG(0x50C), - NRF5_NVMC_ERASEUICR = NRF5_NVMC_REG(0x514), + NRF5_NVMC_READY = 0x400, + NRF5_NVMC_CONFIG = 0x504, + NRF5_NVMC_ERASEPAGE = 0x508, + NRF5_NVMC_ERASEALL = 0x50C, + NRF5_NVMC_ERASEUICR = 0x514, NRF5_BPROT_BASE = 0x40000000, }; @@ -110,6 +90,28 @@ struct nrf5_device_spec { enum nrf5_features features; }; +/* FICR registers offsets */ +struct nrf5_ficr_map { + uint32_t codepagesize; + uint32_t codesize; + uint32_t configid; + uint32_t info_part; + uint32_t info_variant; + uint32_t info_package; + uint32_t info_ram; + uint32_t info_flash; +}; + +/* Map of device */ +struct nrf5_map { + uint32_t flash_base; + uint32_t ficr_base; + uint32_t uicr_base; + uint32_t nvmc_base; + + uint32_t watchdog_refresh_addr; +}; + struct nrf5_info { unsigned int refcount; @@ -127,6 +129,9 @@ struct nrf5_info { enum nrf5_features features; unsigned int flash_size_kb; unsigned int ram_size_kb; + + const struct nrf5_map *map; + const struct nrf5_ficr_map *ficr_offsets; }; #define NRF51_DEVICE_DEF(id, pt, var, bcode, fsize) \ @@ -238,6 +243,31 @@ static const struct nrf5_device_package nrf52_packages_table[] = { { 0x2009, "CF" }, }; +static const struct nrf5_ficr_map nrf51_52_ficr_offsets = { + .codepagesize = 0x10, + .codesize = 0x14, + + /* CONFIGID is documented on nRF51 series only. + * On nRF52 is present but not documented */ + .configid = 0x5c, + + /* Following registers are available on nRF52 and on nRF51 since rev 3 */ + .info_part = 0x100, + .info_variant = 0x104, + .info_package = 0x108, + .info_ram = 0x10c, + .info_flash = 0x110, +}; + +static const struct nrf5_map nrf51_52_map = { + .flash_base = NRF5_FLASH_BASE, + .ficr_base = NRF51_52_FICR_BASE, + .uicr_base = NRF51_52_UICR_BASE, + .nvmc_base = 0x4001E000, + + .watchdog_refresh_addr = 0x40010600, +}; + const struct flash_driver nrf5_flash, nrf51_flash; static bool nrf5_bank_is_probed(const struct flash_bank *bank) @@ -248,6 +278,24 @@ static bool nrf5_bank_is_probed(const struct flash_bank *bank) return nbank->probed; } +static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank) +{ + struct nrf5_info *chip = nbank->chip; + assert(chip); + + return nbank == &chip->bank[1]; +} + +static int nrf5_nvmc_read_u32(struct nrf5_info *chip, uint32_t reg_offset, uint32_t *value) +{ + return target_read_u32(chip->target, chip->map->nvmc_base + reg_offset, value); +} + +static int nrf5_nvmc_write_u32(struct nrf5_info *chip, uint32_t reg_offset, uint32_t value) +{ + return target_write_u32(chip->target, chip->map->nvmc_base + reg_offset, value); +} + static int nrf5_wait_for_nvmc(struct nrf5_info *chip) { uint32_t ready; @@ -256,7 +304,7 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip) int64_t ts_start = timeval_ms(); do { - res = target_read_u32(chip->target, NRF5_NVMC_READY, &ready); + res = nrf5_nvmc_read_u32(chip, NRF5_NVMC_READY, &ready); if (res != ERROR_OK) { LOG_ERROR("Error waiting NVMC_READY: generic flash write/erase error (check protection etc...)"); return res; @@ -276,7 +324,7 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip) static int nrf5_nvmc_erase_enable(struct nrf5_info *chip) { int res; - res = target_write_u32(chip->target, + res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_CONFIG, NRF5_NVMC_CONFIG_EEN); @@ -299,7 +347,7 @@ static int nrf5_nvmc_erase_enable(struct nrf5_info *chip) static int nrf5_nvmc_write_enable(struct nrf5_info *chip) { int res; - res = target_write_u32(chip->target, + res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_CONFIG, NRF5_NVMC_CONFIG_WEN); @@ -322,7 +370,7 @@ static int nrf5_nvmc_write_enable(struct nrf5_info *chip) static int nrf5_nvmc_read_only(struct nrf5_info *chip) { int res; - res = target_write_u32(chip->target, + res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_CONFIG, NRF5_NVMC_CONFIG_REN); @@ -350,7 +398,7 @@ static int nrf5_nvmc_generic_erase(struct nrf5_info *chip, if (res != ERROR_OK) goto error; - res = target_write_u32(chip->target, + res = nrf5_nvmc_write_u32(chip, erase_register, erase_value); if (res != ERROR_OK) @@ -370,7 +418,8 @@ static int nrf5_nvmc_generic_erase(struct nrf5_info *chip, return ERROR_FAIL; } -static int nrf5_protect_check_clenr0(struct flash_bank *bank) +/* nRF51 series only */ +static int nrf51_protect_check_clenr0(struct flash_bank *bank) { int res; uint32_t clenr0; @@ -403,7 +452,8 @@ static int nrf5_protect_check_clenr0(struct flash_bank *bank) return ERROR_OK; } -static int nrf5_protect_check_bprot(struct flash_bank *bank) +/* nRF52 series only */ +static int nrf52_protect_check_bprot(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; assert(nbank); @@ -432,26 +482,27 @@ static int nrf5_protect_check_bprot(struct flash_bank *bank) static int nrf5_protect_check(struct flash_bank *bank) { - /* UICR cannot be write protected so just return early */ - if (bank->base == NRF5_UICR_BASE) - return ERROR_OK; - struct nrf5_bank *nbank = bank->driver_priv; assert(nbank); struct nrf5_info *chip = nbank->chip; assert(chip); + /* UICR cannot be write protected so just return early */ + if (nrf5_bank_is_uicr(nbank)) + return ERROR_OK; + if (chip->features & NRF5_FEATURE_BPROT) - return nrf5_protect_check_bprot(bank); + return nrf52_protect_check_bprot(bank); if (chip->features & NRF5_FEATURE_SERIES_51) - return nrf5_protect_check_clenr0(bank); + return nrf51_protect_check_clenr0(bank); LOG_WARNING("Flash protection of this nRF device is not supported"); return ERROR_FLASH_OPER_UNSUPPORTED; } -static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int first, +/* nRF51 series only */ +static int nrf51_protect_clenr0(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { int res; @@ -517,8 +568,13 @@ static int nrf5_protect_clenr0(struct flash_bank *bank, int set, unsigned int fi static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); + /* UICR cannot be write protected so just bail out early */ - if (bank->base == NRF5_UICR_BASE) { + if (nrf5_bank_is_uicr(nbank)) { LOG_ERROR("UICR page does not support protection"); return ERROR_FLASH_OPER_UNSUPPORTED; } @@ -528,13 +584,8 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, return ERROR_TARGET_NOT_HALTED; } - struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); - struct nrf5_info *chip = nbank->chip; - assert(chip); - if (chip->features & NRF5_FEATURE_SERIES_51) - return nrf5_protect_clenr0(bank, set, first, last); + return nrf51_protect_clenr0(bank, set, first, last); LOG_ERROR("Flash protection setting is not supported on this nRF5 device"); return ERROR_FLASH_OPER_UNSUPPORTED; @@ -564,7 +615,7 @@ static const char *nrf5_decode_info_package(uint32_t package) return "xx"; } -static int get_nrf5_chip_type_str(const struct nrf5_info *chip, char *buf, unsigned int buf_size) +static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsigned int buf_size) { int res; if (chip->spec) { @@ -597,7 +648,7 @@ static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) assert(chip); char chip_type_str[256]; - if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) + if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) return ERROR_FAIL; command_print_sameline(cmd, "%s %ukB Flash, %ukB RAM", @@ -605,14 +656,16 @@ static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) return ERROR_OK; } -static int nrf5_read_ficr_info(struct nrf5_info *chip) +static int nrf5_read_ficr_info(struct nrf5_info *chip, const struct nrf5_map *map, + const struct nrf5_ficr_map *ficr_offsets) { int res; struct target *target = chip->target; + uint32_t ficr_base = map->ficr_base; chip->ficr_info_valid = false; - res = target_read_u32(target, NRF5_FICR_INFO_PART, &chip->ficr_info.part); + res = target_read_u32(target, ficr_base + ficr_offsets->info_part, &chip->ficr_info.part); if (res != ERROR_OK) { LOG_DEBUG("Couldn't read FICR INFO.PART register"); return res; @@ -655,19 +708,19 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip) * VARIANT and PACKAGE coding is unknown for a nRF51 device. * nRF52 devices have FICR INFO documented and always filled. */ - res = target_read_u32(target, NRF5_FICR_INFO_VARIANT, &chip->ficr_info.variant); + res = target_read_u32(target, ficr_base + ficr_offsets->info_variant, &chip->ficr_info.variant); if (res != ERROR_OK) return res; - res = target_read_u32(target, NRF5_FICR_INFO_PACKAGE, &chip->ficr_info.package); + res = target_read_u32(target, ficr_base + ficr_offsets->info_package, &chip->ficr_info.package); if (res != ERROR_OK) return res; - res = target_read_u32(target, NRF5_FICR_INFO_RAM, &chip->ficr_info.ram); + res = target_read_u32(target, ficr_base + ficr_offsets->info_ram, &chip->ficr_info.ram); if (res != ERROR_OK) return res; - res = target_read_u32(target, NRF5_FICR_INFO_FLASH, &chip->ficr_info.flash); + res = target_read_u32(target, ficr_base + ficr_offsets->info_flash, &chip->ficr_info.flash); if (res != ERROR_OK) return res; @@ -675,7 +728,8 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip) return ERROR_OK; } -static int nrf5_get_ram_size(struct target *target, uint32_t *ram_size) +/* nRF51 series only */ +static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size) { int res; @@ -718,24 +772,33 @@ static int nrf5_probe(struct flash_bank *bank) assert(chip); struct target *target = chip->target; - uint32_t configid; - res = target_read_u32(target, NRF5_FICR_CONFIGID, &configid); - if (res != ERROR_OK) { - LOG_ERROR("Couldn't read CONFIGID register"); - return res; - } - - /* HWID is stored in the lower two bytes of the CONFIGID register */ - chip->hwid = configid & 0xFFFF; + chip->spec = NULL; /* guess a nRF51 series if the device has no FICR INFO and we don't know HWID */ chip->features = NRF5_FEATURE_SERIES_51; + chip->map = &nrf51_52_map; + chip->ficr_offsets = &nrf51_52_ficr_offsets; /* Don't bail out on error for the case that some old engineering * sample has FICR INFO registers unreadable. We can proceed anyway. */ - (void)nrf5_read_ficr_info(chip); + (void)nrf5_read_ficr_info(chip, chip->map, chip->ficr_offsets); + + const struct nrf5_ficr_map *ficr_offsets = chip->ficr_offsets; + uint32_t ficr_base = chip->map->ficr_base; + uint32_t configid = 0; + res = target_read_u32(target, ficr_base + ficr_offsets->configid, &configid); + if (res != ERROR_OK) { + if (chip->features & NRF5_FEATURE_SERIES_51) { + LOG_ERROR("Couldn't read FICR CONFIGID register"); + return res; + } + + LOG_DEBUG("Couldn't read FICR CONFIGID register, using FICR INFO"); + } + + /* HWID is stored in the lower two bytes of the CONFIGID register */ + chip->hwid = configid & 0xFFFF; - chip->spec = NULL; for (size_t i = 0; i < ARRAY_SIZE(nrf5_known_devices_table); i++) { if (chip->hwid == nrf5_known_devices_table[i].hwid) { chip->spec = &nrf5_known_devices_table[i]; @@ -753,15 +816,17 @@ static int nrf5_probe(struct flash_bank *bank) if (chip->ficr_info_valid) { chip->ram_size_kb = chip->ficr_info.ram; - } else { + } else if (chip->features & NRF5_FEATURE_SERIES_51) { uint32_t ram_size; - nrf5_get_ram_size(target, &ram_size); + nrf51_get_ram_size(target, &ram_size); chip->ram_size_kb = ram_size / 1024; + } else { + chip->ram_size_kb = 0; } - /* The value stored in NRF5_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */ + /* The value stored in FICR CODEPAGESIZE is the number of bytes in one page of FLASH. */ uint32_t flash_page_size; - res = target_read_u32(chip->target, NRF5_FICR_CODEPAGESIZE, + res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize, &flash_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); @@ -769,9 +834,10 @@ static int nrf5_probe(struct flash_bank *bank) } /* Note the register name is misleading, - * NRF5_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */ + * FICR CODESIZE is the number of pages in flash memory, not the number of bytes! */ uint32_t num_sectors; - res = target_read_u32(chip->target, NRF5_FICR_CODESIZE, &num_sectors); + res = target_read_u32(chip->target, ficr_base + ficr_offsets->codesize, + &num_sectors); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; @@ -781,7 +847,7 @@ static int nrf5_probe(struct flash_bank *bank) if (!chip->bank[0].probed && !chip->bank[1].probed) { char chip_type_str[256]; - if (get_nrf5_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) + if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) return ERROR_FAIL; const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid); LOG_INFO("%s%s %ukB Flash, %ukB RAM", @@ -793,7 +859,7 @@ static int nrf5_probe(struct flash_bank *bank) free(bank->sectors); - if (bank->base == NRF5_FLASH_BASE) { + if (bank->base == chip->map->flash_base) { /* Sanity check */ if (chip->spec && chip->flash_size_kb != chip->spec->flash_size_kb) LOG_WARNING("Chip's reported Flash capacity does not match expected one"); @@ -810,6 +876,7 @@ static int nrf5_probe(struct flash_bank *bank) chip->bank[0].probed = true; } else { + /* UICR bank */ bank->num_sectors = 1; bank->size = flash_page_size; @@ -849,7 +916,7 @@ static int nrf5_erase_page(struct flash_bank *bank, LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset); - if (bank->base == NRF5_UICR_BASE) { + if (bank->base == chip->map->uicr_base) { if (chip->features & NRF5_FEATURE_SERIES_51) { uint32_t ppfc; res = target_read_u32(chip->target, NRF51_FICR_PPFC, @@ -958,7 +1025,7 @@ static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t address, const u buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[3].value, 0, 32, address); buf_set_u32(reg_params[4].value, 0, 32, WATCHDOG_REFRESH_VALUE); - buf_set_u32(reg_params[5].value, 0, 32, WATCHDOG_REFRESH_REGISTER); + buf_set_u32(reg_params[5].value, 0, 32, chip->map->watchdog_refresh_addr); retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4, 0, NULL, @@ -1008,7 +1075,7 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer, * is protected. */ if (chip->features & NRF5_FEATURE_SERIES_51) { - res = nrf5_protect_check_clenr0(bank); + res = nrf51_protect_check_clenr0(bank); if (res != ERROR_OK) return res; @@ -1065,7 +1132,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, * is protected. */ if (chip->features & NRF5_FEATURE_SERIES_51) { - res = nrf5_protect_check_clenr0(bank); + res = nrf51_protect_check_clenr0(bank); if (res != ERROR_OK) return res; } @@ -1136,7 +1203,7 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) switch (bank->base) { case NRF5_FLASH_BASE: - case NRF5_UICR_BASE: + case NRF51_52_UICR_BASE: break; default: LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); @@ -1157,7 +1224,7 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) case NRF5_FLASH_BASE: nbank = &chip->bank[0]; break; - case NRF5_UICR_BASE: + case NRF51_52_UICR_BASE: nbank = &chip->bank[1]; break; } From fc7a428fc2a5d1e74621e56a2cbd2c31566fc63f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 14:17:27 +0100 Subject: [PATCH 0830/1312] flash/nor/nrf5: make flash erase little faster Enable and disable erase mode only once instead of toggling it for each sector. Refactor to decrease the number of call levels. Change-Id: Ie546a4fc24da0eea2753a2bebaa63d941ef7aa1d Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8111 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 85 ++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index b4a8e979e8..641f3ab216 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -375,7 +375,7 @@ static int nrf5_nvmc_read_only(struct nrf5_info *chip) NRF5_NVMC_CONFIG_REN); if (res != ERROR_OK) { - LOG_ERROR("Failed to enable read-only operation"); + LOG_ERROR("Failed to disable write/erase operation"); return res; } /* @@ -389,35 +389,6 @@ static int nrf5_nvmc_read_only(struct nrf5_info *chip) return res; } -static int nrf5_nvmc_generic_erase(struct nrf5_info *chip, - uint32_t erase_register, uint32_t erase_value) -{ - int res; - - res = nrf5_nvmc_erase_enable(chip); - if (res != ERROR_OK) - goto error; - - res = nrf5_nvmc_write_u32(chip, - erase_register, - erase_value); - if (res != ERROR_OK) - goto set_read_only; - - res = nrf5_wait_for_nvmc(chip); - if (res != ERROR_OK) - goto set_read_only; - - return nrf5_nvmc_read_only(chip); - -set_read_only: - nrf5_nvmc_read_only(chip); -error: - LOG_ERROR("Failed to erase reg: 0x%08"PRIx32" val: 0x%08"PRIx32, - erase_register, erase_value); - return ERROR_FAIL; -} - /* nRF51 series only */ static int nrf51_protect_check_clenr0(struct flash_bank *bank) { @@ -900,13 +871,6 @@ static int nrf5_auto_probe(struct flash_bank *bank) return nrf5_probe(bank); } -static int nrf5_erase_all(struct nrf5_info *chip) -{ - LOG_DEBUG("Erasing all non-volatile memory"); - return nrf5_nvmc_generic_erase(chip, - NRF5_NVMC_ERASEALL, - 0x00000001); -} static int nrf5_erase_page(struct flash_bank *bank, struct nrf5_info *chip, @@ -938,17 +902,18 @@ static int nrf5_erase_page(struct flash_bank *bank, } } - res = nrf5_nvmc_generic_erase(chip, - NRF5_NVMC_ERASEUICR, - 0x00000001); - + res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEUICR, 0x00000001); } else { - res = nrf5_nvmc_generic_erase(chip, - NRF5_NVMC_ERASEPAGE, - sector->offset); + res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEPAGE, sector->offset); + } + + if (res != ERROR_OK) { + /* caller logs the error */ + return res; } + res = nrf5_wait_for_nvmc(chip); return res; } @@ -1137,13 +1102,18 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, return res; } + res = nrf5_nvmc_erase_enable(chip); + if (res != ERROR_OK) + goto error; + /* For each sector to be erased */ for (unsigned int s = first; s <= last; s++) { if (chip->features & NRF5_FEATURE_SERIES_51 && bank->sectors[s].is_protected == 1) { LOG_ERROR("Flash sector %d is protected", s); - return ERROR_FLASH_PROTECTED; + res = ERROR_FLASH_PROTECTED; + break; } res = nrf5_erase_page(bank, chip, &bank->sectors[s]); @@ -1153,7 +1123,9 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, } } - return ERROR_OK; +error: + nrf5_nvmc_read_only(chip); + return res; } static void nrf5_free_driver_priv(struct flash_bank *bank) @@ -1277,14 +1249,27 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) } } - res = nrf5_erase_all(chip); + res = nrf5_nvmc_erase_enable(chip); + if (res != ERROR_OK) + goto error; + + res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEALL, 0x00000001); + if (res != ERROR_OK) { + LOG_ERROR("Mass erase failed"); + goto error; + } + + res = nrf5_wait_for_nvmc(chip); + if (res != ERROR_OK) + LOG_ERROR("Mass erase did not complete"); + +error: + nrf5_nvmc_read_only(chip); + if (res == ERROR_OK) { LOG_INFO("Mass erase completed."); if (chip->features & NRF5_FEATURE_SERIES_51) LOG_INFO("A reset or power cycle is required if the flash was protected before."); - - } else { - LOG_ERROR("Failed to erase the chip"); } return res; From d94daf776c5778c94b2ead4db4bc368a20ffa5cf Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 12:45:49 +0100 Subject: [PATCH 0831/1312] flash/nor/nrf5: add basic nRF53 and nRF91 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Probes all flash and UICR areas. Flash erase and write tested. On nRF53 mass erase works on the application core flash bank only. The Tcl script nrf53_recover can serve as the workaround on the network core. TODO: mass erase of the nRF53 network core flash. Some ideas taken from [1] and [2]. Change-Id: I8e27a780f4d82bcabf029f79b87ac46cf6a531c7 Link: [1] 7404: flash: nor: add support for Nordic nRF9160 | https://review.openocd.org/c/openocd/+/7404 Link: [2] 8062: flash: nor: add support for Nordic nRF9160 | https://review.openocd.org/c/openocd/+/8062 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8112 Reviewed-by: Tomáš BeneÅ¡ Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 13 +-- src/flash/nor/nrf5.c | 207 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 181 insertions(+), 39 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index b782e0ba92..8c9f3ff845 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7316,12 +7316,13 @@ flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME @end deffn @deffn {Flash Driver} {nrf5} -All members of the nRF51 microcontroller families from Nordic Semiconductor -include internal flash and use ARM Cortex-M0 core. nRF52 family powered -by ARM Cortex-M4 or M4F core is supported too. nRF52832 is fully supported -including BPROT flash protection scheme. nRF52833 and nRF52840 devices are -supported with the exception of security extensions (flash access control list -- ACL). +Supports all members of the nRF51, nRF52 and nRF53 microcontroller families from +Nordic Semiconductor. nRF91 family is supported too. One driver handles both +the main flash and the UICR area. + +Flash protection is handled on nRF51 family and nRF52805, nRF52810, nRF52811, +nRF52832 devices. Flash access control list (ACL) protection scheme of the newer +devices is not supported. @example flash bank $_FLASHNAME nrf5 0 0x00000000 0 0 $_TARGETNAME diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 641f3ab216..80243ed59f 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -79,6 +79,9 @@ enum nrf5_features { NRF5_FEATURE_SERIES_52 = BIT(1), NRF5_FEATURE_BPROT = BIT(2), NRF5_FEATURE_ACL_PROT = BIT(3), + NRF5_FEATURE_SERIES_53 = BIT(4), + NRF5_FEATURE_SERIES_91 = BIT(5), + NRF5_FEATURE_ERASE_BY_FLASH_WR = BIT(6), }; struct nrf5_device_spec { @@ -268,6 +271,55 @@ static const struct nrf5_map nrf51_52_map = { .watchdog_refresh_addr = 0x40010600, }; + +/* Third generation devices (nRF53, nRF91) */ + +static const struct nrf5_ficr_map nrf53_91_ficr_offsets = { + .codepagesize = 0x220, + .codesize = 0x224, + .configid = 0x200, + .info_part = 0x20c, + .info_variant = 0x210, + .info_package = 0x214, + .info_ram = 0x218, + .info_flash = 0x21c, +}; + +enum { + NRF53APP_91_FICR_BASE = 0x00FF0000, + NRF53APP_91_UICR_BASE = 0x00FF8000, + NRF53NET_FLASH_BASE = 0x01000000, + NRF53NET_FICR_BASE = 0x01FF0000, + NRF53NET_UICR_BASE = 0x01FF8000, +}; + +static const struct nrf5_map nrf53app_91_map = { + .flash_base = NRF5_FLASH_BASE, + .ficr_base = NRF53APP_91_FICR_BASE, + .uicr_base = NRF53APP_91_UICR_BASE, + .nvmc_base = 0x50039000, + + .watchdog_refresh_addr = 0x50018600, +}; + +/* nRF53 duality: + * SoC consists of two Cortex-M33 cores: + * - application core with security extensions + * - network core + * Each core has its own RAM, flash, FICR and UICR + * The flash driver probes and handles flash and UICR of one core + * independently of those dedicated to the other core. + */ +static const struct nrf5_map nrf53net_map = { + .flash_base = NRF53NET_FLASH_BASE, + .ficr_base = NRF53NET_FICR_BASE, + .uicr_base = NRF53NET_UICR_BASE, + .nvmc_base = 0x41080000, + + .watchdog_refresh_addr = 0x41080000, +}; + + const struct flash_driver nrf5_flash, nrf51_flash; static bool nrf5_bank_is_probed(const struct flash_bank *bank) @@ -595,10 +647,15 @@ static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsig } else if (chip->ficr_info_valid) { char variant[5]; nrf5_info_variant_to_str(chip->ficr_info.variant, variant); - res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s%.2s(build code: %s)", - chip->ficr_info.part, - nrf5_decode_info_package(chip->ficr_info.package), - variant, &variant[2]); + if (chip->features & (NRF5_FEATURE_SERIES_53 | NRF5_FEATURE_SERIES_91)) { + res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s", + chip->ficr_info.part, variant); + } else { + res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s%.2s(build code: %s)", + chip->ficr_info.part, + nrf5_decode_info_package(chip->ficr_info.package), + variant, &variant[2]); + } } else { res = snprintf(buf, buf_size, "nRF51xxx (HWID 0x%04" PRIx16 ")", chip->hwid); } @@ -627,26 +684,27 @@ static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) return ERROR_OK; } -static int nrf5_read_ficr_info(struct nrf5_info *chip, const struct nrf5_map *map, +static int nrf5_read_ficr_info_part(struct nrf5_info *chip, const struct nrf5_map *map, const struct nrf5_ficr_map *ficr_offsets) { - int res; struct target *target = chip->target; uint32_t ficr_base = map->ficr_base; - chip->ficr_info_valid = false; - - res = target_read_u32(target, ficr_base + ficr_offsets->info_part, &chip->ficr_info.part); - if (res != ERROR_OK) { + int res = target_read_u32(target, ficr_base + ficr_offsets->info_part, &chip->ficr_info.part); + if (res != ERROR_OK) LOG_DEBUG("Couldn't read FICR INFO.PART register"); - return res; - } + + return res; +} + +static int nrf51_52_partno_check(struct nrf5_info *chip) +{ uint32_t series = chip->ficr_info.part & 0xfffff000; switch (series) { case 0x51000: chip->features = NRF5_FEATURE_SERIES_51; - break; + return ERROR_OK; case 0x52000: chip->features = NRF5_FEATURE_SERIES_52; @@ -665,19 +723,40 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip, const struct nrf5_map *ma chip->features |= NRF5_FEATURE_ACL_PROT; break; } - break; + return ERROR_OK; default: LOG_DEBUG("FICR INFO likely not implemented. Invalid PART value 0x%08" - PRIx32, chip->ficr_info.part); + PRIx32, chip->ficr_info.part); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } +} + +static int nrf53_91_partno_check(struct nrf5_info *chip) +{ + uint32_t series = chip->ficr_info.part & 0xffffff00; + switch (series) { + case 0x5300: + chip->features = NRF5_FEATURE_SERIES_53 | NRF5_FEATURE_ERASE_BY_FLASH_WR; + return ERROR_OK; - /* Now we know the device has FICR INFO filled by something relevant: - * Although it is not documented, the tested nRF51 rev 3 devices - * have FICR INFO.PART, RAM and FLASH of the same format as nRF52. - * VARIANT and PACKAGE coding is unknown for a nRF51 device. - * nRF52 devices have FICR INFO documented and always filled. */ + case 0x9100: + chip->features = NRF5_FEATURE_SERIES_91 | NRF5_FEATURE_ERASE_BY_FLASH_WR; + return ERROR_OK; + + default: + LOG_DEBUG("Invalid FICR INFO PART value 0x%08" + PRIx32, chip->ficr_info.part); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } +} + +static int nrf5_read_ficr_more_info(struct nrf5_info *chip) +{ + int res; + struct target *target = chip->target; + const struct nrf5_ficr_map *ficr_offsets = chip->ficr_offsets; + uint32_t ficr_base = chip->map->ficr_base; res = target_read_u32(target, ficr_base + ficr_offsets->info_variant, &chip->ficr_info.variant); if (res != ERROR_OK) @@ -692,11 +771,7 @@ static int nrf5_read_ficr_info(struct nrf5_info *chip, const struct nrf5_map *ma return res; res = target_read_u32(target, ficr_base + ficr_offsets->info_flash, &chip->ficr_info.flash); - if (res != ERROR_OK) - return res; - - chip->ficr_info_valid = true; - return ERROR_OK; + return res; } /* nRF51 series only */ @@ -735,7 +810,7 @@ static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size) static int nrf5_probe(struct flash_bank *bank) { - int res; + int res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; struct nrf5_bank *nbank = bank->driver_priv; assert(nbank); @@ -744,15 +819,72 @@ static int nrf5_probe(struct flash_bank *bank) struct target *target = chip->target; chip->spec = NULL; + chip->ficr_info_valid = false; - /* guess a nRF51 series if the device has no FICR INFO and we don't know HWID */ - chip->features = NRF5_FEATURE_SERIES_51; - chip->map = &nrf51_52_map; - chip->ficr_offsets = &nrf51_52_ficr_offsets; + /* First try to detect nRF53/91 */ + switch (bank->base) { + case NRF5_FLASH_BASE: + case NRF53APP_91_UICR_BASE: + res = nrf5_read_ficr_info_part(chip, &nrf53app_91_map, &nrf53_91_ficr_offsets); + if (res != ERROR_OK) + break; - /* Don't bail out on error for the case that some old engineering - * sample has FICR INFO registers unreadable. We can proceed anyway. */ - (void)nrf5_read_ficr_info(chip, chip->map, chip->ficr_offsets); + res = nrf53_91_partno_check(chip); + if (res != ERROR_OK) + break; + + chip->map = &nrf53app_91_map; + chip->ficr_offsets = &nrf53_91_ficr_offsets; + break; + + case NRF53NET_FLASH_BASE: + case NRF53NET_UICR_BASE: + res = nrf5_read_ficr_info_part(chip, &nrf53net_map, &nrf53_91_ficr_offsets); + if (res != ERROR_OK) + break; + + res = nrf53_91_partno_check(chip); + if (res != ERROR_OK) + break; + + chip->map = &nrf53net_map; + chip->ficr_offsets = &nrf53_91_ficr_offsets; + break; + + default: + break; + } + + /* If nRF53/91 is not detected, try nRF51/52 */ + if (res != ERROR_OK) { + /* Guess a nRF51 series if the device has no FICR INFO and we don't know HWID */ + chip->features = NRF5_FEATURE_SERIES_51; + chip->map = &nrf51_52_map; + chip->ficr_offsets = &nrf51_52_ficr_offsets; + + /* Don't bail out on error for the case that some old engineering + * sample has FICR INFO registers unreadable. We can proceed anyway. */ + res = nrf5_read_ficr_info_part(chip, chip->map, chip->ficr_offsets); + if (res == ERROR_OK) + res = nrf51_52_partno_check(chip); + } + + if (res == ERROR_OK) { + /* Now we know the device has FICR INFO filled by something relevant: + * Although it is not documented, the tested nRF51 rev 3 devices + * have FICR INFO.PART, RAM and FLASH of the same format as nRF52. + * VARIANT and PACKAGE coding is unknown for a nRF51 device. + * nRF52 devices have FICR INFO documented and always filled. */ + res = nrf5_read_ficr_more_info(chip); + if (res == ERROR_OK) { + chip->ficr_info_valid = true; + } else if (chip->features & NRF5_FEATURE_SERIES_51) { + LOG_DEBUG("Couldn't read some of FICR INFO registers"); + } else { + LOG_ERROR("Couldn't read some of FICR INFO registers"); + return res; + } + } const struct nrf5_ficr_map *ficr_offsets = chip->ficr_offsets; uint32_t ficr_base = chip->map->ficr_base; @@ -904,6 +1036,9 @@ static int nrf5_erase_page(struct flash_bank *bank, res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEUICR, 0x00000001); + } else if (chip->features & NRF5_FEATURE_ERASE_BY_FLASH_WR) { + res = target_write_u32(chip->target, bank->base + sector->offset, 0xffffffff); + } else { res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEPAGE, sector->offset); } @@ -1175,7 +1310,10 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) switch (bank->base) { case NRF5_FLASH_BASE: + case NRF53NET_FLASH_BASE: case NRF51_52_UICR_BASE: + case NRF53APP_91_UICR_BASE: + case NRF53NET_UICR_BASE: break; default: LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); @@ -1194,9 +1332,12 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) switch (bank->base) { case NRF5_FLASH_BASE: + case NRF53NET_FLASH_BASE: nbank = &chip->bank[0]; break; case NRF51_52_UICR_BASE: + case NRF53APP_91_UICR_BASE: + case NRF53NET_UICR_BASE: nbank = &chip->bank[1]; break; } From 17be341d38bda1115b3eb8878ef7f830982fabfb Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 15:33:47 +0100 Subject: [PATCH 0832/1312] tcl/target: add nRF53 and nRF91 config files Both devices can be configured with or without SWD multidrop. nRF53 network core is examined on demand to avoid problems when the core is forced off. Change-Id: I08f88ff48ff7ac592e9214b89ca8e5e9428573a5 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8113 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/nrf53.cfg | 146 ++++++++++++++++++++++++++++++++++++++ tcl/target/nrf91.cfg | 63 ++++++++++++++++ tcl/target/nrf_common.cfg | 86 ++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 tcl/target/nrf53.cfg create mode 100644 tcl/target/nrf91.cfg create mode 100644 tcl/target/nrf_common.cfg diff --git a/tcl/target/nrf53.cfg b/tcl/target/nrf53.cfg new file mode 100644 index 0000000000..307df902c2 --- /dev/null +++ b/tcl/target/nrf53.cfg @@ -0,0 +1,146 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic nRF53 series: dual ARM Cortex-M33, multidrop SWD +# + +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME nrf53 +} + +# Work-area is a space in RAM used for flash programming +# By default use 16kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x4000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x6ba02477 +} + +# Configurable instance ID resides in application UICR TINSTANCE +if { [info exists SWD_INSTANCE_ID] } { + set _SWD_INSTANCE_ID $SWD_INSTANCE_ID +} else { + set _SWD_INSTANCE_ID 0 +} + +swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID + +if { [info exists SWD_MULTIDROP] } { + dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu -dp-id 0x0070289 -instance-id $_SWD_INSTANCE_ID +} else { + dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +} + +set _TARGETNAME_APP $_CHIPNAME.cpuapp +target create $_TARGETNAME_APP cortex_m -dap $_CHIPNAME.dap + +$_TARGETNAME_APP configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# The network core is not accessible over HLA +if { ![using_hla] } { + set _TARGETNAME_NET $_CHIPNAME.cpunet + target create $_TARGETNAME_NET cortex_m -dap $_CHIPNAME.dap -ap-num 1 -defer-examine + + targets $_TARGETNAME_APP + + $_TARGETNAME_NET configure -work-area-phys 0x21000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 +} + +# Keep adapter speed less or equal 2000 kHz or flash programming fails! +adapter speed 1000 + +source [find target/nrf_common.cfg] + +flash bank $_CHIPNAME.app.flash nrf5 0x00000000 0 0 0 $_TARGETNAME_APP +flash bank $_CHIPNAME.app.uicr nrf5 0x00FF8000 0 0 0 $_TARGETNAME_APP + +if { ![using_hla] } { + + flash bank $_CHIPNAME.net.flash nrf5 0x01000000 0 0 0 $_TARGETNAME_NET + flash bank $_CHIPNAME.net.uicr nrf5 0x01FF8000 0 0 0 $_TARGETNAME_NET + + # System reset sets NETWORK.FORCEOFF which keeps the network core in reset + # Don't touch network core during reset + $_TARGETNAME_NET configure -event reset-assert {} + # and start it after application core reset is finished to make all flash accessible + $_TARGETNAME_APP configure -event reset-init "nrf53_cpunet_release $_CHIPNAME" + + $_TARGETNAME_APP cortex_m reset_config sysresetreq + $_TARGETNAME_NET cortex_m reset_config sysresetreq + + $_TARGETNAME_APP configure -event examine-fail { _nrf_check_ap_lock 2 3 } + $_TARGETNAME_NET configure -event examine-fail { _nrf_check_ap_lock 3 3 } + + $_TARGETNAME_NET configure -event gdb-attach "_nrf53_cpunet_gdb_attach $_CHIPNAME" + + proc _nrf53_cpunet_gdb_attach { _CHIPNAME } { + set _TARGETNAME_APP $_CHIPNAME.cpuapp + set _TARGETNAME_NET $_CHIPNAME.cpunet + set RESET_NETWORK_FORCEOFF 0x50005614 + + set is_off [$_TARGETNAME_APP read_memory $RESET_NETWORK_FORCEOFF 32 1] + if { $is_off } { + nrf53_cpunet_release $_CHIPNAME + $_TARGETNAME_NET arp_poll + $_TARGETNAME_NET arp_waitstate halted 100 + } else { + if { ![$_TARGETNAME_NET was_examined] } { + $_TARGETNAME_NET arp_examine + $_TARGETNAME_NET arp_poll + } + set s [$_TARGETNAME_NET curstate] + if { ![string compare $s "halted"] } { + halt + } + } + } + lappend _telnet_autocomplete_skip _nrf53_cpunet_gdb_attach + + # Release the network core + proc nrf53_cpunet_release { {_CHIPNAME nrf53} } { + set _TARGETNAME_APP $_CHIPNAME.cpuapp + set _TARGETNAME_NET $_CHIPNAME.cpunet + set RESET_NETWORK_FORCEOFF 0x50005614 + set RESET_NETWORK_WORKAROUND 0x50005618 + set CORTEX_M_DCB_DEMCR 0xE000EDFC + + $_TARGETNAME_APP mww $RESET_NETWORK_WORKAROUND 1 + $_TARGETNAME_APP mww $RESET_NETWORK_FORCEOFF 0 + $_TARGETNAME_APP mww $RESET_NETWORK_FORCEOFF 1 + set err [catch {$_TARGETNAME_NET arp_examine}] + if { $err } { + if { ![_nrf_check_ap_lock 3 3] } { + echo "Error: \[$_TARGETNAME_NET\] examination failed" + } + return + } + # set TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET + $_TARGETNAME_NET mww $CORTEX_M_DCB_DEMCR 0x01000501 + # Write DEMCR directly intead of permanetly setting by cortex_m vector_catch reset + # following cortex_m_endreset_event() restores the original DEMCR value + $_TARGETNAME_APP mww $RESET_NETWORK_FORCEOFF 0 + $_TARGETNAME_APP mww $RESET_NETWORK_WORKAROUND 0 + } + + # Mass erase and unlock the device using proprietary nRF CTRL-AP (AP #2 or #3) + proc nrf53_cpuapp_recover {} { + _nrf_ctrl_ap_recover 2 + } + add_help_text nrf53_cpuapp_recover "Mass erase flash and unlock nRF53 application CPU" + + proc nrf53_recover {} { + _nrf_ctrl_ap_recover 3 1 + } + add_help_text nrf53_recover "Mass erase all device flash and unlock nRF53" +} diff --git a/tcl/target/nrf91.cfg b/tcl/target/nrf91.cfg new file mode 100644 index 0000000000..e0ff4e5460 --- /dev/null +++ b/tcl/target/nrf91.cfg @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic nRF91 series: ARM Cortex-M33, SWD only +# + +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME nrf91 +} + +# Work-area is a space in RAM used for flash programming +# By default use 16kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x4000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x6ba02477 +} + +swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID + +# Contrary to the product specification at least nRF9161 supports multidrop SWD. +# The instance ID is fixed, no more than one nRF91 can be connected to one SWD bus. +if { [info exists SWD_MULTIDROP] } { + dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu -dp-id 0x0090289 -instance-id 0 +} else { + dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap + +# Keep adapter speed less or equal 2000 kHz or flash programming fails! +adapter speed 1000 + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +source [find target/nrf_common.cfg] + +flash bank $_CHIPNAME.flash nrf5 0x00000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.uicr nrf5 0x00FF8000 0 0 0 $_TARGETNAME + +if { ![using_hla] } { + $_TARGETNAME cortex_m reset_config sysresetreq + + $_TARGETNAME configure -event examine-fail { _nrf_check_ap_lock 4 3 } +} + +# Mass erase and unlock the device using proprietary nRF CTRL-AP (AP #4) +proc nrf91_recover {} { + _nrf_ctrl_ap_recover 4 +} +add_help_text nrf91_recover "Mass erase and unlock nRF91 device" diff --git a/tcl/target/nrf_common.cfg b/tcl/target/nrf_common.cfg new file mode 100644 index 0000000000..2ae5011e4e --- /dev/null +++ b/tcl/target/nrf_common.cfg @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic nRF52, nRF53 and nRF91 CTRL-AP handling +# + +if { [using_hla] } { + echo "" + echo "nRF device has a CTRL-AP dedicated to recover the device from AP lock." + echo "A high level adapter (like a ST-Link) you are currently using cannot access" + echo "the CTRL-AP so 'nrfxx_recover' command will not work." + echo "Do not enable UICR APPROTECT." + echo "" +} else { + + # Test if debug/MEM-AP is locked by UICR APPROTECT + proc _nrf_check_ap_lock { ctrl_ap_num unlocked_value } { + set target [target current] + set dap [$target cget -dap] + set err [catch {set APPROTECTSTATUS [$dap apreg $ctrl_ap_num 0xc]}] + if {$err == 0 && $APPROTECTSTATUS < $unlocked_value} { + echo "" + echo "****** WARNING ******" + echo "\[$target\] device has AP lock engaged (see UICR APPROTECT register)." + echo "Debug access is denied." + echo "Use 'nrfxx_recover' to erase and unlock the device." + echo "" + poll off + return 1 + } + return 0 + } + + # Mass erase and unlock the device using proprietary nRF CTRL-AP + proc _nrf_ctrl_ap_recover { ctrl_ap_num {is_cpunet 0} } { + set target [target current] + set dap [$target cget -dap] + + set IDR [$dap apreg $ctrl_ap_num 0xfc] + if {$IDR != 0x12880000} { + echo "Error: Cannot access nRF CTRL-AP!" + return + } + + poll off + + # Reset and trigger ERASEALL task + $dap apreg $ctrl_ap_num 4 0 + $dap apreg $ctrl_ap_num 4 1 + + for {set i 0} {1} {incr i} { + set ERASEALLSTATUS [$dap apreg $ctrl_ap_num 8] + if {$ERASEALLSTATUS == 0} { + echo "\[$target\] device has been successfully erased and unlocked." + break + } + if {$i == 0} { + echo "Waiting for chip erase..." + } + if {$i >= 150} { + echo "Error: \[$target\] recovery failed." + break + } + sleep 100 + } + + # Assert reset + $dap apreg $ctrl_ap_num 0 1 + + # Deassert reset + $dap apreg $ctrl_ap_num 0 0 + + # Reset ERASEALL task + $dap apreg $ctrl_ap_num 4 0 + + if { $is_cpunet } { + reset init + } else { + sleep 100 + $target arp_examine + poll on + } + } + + lappend _telnet_autocomplete_skip _nrf_check_ap_lock _nrf_ctrl_ap_recover +} From 70b362d4f47194eced99b448cc99b093641d1465 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 18:17:48 +0100 Subject: [PATCH 0833/1312] flash/nor/nrf5: show proper SoC type on newer nRF91 devices Since nRF9160 Product Specification v2.1 the new UICR SIPINFO fields should be preferred over UICR INFO. Tested on nRF9161. Signed-off-by: Tomas Vanek Change-Id: Ib8005b3b6292aa20fa83c1dcebd2de27df58b661 Reviewed-on: https://review.openocd.org/c/openocd/+/8114 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 80243ed59f..cac233d475 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -285,6 +285,22 @@ static const struct nrf5_ficr_map nrf53_91_ficr_offsets = { .info_flash = 0x21c, }; +/* Since nRF9160 Product Specification v2.1 there is + * a new UICR field SIPINFO, which should be preferred. + * The original INFO fields describe just a part of the chip + * (PARTNO=9120 at nRF9161) + */ +static const struct nrf5_ficr_map nrf91new_ficr_offsets = { + .codepagesize = 0x220, + .codesize = 0x224, + .configid = 0x200, + .info_part = 0x140, /* SIPINFO.PARTNO */ + .info_variant = 0x148, /* SIPINFO.VARIANT */ + .info_package = 0x214, + .info_ram = 0x218, + .info_flash = 0x21c, +}; + enum { NRF53APP_91_FICR_BASE = 0x00FF0000, NRF53APP_91_UICR_BASE = 0x00FF8000, @@ -614,12 +630,17 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, return ERROR_FLASH_OPER_UNSUPPORTED; } -static bool nrf5_info_variant_to_str(uint32_t variant, char *bf) +static bool nrf5_info_variant_to_str(uint32_t variant, char *bf, bool swap) { uint8_t b[4]; - h_u32_to_be(b, variant); - if (isalnum(b[0]) && isalnum(b[1]) && isalnum(b[2]) && isalnum(b[3])) { + if (swap) + h_u32_to_le(b, variant); + else + h_u32_to_be(b, variant); + + if (isalnum(b[0]) && isalnum(b[1]) && isalnum(b[2]) && + (isalnum(b[3]) || b[3] == 0)) { memcpy(bf, b, 4); bf[4] = 0; return true; @@ -646,7 +667,10 @@ static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsig chip->spec->part, chip->spec->variant, chip->spec->build_code); } else if (chip->ficr_info_valid) { char variant[5]; - nrf5_info_variant_to_str(chip->ficr_info.variant, variant); + + nrf5_info_variant_to_str(chip->ficr_info.variant, variant, + chip->features & NRF5_FEATURE_SERIES_91); + if (chip->features & (NRF5_FEATURE_SERIES_53 | NRF5_FEATURE_SERIES_91)) { res = snprintf(buf, buf_size, "nRF%" PRIx32 "-%s", chip->ficr_info.part, variant); @@ -825,6 +849,16 @@ static int nrf5_probe(struct flash_bank *bank) switch (bank->base) { case NRF5_FLASH_BASE: case NRF53APP_91_UICR_BASE: + res = nrf5_read_ficr_info_part(chip, &nrf53app_91_map, &nrf91new_ficr_offsets); + if (res == ERROR_OK) { + res = nrf53_91_partno_check(chip); + if (res == ERROR_OK) { + chip->map = &nrf53app_91_map; + chip->ficr_offsets = &nrf91new_ficr_offsets; + break; + } + } + res = nrf5_read_ficr_info_part(chip, &nrf53app_91_map, &nrf53_91_ficr_offsets); if (res != ERROR_OK) break; From e4c0904731320c686e5074e68db8358e2f3ce83d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 22 Jan 2024 21:09:31 +0100 Subject: [PATCH 0834/1312] flash/nor/nrf5: handle ERROR_WAIT during nRF91 flash erase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Erase is initiated by write to a flash address. Due to the silicon errata of nRF91 the write stalls the bus until the page erase is finished (takes up to 87ms). If the adapter does not handle SWD WAIT properly, the following read in nrf5_wait_for_nvmc() returns ERROR_WAIT. Wait for fixed time before accessing AP. Not nice, but the only working solution until all adapters handle SWD WAIT. If the fixed wait does not suffice, continue the wait loop after a delay. It makes some unnecessary noise however erase works. Signed-off-by: Tomas Vanek Change-Id: I63faf38dad79440a0117ed79930442bd2843c6db Reviewed-on: https://review.openocd.org/c/openocd/+/8115 Reviewed-by: Tomáš BeneÅ¡ Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index cac233d475..f07433e674 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -373,6 +373,12 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip) do { res = nrf5_nvmc_read_u32(chip, NRF5_NVMC_READY, &ready); + if (res == ERROR_WAIT) { + /* The adapter does not handle SWD WAIT properly, + * add some delay to reduce number of error messages */ + alive_sleep(10); + continue; + } if (res != ERROR_OK) { LOG_ERROR("Error waiting NVMC_READY: generic flash write/erase error (check protection etc...)"); return res; @@ -1072,6 +1078,22 @@ static int nrf5_erase_page(struct flash_bank *bank, } else if (chip->features & NRF5_FEATURE_ERASE_BY_FLASH_WR) { res = target_write_u32(chip->target, bank->base + sector->offset, 0xffffffff); + /* nRF9160 errata [2] NVMC: CPU code execution from RAM halted during + * flash page erase operation + * https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF9160_Rev1%2FERR%2FnRF9160%2FRev1%2Flatest%2Fanomaly_160_2.html + * affects also erasing by debugger MEM-AP write: + * + * Write to a flash address stalls the bus for 87 ms until + * page erase finishes! This makes problems if the adapter does not + * handle SWD WAIT properly or does not wait long enough. + * Using a target algo would not help, AP gets unresponsive too. + * Neither sending AP ABORT helps, the next AP access stalls again. + * Simply wait long enough before accessing AP again... + * + * The same errata was observed in nRF9161 + */ + if (chip->features & NRF5_FEATURE_SERIES_91) + alive_sleep(90); } else { res = nrf5_nvmc_write_u32(chip, NRF5_NVMC_ERASEPAGE, sector->offset); From 400cf213c05d17cede4dca4787a5533959bd2183 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Mon, 27 May 2024 14:54:05 +0300 Subject: [PATCH 0835/1312] fix GCC's `-Wcalloc-transposed-args` warning GCC 14.1.0 warns about calls to `calloc()` with element size as the first argument. Link: https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/Warning-Options.html#index-Wcalloc-transposed-args Change-Id: I7d44a74a003ee6ec49d165f91727972478214587 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8301 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- src/flash/nor/ambiqmicro.c | 2 +- src/flash/nor/at91sam7.c | 4 ++-- src/flash/nor/kinetis.c | 4 ++-- src/flash/nor/max32xxx.c | 2 +- src/flash/nor/msp432.c | 2 +- src/flash/nor/stellaris.c | 2 +- src/flash/nor/stm32f2x.c | 2 +- src/jtag/drivers/angie.c | 2 +- src/jtag/drivers/ulink.c | 2 +- src/target/arc_jtag.c | 4 ++-- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c index 2b458bc8fd..bb893778ce 100644 --- a/src/flash/nor/ambiqmicro.c +++ b/src/flash/nor/ambiqmicro.c @@ -124,7 +124,7 @@ FLASH_BANK_COMMAND_HANDLER(ambiqmicro_flash_bank_command) if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; - ambiqmicro_info = calloc(sizeof(struct ambiqmicro_flash_bank), 1); + ambiqmicro_info = calloc(1, sizeof(struct ambiqmicro_flash_bank)); bank->driver_priv = ambiqmicro_info; diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index 6879a1bf23..86c80765fc 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -560,7 +560,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank) if (bnk > 0) { if (!t_bank->next) { /* create a new flash bank element */ - struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1); + struct flash_bank *fb = calloc(1, sizeof(struct flash_bank)); if (!fb) { LOG_ERROR("No memory for flash bank"); return ERROR_FAIL; @@ -748,7 +748,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command) if (bnk > 0) { if (!t_bank->next) { /* create a new bank element */ - struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1); + struct flash_bank *fb = calloc(1, sizeof(struct flash_bank)); if (!fb) { LOG_ERROR("No memory for flash bank"); return ERROR_FAIL; diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index e8074e35bb..fee36444e6 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -930,7 +930,7 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) k_chip = kinetis_get_chip(target); if (!k_chip) { - k_chip = calloc(sizeof(struct kinetis_chip), 1); + k_chip = calloc(1, sizeof(struct kinetis_chip)); if (!k_chip) { LOG_ERROR("No memory"); return ERROR_FAIL; @@ -1031,7 +1031,7 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) bank_idx - k_chip->num_pflash_blocks); } - bank = calloc(sizeof(struct flash_bank), 1); + bank = calloc(1, sizeof(struct flash_bank)); if (!bank) return ERROR_FAIL; diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index 51d6ae271a..59a14af8b8 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -87,7 +87,7 @@ FLASH_BANK_COMMAND_HANDLER(max32xxx_flash_bank_command) return ERROR_FLASH_BANK_INVALID; } - info = calloc(sizeof(struct max32xxx_flash_bank), 1); + info = calloc(1, sizeof(struct max32xxx_flash_bank)); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], info->flash_size); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], info->flc_base); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], info->sector_size); diff --git a/src/flash/nor/msp432.c b/src/flash/nor/msp432.c index 5e2935d02b..b5e2b0bf86 100644 --- a/src/flash/nor/msp432.c +++ b/src/flash/nor/msp432.c @@ -937,7 +937,7 @@ static int msp432_probe(struct flash_bank *bank) if (is_main && MSP432P4 == msp432_bank->family_type) { /* Create the info flash bank needed by MSP432P4 variants */ - struct flash_bank *info = calloc(sizeof(struct flash_bank), 1); + struct flash_bank *info = calloc(1, sizeof(struct flash_bank)); if (!info) return ERROR_FAIL; diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 972686e3f3..eab6244d43 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -453,7 +453,7 @@ FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command) if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; - stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1); + stellaris_info = calloc(1, sizeof(struct stellaris_flash_bank)); bank->base = 0x0; bank->driver_priv = stellaris_info; diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 4e0f731827..3bafde56f8 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -1020,7 +1020,7 @@ static int stm32x_probe(struct flash_bank *bank) assert(num_sectors > 0); bank->num_sectors = num_sectors; - bank->sectors = calloc(sizeof(struct flash_sector), num_sectors); + bank->sectors = calloc(num_sectors, sizeof(struct flash_sector)); if (stm32x_otp_is_f7(bank)) bank->size = STM32F7_OTP_SIZE; diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index c024667bdb..81dd1af82a 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -1597,7 +1597,7 @@ static int angie_queue_scan(struct angie *device, struct jtag_command *cmd) /* Allocate TDO buffer if required */ if (type == SCAN_IN || type == SCAN_IO) { - tdo_buffer_start = calloc(sizeof(uint8_t), scan_size_bytes); + tdo_buffer_start = calloc(scan_size_bytes, sizeof(uint8_t)); if (!tdo_buffer_start) return ERROR_FAIL; diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 4f23c6c7fa..0fe8989b9d 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -1473,7 +1473,7 @@ static int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd) /* Allocate TDO buffer if required */ if ((type == SCAN_IN) || (type == SCAN_IO)) { - tdo_buffer_start = calloc(sizeof(uint8_t), scan_size_bytes); + tdo_buffer_start = calloc(scan_size_bytes, sizeof(uint8_t)); if (!tdo_buffer_start) return ERROR_FAIL; diff --git a/src/target/arc_jtag.c b/src/target/arc_jtag.c index ddb4f62322..a186709c61 100644 --- a/src/target/arc_jtag.c +++ b/src/target/arc_jtag.c @@ -298,7 +298,7 @@ static int arc_jtag_read_registers(struct arc_jtag *jtag_info, uint32_t type, ARC_JTAG_READ_FROM_CORE_REG : ARC_JTAG_READ_FROM_AUX_REG); arc_jtag_enque_set_transaction(jtag_info, transaction, TAP_DRPAUSE); - uint8_t *data_buf = calloc(sizeof(uint8_t), count * 4); + uint8_t *data_buf = calloc(count * 4, sizeof(uint8_t)); arc_jtag_enque_register_rw(jtag_info, addr, data_buf, NULL, count); @@ -498,7 +498,7 @@ int arc_jtag_read_memory(struct arc_jtag *jtag_info, uint32_t addr, if (!count) return ERROR_OK; - data_buf = calloc(sizeof(uint8_t), count * 4); + data_buf = calloc(count * 4, sizeof(uint8_t)); arc_jtag_enque_reset_transaction(jtag_info); /* We are reading from memory. */ From b49e03f77ed890b39274d94ae6267bf07a68ba98 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 26 May 2024 12:38:43 +0200 Subject: [PATCH 0836/1312] target/arm_tpiu_swo: Fix memory leak on error In case of fail to allocate 'obj->name', the memory allocated for 'obj->out_filename' is not freed, thus leaking. Since 'obj' is allocated with calloc(), thus zeroed, switch to use the common error exit path for both allocations of 'obj->name' and 'obj->out_filename'. Fixes: 2506ccb50915 ("target/arm_tpiu_swo: Fix division by zero") Change-Id: I412f66ddd7bf7d260cee495324058482b26ff0c5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8300 Tested-by: jenkins Reviewed-by: zapb --- src/target/arm_tpiu_swo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index b5a4882011..55a9778447 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -965,8 +965,7 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const obj->out_filename = strdup("external"); if (!obj->out_filename) { LOG_ERROR("Out of memory"); - free(obj); - return JIM_ERR; + goto err_exit; } Jim_Obj *n; @@ -974,8 +973,7 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const obj->name = strdup(Jim_GetString(n, NULL)); if (!obj->name) { LOG_ERROR("Out of memory"); - free(obj); - return JIM_ERR; + goto err_exit; } /* Do the rest as "configure" options */ From ed30c9a572ba8b7e8959f8998ebfeaaa12a37d70 Mon Sep 17 00:00:00 2001 From: George Voicu Date: Sat, 5 Nov 2022 10:48:47 +0100 Subject: [PATCH 0837/1312] tcl/fpga/xilinx-dna: Support for reading Spartan3 DNA code Add Xilinx Spartan3 ISC_DNA instruction Signed-off-by: George Voicu Change-Id: Iaddb079c9fdd1b91c65def36878fe81783098696 Reviewed-on: https://review.openocd.org/c/openocd/+/7331 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/fpga/xilinx-dna.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tcl/fpga/xilinx-dna.cfg b/tcl/fpga/xilinx-dna.cfg index 56f8c14119..6b16b78fb1 100644 --- a/tcl/fpga/xilinx-dna.cfg +++ b/tcl/fpga/xilinx-dna.cfg @@ -1,7 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-or-later +# Spartan3: Table 9-5 in https://www.xilinx.com/support/documentation/user_guides/ug332.pdf proc xilinx_dna_addr {chip} { array set addrs { + Spartan3 0x31 Spartan6 0x30 Series7 0x17 } @@ -43,3 +45,7 @@ proc xc7_get_dna {tap} { proc xc6s_get_dna {tap} { return [xilinx_get_dna $tap Spartan6] } + +proc xc3s_get_dna {tap} { + return [xilinx_get_dna $tap Spartan3] +} From a420f00d106cb2638bb4c272a4780e05623ea64b Mon Sep 17 00:00:00 2001 From: George Voicu Date: Sat, 5 Nov 2022 11:08:43 +0100 Subject: [PATCH 0838/1312] tcl/fpga: Support for Xilinx Spartan3 series devices Tap definition for Xilinx Spartan 3/3E/3A/3AN/3A-DSP devices. Signed-off-by: George Voicu Change-Id: Ieda2b61fc270840f9192976697fcac259c45e3b8 Reviewed-on: https://review.openocd.org/c/openocd/+/7335 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/fpga/xilinx-xc3s.cfg | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tcl/fpga/xilinx-xc3s.cfg diff --git a/tcl/fpga/xilinx-xc3s.cfg b/tcl/fpga/xilinx-xc3s.cfg new file mode 100644 index 0000000000..7c17206c95 --- /dev/null +++ b/tcl/fpga/xilinx-xc3s.cfg @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Xilinx Spartan3 generation +# https://www.xilinx.com/support/documentation/user_guides/ug331.pdf + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME xc3s +} + +# Table 12-4 in https://www.xilinx.com/support/documentation/user_guides/ug332.pdf +# the 4 top bits (28:31) are the die stepping, ignore them. +jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \ + -expected-id 0x02210093 \ + -expected-id 0x02218093 \ + -expected-id 0x02220093 \ + -expected-id 0x02228093 \ + -expected-id 0x02230093 \ + -expected-id 0x02610093 \ + -expected-id 0x02618093 \ + -expected-id 0x02620093 \ + -expected-id 0x02628093 \ + -expected-id 0x02630093 \ + -expected-id 0x03840093 \ + -expected-id 0x0384E093 \ + -expected-id 0x01C10093 \ + -expected-id 0x01C1A093 \ + -expected-id 0x01C22093 \ + -expected-id 0x01C2E093 \ + -expected-id 0x01C3A093 \ + -expected-id 0x0140C093 \ + -expected-id 0x01414093 \ + -expected-id 0x0141C093 \ + -expected-id 0x01428093 \ + -expected-id 0x01434093 \ + -expected-id 0x01440093 \ + -expected-id 0x01448093 \ + -expected-id 0x01450093 + +pld create $_CHIPNAME.pld virtex2 -chain-position $_CHIPNAME.tap + +source [find fpga/xilinx-dna.cfg] From b1600bb342e191463094f534f71a4e5d51407e18 Mon Sep 17 00:00:00 2001 From: George Voicu Date: Sat, 5 Nov 2022 11:14:22 +0100 Subject: [PATCH 0839/1312] tcl/board: Support for Digilent Nexys 2 board Support Digilent Nexys 2 board JTAG chain Signed-off-by: George Voicu Change-Id: I350f80b49303c4b0402d93ebc120a591ef727551 Reviewed-on: https://review.openocd.org/c/openocd/+/7336 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/digilent_nexys2.cfg | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tcl/board/digilent_nexys2.cfg diff --git a/tcl/board/digilent_nexys2.cfg b/tcl/board/digilent_nexys2.cfg new file mode 100644 index 0000000000..c1c5b2ac68 --- /dev/null +++ b/tcl/board/digilent_nexys2.cfg @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# https://digilent.com/reference/programmable-logic/nexys-2/start +# +# The Digilent Nexy2 normally requires proprietary tools to program and will +# enumerate as: +# ID 1443:0005 1443 ONBOARD USB +# +# However, the ixo-usb-jtag project provides an alternative open firmware for +# the on board programmer. When using this firmware the board will then +# enumerate as: +# ID 16c0:06ad ixo.de USB-JTAG-IF (With SerialNumber == hw_nexys) +# +# See the interface/usb-jtag.cfg for more information. + +source [find interface/usb-jtag.cfg] +source [find cpld/xilinx-xcf-s.cfg] +source [find fpga/xilinx-xc3s.cfg] + +# Usage: +# +# Load Bitstream into FPGA: +# openocd -f board/digilent_nexys2.cfg -c "init;\ +# pld load 0 bitstream.bit;\ +# shutdown" + +# Read Unique Device Identifier (DNA): +# openocd -f board/digilent_nexys2.cfg -c "init;\ +# xilinx_print_dna [xc3s_get_dna xc3s.tap];\ +# shutdown" From 7e4c9609ca9dfd2734f59d6261d2681b2211283b Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Fri, 23 Feb 2024 20:49:54 +0100 Subject: [PATCH 0840/1312] pld/intel: remove duplicated code Change-Id: I043d16c77ce97d3e888774747ed6bfc4c7e63c04 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/8082 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/pld/intel.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pld/intel.c b/src/pld/intel.c index a39e16c212..fe85cd62cf 100644 --- a/src/pld/intel.c +++ b/src/pld/intel.c @@ -248,9 +248,6 @@ static int intel_load(struct pld_device *pld_device, const char *filename) if (retval != ERROR_OK) return retval; - if (retval != ERROR_OK) - return retval; - retval = intel_set_instr(tap, 0x002); if (retval != ERROR_OK) { free(bit_file.data); From 9bc7a381b26703f38752771b924fe1c4b918b23d Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Mon, 19 Feb 2024 23:22:19 +0100 Subject: [PATCH 0841/1312] pld/intel: remove idcodes from intel.c Remove list of id codes for all families. Maintain a list with id, bscan-length and check position in the tcl config files for each family. The Intel FPGA Driver option 'family' is not otional anymore. Change-Id: I9a40a041069e84f6b4728f2cd715756a36759c89 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/8083 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 5 +- src/jtag/tcl.c | 5 +- src/pld/intel.c | 174 ++++---------------------------- tcl/fpga/altera-arriaii.cfg | 27 +++-- tcl/fpga/altera-cyclone10.cfg | 44 ++++---- tcl/fpga/altera-cycloneiii.cfg | 43 ++++---- tcl/fpga/altera-cycloneiv.cfg | 53 +++++----- tcl/fpga/altera-cyclonev.cfg | 58 +++++------ tcl/fpga/altera_common_init.cfg | 9 ++ 9 files changed, 153 insertions(+), 265 deletions(-) create mode 100644 tcl/fpga/altera_common_init.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 8c9f3ff845..03fa944661 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8886,13 +8886,12 @@ For the option @option{-family} @var{name} is one of @var{trion|titanium}. @end deffn -@deffn {FPGA Driver} {intel} [@option{-family} ] +@deffn {FPGA Driver} {intel} @option{-family} This driver can be used to load the bitstream into Intel (former Altera) FPGAs. The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10, Arria II are supported. @c Arria V and Arria 10, MAX II, MAX V, MAX10) -For the option @option{-family} @var{name} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}. -This is needed when the JTAG ID of the device is ambiguous (same ID is used for chips in different families). +The option @option{-family} @var{name} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}. As input file format the driver supports a '.rbf' (raw bitstream file) file. The '.rbf' file can be generated from a '.sof' file with @verb{|quartus_cpf -c blinker.sof blinker.rbf|} diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 7995529018..1a4c4b774e 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -760,8 +760,9 @@ static const struct command_registration jtag_subcommand_handlers[] = { .mode = COMMAND_EXEC, .handler = handle_jtag_configure, .help = "Return any Tcl handler for the specified " - "TAP event.", - .usage = "tap_name '-event' event_name", + "TAP event or the value of the IDCODE found in hardware.", + .usage = "tap_name '-event' event_name | " + "tap_name '-idcode'", }, { .name = "names", diff --git a/src/pld/intel.c b/src/pld/intel.c index fe85cd62cf..a4bdabe26f 100644 --- a/src/pld/intel.c +++ b/src/pld/intel.c @@ -37,142 +37,11 @@ struct intel_pld_device { enum intel_family_e family; }; -struct intel_device_parameters_elem { - uint32_t id; - unsigned int boundary_scan_length; - int checkpos; - enum intel_family_e family; -}; - -static const struct intel_device_parameters_elem intel_device_parameters[] = { - {0x020f10dd, 603, 226, INTEL_CYCLONEIII}, /* EP3C5 EP3C10 */ - {0x020f20dd, 1080, 409, INTEL_CYCLONEIII}, /* EP3C16 */ - {0x020f30dd, 732, 286, INTEL_CYCLONEIII}, /* EP3C25 */ - {0x020f40dd, 1632, 604, INTEL_CYCLONEIII}, /* EP3C40 */ - {0x020f50dd, 1164, 442, INTEL_CYCLONEIII}, /* EP3C55 */ - {0x020f60dd, 1314, 502, INTEL_CYCLONEIII}, /* EP3C80 */ - {0x020f70dd, 1620, 613, INTEL_CYCLONEIII}, /* EP3C120*/ - {0x027010dd, 1314, 226, INTEL_CYCLONEIII}, /* EP3CLS70 */ - {0x027000dd, 1314, 226, INTEL_CYCLONEIII}, /* EP3CLS100 */ - {0x027030dd, 1314, 409, INTEL_CYCLONEIII}, /* EP3CLS150 */ - {0x027020dd, 1314, 409, INTEL_CYCLONEIII}, /* EP3CLS200 */ - - {0x020f10dd, 603, 226, INTEL_CYCLONEIV}, /* EP4CE6 EP4CE10 */ - {0x020f20dd, 1080, 409, INTEL_CYCLONEIV}, /* EP4CE15 */ - {0x020f30dd, 732, 286, INTEL_CYCLONEIV}, /* EP4CE22 */ - {0x020f40dd, 1632, 604, INTEL_CYCLONEIV}, /* EP4CE30 EP4CE40 */ - {0x020f50dd, 1164, 442, INTEL_CYCLONEIV}, /* EP4CE55 */ - {0x020f60dd, 1314, 502, INTEL_CYCLONEIV}, /* EP4CE75 */ - {0x020f70dd, 1620, 613, INTEL_CYCLONEIV}, /* EP4CE115 */ - {0x028010dd, 260, 229, INTEL_CYCLONEIV}, /* EP4CGX15 */ - {0x028120dd, 494, 463, INTEL_CYCLONEIV}, /* EP4CGX22 */ - {0x028020dd, 494, 463, INTEL_CYCLONEIV}, /* EP4CGX30 */ - {0x028230dd, 1006, 943, INTEL_CYCLONEIV}, /* EP4CGX30 */ - {0x028130dd, 1006, 943, INTEL_CYCLONEIV}, /* EP4CGX50 */ - {0x028030dd, 1006, 943, INTEL_CYCLONEIV}, /* EP4CGX75 */ - {0x028140dd, 1495, 1438, INTEL_CYCLONEIV}, /* EP4CGX110 */ - {0x028040dd, 1495, 1438, INTEL_CYCLONEIV}, /* EP4CGX150 */ - - {0x02b150dd, 864, 163, INTEL_CYCLONEV}, /* 5CEBA2F23 5CEBA2F17 5CEFA2M13 5CEFA2F23 5CEBA2U15 5CEFA2U19 5CEBA2U19 */ - {0x02d020dd, 1485, 19, INTEL_CYCLONEV}, /* 5CSXFC6D6F31 5CSTFD6D5F31 5CSEBA6U23 5CSEMA6U23 5CSEBA6U19 5CSEBA6U23 - 5CSEBA6U19 5CSEMA6F31 5CSXFC6C6U23 */ - {0x02b040dd, 1728, -1, INTEL_CYCLONEV}, /* 5CGXFC9EF35 5CGXBC9AU19 5CGXBC9CF23 5CGTFD9CF23 5CGXFC9AU19 5CGXFC9CF23 - 5CGXFC9EF31 5CGXFC9DF27 5CGXBC9DF27 5CGXBC9EF31 5CGTFD9EF31 5CGTFD9EF35 - 5CGTFD9AU19 5CGXBC9EF35 5CGTFD9DF27 */ - {0x02b050dd, 864, 163, INTEL_CYCLONEV}, /* 5CEFA4U19 5CEFA4F23 5CEFA4M13 5CEBA4F17 5CEBA4U15 5CEBA4U19 5CEBA4F23 */ - {0x02b030dd, 1488, 19, INTEL_CYCLONEV}, /* 5CGXBC7CU19 5CGTFD7CU19 5CGTFD7DF27 5CGXFC7BM15 5CGXFC7DF27 5CGXFC7DF31 - 5CGTFD7CF23 5CGXBC7CF23 5CGXBC7DF31 5CGTFD7BM15 5CGXFC7CU19 5CGTFD7DF31 - 5CGXBC7BM15 5CGXFC7CF23 5CGXBC7DF27 */ - {0x02d120dd, 1485, -1, INTEL_CYCLONEV}, /* 5CSEBA5U23 5CSEBA5U23 5CSTFD5D5F31 5CSEBA5U19 5CSXFC5D6F31 5CSEMA5U23 - 5CSEMA5F31 5CSXFC5C6U23 5CSEBA5U19 */ - {0x02b220dd, 1104, 19, INTEL_CYCLONEV}, /* 5CEBA5U19 5CEFA5U19 5CEFA5M13 5CEBA5F23 5CEFA5F23 */ - {0x02b020dd, 1104, 19, INTEL_CYCLONEV}, /* 5CGXBC5CU19 5CGXFC5F6M11 5CGXFC5CM13 5CGTFD5CF23 5CGXBC5CF23 5CGTFD5CF27 - 5CGTFD5F5M11 5CGXFC5CF27 5CGXFC5CU19 5CGTFD5CM13 5CGXFC5CF23 5CGXBC5CF27 - 5CGTFD5CU19 */ - {0x02d010dd, 1197, -1, INTEL_CYCLONEV}, /* 5CSEBA4U23 5CSXFC4C6U23 5CSEMA4U23 5CSEBA4U23 5CSEBA4U19 5CSEBA4U19 - 5CSXFC2C6U23 */ - {0x02b120dd, 1104, 19, INTEL_CYCLONEV}, /* 5CGXFC4CM13 5CGXFC4CU19 5CGXFC4F6M11 5CGXBC4CU19 5CGXFC4CF27 5CGXBC4CF23 - 5CGXBC4CF27 5CGXFC4CF23 */ - {0x02b140dd, 1728, -1, INTEL_CYCLONEV}, /* 5CEFA9F31 5CEBA9F31 5CEFA9F27 5CEBA9U19 5CEBA9F27 5CEFA9U19 5CEBA9F23 - 5CEFA9F23 */ - {0x02b010dd, 720, 19, INTEL_CYCLONEV}, /* 5CGXFC3U15 5CGXBC3U15 5CGXFC3F23 5CGXFC3U19 5CGXBC3U19 5CGXBC3F23 */ - {0x02b130dd, 1488, 19, INTEL_CYCLONEV}, /* 5CEFA7F31 5CEBA7F27 5CEBA7M15 5CEFA7U19 5CEBA7F23 5CEFA7F23 5CEFA7F27 - 5CEFA7M15 5CEBA7U19 5CEBA7F31 */ - {0x02d110dd, 1197, -1, INTEL_CYCLONEV}, /* 5CSEBA2U23 5CSEMA2U23 5CSEBA2U23 5CSEBA2U19 5CSEBA2U19 */ - - {0x020f10dd, 603, 226, INTEL_CYCLONE10}, /* 10CL006E144 10CL006U256 10CL010M164 10CL010U256 10CL010E144 */ - {0x020f20dd, 1080, 409, INTEL_CYCLONE10}, /* 10CL016U256 10CL016E144 10CL016U484 10CL016F484 10CL016M164 */ - {0x020f30dd, 732, 286, INTEL_CYCLONE10}, /* 10CL025U256 10CL025E144 */ - {0x020f40dd, 1632, 604, INTEL_CYCLONE10}, /* 10CL040F484 10CL040U484 */ - {0x020f50dd, 1164, 442, INTEL_CYCLONE10}, /* 10CL055F484 10CL055U484 */ - {0x020f60dd, 1314, 502, INTEL_CYCLONE10}, /* 10CL080F484 10CL080F780 10CL080U484 */ - {0x020f70dd, 1620, 613, INTEL_CYCLONE10}, /* 10CL120F484 10CL120F780 */ - - {0x02e120dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX085U484 10CX085F672 */ - {0x02e320dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX105F780 10CX105U484 10CX105F672 */ - {0x02e720dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX150F672 10CX150F780 10CX150U484 */ - {0x02ef20dd, 1339, -1, INTEL_CYCLONE10}, /* 10CX220F672 10CX220F780 10CX220U484 */ - - {0x025120dd, 1227, 1174, INTEL_ARRIAII}, /* EP2AGX45 */ - {0x025020dd, 1227, -1, INTEL_ARRIAII}, /* EP2AGX65 */ - {0x025130dd, 1467, -1, INTEL_ARRIAII}, /* EP2AGX95 */ - {0x025030dd, 1467, -1, INTEL_ARRIAII}, /* EP2AGX125 */ - {0x025140dd, 1971, -1, INTEL_ARRIAII}, /* EP2AGX190 */ - {0x025040dd, 1971, -1, INTEL_ARRIAII}, /* EP2AGX260 */ - {0x024810dd, 2274, -1, INTEL_ARRIAII}, /* EP2AGZ225 */ - {0x0240a0dd, 2682, -1, INTEL_ARRIAII}, /* EP2AGZ300 */ - {0x024820dd, 2682, -1, INTEL_ARRIAII}, /* EP2AGZ350 */ -}; - -static int intel_fill_device_parameters(struct intel_pld_device *intel_info) -{ - for (size_t i = 0; i < ARRAY_SIZE(intel_device_parameters); ++i) { - if (intel_device_parameters[i].id == intel_info->tap->idcode && - intel_info->family == intel_device_parameters[i].family) { - if (intel_info->boundary_scan_length == 0) - intel_info->boundary_scan_length = intel_device_parameters[i].boundary_scan_length; - - if (intel_info->checkpos == -1) - intel_info->checkpos = intel_device_parameters[i].checkpos; - - return ERROR_OK; - } - } - - return ERROR_FAIL; -} - -static int intel_check_for_unique_id(struct intel_pld_device *intel_info) -{ - int found = 0; - for (size_t i = 0; i < ARRAY_SIZE(intel_device_parameters); ++i) { - if (intel_device_parameters[i].id == intel_info->tap->idcode) { - ++found; - intel_info->family = intel_device_parameters[i].family; - } - } - - return (found == 1) ? ERROR_OK : ERROR_FAIL; -} - static int intel_check_config(struct intel_pld_device *intel_info) { - if (!intel_info->tap->has_idcode) { - LOG_ERROR("no IDCODE"); - return ERROR_FAIL; - } - - if (intel_info->family == INTEL_UNKNOWN) { - if (intel_check_for_unique_id(intel_info) != ERROR_OK) { - LOG_ERROR("id is ambiguous, please specify family"); + if (intel_info->boundary_scan_length == 0) { + LOG_ERROR("unknown boundary scan length. Please specify with 'intel set_bscan'."); return ERROR_FAIL; - } - } - - if (intel_info->boundary_scan_length == 0 || intel_info->checkpos == -1) { - int ret = intel_fill_device_parameters(intel_info); - if (ret != ERROR_OK) - return ret; } if (intel_info->checkpos >= 0 && (unsigned int)intel_info->checkpos >= intel_info->boundary_scan_length) { @@ -305,6 +174,8 @@ static int intel_load(struct pld_device *pld_device, const char *filename) LOG_ERROR("Check failed"); return ERROR_FAIL; } + } else { + LOG_INFO("unable to check. Please specify with position 'intel set_check_pos'."); } retval = intel_set_instr(tap, 0x003); @@ -417,7 +288,7 @@ COMMAND_HANDLER(intel_set_check_pos_command_handler) PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command) { - if (CMD_ARGC != 4 && CMD_ARGC != 6) + if (CMD_ARGC != 6) return ERROR_COMMAND_SYNTAX_ERROR; if (strcmp(CMD_ARGV[2], "-chain-position") != 0) @@ -430,24 +301,23 @@ PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command) } enum intel_family_e family = INTEL_UNKNOWN; - if (CMD_ARGC == 6) { - if (strcmp(CMD_ARGV[4], "-family") != 0) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (strcmp(CMD_ARGV[5], "cycloneiii") == 0) { - family = INTEL_CYCLONEIII; - } else if (strcmp(CMD_ARGV[5], "cycloneiv") == 0) { - family = INTEL_CYCLONEIV; - } else if (strcmp(CMD_ARGV[5], "cyclonev") == 0) { - family = INTEL_CYCLONEV; - } else if (strcmp(CMD_ARGV[5], "cyclone10") == 0) { - family = INTEL_CYCLONE10; - } else if (strcmp(CMD_ARGV[5], "arriaii") == 0) { - family = INTEL_ARRIAII; - } else { - command_print(CMD, "unknown family"); - return ERROR_FAIL; - } + + if (strcmp(CMD_ARGV[4], "-family") != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[5], "cycloneiii") == 0) { + family = INTEL_CYCLONEIII; + } else if (strcmp(CMD_ARGV[5], "cycloneiv") == 0) { + family = INTEL_CYCLONEIV; + } else if (strcmp(CMD_ARGV[5], "cyclonev") == 0) { + family = INTEL_CYCLONEV; + } else if (strcmp(CMD_ARGV[5], "cyclone10") == 0) { + family = INTEL_CYCLONE10; + } else if (strcmp(CMD_ARGV[5], "arriaii") == 0) { + family = INTEL_ARRIAII; + } else { + command_print(CMD, "unknown family"); + return ERROR_FAIL; } struct intel_pld_device *intel_info = malloc(sizeof(struct intel_pld_device)); diff --git a/tcl/fpga/altera-arriaii.cfg b/tcl/fpga/altera-arriaii.cfg index d59c182070..9cf680d5fd 100644 --- a/tcl/fpga/altera-arriaii.cfg +++ b/tcl/fpga/altera-arriaii.cfg @@ -21,11 +21,26 @@ if { [info exists CHIPNAME] } { set _CHIPNAME arriaii } -jtag newtap $_CHIPNAME tap -irlen 10 \ - -expected-id 0x025120dd -expected-id 0x025040dd \ - -expected-id 0x025020dd -expected-id 0x024810dd \ - -expected-id 0x025130dd -expected-id 0x0240a0dd \ - -expected-id 0x025030dd -expected-id 0x024820dd \ - -expected-id 0x025140dd +array set _ARRIA_2_DATA { + 0x025120dd {1227 1174 EP2AGX45} + 0x025020dd {1227 -1 EP2AGX65} + 0x025130dd {1467 -1 EP2AGX95} + 0x025030dd {1467 -1 EP2AGX125} + 0x025140dd {1971 -1 EP2AGX190} + 0x025040dd {1971 -1 EP2AGX260} + 0x024810dd {2274 -1 EP2AGZ225} + 0x0240a0dd {2682 -1 EP2AGZ300} + 0x024820dd {2682 -1 EP2AGZ350} +} + +set jtag_newtap_cmd {jtag newtap $_CHIPNAME tap -irlen 10 -ignore-version} +foreach id [array names _ARRIA_2_DATA] { + set cmd [concat "-expected-id" id] +} +eval $jtag_newtap_cmd + +source [find fpga/altera_common_init.cfg] pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family arriaii +jtag configure $_CHIPNAME.tap -event setup "set_bscan_checkpos_on_setup $_CHIPNAME {$_ARRIA_2_DATA}" + diff --git a/tcl/fpga/altera-cyclone10.cfg b/tcl/fpga/altera-cyclone10.cfg index 3a1bc1f65c..0898c74e17 100644 --- a/tcl/fpga/altera-cyclone10.cfg +++ b/tcl/fpga/altera-cyclone10.cfg @@ -4,31 +4,33 @@ # see: https://www.intel.com/content/www/us/en/docs/programmable/683777/current/bst-operation-control.html # and: https://www.intel.cn/content/dam/support/us/en/programmable/kdb/pdfs/literature/hb/cyclone-10/c10gx-51003.pdf -# GX085: 0x02e120dd -# GX105: 0x02e320dd -# GX150: 0x02e720dd -# GX220: 0x02ef20dd -# 10cl006: 0x020f10dd -# 10cl010: 0x020f10dd -# 10cl016: 0x020f20dd -# 10cl025: 0x020f30dd -# 10cl040: 0x020f40dd -# 10cl055: 0x020f50dd -# 10cl080: 0x020f60dd -# 10cl120: 0x020f70dd - if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cyclone10 } -jtag newtap $_CHIPNAME tap -irlen 10 \ - -expected-id 0x02e720dd -expected-id 0x02e120dd \ - -expected-id 0x02ef20dd -expected-id 0x02e320dd \ - -expected-id 0x020f10dd -expected-id 0x020f20dd \ - -expected-id 0x020f30dd -expected-id 0x020f40dd \ - -expected-id 0x020f50dd -expected-id 0x020f60dd \ - -expected-id 0x020f70dd +array set _CYCLONE_10_DATA { + 0x020f10dd { 603 226 10cl006_10cl010} + 0x020f20dd {1080 409 10cl016} + 0x020f30dd { 732 286 10cl025} + 0x020f40dd {1632 604 10cl040} + 0x020f50dd {1164 442 10cl055} + 0x020f60dd {1314 502 10cl080} + 0x020f70dd {1620 613 10cl120} + 0x02e120dd {1339 -1 GX085} + 0x02e320dd {1339 -1 GX105} + 0x02e720dd {1339 -1 GX150} + 0x02ef20dd {1339 -1 GX220} +} + +set jtag_newtap_cmd {jtag newtap $_CHIPNAME tap -irlen 10 -ignore-version} +foreach id [array names _CYCLONE_10_DATA] { + set cmd [concat "-expected-id" id] +} +eval $jtag_newtap_cmd + +source [find fpga/altera_common_init.cfg] -pld device intel $_CHIPNAME.tap cyclone10 +pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cyclone10 +jtag configure $_CHIPNAME.tap -event setup "set_bscan_checkpos_on_setup $_CHIPNAME {$_CYCLONE_10_DATA}" diff --git a/tcl/fpga/altera-cycloneiii.cfg b/tcl/fpga/altera-cycloneiii.cfg index d9be6455df..b0da418c0a 100644 --- a/tcl/fpga/altera-cycloneiii.cfg +++ b/tcl/fpga/altera-cycloneiii.cfg @@ -4,32 +4,33 @@ # see Cyclone III Device Handbook # Table 12-2: Device IDCODE for Cyclone III Device Family -#EP3C5 0x020f10dd -#EP3C10 0x020f10dd -#EP3C16 0x020f20dd -#EP3C25 0x020f30dd -#EP3C40 0x020f40dd -#EP3C55 0x020f50dd -#EP3C80 0x020f60dd -#EP3C120 0x020f70dd -#Cyclone III LS -#EP3CLS70 0x027010dd -#EP3CLS100 0x027000dd -#EP3CLS150 0x027030dd -#EP3CLS200 0x027020dd - if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cycloneiii } -jtag newtap $_CHIPNAME tap -irlen 10 \ - -expected-id 0x020f10dd -expected-id 0x020f20dd \ - -expected-id 0x020f30dd -expected-id 0x020f40dd \ - -expected-id 0x020f50dd -expected-id 0x020f60dd \ - -expected-id 0x020f70dd -expected-id 0x027010dd \ - -expected-id 0x027000dd -expected-id 0x027030dd \ - -expected-id 0x027020dd +array set _CYCLONE_3_DATA { + 0x020f10dd { 603 226 EP3C5_EP3C10} + 0x020f20dd {1080 409 EP3C16} + 0x020f30dd { 732 286 EP3C25} + 0x020f40dd {1632 604 EP3C40} + 0x020f50dd {1164 442 EP3C55} + 0x020f60dd {1314 502 EP3C80} + 0x020f70dd {1620 613 EP3C120} + 0x027010dd {1314 226 EP3CLS70} + 0x027000dd {1314 226 EP3CLS100} + 0x027030dd {1314 409 EP3CLS150} + 0x027020dd {1314 409 EP3CLS200} +} + +set jtag_newtap_cmd {jtag newtap $_CHIPNAME tap -irlen 10 -ignore-version} +foreach id [array names _CYCLONE_3_DATA] { + set cmd [concat "-expected-id" id] +} +eval $jtag_newtap_cmd + +source [find fpga/altera_common_init.cfg] pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cycloneiii +jtag configure $_CHIPNAME.tap -event setup "set_bscan_checkpos_on_setup $_CHIPNAME {$_CYCLONE_3_DATA}" diff --git a/tcl/fpga/altera-cycloneiv.cfg b/tcl/fpga/altera-cycloneiv.cfg index 6a908e8af5..44eb89dec4 100644 --- a/tcl/fpga/altera-cycloneiv.cfg +++ b/tcl/fpga/altera-cycloneiv.cfg @@ -4,38 +4,37 @@ # see Cyclone IV Device Handbook # Table 10-2: IDCODE Information for 32-Bit Cyclone IV Devices -#EP4CE6 0x020f10dd -#EP4CE10 0x020f10dd -#EP4CE15 0x020f20dd -#EP4CE22 0x020f30dd -#EP4CE30 0x020f40dd -#EP4CE40 0x020f40dd -#EP4CE55 0x020f50dd -#EP4CE75 0x020f60dd -#EP4CE115 0x020f70dd -#EP4CGX15 0x028010dd -#EP4CGX22 0x028120dd -#EP4CGX30 (3) 0x028020dd -#EP4CGX30 (4) 0x028230dd -#EP4CGX50 0x028130dd -#EP4CGX75 0x028030dd -#EP4CGX110 0x028140dd -#EP4CGX150 0x028040dd - if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cycloneiv } -jtag newtap $_CHIPNAME tap -irlen 10 \ - -expected-id 0x020f10dd -expected-id 0x020f20dd \ - -expected-id 0x020f30dd -expected-id 0x020f40dd \ - -expected-id 0x020f50dd -expected-id 0x020f60dd \ - -expected-id 0x020f70dd -expected-id 0x028010dd \ - -expected-id 0x028120dd -expected-id 0x028020dd \ - -expected-id 0x028230dd -expected-id 0x028130dd \ - -expected-id 0x028030dd -expected-id 0x028140dd \ - -expected-id 0x028040dd +array set _CYCLON_4_DATA { + 0x020f10dd { 603 226 EP4CE6_EP4CE10} + 0x020f20dd {1080 409 EP4CE15} + 0x020f30dd { 732 286 EP4CE22} + 0x020f40dd {1632 604 EP4CE30_EP4CE40} + 0x020f50dd {1164 442 EP4CE55} + 0x020f60dd {1314 502 EP4CE75} + 0x020f70dd {1620 613 EP4CE115} + 0x028010dd { 260 229 EP4CGX15} + 0x028120dd { 494 463 EP4CGX22} + 0x028020dd { 494 463 EP4CGX30} + 0x028230dd {1006 943 EP4CGX30} + 0x028130dd {1006 943 EP4CGX50} + 0x028030dd {1006 943 EP4CGX75} + 0x028140dd {1495 1438 EP4CGX110} + 0x028040dd {1495 1438 EP4CGX150} +} + +set jtag_newtap_cmd {jtag newtap $_CHIPNAME tap -irlen 10 -ignore-version} +foreach id [array names _CYCLON_4_DATA] { + set cmd [concat "-expected-id" id] +} +eval $jtag_newtap_cmd + +source [find fpga/altera_common_init.cfg] pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cycloneiv +jtag configure $_CHIPNAME.tap -event setup "set_bscan_checkpos_on_setup $_CHIPNAME {$_CYCLONE_4_DATA}" diff --git a/tcl/fpga/altera-cyclonev.cfg b/tcl/fpga/altera-cyclonev.cfg index 46532a556c..8d19cd8de8 100644 --- a/tcl/fpga/altera-cyclonev.cfg +++ b/tcl/fpga/altera-cyclonev.cfg @@ -4,44 +4,36 @@ # see Cyclone V Device Handbook # Table 9-1: IDCODE Information for Cyclone V Devices -#5CEA2 0x02b150dd -#5CEA4 0x02b050dd -#5CEA5 0x02b220dd -#5CEA7 0x02b130dd -#5CEA9 0x02b140dd -#5CGXC3 0x02b010dd -#5CGXC4 0x02b120dd -#5CGXC5 0x02b020dd -#5CGXC7 0x02b030dd -#5CGXC9 0x02b040dd -#5CGTD5 0x02b020dd -#5CGTD7 0x02b030dd -#5CGTD9 0x02b040dd -#5CSEA2 0x02d110dd -#5CSEA4 0x02d010dd -#5CSEA5 0x02d120dd -#5CSEA6 0x02d020dd -#5CSXC2 0x02d110dd -#5CSXC4 0x02d010dd -#5CSXC5 0x02d120dd -#5CSXC6 0x02d020dd -#5CSTD5 0x02d120dd -#5CSTD6 0x02d020dd - - if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME cyclonev } -jtag newtap $_CHIPNAME tap -irlen 10 \ - -expected-id 0x02b150dd -expected-id 0x02b050dd \ - -expected-id 0x02b220dd -expected-id 0x02b130dd \ - -expected-id 0x02b140dd -expected-id 0x02b010dd \ - -expected-id 0x02b120dd -expected-id 0x02b020dd \ - -expected-id 0x02b030dd -expected-id 0x02b040dd \ - -expected-id 0x02d110dd -expected-id 0x02d010dd \ - -expected-id 0x02d120dd -expected-id 0x02d020dd +array set _CYCLONE_5_DATA { + 0x02b150dd { 864 163 5CEA2} + 0x02d020dd {1485 19 5CSEA6_5CSXC6_5CSTD6} + 0x02b040dd {1728 -1 5CGXC9_5CGTD9} + 0x02b050dd { 864 163 5CEA4} + 0x02b030dd {1488 19 5CGXC7_5CGTD7} + 0x02d120dd {1485 -1 5CSEA5_5CSXC5_5CSTD5} + 0x02b220dd {1104 19 5CEA5} + 0x02b020dd {1104 19 5CGXC5_5CGTD5} + 0x02d010dd {1197 -1 5CSEA4_5CSXC4} + 0x02b120dd {1104 19 5CGXC4} + 0x02b140dd {1728 -1 5CEA9} + 0x02b010dd { 720 19 5CGXC3} + 0x02b130dd {1488 19 5CEA7} + 0x02d110dd {1197 -1 5CSEA2_5CSXC2} +} + +set jtag_newtap_cmd {jtag newtap $_CHIPNAME tap -irlen 10 -ignore-version} +foreach id [array names _CYCLONE_5_DATA] { + set cmd [concat "-expected-id" id] +} +eval $jtag_newtap_cmd + +source [find fpga/altera_common_init.cfg] pld create $_CHIPNAME.pld intel -chain-position $_CHIPNAME.tap -family cyclonev +jtag configure $_CHIPNAME.tap -event setup "set_bscan_checkpos_on_setup $_CHIPNAME {$_CYCLONE_5_DATA}" diff --git a/tcl/fpga/altera_common_init.cfg b/tcl/fpga/altera_common_init.cfg new file mode 100644 index 0000000000..683a844cba --- /dev/null +++ b/tcl/fpga/altera_common_init.cfg @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +proc set_bscan_checkpos_on_setup {chipname data} { + set tapid_w_version [jtag cget $chipname.tap -idcode] + set version_mask 0x0fffffff + set tapid [format 0x%08x [expr {$tapid_w_version & $version_mask}]] + intel set_bscan $chipname.pld [lindex $data($tapid) 0] + intel set_check_pos $chipname.pld [lindex $data($tapid) 1] +} From bf4be566a7e7f510977533a0402716d92f208f95 Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Mon, 19 Feb 2024 23:22:19 +0100 Subject: [PATCH 0842/1312] pld: small documentation fixes. Change-Id: I969f51c38fc0c34c6bdba98b0e618d7f28ea4052 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/8084 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 03fa944661..e46e6004bc 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8799,8 +8799,8 @@ The file format must be inferred by the driver. @section PLD/FPGA Drivers, Options, and Commands -Drivers may support PLD-specific options to the @command{pld device} -definition command, and may also define commands usable only with +Drivers may support PLD-specific options to the @command{pld create} +command, and may also define commands usable only with that particular type of PLD. @deffn {FPGA Driver} {virtex2} [@option{-no_jstart}] @@ -8888,7 +8888,7 @@ For the option @option{-family} @var{name} is one of @var{trion|titanium}. @deffn {FPGA Driver} {intel} @option{-family} This driver can be used to load the bitstream into Intel (former Altera) FPGAs. -The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10, Arria II are supported. +The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10 and Arria II are supported. @c Arria V and Arria 10, MAX II, MAX V, MAX10) The option @option{-family} @var{name} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}. From 4892e32294c6ea4cf53251adb81dee4e85aee0b0 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 17 May 2024 21:27:24 +0200 Subject: [PATCH 0843/1312] target/cortex_m: allow poll quickly get out of TARGET_RESET state cortex_m_poll_one() detects reset testing S_RESET_ST sticky bit. If the signal comes unexpectedly, poll must return TARGET_RESET state. On the contrary in case of polling inside of an OpenOCD reset command, TARGET_RESET has been has already been set and we need to get out of it as quickly as possible. The original code needs 2 polls: the first clears S_RESET_ST and keeps TARGET_RESET state, the current TARGET_RUNNING or TARGET_HALTED is reflected as late as the second poll is done. Change the logic to keep in TARGET_RESET only when necessary. See also [1] Link: [1] 8284: tcl/target: ti_cc3220sf: Use halt for CC3320SF targets | https://review.openocd.org/c/openocd/+/8284 Fixes: https://sourceforge.net/p/openocd/tickets/360/ Signed-off-by: Tomas Vanek Change-Id: I759461e5f89ca48a6e16e4b4101570260421dba1 Reviewed-on: https://review.openocd.org/c/openocd/+/8285 Tested-by: jenkins Reviewed-by: Dhruva Gole --- src/target/cortex_m.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index c225b1aa9d..7f62a6de2d 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -931,8 +931,12 @@ static int cortex_m_poll_one(struct target *target) if (target->state != TARGET_RESET) { target->state = TARGET_RESET; LOG_TARGET_INFO(target, "external reset detected"); + /* In case of an unexpected S_RESET_ST set TARGET_RESET state + * and keep it until the next poll to allow its detection */ + return ERROR_OK; } - return ERROR_OK; + /* S_RESET_ST was expected (in a reset command). Continue processing + * to quickly get out of TARGET_RESET state */ } if (target->state == TARGET_RESET) { From c5358c84ad0d3e7497498e0457cec7785f72910a Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 2 Jun 2024 14:39:36 +0100 Subject: [PATCH 0844/1312] target: Do not use LOG_USER() for error messages Use LOG_TARGET_ERROR() to print the error messages and additionally add a reference to the related target. Change-Id: I06722f3911ef4034fdd05dc9b0e2571b01b657a4 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8314 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/target/target.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 7d4947a6ef..1f4817d5c1 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2997,14 +2997,14 @@ static int handle_target(void *priv) target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } if (target->backoff.times > 0) { - LOG_USER("Polling target %s failed, trying to reexamine", target_name(target)); + LOG_TARGET_ERROR(target, "Polling failed, trying to reexamine"); target_reset_examined(target); retval = target_examine_one(target); /* Target examination could have failed due to unstable connection, * but we set the examined flag anyway to repoll it later */ if (retval != ERROR_OK) { target_set_examined(target); - LOG_USER("Examination failed, GDB will be halted. Polling again in %dms", + LOG_TARGET_ERROR(target, "Examination failed, GDB will be halted. Polling again in %dms", target->backoff.times * polling_interval); return retval; } @@ -4691,9 +4691,8 @@ void target_handle_event(struct target *target, enum target_event e) if (retval != JIM_OK) { Jim_MakeErrorMessage(teap->interp); - LOG_USER("Error executing event %s on target %s:\n%s", + LOG_TARGET_ERROR(target, "Execution of event %s failed:\n%s", target_event_name(e), - target_name(target), Jim_GetString(Jim_GetResult(teap->interp), NULL)); /* clean both error code and stacktrace before return */ Jim_Eval(teap->interp, "error \"\" \"\""); From 91043cecee396209bd4d616fe6e78d835bebd978 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 13 May 2024 15:40:15 +0200 Subject: [PATCH 0845/1312] target: aarch64: align armv8_read_reg() and armv8_read_reg32() These functions are today always called with non-NULL parameter regval, so the actual check is not needed. Anyway, for any future code change, check the parameter at the entry of the functions and return error if it is not valid. Simplify the check to assign the result value and align the code of the two functions. Change-Id: Ie4d98063006d70d9e2bcfc00bc930133caf33515 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8266 Tested-by: jenkins --- src/target/armv8.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index bf582ff801..8d97902f55 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -282,6 +282,9 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv uint32_t value; uint64_t value_64; + if (!regval) + return ERROR_FAIL; + switch (regnum) { case 0 ... 30: retval = dpm->instr_read_data_dcc_64(dpm, @@ -361,10 +364,8 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv break; } - if (retval == ERROR_OK && regval) + if (retval == ERROR_OK) *regval = value_64; - else - retval = ERROR_FAIL; return retval; } @@ -512,6 +513,9 @@ static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *re uint32_t value = 0; int retval; + if (!regval) + return ERROR_FAIL; + switch (regnum) { case ARMV8_R0 ... ARMV8_R14: /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */ @@ -587,7 +591,7 @@ static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *re break; } - if (retval == ERROR_OK && regval) + if (retval == ERROR_OK) *regval = value; return retval; From bcd6a1022322f67f25f74af2dfe40d440d382e74 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 13 May 2024 17:20:52 +0200 Subject: [PATCH 0846/1312] target: armv8_dpm: silence error on register R/W The command 'gdb_report_register_access_error' is used to silence errors while reading registers and not reporting them to GDB. Nevertheless, the error is printed by a LOG_ERROR() in armv8_dpm. Change the message to LOG_DEBUG(). It will still cause the error to be propagated and eventually printed by the caller (e.g. by the command 'reg'). Change-Id: Ic0db74fa28235d686ddd21a5960c52ae003e0931 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8267 Tested-by: jenkins --- src/target/armv8_dpm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 8bb24f225b..271bd91c3b 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -677,7 +677,7 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) } if (retval != ERROR_OK) - LOG_ERROR("Failed to read %s register", r->name); + LOG_DEBUG("Failed to read %s register", r->name); return retval; } @@ -719,7 +719,7 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) } if (retval != ERROR_OK) - LOG_ERROR("Failed to write %s register", r->name); + LOG_DEBUG("Failed to write %s register", r->name); return retval; } From 8c75e4760333a4e0408bdf9dd58a702e4fb67c51 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 13 May 2024 18:19:55 +0200 Subject: [PATCH 0847/1312] target: aarch64: access reg ELR_EL3 only in EL3 The register ELR_EL3 is accessible and it's content is relevant only when the target is in EL3. Without this patch, an error: Error: Opcode 0xd53e4020, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $ELR_EL3 or through OpenOCD command reg ELR_EL3 Detect the EL and return error if the register cannot be accessed. Change-Id: I545abb196e5c34e462c7e5d5d3ec952e588642da Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8268 Tested-by: jenkins --- src/target/armv8.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/target/armv8.c b/src/target/armv8.c index 8d97902f55..e36e2f6f41 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -278,6 +278,7 @@ static int armv8_get_pauth_mask(struct armv8_common *armv8, uint64_t *mask) static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regval) { struct arm_dpm *dpm = &armv8->dpm; + unsigned int curel = armv8_curel_from_core_mode(dpm->arm->core_mode); int retval; uint32_t value; uint64_t value_64; @@ -322,6 +323,11 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv ARMV8_MRS(SYSTEM_ELR_EL2, 0), &value_64); break; case ARMV8_ELR_EL3: + if (curel < SYSTEM_CUREL_EL3) { + LOG_DEBUG("ELR_EL3 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS(SYSTEM_ELR_EL3, 0), &value_64); break; @@ -396,6 +402,7 @@ static int armv8_read_reg_simdfp_aarch64(struct armv8_common *armv8, int regnum, static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t value_64) { struct arm_dpm *dpm = &armv8->dpm; + unsigned int curel = armv8_curel_from_core_mode(dpm->arm->core_mode); int retval; uint32_t value; @@ -443,6 +450,11 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_ELR_EL2, 0), value_64); break; case ARMV8_ELR_EL3: + if (curel < SYSTEM_CUREL_EL3) { + LOG_DEBUG("ELR_EL3 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } retval = dpm->instr_write_data_r0_64(dpm, ARMV8_MSR_GP(SYSTEM_ELR_EL3, 0), value_64); break; From 230680916039ba413278b74f3440ffa49e55de27 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 10:03:09 +0200 Subject: [PATCH 0848/1312] target: aarch64: access reg ESR_EL3 only in EL3 The register ESR_EL3 is accessible and it's content is relevant only when the target is in EL3. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd53e5200, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $ESR_EL3 or through OpenOCD command reg ESR_EL3 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Drop the FIXME comment on Aarch32 case, as the register exists in Aarch64 only. Change-Id: Ie8c69dc7b50ae81a52506cf151c8e64e15752d0d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8269 Tested-by: jenkins --- src/target/armv8.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index e36e2f6f41..383ac3ef4d 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -342,9 +342,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv value_64 = value; break; case ARMV8_ESR_EL3: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_ESR_EL3, 0), &value); - value_64 = value; + if (curel < SYSTEM_CUREL_EL3) { + LOG_DEBUG("ESR_EL3 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_ESR_EL3, 0), &value_64); break; case ARMV8_SPSR_EL1: retval = dpm->instr_read_data_r0(dpm, @@ -469,9 +473,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_ESR_EL2, 0), value); break; case ARMV8_ESR_EL3: - value = value_64; - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_ESR_EL3, 0), value); + if (curel < SYSTEM_CUREL_EL3) { + LOG_DEBUG("ESR_EL3 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_ESR_EL3, 0), value_64); break; case ARMV8_SPSR_EL1: value = value_64; @@ -575,7 +583,7 @@ static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *re ARMV4_5_MRC(15, 4, 0, 5, 2, 0), &value); break; - case ARMV8_ESR_EL3: /* FIXME: no equivalent in aarch32? */ + case ARMV8_ESR_EL3: /* no equivalent in aarch32 */ retval = ERROR_FAIL; break; case ARMV8_SPSR_EL1: /* mapped to SPSR_svc */ @@ -711,7 +719,7 @@ static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t va ARMV4_5_MCR(15, 4, 0, 5, 2, 0), value); break; - case ARMV8_ESR_EL3: /* FIXME: no equivalent in aarch32? */ + case ARMV8_ESR_EL3: /* no equivalent in aarch32 */ retval = ERROR_FAIL; break; case ARMV8_SPSR_EL1: /* mapped to SPSR_svc */ @@ -1534,7 +1542,7 @@ static const struct { { ARMV8_ELR_EL3, "ELR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked", NULL}, - { ARMV8_ESR_EL3, "ESR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", + { ARMV8_ESR_EL3, "ESR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", NULL}, From 405e78771b7f2a09298b675e7fbd05803672416c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 10:40:32 +0200 Subject: [PATCH 0849/1312] target: aarch64: access reg SPSR_EL3 only in EL3 The register SPSR_EL3 is accessible and it's content is relevant only when the target is in EL3. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd53e4000, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $SPSR_EL3 or through OpenOCD command reg SPSR_EL3 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Change-Id: I00849d99feeb96589c426fcafda98127dbd19a67 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8270 Tested-by: jenkins --- src/target/armv8.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 383ac3ef4d..e8c189c1c8 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -361,9 +361,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv value_64 = value; break; case ARMV8_SPSR_EL3: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_SPSR_EL3, 0), &value); - value_64 = value; + if (curel < SYSTEM_CUREL_EL3) { + LOG_DEBUG("SPSR_EL3 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_SPSR_EL3, 0), &value_64); break; case ARMV8_PAUTH_CMASK: case ARMV8_PAUTH_DMASK: @@ -492,9 +496,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_SPSR_EL2, 0), value); break; case ARMV8_SPSR_EL3: - value = value_64; - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_SPSR_EL3, 0), value); + if (curel < SYSTEM_CUREL_EL3) { + LOG_DEBUG("SPSR_EL3 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_SPSR_EL3, 0), value_64); break; default: retval = ERROR_FAIL; @@ -1544,7 +1552,7 @@ static const struct { NULL}, { ARMV8_ESR_EL3, "ESR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, - { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", + { ARMV8_SPSR_EL3, "SPSR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, { ARMV8_PAUTH_DMASK, "pauth_dmask", 64, ARM_MODE_ANY, REG_TYPE_UINT64, NULL, "org.gnu.gdb.aarch64.pauth", NULL}, { ARMV8_PAUTH_CMASK, "pauth_cmask", 64, ARM_MODE_ANY, REG_TYPE_UINT64, NULL, "org.gnu.gdb.aarch64.pauth", NULL}, From 190176a6bc947fd2516b959217084e531374b9bf Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 11:03:45 +0200 Subject: [PATCH 0850/1312] target: aarch64: access reg ELR_EL2 only in EL2 and EL3 The register ELR_EL2 is accessible and it's content is relevant only when the target is in EL2 or EL3. Virtualization SW in EL1 can also access it, but this either triggers a trap to EL2 or returns ELR_EL1. Debugger should not mix the real ELR_EL2 with the virtual register. Without this patch, an error: Error: Opcode 0xd53c4020, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $ELR_EL2 or through OpenOCD command reg ELR_EL2 Detect the EL and return error if the register cannot be accessed. Change-Id: Idf02b42a7339df83260c1e44ceabbb05fbf392b9 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8271 Tested-by: jenkins --- src/target/armv8.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target/armv8.c b/src/target/armv8.c index e8c189c1c8..a537d610ca 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -319,6 +319,11 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv ARMV8_MRS(SYSTEM_ELR_EL1, 0), &value_64); break; case ARMV8_ELR_EL2: + if (curel < SYSTEM_CUREL_EL2) { + LOG_DEBUG("ELR_EL2 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS(SYSTEM_ELR_EL2, 0), &value_64); break; @@ -454,6 +459,11 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_ELR_EL1, 0), value_64); break; case ARMV8_ELR_EL2: + if (curel < SYSTEM_CUREL_EL2) { + LOG_DEBUG("ELR_EL2 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } retval = dpm->instr_write_data_r0_64(dpm, ARMV8_MSR_GP(SYSTEM_ELR_EL2, 0), value_64); break; From 766a84b79892c1321f3f86d3f1b301519269b4f5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 12:07:58 +0200 Subject: [PATCH 0851/1312] target: aarch64: access reg ESR_EL2 only in EL2 and EL3 The register ESR_EL2 is accessible and it's content is relevant only when the target is in EL2 or EL3. Virtualization SW in EL1 can also access it, but this either triggers a trap to EL2 or returns ESR_EL1. Debugger should not mix the real ESR_EL2 with the virtual register. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd53c5200, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $ESR_EL2 or through OpenOCD command reg ESR_EL2 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Change-Id: Icb32b44886d50907f29b068ce61e4be8bed10208 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8272 Tested-by: jenkins --- src/target/armv8.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index a537d610ca..49fcb7217d 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -342,9 +342,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv value_64 = value; break; case ARMV8_ESR_EL2: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_ESR_EL2, 0), &value); - value_64 = value; + if (curel < SYSTEM_CUREL_EL2) { + LOG_DEBUG("ESR_EL2 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_ESR_EL2, 0), &value_64); break; case ARMV8_ESR_EL3: if (curel < SYSTEM_CUREL_EL3) { @@ -482,9 +486,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_ESR_EL1, 0), value); break; case ARMV8_ESR_EL2: - value = value_64; - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_ESR_EL2, 0), value); + if (curel < SYSTEM_CUREL_EL2) { + LOG_DEBUG("ESR_EL2 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_ESR_EL2, 0), value_64); break; case ARMV8_ESR_EL3: if (curel < SYSTEM_CUREL_EL3) { @@ -1553,7 +1561,7 @@ static const struct { { ARMV8_ELR_EL2, "ELR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked", NULL}, - { ARMV8_ESR_EL2, "ESR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", + { ARMV8_ESR_EL2, "ESR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, { ARMV8_SPSR_EL2, "SPSR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", NULL}, From 2a63fabd095044f0a05cf69a34300409809f676b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 12:16:13 +0200 Subject: [PATCH 0852/1312] target: aarch64: access reg SPSR_EL2 only in EL2 and EL3 The register SPSR_EL2 is accessible and it's content is relevant only when the target is in EL2 or EL3. Virtualization SW in EL1 can also access it, but this either triggers a trap to EL2 or returns SPSR_EL1. Debugger should not mix the real SPSR_EL2 with the virtual register. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd53c4000, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $SPSR_EL2 or through OpenOCD command reg SPSR_EL2 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Change-Id: If3792296b36282c08d597dd46cfe044d6b8288ea Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8273 Tested-by: jenkins --- src/target/armv8.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 49fcb7217d..b622dc990e 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -365,9 +365,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv value_64 = value; break; case ARMV8_SPSR_EL2: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_SPSR_EL2, 0), &value); - value_64 = value; + if (curel < SYSTEM_CUREL_EL2) { + LOG_DEBUG("SPSR_EL2 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_SPSR_EL2, 0), &value_64); break; case ARMV8_SPSR_EL3: if (curel < SYSTEM_CUREL_EL3) { @@ -509,9 +513,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_SPSR_EL1, 0), value); break; case ARMV8_SPSR_EL2: - value = value_64; - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_SPSR_EL2, 0), value); + if (curel < SYSTEM_CUREL_EL2) { + LOG_DEBUG("SPSR_EL2 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_SPSR_EL2, 0), value_64); break; case ARMV8_SPSR_EL3: if (curel < SYSTEM_CUREL_EL3) { @@ -1563,7 +1571,7 @@ static const struct { NULL}, { ARMV8_ESR_EL2, "ESR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, - { ARMV8_SPSR_EL2, "SPSR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", + { ARMV8_SPSR_EL2, "SPSR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, { ARMV8_ELR_EL3, "ELR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked", From f39f136e012589212b463af4ef1ac7d855901810 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 14:17:39 +0200 Subject: [PATCH 0853/1312] target: aarch64: access reg ELR_EL1 only in EL1, EL2 and EL3 The register ELR_EL1 is accessible and it's content is relevant only when the target is in EL1 or EL2 or EL3. Without this patch, an error: Error: Opcode 0xd5384020, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $ELR_EL1 or through OpenOCD command reg ELR_EL1 Detect the EL and return error if the register cannot be accessed. Change-Id: I402dda4cd9dae502b05572fc6c1a8f0edf349bb1 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8274 Tested-by: jenkins --- src/target/armv8.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target/armv8.c b/src/target/armv8.c index b622dc990e..1767470138 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -315,6 +315,11 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv value_64 = value; break; case ARMV8_ELR_EL1: + if (curel < SYSTEM_CUREL_EL1) { + LOG_DEBUG("ELR_EL1 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS(SYSTEM_ELR_EL1, 0), &value_64); break; @@ -463,6 +468,11 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu break; /* registers clobbered by taking exception in debug state */ case ARMV8_ELR_EL1: + if (curel < SYSTEM_CUREL_EL1) { + LOG_DEBUG("ELR_EL1 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } retval = dpm->instr_write_data_r0_64(dpm, ARMV8_MSR_GP(SYSTEM_ELR_EL1, 0), value_64); break; From b5dfef7577f87c34bd397981c17e5d461d1c217f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 14:23:07 +0200 Subject: [PATCH 0854/1312] target: aarch64: access reg ESR_EL1 only in EL1, EL2 and EL3 The register ESR_EL1 is accessible and it's content is relevant only when the target is in EL1 or EL2 or EL3. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd5385200, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $ESR_EL1 or through OpenOCD command reg ESR_EL1 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Change-Id: Icd65470c279e5cfd03091db6435cdaa1c447644c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8275 Tested-by: jenkins --- src/target/armv8.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 1767470138..14b1726892 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -342,9 +342,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv ARMV8_MRS(SYSTEM_ELR_EL3, 0), &value_64); break; case ARMV8_ESR_EL1: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_ESR_EL1, 0), &value); - value_64 = value; + if (curel < SYSTEM_CUREL_EL1) { + LOG_DEBUG("ESR_EL1 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_ESR_EL1, 0), &value_64); break; case ARMV8_ESR_EL2: if (curel < SYSTEM_CUREL_EL2) { @@ -495,9 +499,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_ELR_EL3, 0), value_64); break; case ARMV8_ESR_EL1: - value = value_64; - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_ESR_EL1, 0), value); + if (curel < SYSTEM_CUREL_EL1) { + LOG_DEBUG("ESR_EL1 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_ESR_EL1, 0), value_64); break; case ARMV8_ESR_EL2: if (curel < SYSTEM_CUREL_EL2) { @@ -1572,7 +1580,7 @@ static const struct { { ARMV8_ELR_EL1, "ELR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked", NULL}, - { ARMV8_ESR_EL1, "ESR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", + { ARMV8_ESR_EL1, "ESR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, { ARMV8_SPSR_EL1, "SPSR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", NULL}, From 198fecf5e4b03c2024c9d75fd5e6045daf681ed5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 14 May 2024 14:40:07 +0200 Subject: [PATCH 0855/1312] target: aarch64: access reg SPSR_EL1 only in EL1, EL2 and EL3 The register SPSR_EL1 is accessible and it's content is relevant only when the target is in EL1 or EL2 or EL3. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd5384000, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $SPSR_EL1 or through OpenOCD command reg SPSR_EL1 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Change-Id: Ia0f984d52920cc32b8ee31157d62c13dea616a3a Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8276 Tested-by: jenkins --- src/target/armv8.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 14b1726892..b54ef13d37 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -369,9 +369,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv ARMV8_MRS(SYSTEM_ESR_EL3, 0), &value_64); break; case ARMV8_SPSR_EL1: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_SPSR_EL1, 0), &value); - value_64 = value; + if (curel < SYSTEM_CUREL_EL1) { + LOG_DEBUG("SPSR_EL1 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_SPSR_EL1, 0), &value_64); break; case ARMV8_SPSR_EL2: if (curel < SYSTEM_CUREL_EL2) { @@ -526,9 +530,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu ARMV8_MSR_GP(SYSTEM_ESR_EL3, 0), value_64); break; case ARMV8_SPSR_EL1: - value = value_64; - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_SPSR_EL1, 0), value); + if (curel < SYSTEM_CUREL_EL1) { + LOG_DEBUG("SPSR_EL1 not accessible in EL%u", curel); + retval = ERROR_FAIL; + break; + } + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_SPSR_EL1, 0), value_64); break; case ARMV8_SPSR_EL2: if (curel < SYSTEM_CUREL_EL2) { @@ -1582,7 +1590,7 @@ static const struct { NULL}, { ARMV8_ESR_EL1, "ESR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, - { ARMV8_SPSR_EL1, "SPSR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked", + { ARMV8_SPSR_EL1, "SPSR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked", NULL}, { ARMV8_ELR_EL2, "ELR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked", From dde096e03fa4912aa44b2b72cfbdb7676340a3d1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 17 Sep 2023 11:15:22 +0200 Subject: [PATCH 0856/1312] itm: fix default initialization Commit f9509c92dba3 ("itm: rework itm commands before 'init'") ignores the default enable of ITM channel 0, that is applied when no 'itm port[s]' is issued. Call armv7m_trace_itm_config() unconditionally to handle it. Change-Id: I3e85d0b063ed38c1552f6af9ea9eea2e76aa9025 Signed-off-by: Antonio Borneo Reported-by: Paul Fertser Fixes: f9509c92dba3 ("itm: rework itm commands before 'init'") Reviewed-on: https://review.openocd.org/c/openocd/+/7900 Reviewed-by: Tested-by: jenkins --- src/target/armv7m_trace.c | 22 ++++++++++++++-------- src/target/armv7m_trace.h | 2 -- src/target/cortex_m.c | 4 ++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/target/armv7m_trace.c b/src/target/armv7m_trace.c index 45117d2db8..556568d71a 100644 --- a/src/target/armv7m_trace.c +++ b/src/target/armv7m_trace.c @@ -92,11 +92,14 @@ COMMAND_HANDLER(handle_itm_port_command) else armv7m->trace_config.itm_ter[reg_idx] &= ~(1 << port); - if (CMD_CTX->mode == COMMAND_EXEC) - return armv7m_trace_itm_config(target); + /* + * In config mode ITM is not accessible yet. + * Keep the value and it will be programmed at target init. + */ + if (CMD_CTX->mode == COMMAND_CONFIG) + return ERROR_OK; - armv7m->trace_config.itm_deferred_config = true; - return ERROR_OK; + return armv7m_trace_itm_config(target); } COMMAND_HANDLER(handle_itm_ports_command) @@ -112,11 +115,14 @@ COMMAND_HANDLER(handle_itm_ports_command) memset(armv7m->trace_config.itm_ter, enable ? 0xff : 0, sizeof(armv7m->trace_config.itm_ter)); - if (CMD_CTX->mode == COMMAND_EXEC) - return armv7m_trace_itm_config(target); + /* + * In config mode ITM is not accessible yet. + * Keep the value and it will be programmed at target init. + */ + if (CMD_CTX->mode == COMMAND_CONFIG) + return ERROR_OK; - armv7m->trace_config.itm_deferred_config = true; - return ERROR_OK; + return armv7m_trace_itm_config(target); } static const struct command_registration itm_command_handlers[] = { diff --git a/src/target/armv7m_trace.h b/src/target/armv7m_trace.h index 5abb0b9406..02eca932df 100644 --- a/src/target/armv7m_trace.h +++ b/src/target/armv7m_trace.h @@ -35,8 +35,6 @@ struct armv7m_trace_config { bool itm_async_timestamps; /** Enable synchronisation packet transmission (for sync port only) */ bool itm_synchro_packets; - /** Config ITM after target examine */ - bool itm_deferred_config; }; extern const struct command_registration armv7m_trace_command_handlers[]; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 7f62a6de2d..34c7cd4d2e 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2659,8 +2659,8 @@ int cortex_m_examine(struct target *target) if (retval != ERROR_OK) return retval; - if (armv7m->trace_config.itm_deferred_config) - armv7m_trace_itm_config(target); + /* Configure ITM */ + armv7m_trace_itm_config(target); /* NOTE: FPB and DWT are both optional. */ From 23ba602ca5be4a4c0841a178775bc82b3be0b38f Mon Sep 17 00:00:00 2001 From: Timur Golubovich Date: Fri, 7 Jun 2024 16:42:16 +0300 Subject: [PATCH 0857/1312] remote_bitbang: fix assertion failure for the cases when connection is abruptly terminated Changes affect the function remote_bitbang_fill_buf. When read_socket returns 0, socket reached EOF and there is no data to read. But if request was blocking, the caller expected some data. Such situations should be treated as ERROR. Change-Id: I02ed484e61fb776c1625f6e36ab14c85891939b2 Signed-off-by: Timur Golubovich Reviewed-on: https://review.openocd.org/c/openocd/+/8325 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/jtag/drivers/remote_bitbang.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 53d2151fdc..edd36f2e67 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -114,12 +114,18 @@ static int remote_bitbang_fill_buf(enum block_bool block) contiguous_available_space); if (first && block == BLOCK) socket_nonblock(remote_bitbang_fd); - first = false; if (count > 0) { remote_bitbang_recv_buf_end += count; if (remote_bitbang_recv_buf_end == sizeof(remote_bitbang_recv_buf)) remote_bitbang_recv_buf_end = 0; } else if (count == 0) { + /* When read_socket returns 0, socket reached EOF and there is + * no data to read. But if request was blocking, the caller + * expected some data. Such situations should be treated as ERROR. */ + if (first && block == BLOCK) { + LOG_ERROR("remote_bitbang: socket closed by remote"); + return ERROR_FAIL; + } return ERROR_OK; } else if (count < 0) { #ifdef _WIN32 @@ -133,6 +139,7 @@ static int remote_bitbang_fill_buf(enum block_bool block) return ERROR_FAIL; } } + first = false; } return ERROR_OK; From 92e8823ebdb6d01b41bb5d79af49501d525acd1d Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 2 Jun 2024 12:20:36 +0100 Subject: [PATCH 0858/1312] server/gdb: Use LOG_TARGET_xxx() to show target name The output "gdb port disabled" is confusing without reference to the target. Use LOG_TARGET_INFO() to output the target name. While at it, use LOG_TARGET_xxx() for all log statements where the target name is already used. Change-Id: I70b134145837db623e008a4a6c0be0008d9a0d87 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8313 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/server/gdb_server.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 0ded8e4404..58326f77be 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1067,15 +1067,15 @@ static int gdb_new_connection(struct connection *connection) target_state_name(target)); if (!target_was_examined(target)) { - LOG_ERROR("Target %s not examined yet, refuse gdb connection %d!", - target_name(target), gdb_connection->unique_index); + LOG_TARGET_ERROR(target, "Target not examined yet, refuse gdb connection %d!", + gdb_connection->unique_index); return ERROR_TARGET_NOT_EXAMINED; } gdb_actual_connections++; if (target->state != TARGET_HALTED) - LOG_WARNING("GDB connection %d on target %s not halted", - gdb_actual_connections, target_name(target)); + LOG_TARGET_WARNING(target, "GDB connection %d not halted", + gdb_actual_connections); /* DANGER! If we fail subsequently, we must remove this handler, * otherwise we occasionally see crashes as the timer can invoke the @@ -1102,9 +1102,8 @@ static int gdb_connection_closed(struct connection *connection) log_remove_callback(gdb_log_callback, connection); gdb_actual_connections--; - LOG_DEBUG("{%d} GDB Close, Target: %s, state: %s, gdb_actual_connections=%d", + LOG_TARGET_DEBUG(target, "{%d} GDB Close, state: %s, gdb_actual_connections=%d", gdb_connection->unique_index, - target_name(target), target_state_name(target), gdb_actual_connections); @@ -2350,7 +2349,7 @@ static int smp_reg_list_noread(struct target *target, } } if (!found) { - LOG_DEBUG("[%s] %s not found in combined list", target_name(target), a->name); + LOG_TARGET_DEBUG(target, "%s not found in combined list", a->name); if (local_list_size >= combined_allocated) { combined_allocated *= 2; local_list = realloc(local_list, combined_allocated * sizeof(struct reg *)); @@ -2398,9 +2397,8 @@ static int smp_reg_list_noread(struct target *target, } } if (!found) { - LOG_WARNING("Register %s does not exist in %s, which is part of an SMP group where " - "this register does exist.", - a->name, target_name(head->target)); + LOG_TARGET_WARNING(head->target, "Register %s does not exist, which is part of an SMP group where " + "this register does exist.", a->name); } } free(reg_list); @@ -3012,17 +3010,17 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p /* simple case, a continue packet */ if (parse[0] == 'c') { gdb_running_type = 'c'; - LOG_DEBUG("target %s continue", target_name(target)); + LOG_TARGET_DEBUG(target, "target continue"); gdb_connection->output_flag = GDB_OUTPUT_ALL; retval = target_resume(target, 1, 0, 0, 0); if (retval == ERROR_TARGET_NOT_HALTED) - LOG_INFO("target %s was not halted when resume was requested", target_name(target)); + LOG_TARGET_INFO(target, "target was not halted when resume was requested"); /* poll target in an attempt to make its internal state consistent */ if (retval != ERROR_OK) { retval = target_poll(target); if (retval != ERROR_OK) - LOG_DEBUG("error polling target %s after failed resume", target_name(target)); + LOG_TARGET_DEBUG(target, "error polling target after failed resume"); } /* @@ -3100,7 +3098,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p } } - LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id); + LOG_TARGET_DEBUG(ct, "single-step thread %" PRIx64, thread_id); gdb_connection->output_flag = GDB_OUTPUT_ALL; target_call_event_callbacks(ct, TARGET_EVENT_GDB_START); @@ -3142,13 +3140,13 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p retval = target_step(ct, current_pc, 0, 0); if (retval == ERROR_TARGET_NOT_HALTED) - LOG_INFO("target %s was not halted when step was requested", target_name(ct)); + LOG_TARGET_INFO(ct, "target was not halted when step was requested"); /* if step was successful send a reply back to gdb */ if (retval == ERROR_OK) { retval = target_poll(ct); if (retval != ERROR_OK) - LOG_DEBUG("error polling target %s after successful step", target_name(ct)); + LOG_TARGET_DEBUG(ct, "error polling target after successful step"); /* send back signal information */ gdb_signal_reply(ct, connection); /* stop forwarding log packets! */ @@ -3839,7 +3837,7 @@ static int gdb_target_start(struct target *target, const char *port) if (!gdb_service) return -ENOMEM; - LOG_INFO("starting gdb server for %s on %s", target_name(target), port); + LOG_TARGET_INFO(target, "starting gdb server on %s", port); gdb_service->target = target; gdb_service->core[0] = -1; @@ -3867,20 +3865,20 @@ static int gdb_target_add_one(struct target *target) /* skip targets that cannot handle a gdb connections (e.g. mem_ap) */ if (!target_supports_gdb_connection(target)) { - LOG_DEBUG("skip gdb server for target %s", target_name(target)); + LOG_TARGET_DEBUG(target, "skip gdb server"); return ERROR_OK; } if (target->gdb_port_override) { if (strcmp(target->gdb_port_override, "disabled") == 0) { - LOG_INFO("gdb port disabled"); + LOG_TARGET_INFO(target, "gdb port disabled"); return ERROR_OK; } return gdb_target_start(target, target->gdb_port_override); } if (strcmp(gdb_port_next, "disabled") == 0) { - LOG_INFO("gdb port disabled"); + LOG_TARGET_INFO(target, "gdb port disabled"); return ERROR_OK; } From 6b984a54c9a44780729c85e44f60a1d0ae8d3932 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 14 Jun 2024 18:12:03 +0200 Subject: [PATCH 0859/1312] Remove '_s' suffix from structs Change-Id: I956acce316e60252b317daa41274403d87f704b8 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8340 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/jtag/drivers/nulink_usb.c | 60 +++++----- src/jtag/drivers/rlink.c | 6 +- src/jtag/drivers/stlink_usb.c | 206 ++++++++++++++++----------------- src/jtag/drivers/ti_icdi_usb.c | 36 +++--- src/jtag/hla/hla_interface.c | 2 +- src/jtag/hla/hla_interface.h | 6 +- src/jtag/hla/hla_layout.c | 6 +- src/jtag/hla/hla_layout.h | 22 ++-- src/target/hla_target.c | 28 ++--- 9 files changed, 186 insertions(+), 186 deletions(-) diff --git a/src/jtag/drivers/nulink_usb.c b/src/jtag/drivers/nulink_usb.c index 4fdb857827..66cf25a6d1 100644 --- a/src/jtag/drivers/nulink_usb.c +++ b/src/jtag/drivers/nulink_usb.c @@ -34,7 +34,7 @@ #define NULINK2_USB_PID1 (0x5200) #define NULINK2_USB_PID2 (0x5201) -struct nulink_usb_handle_s { +struct nulink_usb_handle { hid_device *dev_handle; uint16_t max_packet_size; uint8_t usbcmdidx; @@ -87,7 +87,7 @@ enum nulink_connect { static int nulink_usb_xfer_rw(void *handle, uint8_t *buf) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -107,7 +107,7 @@ static int nulink_usb_xfer_rw(void *handle, uint8_t *buf) static int nulink1_usb_xfer(void *handle, uint8_t *buf, int size) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -120,7 +120,7 @@ static int nulink1_usb_xfer(void *handle, uint8_t *buf, int size) static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -133,7 +133,7 @@ static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size) static void nulink1_usb_init_buffer(void *handle, uint32_t size) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; h->cmdidx = 0; @@ -149,7 +149,7 @@ static void nulink1_usb_init_buffer(void *handle, uint32_t size) static void nulink2_usb_init_buffer(void *handle, uint32_t size) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; h->cmdidx = 0; @@ -165,7 +165,7 @@ static void nulink2_usb_init_buffer(void *handle, uint32_t size) static inline int nulink_usb_xfer(void *handle, uint8_t *buf, int size) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -174,7 +174,7 @@ static inline int nulink_usb_xfer(void *handle, uint8_t *buf, int size) static inline void nulink_usb_init_buffer(void *handle, uint32_t size) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -183,7 +183,7 @@ static inline void nulink_usb_init_buffer(void *handle, uint32_t size) static int nulink_usb_version(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_version"); @@ -219,7 +219,7 @@ static int nulink_usb_version(void *handle) static int nulink_usb_idcode(void *handle, uint32_t *idcode) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_idcode"); @@ -243,7 +243,7 @@ static int nulink_usb_idcode(void *handle, uint32_t *idcode) static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 " 0x%08" PRIX32, addr, val); @@ -278,7 +278,7 @@ static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) static enum target_state nulink_usb_state(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -299,7 +299,7 @@ static enum target_state nulink_usb_state(void *handle) static int nulink_usb_assert_srst(void *handle, int srst) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_assert_srst"); @@ -324,7 +324,7 @@ static int nulink_usb_assert_srst(void *handle, int srst) static int nulink_usb_reset(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_reset"); @@ -349,7 +349,7 @@ static int nulink_usb_reset(void *handle) static int nulink_usb_run(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_run"); @@ -365,7 +365,7 @@ static int nulink_usb_run(void *handle) static int nulink_usb_halt(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_halt"); @@ -385,7 +385,7 @@ static int nulink_usb_halt(void *handle) static int nulink_usb_step(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_step"); @@ -405,7 +405,7 @@ static int nulink_usb_step(void *handle) static int nulink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -444,7 +444,7 @@ static int nulink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) static int nulink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -483,7 +483,7 @@ static int nulink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, int res = ERROR_OK; uint32_t offset = 0; uint32_t bytes_remaining = 12; - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_read_mem8: addr 0x%08" PRIx32 ", len %" PRId16, addr, len); @@ -568,7 +568,7 @@ static int nulink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, int res = ERROR_OK; uint32_t offset = 0; uint32_t bytes_remaining = 12; - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_write_mem8: addr 0x%08" PRIx32 ", len %" PRIu16, addr, len); @@ -675,7 +675,7 @@ static int nulink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, { int res = ERROR_OK; uint32_t bytes_remaining = 12; - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -744,7 +744,7 @@ static int nulink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, { int res = ERROR_OK; uint32_t bytes_remaining = 12; - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; assert(handle); @@ -819,7 +819,7 @@ static int nulink_usb_read_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { int retval = ERROR_OK; - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; /* calculate byte count */ count *= size; @@ -879,7 +879,7 @@ static int nulink_usb_write_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval = ERROR_OK; - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; if (addr < ARM_SRAM_BASE) { LOG_DEBUG("nulink_usb_write_mem: address below ARM_SRAM_BASE, not supported.\n"); @@ -950,7 +950,7 @@ static int nulink_usb_override_target(const char *targetname) static int nulink_speed(void *handle, int khz, bool query) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; unsigned long max_ice_clock = khz; LOG_DEBUG("nulink_speed: query %s", query ? "yes" : "no"); @@ -1004,7 +1004,7 @@ static int nulink_speed(void *handle, int khz, bool query) static int nulink_usb_close(void *handle) { - struct nulink_usb_handle_s *h = handle; + struct nulink_usb_handle *h = handle; LOG_DEBUG("nulink_usb_close"); @@ -1018,7 +1018,7 @@ static int nulink_usb_close(void *handle) return ERROR_OK; } -static int nulink_usb_open(struct hl_interface_param_s *param, void **fd) +static int nulink_usb_open(struct hl_interface_param *param, void **fd) { struct hid_device_info *devs, *cur_dev; uint16_t target_vid = 0; @@ -1040,7 +1040,7 @@ static int nulink_usb_open(struct hl_interface_param_s *param, void **fd) return ERROR_FAIL; } - struct nulink_usb_handle_s *h = calloc(1, sizeof(*h)); + struct nulink_usb_handle *h = calloc(1, sizeof(*h)); if (!h) { LOG_ERROR("Out of memory"); goto error_open; @@ -1154,7 +1154,7 @@ static int nulink_usb_open(struct hl_interface_param_s *param, void **fd) return ERROR_FAIL; } -struct hl_layout_api_s nulink_usb_layout_api = { +struct hl_layout_api nulink_usb_layout_api = { .open = nulink_usb_open, .close = nulink_usb_close, .idcode = nulink_usb_idcode, diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index 1b1f2e4de6..afdf16e587 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -286,13 +286,13 @@ static uint8_t dtc_entry_download; static int dtc_load_from_buffer(struct libusb_device_handle *hdev_param, const uint8_t *buffer, size_t length) { - struct header_s { + struct header { uint8_t type; uint8_t length; }; int usb_err; - struct header_s *header; + struct header *header; uint8_t lut_start = 0xc0; dtc_entry_download = 0; @@ -311,7 +311,7 @@ static int dtc_load_from_buffer(struct libusb_device_handle *hdev_param, const u exit(1); } - header = (struct header_s *)buffer; + header = (struct header *)buffer; buffer += sizeof(*header); length -= sizeof(*header); diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index b14fbf1f38..8cf3b0c73a 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -140,7 +140,7 @@ struct stlink_usb_version { uint32_t flags; }; -struct stlink_usb_priv_s { +struct stlink_usb_priv { /** */ struct libusb_device_handle *fd; /** */ @@ -154,7 +154,7 @@ struct stlink_tcp_version { uint32_t build; }; -struct stlink_tcp_priv_s { +struct stlink_tcp_priv { /** */ int fd; /** */ @@ -171,9 +171,9 @@ struct stlink_tcp_priv_s { struct stlink_tcp_version version; }; -struct stlink_backend_s { +struct stlink_backend { /** */ - int (*open)(void *handle, struct hl_interface_param_s *param); + int (*open)(void *handle, struct hl_interface_param *param); /** */ int (*close)(void *handle); /** */ @@ -245,13 +245,13 @@ struct dap_queue { }; /** */ -struct stlink_usb_handle_s { +struct stlink_usb_handle { /** */ - struct stlink_backend_s *backend; + struct stlink_backend *backend; /** */ union { - struct stlink_usb_priv_s usb_backend_priv; - struct stlink_tcp_priv_s tcp_backend_priv; + struct stlink_usb_priv usb_backend_priv; + struct stlink_tcp_priv tcp_backend_priv; }; /** */ uint8_t rx_ep; @@ -294,22 +294,22 @@ struct stlink_usb_handle_s { }; /** */ -static inline int stlink_usb_open(void *handle, struct hl_interface_param_s *param) +static inline int stlink_usb_open(void *handle, struct hl_interface_param *param) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; return h->backend->open(handle, param); } /** */ static inline int stlink_usb_close(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; return h->backend->close(handle); } /** */ static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; return h->backend->xfer_noerrcheck(handle, buf, size); } @@ -567,7 +567,7 @@ static int stlink_usb_open_ap(void *handle, unsigned short apsel); /** */ static unsigned int stlink_usb_block(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -727,7 +727,7 @@ static int jtag_libusb_bulk_transfer_n( /** */ static int stlink_usb_xfer_v1_get_status(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int tr, ret; assert(handle); @@ -762,7 +762,7 @@ static int stlink_usb_xfer_v1_get_status(void *handle) #ifdef USE_LIBUSB_ASYNCIO static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -800,7 +800,7 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int #else static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int tr, ret; assert(handle); @@ -834,7 +834,7 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int static int stlink_usb_xfer_v1_get_sense(void *handle) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -860,7 +860,7 @@ static int stlink_usb_xfer_v1_get_sense(void *handle) /** */ static int stlink_usb_usb_read_trace(void *handle, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int tr, ret; ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->trace_ep, (char *)buf, size, @@ -882,7 +882,7 @@ static int stlink_usb_usb_read_trace(void *handle, const uint8_t *buf, int size) static int stlink_usb_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size) { int err, cmdsize = STLINK_CMD_SIZE_V2; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -915,7 +915,7 @@ static int stlink_usb_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, bool check_tcp_status) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -980,7 +980,7 @@ static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, bool /** */ static int stlink_tcp_xfer_noerrcheck(void *handle, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int send_size = STLINK_TCP_USB_CMD_SIZE; int recv_size = STLINK_TCP_SS_SIZE; @@ -1040,7 +1040,7 @@ static int stlink_tcp_xfer_noerrcheck(void *handle, const uint8_t *buf, int size /** */ static int stlink_tcp_read_trace(void *handle, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; stlink_usb_init_buffer(h, h->trace_ep, 0); return stlink_tcp_xfer_noerrcheck(handle, buf, size); @@ -1052,7 +1052,7 @@ static int stlink_tcp_read_trace(void *handle, const uint8_t *buf, int size) */ static int stlink_usb_error_check(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1162,7 +1162,7 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) { int retries = 0; int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; while (1) { if ((h->st_mode != STLINK_MODE_DEBUG_SWIM) || !retries) { @@ -1191,7 +1191,7 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) /** */ static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1206,14 +1206,14 @@ static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size) */ static void stlink_usb_set_cbw_transfer_datalength(void *handle, uint32_t size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; buf_set_u32(h->cmdbuf+8, 0, 32, size); } static void stlink_usb_xfer_v1_create_cmd(void *handle, uint8_t direction, uint32_t size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; /* fill the send buffer */ strcpy((char *)h->cmdbuf, "USBC"); @@ -1234,7 +1234,7 @@ static void stlink_usb_xfer_v1_create_cmd(void *handle, uint8_t direction, uint3 /** */ static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; h->direction = direction; @@ -1256,7 +1256,7 @@ static int stlink_usb_version(void *handle) uint8_t v, x, y, jtag, swim, msd, bridge = 0; char v_str[5 * (1 + 3) + 1]; /* VvJjMmBbSs */ char *p; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1479,7 +1479,7 @@ static int stlink_usb_version(void *handle) static int stlink_usb_check_voltage(void *handle, float *target_voltage) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; uint32_t adc_results[2]; /* no error message, simply quit with error */ @@ -1511,7 +1511,7 @@ static int stlink_usb_check_voltage(void *handle, float *target_voltage) static int stlink_usb_set_swdclk(void *handle, uint16_t clk_divisor) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1535,7 +1535,7 @@ static int stlink_usb_set_swdclk(void *handle, uint16_t clk_divisor) static int stlink_usb_set_jtagclk(void *handle, uint16_t clk_divisor) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1561,7 +1561,7 @@ static int stlink_usb_set_jtagclk(void *handle, uint16_t clk_divisor) static int stlink_usb_current_mode(void *handle, uint8_t *mode) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1583,7 +1583,7 @@ static int stlink_usb_current_mode(void *handle, uint8_t *mode) static int stlink_usb_mode_enter(void *handle, enum stlink_mode type) { int rx_size = 0; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1631,7 +1631,7 @@ static int stlink_usb_mode_enter(void *handle, enum stlink_mode type) static int stlink_usb_mode_leave(void *handle, enum stlink_mode type) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1725,7 +1725,7 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int init int res; uint8_t mode; enum stlink_mode emode; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -1829,7 +1829,7 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int init /* request status from last swim request */ static int stlink_swim_status(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 4); @@ -1849,7 +1849,7 @@ static int stlink_swim_status(void *handle) __attribute__((unused)) static int stlink_swim_cap(void *handle, uint8_t *cap) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 8); @@ -1866,7 +1866,7 @@ static int stlink_swim_cap(void *handle, uint8_t *cap) /* debug dongle assert/deassert sreset line */ static int stlink_swim_assert_reset(void *handle, int reset) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 0); @@ -1887,7 +1887,7 @@ static int stlink_swim_assert_reset(void *handle, int reset) */ static int stlink_swim_enter(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 0); @@ -1902,7 +1902,7 @@ static int stlink_swim_enter(void *handle) /* switch high/low speed swim */ static int stlink_swim_speed(void *handle, int speed) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 0); @@ -1924,7 +1924,7 @@ static int stlink_swim_speed(void *handle, int speed) */ static int stlink_swim_generate_rst(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 0); @@ -1943,7 +1943,7 @@ static int stlink_swim_generate_rst(void *handle) */ static int stlink_swim_resync(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; stlink_usb_init_buffer(handle, h->rx_ep, 0); @@ -1957,7 +1957,7 @@ static int stlink_swim_resync(void *handle) static int stlink_swim_writebytes(void *handle, uint32_t addr, uint32_t len, const uint8_t *data) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; unsigned int i; unsigned int datalen = 0; @@ -1993,7 +1993,7 @@ static int stlink_swim_writebytes(void *handle, uint32_t addr, uint32_t len, con static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint8_t *data) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; if (len > STLINK_SWIM_DATA_SIZE) @@ -2024,7 +2024,7 @@ static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint static int stlink_usb_idcode(void *handle, uint32_t *idcode) { int res, offset; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2061,7 +2061,7 @@ static int stlink_usb_idcode(void *handle, uint32_t *idcode) static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *val) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int res; assert(handle); @@ -2083,7 +2083,7 @@ static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *v static int stlink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2105,7 +2105,7 @@ static int stlink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) /** */ static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2156,7 +2156,7 @@ static enum target_state stlink_usb_v2_get_status(void *handle) static enum target_state stlink_usb_state(void *handle) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2198,7 +2198,7 @@ static enum target_state stlink_usb_state(void *handle) static int stlink_usb_assert_srst(void *handle, int srst) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2221,7 +2221,7 @@ static int stlink_usb_assert_srst(void *handle, int srst) static void stlink_usb_trace_disable(void *handle) { int res = ERROR_OK; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2243,7 +2243,7 @@ static void stlink_usb_trace_disable(void *handle) static int stlink_usb_trace_enable(void *handle) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2274,7 +2274,7 @@ static int stlink_usb_trace_enable(void *handle) /** */ static int stlink_usb_reset(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int retval; assert(handle); @@ -2304,7 +2304,7 @@ static int stlink_usb_reset(void *handle) static int stlink_usb_run(void *handle) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2326,7 +2326,7 @@ static int stlink_usb_run(void *handle) static int stlink_usb_halt(void *handle) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2347,7 +2347,7 @@ static int stlink_usb_halt(void *handle) /** */ static int stlink_usb_step(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2371,7 +2371,7 @@ static int stlink_usb_step(void *handle) static int stlink_usb_read_regs(void *handle) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2396,7 +2396,7 @@ static int stlink_usb_read_regs(void *handle) static int stlink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2436,7 +2436,7 @@ static int stlink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) /** */ static int stlink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2465,7 +2465,7 @@ static int stlink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) static int stlink_usb_get_rw_status(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2490,7 +2490,7 @@ static int stlink_usb_read_mem8(void *handle, uint8_t ap_num, uint32_t csw, { int res; uint16_t read_len = len; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2534,7 +2534,7 @@ static int stlink_usb_write_mem8(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2572,7 +2572,7 @@ static int stlink_usb_read_mem16(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, uint8_t *buffer) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2620,7 +2620,7 @@ static int stlink_usb_write_mem16(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2666,7 +2666,7 @@ static int stlink_usb_read_mem32(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, uint8_t *buffer) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2711,7 +2711,7 @@ static int stlink_usb_write_mem32(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, const uint8_t *buffer) { int res; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -2752,7 +2752,7 @@ static int stlink_usb_write_mem32(void *handle, uint8_t ap_num, uint32_t csw, static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, uint8_t *buffer) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle != NULL); @@ -2794,7 +2794,7 @@ static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_ static int stlink_usb_write_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_t csw, uint32_t addr, uint16_t len, const uint8_t *buffer) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle != NULL); @@ -2845,7 +2845,7 @@ static int stlink_usb_read_ap_mem(void *handle, uint8_t ap_num, uint32_t csw, int retval = ERROR_OK; uint32_t bytes_remaining; int retries = 0; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; /* calculate byte count */ count *= size; @@ -2930,7 +2930,7 @@ static int stlink_usb_write_ap_mem(void *handle, uint8_t ap_num, uint32_t csw, int retval = ERROR_OK; uint32_t bytes_remaining; int retries = 0; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; /* calculate byte count */ count *= size; @@ -3080,7 +3080,7 @@ static int stlink_match_speed_map(const struct speed_map *map, unsigned int map_ static int stlink_speed_swd(void *handle, int khz, bool query) { int speed_index; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; /* old firmware cannot change it */ if (!(h->version.flags & STLINK_F_HAS_SWD_SET_FREQ)) @@ -3103,7 +3103,7 @@ static int stlink_speed_swd(void *handle, int khz, bool query) static int stlink_speed_jtag(void *handle, int khz, bool query) { int speed_index; - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; /* old firmware cannot change it */ if (!(h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ)) @@ -3135,7 +3135,7 @@ static void stlink_dump_speed_map(const struct speed_map *map, unsigned int map_ static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int i; if (h->version.jtag_api != STLINK_JTAG_API_V3) { @@ -3170,7 +3170,7 @@ static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map static int stlink_set_com_freq(void *handle, bool is_jtag, unsigned int frequency) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; if (h->version.jtag_api != STLINK_JTAG_API_V3) { LOG_ERROR("Unknown command"); @@ -3191,7 +3191,7 @@ static int stlink_set_com_freq(void *handle, bool is_jtag, unsigned int frequenc static int stlink_speed_v3(void *handle, bool is_jtag, int khz, bool query) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int speed_index; struct speed_map map[STLINK_V3_MAX_FREQ_NB]; @@ -3211,7 +3211,7 @@ static int stlink_speed_v3(void *handle, bool is_jtag, int khz, bool query) static int stlink_speed(void *handle, int khz, bool query) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; if (!handle) return khz; @@ -3241,7 +3241,7 @@ static int stlink_speed(void *handle, int khz, bool query) /** */ static int stlink_usb_usb_close(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; if (!h) return ERROR_OK; @@ -3262,7 +3262,7 @@ static int stlink_usb_usb_close(void *handle) /** */ static int stlink_tcp_close(void *handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; if (!h) return ERROR_OK; @@ -3295,7 +3295,7 @@ static int stlink_tcp_close(void *handle) static int stlink_close(void *handle) { if (handle) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; stlink_usb_close(handle); @@ -3385,9 +3385,9 @@ static char *stlink_usb_get_alternate_serial(struct libusb_device_handle *device } /** */ -static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param) +static int stlink_usb_usb_open(void *handle, struct hl_interface_param *param) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int err, retry_count = 1; h->cmdbuf = malloc(STLINK_SG_SIZE); @@ -3496,9 +3496,9 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param) } /** */ -static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param) +static int stlink_tcp_open(void *handle, struct hl_interface_param *param) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int ret; /* SWIM is not supported using stlink-server */ @@ -3711,27 +3711,27 @@ static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param) return stlink_usb_version(h); } -static struct stlink_backend_s stlink_usb_backend = { +static struct stlink_backend stlink_usb_backend = { .open = stlink_usb_usb_open, .close = stlink_usb_usb_close, .xfer_noerrcheck = stlink_usb_usb_xfer_noerrcheck, .read_trace = stlink_usb_usb_read_trace, }; -static struct stlink_backend_s stlink_tcp_backend = { +static struct stlink_backend stlink_tcp_backend = { .open = stlink_tcp_open, .close = stlink_tcp_close, .xfer_noerrcheck = stlink_tcp_xfer_noerrcheck, .read_trace = stlink_tcp_read_trace, }; -static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode, void **fd) +static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode, void **fd) { - struct stlink_usb_handle_s *h; + struct stlink_usb_handle *h; LOG_DEBUG("stlink_open"); - h = calloc(1, sizeof(struct stlink_usb_handle_s)); + h = calloc(1, sizeof(struct stlink_usb_handle)); if (!h) { LOG_DEBUG("malloc failed"); @@ -3829,7 +3829,7 @@ static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode return ERROR_FAIL; } -static int stlink_usb_hl_open(struct hl_interface_param_s *param, void **fd) +static int stlink_usb_hl_open(struct hl_interface_param *param, void **fd) { return stlink_open(param, stlink_get_mode(param->transport), fd); } @@ -3839,7 +3839,7 @@ static int stlink_config_trace(void *handle, bool enabled, unsigned int *trace_freq, unsigned int traceclkin_freq, uint16_t *prescaler) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; if (!(h->version.flags & STLINK_F_HAS_TRACE)) { LOG_ERROR("The attached ST-LINK version doesn't support trace"); @@ -3900,7 +3900,7 @@ static int stlink_config_trace(void *handle, bool enabled, /** */ static int stlink_usb_init_access_port(void *handle, unsigned char ap_num) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -3919,7 +3919,7 @@ static int stlink_usb_init_access_port(void *handle, unsigned char ap_num) /** */ static int stlink_usb_close_access_port(void *handle, unsigned char ap_num) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -3942,7 +3942,7 @@ static int stlink_usb_close_access_port(void *handle, unsigned char ap_num) static int stlink_usb_rw_misc_out(void *handle, uint32_t items, const uint8_t *buffer) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; unsigned int buflen = ALIGN_UP(items, 4) + 4 * items; LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); @@ -3963,7 +3963,7 @@ static int stlink_usb_rw_misc_out(void *handle, uint32_t items, const uint8_t *b static int stlink_usb_rw_misc_in(void *handle, uint32_t items, uint8_t *buffer) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; unsigned int buflen = 2 * 4 * items; LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); @@ -3991,7 +3991,7 @@ static int stlink_usb_rw_misc_in(void *handle, uint32_t items, uint8_t *buffer) static int stlink_read_dap_register(void *handle, unsigned short dap_port, unsigned short addr, uint32_t *val) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int retval; assert(handle); @@ -4015,7 +4015,7 @@ static int stlink_read_dap_register(void *handle, unsigned short dap_port, static int stlink_write_dap_register(void *handle, unsigned short dap_port, unsigned short addr, uint32_t val) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; assert(handle); @@ -4033,7 +4033,7 @@ static int stlink_write_dap_register(void *handle, unsigned short dap_port, } /** */ -struct hl_layout_api_s stlink_usb_layout_api = { +struct hl_layout_api stlink_usb_layout_api = { /** */ .open = stlink_usb_hl_open, /** */ @@ -4078,8 +4078,8 @@ struct hl_layout_api_s stlink_usb_layout_api = { * DAP direct interface */ -static struct stlink_usb_handle_s *stlink_dap_handle; -static struct hl_interface_param_s stlink_dap_param; +static struct stlink_usb_handle *stlink_dap_handle; +static struct hl_interface_param stlink_dap_param; static DECLARE_BITMAP(opened_ap, DP_APSEL_MAX + 1); static uint32_t last_csw_default[DP_APSEL_MAX + 1]; static int stlink_dap_error = ERROR_OK; @@ -4107,7 +4107,7 @@ static int stlink_dap_get_error(void) static int stlink_usb_open_ap(void *handle, unsigned short apsel) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; int retval; /* nothing to do on old versions */ @@ -4523,7 +4523,7 @@ static int stlink_usb_buf_rw_segment(void *handle, const struct dap_queue *q, un static int stlink_usb_count_misc_rw_queue(void *handle, const struct dap_queue *q, unsigned int len, unsigned int *pkt_items) { - struct stlink_usb_handle_s *h = handle; + struct stlink_usb_handle *h = handle; unsigned int i, items = 0; uint32_t ap_num = DP_APSEL_INVALID; unsigned int misc_max_items = (h->version.stlink == 2) ? STLINK_V2_RW_MISC_SIZE : STLINK_V3_RW_MISC_SIZE; @@ -5039,7 +5039,7 @@ COMMAND_HANDLER(stlink_dap_backend_command) COMMAND_HANDLER(stlink_dap_cmd_command) { unsigned int rx_n, tx_n; - struct stlink_usb_handle_s *h = stlink_dap_handle; + struct stlink_usb_handle *h = stlink_dap_handle; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index 4260e2d39d..0e01171ea9 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -33,7 +33,7 @@ #define PACKET_START "$" #define PACKET_END "#" -struct icdi_usb_handle_s { +struct icdi_usb_handle { struct libusb_device_handle *usb_dev; char *read_buffer; @@ -108,7 +108,7 @@ static int remote_unescape_input(const char *buffer, int len, char *out_buf, int static int icdi_send_packet(void *handle, int len) { unsigned char cksum = 0; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; int result, retry = 0; int transferred = 0; @@ -220,7 +220,7 @@ static int icdi_send_packet(void *handle, int len) static int icdi_send_cmd(void *handle, const char *cmd) { - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; int cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "%s", cmd); return icdi_send_packet(handle, cmd_len); @@ -228,7 +228,7 @@ static int icdi_send_cmd(void *handle, const char *cmd) static int icdi_send_remote_cmd(void *handle, const char *data) { - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,"); cmd_len += hexify(h->write_buffer + cmd_len, (const uint8_t *)data, @@ -239,7 +239,7 @@ static int icdi_send_remote_cmd(void *handle, const char *data) static int icdi_get_cmd_result(void *handle) { - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; int offset = 0; char ch; @@ -284,7 +284,7 @@ static int icdi_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) static enum target_state icdi_usb_state(void *handle) { int result; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; uint32_t dhcsr; uint8_t buf[4]; @@ -303,7 +303,7 @@ static enum target_state icdi_usb_state(void *handle) static int icdi_usb_version(void *handle) { - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; char version[20]; @@ -335,7 +335,7 @@ static int icdi_usb_query(void *handle) { int result; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; result = icdi_send_cmd(handle, "qSupported"); if (result != ERROR_OK) @@ -468,7 +468,7 @@ static int icdi_usb_read_regs(void *handle) static int icdi_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) { int result; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; char cmd[10]; snprintf(cmd, sizeof(cmd), "p%x", regsel); @@ -521,7 +521,7 @@ static int icdi_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) static int icdi_usb_read_mem_int(void *handle, uint32_t addr, uint32_t len, uint8_t *buffer) { int result; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; char cmd[20]; snprintf(cmd, sizeof(cmd), "x%" PRIx32 ",%" PRIx32, addr, len); @@ -549,7 +549,7 @@ static int icdi_usb_read_mem_int(void *handle, uint32_t addr, uint32_t len, uint static int icdi_usb_write_mem_int(void *handle, uint32_t addr, uint32_t len, const uint8_t *buffer) { int result; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; size_t cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "X%" PRIx32 ",%" PRIx32 ":", addr, len); @@ -581,7 +581,7 @@ static int icdi_usb_read_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer) { int retval = ERROR_OK; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; uint32_t bytes_remaining; /* calculate byte count */ @@ -609,7 +609,7 @@ static int icdi_usb_write_mem(void *handle, uint32_t addr, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval = ERROR_OK; - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; uint32_t bytes_remaining; /* calculate byte count */ @@ -640,7 +640,7 @@ static int icdi_usb_override_target(const char *targetname) static int icdi_usb_close(void *handle) { - struct icdi_usb_handle_s *h = handle; + struct icdi_usb_handle *h = handle; if (!h) return ERROR_OK; @@ -654,15 +654,15 @@ static int icdi_usb_close(void *handle) return ERROR_OK; } -static int icdi_usb_open(struct hl_interface_param_s *param, void **fd) +static int icdi_usb_open(struct hl_interface_param *param, void **fd) { /* TODO: Convert remaining libusb_ calls to jtag_libusb_ */ int retval; - struct icdi_usb_handle_s *h; + struct icdi_usb_handle *h; LOG_DEBUG("icdi_usb_open"); - h = calloc(1, sizeof(struct icdi_usb_handle_s)); + h = calloc(1, sizeof(struct icdi_usb_handle)); if (!h) { LOG_ERROR("unable to allocate memory"); @@ -743,7 +743,7 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd) return ERROR_FAIL; } -struct hl_layout_api_s icdi_usb_layout_api = { +struct hl_layout_api icdi_usb_layout_api = { .open = icdi_usb_open, .close = icdi_usb_close, .idcode = icdi_usb_idcode, diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index 9c8d0fadea..6ac680128c 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -23,7 +23,7 @@ #include -static struct hl_interface_s hl_if = { +static struct hl_interface hl_if = { .param = { .device_desc = NULL, .vid = { 0 }, diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index fa4965806b..c95638b92a 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -20,7 +20,7 @@ extern const char *hl_transports[]; #define HLA_MAX_USB_IDS 16 -struct hl_interface_param_s { +struct hl_interface_param { /** */ const char *device_desc; /** List of recognised VIDs */ @@ -39,9 +39,9 @@ struct hl_interface_param_s { uint16_t stlink_tcp_port; }; -struct hl_interface_s { +struct hl_interface { /** */ - struct hl_interface_param_s param; + struct hl_interface_param param; /** */ const struct hl_layout *layout; /** */ diff --git a/src/jtag/hla/hla_layout.c b/src/jtag/hla/hla_layout.c index 51671d60aa..04c963f0e8 100644 --- a/src/jtag/hla/hla_layout.c +++ b/src/jtag/hla/hla_layout.c @@ -21,7 +21,7 @@ #include #include -static int hl_layout_open(struct hl_interface_s *adapter) +static int hl_layout_open(struct hl_interface *adapter) { int res; @@ -39,7 +39,7 @@ static int hl_layout_open(struct hl_interface_s *adapter) return ERROR_OK; } -static int hl_layout_close(struct hl_interface_s *adapter) +static int hl_layout_close(struct hl_interface *adapter) { return ERROR_OK; } @@ -78,7 +78,7 @@ const struct hl_layout *hl_layout_get_list(void) return hl_layouts; } -int hl_layout_init(struct hl_interface_s *adapter) +int hl_layout_init(struct hl_interface *adapter) { LOG_DEBUG("hl_layout_init"); diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h index e13da6531c..71a7563e1f 100644 --- a/src/jtag/hla/hla_layout.h +++ b/src/jtag/hla/hla_layout.h @@ -15,18 +15,18 @@ #include /** */ -struct hl_interface_s; -struct hl_interface_param_s; +struct hl_interface; +struct hl_interface_param; /** */ -extern struct hl_layout_api_s stlink_usb_layout_api; -extern struct hl_layout_api_s icdi_usb_layout_api; -extern struct hl_layout_api_s nulink_usb_layout_api; +extern struct hl_layout_api stlink_usb_layout_api; +extern struct hl_layout_api icdi_usb_layout_api; +extern struct hl_layout_api nulink_usb_layout_api; /** */ -struct hl_layout_api_s { +struct hl_layout_api { /** */ - int (*open)(struct hl_interface_param_s *param, void **handle); + int (*open)(struct hl_interface_param *param, void **handle); /** */ int (*close)(void *handle); /** */ @@ -121,16 +121,16 @@ struct hl_layout { /** */ char *name; /** */ - int (*open)(struct hl_interface_s *adapter); + int (*open)(struct hl_interface *adapter); /** */ - int (*close)(struct hl_interface_s *adapter); + int (*close)(struct hl_interface *adapter); /** */ - struct hl_layout_api_s *api; + struct hl_layout_api *api; }; /** */ const struct hl_layout *hl_layout_get_list(void); /** */ -int hl_layout_init(struct hl_interface_s *adapter); +int hl_layout_init(struct hl_interface *adapter); #endif /* OPENOCD_JTAG_HLA_HLA_LAYOUT_H */ diff --git a/src/target/hla_target.c b/src/target/hla_target.c index c1bda996ce..d6f2afb4e8 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -36,7 +36,7 @@ #define ARMV7M_SCS_DCRSR DCB_DCRSR #define ARMV7M_SCS_DCRDR DCB_DCRDR -static inline struct hl_interface_s *target_to_adapter(struct target *target) +static inline struct hl_interface *target_to_adapter(struct target *target) { return target->tap->priv; } @@ -44,14 +44,14 @@ static inline struct hl_interface_s *target_to_adapter(struct target *target) static int adapter_load_core_reg_u32(struct target *target, uint32_t regsel, uint32_t *value) { - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); return adapter->layout->api->read_reg(adapter->handle, regsel, value); } static int adapter_store_core_reg_u32(struct target *target, uint32_t regsel, uint32_t value) { - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); return adapter->layout->api->write_reg(adapter->handle, regsel, value); } @@ -65,7 +65,7 @@ static int adapter_examine_debug_reason(struct target *target) return ERROR_OK; } -static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ctrl) +static int hl_dcc_read(struct hl_interface *hl_if, uint8_t *value, uint8_t *ctrl) { uint16_t dcrdr; int retval = hl_if->layout->api->read_mem(hl_if->handle, @@ -90,7 +90,7 @@ static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ct static int hl_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { - struct hl_interface_s *hl_if = target_to_adapter(target); + struct hl_interface *hl_if = target_to_adapter(target); uint8_t data; uint8_t ctrl; uint32_t i; @@ -113,7 +113,7 @@ static int hl_handle_target_request(void *priv) if (!target_was_examined(target)) return ERROR_OK; - struct hl_interface_s *hl_if = target_to_adapter(target); + struct hl_interface *hl_if = target_to_adapter(target); if (!target->dbg_msg_enabled) return ERROR_OK; @@ -227,7 +227,7 @@ static int adapter_load_context(struct target *target) static int adapter_debug_entry(struct target *target) { - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); struct arm *arm = &armv7m->arm; struct reg *r; @@ -286,7 +286,7 @@ static int adapter_debug_entry(struct target *target) static int adapter_poll(struct target *target) { enum target_state state; - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); enum target_state prev_target_state = target->state; @@ -329,7 +329,7 @@ static int adapter_poll(struct target *target) static int hl_assert_reset(struct target *target) { int res = ERROR_OK; - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); bool use_srst_fallback = true; @@ -412,7 +412,7 @@ static int hl_deassert_reset(struct target *target) static int adapter_halt(struct target *target) { int res; - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); LOG_DEBUG("%s", __func__); @@ -439,7 +439,7 @@ static int adapter_resume(struct target *target, int current, int debug_execution) { int res; - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); uint32_t resume_pc; struct breakpoint *breakpoint = NULL; @@ -529,7 +529,7 @@ static int adapter_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { int res; - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); struct armv7m_common *armv7m = target_to_armv7m(target); struct breakpoint *breakpoint = NULL; struct reg *pc = armv7m->arm.pc; @@ -593,7 +593,7 @@ static int adapter_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; @@ -608,7 +608,7 @@ static int adapter_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - struct hl_interface_s *adapter = target_to_adapter(target); + struct hl_interface *adapter = target_to_adapter(target); if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; From 67be8188bb0625246f37347fa98e0f90bda1ad7a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 15 Jun 2024 17:57:25 +0200 Subject: [PATCH 0860/1312] Remove other '_s' suffix from structs Most of the work is already done by [1]. Remove few more '_s' suffix and also fix some comment referring to the old name of the struct. Link: https://review.openocd.org/c/openocd/+/8340 Change-Id: Ifddc401c3b05e62ece3aa7926af1e78f0c4a671e Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8341 Reviewed-by: zapb Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/core.h | 10 +++++----- src/flash/nor/driver.h | 8 ++++---- src/flash/nor/pic32mx.c | 2 +- src/jtag/commands.h | 6 +++--- src/target/xtensa/xtensa.c | 2 +- src/target/xtensa/xtensa.h | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index 80911f799c..ff175a1329 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -32,18 +32,18 @@ struct flash_sector { uint32_t size; /** * Indication of erasure status: 0 = not erased, 1 = erased, - * other = unknown. Set by @c flash_driver_s::erase_check only. + * other = unknown. Set by @c flash_driver::erase_check only. * * This information must be considered stale immediately. - * Don't set it in flash_driver_s::erase or a device mass_erase - * Don't clear it in flash_driver_s::write + * Don't set it in flash_driver::erase or a device mass_erase + * Don't clear it in flash_driver::write * The flag is not used in a protection block */ int is_erased; /** * Indication of protection status: 0 = unprotected/unlocked, * 1 = protected/locked, other = unknown. Set by - * @c flash_driver_s::protect_check. + * @c flash_driver::protect_check. * * This information must be considered stale immediately. * A million things could make it stale: power cycle, @@ -67,7 +67,7 @@ struct flash_sector { * a major interface. * * This structure will be passed as a parameter to the callbacks in the - * flash_driver_s structure, some of which may modify the contents of + * flash_driver structure, some of which may modify the contents of * this structure of the area of flash that it defines. Driver writers * may use the @c driver_priv member to store additional data on a * per-bank basis, if required. diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 7d6f8c5cc4..211661e214 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -29,7 +29,7 @@ struct flash_bank; * flash bank DRIVERNAME ...parameters... * @endcode * - * OpenOCD will search for the driver with a @c flash_driver_s::name + * OpenOCD will search for the driver with a @c flash_driver::name * that matches @c DRIVERNAME. * * The flash subsystem calls some of the other drivers routines a using @@ -170,7 +170,7 @@ struct flash_driver { /** * Check the erasure status of a flash bank. * When called, the driver routine must perform the required - * checks and then set the @c flash_sector_s::is_erased field + * checks and then set the @c flash_sector::is_erased field * for each of the flash banks's sectors. * * @param bank The bank to check @@ -182,7 +182,7 @@ struct flash_driver { * Determine if the specific bank is "protected" or not. * When called, the driver routine must must perform the * required protection check(s) and then set the @c - * flash_sector_s::is_protected field for each of the flash + * flash_sector::is_protected field for each of the flash * bank's sectors. * * If protection is not implemented, set method to NULL @@ -204,7 +204,7 @@ struct flash_driver { int (*info)(struct flash_bank *bank, struct command_invocation *cmd); /** - * A more gentle flavor of flash_driver_s::probe, performing + * A more gentle flavor of flash_driver::probe, performing * setup with less noise. Generally, driver routines should test * to see if the bank has already been probed; if it has, the * driver probably should not perform its probe a second time. diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index 0f3937cfc2..982c9610a4 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -92,7 +92,7 @@ struct pic32mx_flash_bank { * DEVID values as per PIC32MX Flash Programming Specification Rev N */ -static const struct pic32mx_devs_s { +static const struct pic32mx_devs { uint32_t devid; const char *name; } pic32mx_devs[] = { diff --git a/src/jtag/commands.h b/src/jtag/commands.h index a1096daa77..825907733f 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -15,7 +15,7 @@ #define OPENOCD_JTAG_COMMANDS_H /** - * The inferred type of a scan_command_s structure, indicating whether + * The inferred type of a scan_command structure, indicating whether * the command has the host scan in from the device, the host scan out * to the device, or both. */ @@ -29,7 +29,7 @@ enum scan_type { }; /** - * The scan_command provide a means of encapsulating a set of scan_field_s + * The scan_command provide a means of encapsulating a set of scan_field * structures that should be scanned in/out to the device. */ struct scan_command { @@ -123,7 +123,7 @@ union jtag_command_container { /** * The type of the @c jtag_command_container contained by a - * @c jtag_command_s structure. + * @c jtag_command structure. */ enum jtag_command_type { JTAG_SCAN = 1, diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index f7c82efed4..702b8fc6b8 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -331,7 +331,7 @@ union xtensa_reg_val_u { uint8_t buf[4]; }; -static const struct xtensa_keyval_info_s xt_qerr[XT_QERR_NUM] = { +static const struct xtensa_keyval_info xt_qerr[XT_QERR_NUM] = { { .chrval = "E00", .intval = ERROR_FAIL }, { .chrval = "E01", .intval = ERROR_FAIL }, { .chrval = "E02", .intval = ERROR_COMMAND_ARGUMENT_INVALID }, diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index a220021a68..1d56f83682 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -97,7 +97,7 @@ enum xtensa_ar_scratch_set_e { XT_AR_SCRATCH_NUM }; -struct xtensa_keyval_info_s { +struct xtensa_keyval_info { char *chrval; int intval; }; @@ -283,7 +283,7 @@ struct xtensa { bool halt_request; uint32_t nx_stop_cause; uint32_t nx_reg_idx[XT_NX_REG_IDX_NUM]; - struct xtensa_keyval_info_s scratch_ars[XT_AR_SCRATCH_NUM]; + struct xtensa_keyval_info scratch_ars[XT_AR_SCRATCH_NUM]; bool regs_fetched; /* true after first register fetch completed successfully */ }; From ad87fbd1cf28760795c4e18f3318a2d720e5a8a6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 11 Jun 2024 16:40:29 +0200 Subject: [PATCH 0861/1312] tcl/interface: support for Raspberry Pi 5 Make sure raspberrypi-native.cfg cannot be used on RPi5. Add raspberrypi5-gpiod.cfg which uses linuxgpiod adapter driver. Issue a warning if PCIe is in power save mode. While on it, re-format warnings issued from Tcl to look similar to LOG_WARNING() output. Change-Id: If19b0350bd5fff83d9a0c65999e33b161fb6957a Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8333 Tested-by: jenkins Reviewed-by: Jonathan Bell --- tcl/interface/raspberrypi-gpio-connector.cfg | 22 +++++++++------ tcl/interface/raspberrypi-native.cfg | 12 +++++--- tcl/interface/raspberrypi5-gpiod.cfg | 29 ++++++++++++++++++++ 3 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 tcl/interface/raspberrypi5-gpiod.cfg diff --git a/tcl/interface/raspberrypi-gpio-connector.cfg b/tcl/interface/raspberrypi-gpio-connector.cfg index eff73fc927..af7266b51b 100644 --- a/tcl/interface/raspberrypi-gpio-connector.cfg +++ b/tcl/interface/raspberrypi-gpio-connector.cfg @@ -10,6 +10,12 @@ # Do not forget the GND connection, e.g. pin 20 of the GPIO header. # +if { [info exists GPIO_CHIP] } { + set _GPIO_CHIP $GPIO_CHIP +} else { + set _GPIO_CHIP 0 +} + # GPIO 25 (pin 22) previously used for TMS/SWDIO is pulled-down by default. # The JTAG/SWD specification requires pull-up at the target board # for either signal. Connecting the signal pulled-up on the target @@ -19,23 +25,23 @@ echo "Warn : TMS/SWDIO moved to GPIO 8 (pin 24). Check the wiring please!" # Each of the JTAG lines need a gpio number set: tck tms tdi tdo # Header pin numbers: 23 24 19 21 -adapter gpio tck -chip 0 11 -adapter gpio tms -chip 0 8 -adapter gpio tdi -chip 0 10 -adapter gpio tdo -chip 0 9 +adapter gpio tck -chip $_GPIO_CHIP 11 +adapter gpio tms -chip $_GPIO_CHIP 8 +adapter gpio tdi -chip $_GPIO_CHIP 10 +adapter gpio tdo -chip $_GPIO_CHIP 9 # Each of the SWD lines need a gpio number set: swclk swdio # Header pin numbers: 23 24 -adapter gpio swclk -chip 0 11 -adapter gpio swdio -chip 0 8 +adapter gpio swclk -chip $_GPIO_CHIP 11 +adapter gpio swdio -chip $_GPIO_CHIP 8 # If you define trst or srst, use appropriate reset_config # Header pin numbers: TRST - 26, SRST - 18 -# adapter gpio trst -chip 0 7 +# adapter gpio trst -chip $_GPIO_CHIP 7 # reset_config trst_only -# adapter gpio srst -chip 0 24 +# adapter gpio srst -chip $_GPIO_CHIP 24 # reset_config srst_only srst_push_pull # or if you have both connected, diff --git a/tcl/interface/raspberrypi-native.cfg b/tcl/interface/raspberrypi-native.cfg index 7224723d63..c80f90a146 100644 --- a/tcl/interface/raspberrypi-native.cfg +++ b/tcl/interface/raspberrypi-native.cfg @@ -37,9 +37,9 @@ proc get_max_cpu_clock { default } { return $clock } - echo "WARNING: Host CPU clock unknown." - echo "WARNING: Using the highest possible value $default kHz as a safe default." - echo "WARNING: Expect JTAG/SWD clock significantly slower than requested." + echo "Warn : Host CPU clock unknown." + echo "Warn : Using the highest possible value $default kHz as a safe default." + echo "Warn : Expect JTAG/SWD clock significantly slower than requested." return $default } @@ -56,9 +56,13 @@ if {[string match *bcm2711* $compat]} { } elseif {[string match *bcm2835* $compat] || [string match *bcm2708* $compat]} { set clocks_per_timing_loop 6 set speed_offset 32 +} elseif {[string match *bcm2712* $compat]} { + echo "Error: Raspberrypi Pi 5 has moved GPIOs to PCIe connected RP1 chip." + echo "Error: Native GPIO handling is not supported, use 'raspberrypi5-gpiod.cfg'" + shutdown } else { set speed_offset 32 - echo "WARNING: Unknown type of the host SoC. Expect JTAG/SWD clock slower than requested." + echo "Warn : Unknown type of the host SoC. Expect JTAG/SWD clock slower than requested." } set clock [get_max_cpu_clock 2000000] diff --git a/tcl/interface/raspberrypi5-gpiod.cfg b/tcl/interface/raspberrypi5-gpiod.cfg new file mode 100644 index 0000000000..f3fdde0f20 --- /dev/null +++ b/tcl/interface/raspberrypi5-gpiod.cfg @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Config for Raspberry Pi 5 used as a bitbang adapter. +# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html + +# Raspberry Pi 5 is not compatible with bcm2835gpio native GPIO driver. +# The linuxgpiod driver without configurable adapter speed runs at approximately +# 800 kHz (SWD writes) and 360 kHz (SWD reads) + +adapter driver linuxgpiod + +proc read_file { name } { + if {[catch {open $name r} fd]} { + return "" + } + set result [read $fd] + close $fd + return $result +} + +set pcie_aspm [read_file /sys/module/pcie_aspm/parameters/policy] +# escaping [ ] characters in string match pattern does not work in Jim-Tcl +if {![string match "**" [string map { "\[" < "\]" > } $pcie_aspm]]} { + echo "Warn : Switch PCIe power saving off or the first couple of pulses gets clocked as fast as 20 MHz" + echo "Warn : Issue 'echo performance | sudo tee /sys/module/pcie_aspm/parameters/policy'" +} + +set GPIO_CHIP 4 +source [find interface/raspberrypi-gpio-connector.cfg] From 23c33e1d3a332a94ef080451d43c6dc004e34750 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 10 Jun 2024 13:10:44 +0200 Subject: [PATCH 0862/1312] target/cortex_m: workaround Cortex-M7 erratum 3092511 When an asynchronous exception occurs at the same time as a breakpoint event (either hardware breakpoint or software breakpoint), it is possible for the processor to halt at the beginning of the exception handler instead of the instruction address pointed by the breakpoint. During debug entry in exception handler state and with BKPT bit set as the only break reason in DFSR, check if there is a breakpoint, which have triggered the debug halt. If there is no such breakpoint, resume execution. The processor services the interrupt and halts again at the correct breakpoint address. The workaround is not needed during target algo run (debug_execution) because interrupts are disabled in PRIMASK register. Also after single step the workaround resume never takes place: the situation is treated as error. Link: https://developer.arm.com/documentation/SDEN1068427/latest/ Signed-off-by: Tomas Vanek Change-Id: I8b23f39cedd7dccabe7e7066d616fb972b69f769 Reviewed-on: https://review.openocd.org/c/openocd/+/8332 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Liviu Ionescu --- src/target/cortex_m.c | 81 +++++++++++++++++++++++++++++++++++++++++-- src/target/cortex_m.h | 4 +++ src/target/target.h | 1 + 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 34c7cd4d2e..9b00a2796f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -797,6 +797,42 @@ static int cortex_m_examine_exception_reason(struct target *target) return retval; } +/* Errata 3092511 workaround + * Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ +static int cortex_m_erratum_check_breakpoint(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = &cortex_m->armv7m; + struct arm *arm = &armv7m->arm; + + uint32_t pc = buf_get_u32(arm->pc->value, 0, 32); + + /* To reduce the workaround processing cost we assume FPB is in sync + * with OpenOCD breakpoints. If the target app writes to FPB + * OpenOCD will resume after the break set by app */ + struct breakpoint *bkpt = breakpoint_find(target, pc); + if (bkpt) { + LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint confirmed"); + return ERROR_OK; + } + if (pc >= 0xe0000000u) + /* not executable area, do not read instruction @ pc */ + return ERROR_OK; + + uint16_t insn; + int retval = target_read_u16(target, pc, &insn); + if (retval != ERROR_OK) + return ERROR_OK; /* do not propagate the error, just avoid workaround */ + + if ((insn & 0xff00) == (ARMV5_T_BKPT(0) & 0xff00)) { + LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint embedded in code confirmed"); + return ERROR_OK; + } + LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint not found, proceed with resume"); + return ERROR_TARGET_HALTED_DO_RESUME; +} + static int cortex_m_debug_entry(struct target *target) { uint32_t xpsr; @@ -883,6 +919,17 @@ static int cortex_m_debug_entry(struct target *target) secure_state ? "Secure" : "Non-Secure", target_state_name(target)); + /* Errata 3092511 workaround + * Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ + if (cortex_m->incorrect_halt_erratum + && armv7m->exception_number + && cortex_m->nvic_dfsr == (DFSR_BKPT | DFSR_HALTED)) { + retval = cortex_m_erratum_check_breakpoint(target); + if (retval != ERROR_OK) + return retval; + } + if (armv7m->post_debug_entry) { retval = armv7m->post_debug_entry(target); if (retval != ERROR_OK) @@ -960,6 +1007,28 @@ static int cortex_m_poll_one(struct target *target) if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) { retval = cortex_m_debug_entry(target); + /* Errata 3092511 workaround + * Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ + if (retval == ERROR_TARGET_HALTED_DO_RESUME) { + struct arm *arm = &armv7m->arm; + LOG_TARGET_INFO(target, "Resuming after incorrect halt @ PC 0x%08" PRIx32 + ", ARM Cortex-M7 erratum 3092511", + buf_get_u32(arm->pc->value, 0, 32)); + /* We don't need to restore registers, just restart the core */ + cortex_m_set_maskints_for_run(target); + retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT); + if (retval != ERROR_OK) + return retval; + + target->debug_reason = DBG_REASON_NOTHALTED; + /* registers are now invalid */ + register_cache_invalidate(armv7m->arm.core_cache); + + target->state = TARGET_RUNNING; + return ERROR_OK; + } + /* arm_semihosting needs to know registers, don't run if debug entry returned error */ if (retval == ERROR_OK && arm_semihosting(target, &retval) != 0) return retval; @@ -1582,7 +1651,7 @@ static int cortex_m_step(struct target *target, int current, cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); retval = cortex_m_debug_entry(target); - if (retval != ERROR_OK) + if (retval != ERROR_OK && retval != ERROR_TARGET_HALTED_DO_RESUME) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); @@ -2560,14 +2629,22 @@ int cortex_m_examine(struct target *target) (uint8_t)((cpuid >> 0) & 0xf)); cortex_m->maskints_erratum = false; + cortex_m->incorrect_halt_erratum = false; if (impl_part == CORTEX_M7_PARTNO) { uint8_t rev, patch; rev = (cpuid >> 20) & 0xf; patch = (cpuid >> 0) & 0xf; if ((rev == 0) && (patch < 2)) { - LOG_TARGET_WARNING(target, "Silicon bug: single stepping may enter pending exception handler!"); + LOG_TARGET_WARNING(target, "Erratum 702596: single stepping may enter pending exception handler!"); cortex_m->maskints_erratum = true; } + /* TODO: add revision check when a Cortex-M7 revision with fixed 3092511 is out */ + LOG_TARGET_WARNING(target, "Erratum 3092511: Cortex-M7 can halt in an incorrect address when breakpoint and exception occurs simultaneously"); + cortex_m->incorrect_halt_erratum = true; + if (armv7m->is_hla_target) + LOG_WARNING("No erratum 3092511 workaround on hla adapter"); + else + LOG_INFO("The erratum 3092511 workaround will resume after an incorrect halt"); } LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid); diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index a585b786b9..eb646e4726 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -256,6 +256,10 @@ struct cortex_m_common { /* Whether this target has the erratum that makes C_MASKINTS not apply to * already pending interrupts */ bool maskints_erratum; + + /* Errata 3092511 Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ + bool incorrect_halt_erratum; }; static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m) diff --git a/src/target/target.h b/src/target/target.h index d5c0e0e8c7..03db3950ce 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -799,6 +799,7 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t #define ERROR_TARGET_ALGO_EXIT (-313) #define ERROR_TARGET_SIZE_NOT_SUPPORTED (-314) #define ERROR_TARGET_PACKING_NOT_SUPPORTED (-315) +#define ERROR_TARGET_HALTED_DO_RESUME (-316) /* used to workaround incorrect debug halt */ extern bool get_target_reset_nag(void); From c9f22c79dfecf61a7160a324a8b9f4fce695c67c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 3 Feb 2024 19:25:21 +0100 Subject: [PATCH 0863/1312] doc: document 'target create' flags '-dbgbase' and '-coreid' Add to the command 'target create' the description for the flags '-dbgbase' and '-coreid'. Report that '-coreid' is currently used for purposes other than CPU detection/examination, and that such uses are going to be re-considered. Change-Id: I25c839e3653101234c5862ce9da77019a5bb3249 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8129 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/openocd.texi | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index e46e6004bc..667c7a693c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5161,6 +5161,38 @@ On ADIv6 DAP @var{ap_number} is the base address of the DAP AP the target is con Use this option with systems where multiple, independent cores are connected to separate access ports of the same DAP. +@item @code{-dbgbase} @var{dbg_base_address} -- set the base address of the +debug controller. +This is ignored and not required for target types that have the debug controller +at fixed addresses, like @code{cortex_m}. +On DAP based SoC, OpenOCD can parse the ROM table in the DAP access port to +identify the base address of the debug controller, but the parsing can be slow +on devices with big ROM tables. +While using @code{-dbgbase} is suggested to speed up the target examination, +it is often the only viable solution for devices with incorrect ROM table +content or with ROM table partially not accessible due to clock gating or +power management. + +@item @code{-coreid} @var{coreid} -- set an index to identify the CPU or its +debug controller. + +@itemize @minus +@item When @code{-dbgbase} option is not provided on devices with multiple +CPUs on the same DAP access port +(e.g. @code{cortex_a}, @code{cortex_r4}, @code{aarch64} and @code{armv8r}), +this option specifies that the ROM table parsing should select the CPU in +position @var{coreid}. + +@item On target type @code{riscv}, @var{coreid} specifies the hart +(HARdware Threads) on the DM (Debug Module). It is used on multi-hart +devices to index a specific hart ID. +When not present, it's default value is zero. + +@item This value @var{coreid} is currently also used in other contexts as a +general CPU index, e.g. in SMP nodes or to select a specific CPU in a chip. +To avoid confusion, these additional use cases are going to be dropped. +@end itemize + @item @code{-cti} @var{cti_name} -- set Cross-Trigger Interface (CTI) connected to the target. Currently, only the @code{aarch64} target makes use of this option, where it is a mandatory configuration for the target run control. From 2fe392ef5085432bb5ae762469ed16e08678f102 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 3 Feb 2024 14:29:57 +0100 Subject: [PATCH 0864/1312] flash: psoc6: drop use of 'coreid' to identify the CPU The flag '-coreid' is used by the command 'target create' to specify the debug controller of the target, either in case of a single debug controller for multiple CPU (e.g. RISC-V harts) or in case of multiple CPU on a DAP access port (e.g. Cortex-A SMP cluster). It is also currently used to specify the CPU ID in a SMP cluster, but this is going to be reworked. This flag has no effects on Cortex-M; ARM specifies that only one CPU Cortex-M can occupy the DAP access port by using hardcoded addresses. The flash driver 'psoc6' uses the flag '-coreid' to detect if the current target is the Cortex-M0 on AP#1 or the Cortex-M4 on AP#2 in the SoC. There are other ways to run such detection, without using such unrelated '-coreid' flag, e.g. using the AP number or the arch type of the target. Use the arch type to detect Cortex-M0 (ARM_ARCH_V6M) vs Cortex-M4 (ARM_ARCH_V7M). Drop the flags '-coreid' from the psoc6 configuration file. Change-Id: I0b9601c160dd4f2421a03ce6e3e7c55c6212f714 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8128 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/psoc6.c | 7 +++++-- tcl/target/psoc6.cfg | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 859b3e9ec5..47f3ac6980 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -223,6 +223,8 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_ { int hr; uint32_t reg_val; + struct armv7m_common *armv7m = target_to_armv7m(target); + bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M); struct timeout to; timeout_init(&to, IPC_TIMEOUT_MS); @@ -244,7 +246,7 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_ return ERROR_OK; } - if (target->coreid) { + if (!is_cm0) { LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. " "Please perform all Flash-related operations via CM0+ target on dual-core devices."); } @@ -886,7 +888,8 @@ static int handle_reset_halt(struct target *target) { int hr; uint32_t reset_addr; - bool is_cm0 = (target->coreid == 0); + struct armv7m_common *armv7m = target_to_armv7m(target); + bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M); /* Halt target device */ if (target->state != TARGET_HALTED) { diff --git a/tcl/target/psoc6.cfg b/tcl/target/psoc6.cfg index d69515cdf7..52b04f5694 100644 --- a/tcl/target/psoc6.cfg +++ b/tcl/target/psoc6.cfg @@ -113,7 +113,7 @@ proc psoc6_deassert_post { target } { } if { $_ENABLE_CM0 } { - target create ${TARGET}.cm0 cortex_m -dap $_CHIPNAME.dap -ap-num 1 -coreid 0 + target create ${TARGET}.cm0 cortex_m -dap $_CHIPNAME.dap -ap-num 1 ${TARGET}.cm0 configure -work-area-phys $_WORKAREAADDR_CM0 -work-area-size $_WORKAREASIZE_CM0 -work-area-backup 0 flash bank main_flash_cm0 psoc6 0x10000000 0 0 0 ${TARGET}.cm0 @@ -128,7 +128,7 @@ if { $_ENABLE_CM0 } { } if { $_ENABLE_CM4 } { - target create ${TARGET}.cm4 cortex_m -dap $_CHIPNAME.dap -ap-num 2 -coreid 1 + target create ${TARGET}.cm4 cortex_m -dap $_CHIPNAME.dap -ap-num 2 ${TARGET}.cm4 configure -work-area-phys $_WORKAREAADDR_CM4 -work-area-size $_WORKAREASIZE_CM4 -work-area-backup 0 flash bank main_flash_cm4 psoc6 0x10000000 0 0 0 ${TARGET}.cm4 From 31e0fc4a7aa049d5cc66a48e2353693b3d52b4a7 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 19 Jun 2024 08:52:04 +0200 Subject: [PATCH 0865/1312] doc: Remove outdated '-pipe' option Change-Id: Ie3a7a3aaf69485f16b2447bd1dfa7622b584c7c0 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8348 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 667c7a693c..267430d1fc 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2179,8 +2179,6 @@ only during configuration (before those ports are opened). For reasons including security, you may wish to prevent remote access using one or more of these ports. In such cases, just specify the relevant port number as "disabled". -If you disable all access through TCP/IP, you will need to -use the command line @option{-pipe} option. You can request the operating system to select one of the available ports for the server by specifying the relevant port number as "0". From 636f003eee040b41d4aaa48fc1b324b447122b79 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 18 Jun 2024 11:03:11 +0200 Subject: [PATCH 0866/1312] AUTHORS: Refer to source code and Git history The list of authors and contributors is not maintained and outdated for years now. Refer to the source code and Git history instead of keeping a separate list. Change-Id: I9a92e8e0d5073b56030bc36086b76e28de96389f Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8346 Reviewed-by: Jonathan McDowell Tested-by: jenkins Reviewed-by: Antonio Borneo --- AUTHORS | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/AUTHORS b/AUTHORS index 2a989f37ec..7489834647 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,12 +1,2 @@ -Dominic Rath -Magnus Lundin -Michael Fischer -Spencer Oliver -Carsten Schlote -Øyvind Harboe -Duane Ellis -Michael Schwingen -Rick Altherr -David Brownell -Vincint Palatin -Zachary T Welch +Please check the source code files and/or Git history for a list of all authors +and contributors. From 6ed058933cfc023ef02e8c6d08c37ddc5b0328c2 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 18 Jun 2024 17:26:21 +0200 Subject: [PATCH 0867/1312] doc: Refurbish manual page Remove the outdated option '--pipe' and bring the description of OpenOCD up to date without focus on JTAG only. Change-Id: If52e936a366dde21c1dd514bd3960d100b540e77 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8347 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.1 | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/doc/openocd.1 b/doc/openocd.1 index 4278486e5d..34ec7617d1 100644 --- a/doc/openocd.1 +++ b/doc/openocd.1 @@ -1,24 +1,21 @@ -.TH "OPENOCD" "1" "November 24, 2009" +.TH "OPENOCD" "1" "June 18, 2024" .SH "NAME" openocd \- A free and open on\-chip debugging, in\-system programming and -boundary\-scan testing tool for ARM and MIPS systems +boundary\-scan testing tool for microcontrollers and other embedded devices .SH "SYNOPSIS" -.B openocd \fR[\fB\-fsdlcphv\fR] [\fB\-\-file\fR ] [\fB\-\-search\fR ] [\fB\-\-debug\fR ] [\fB\-\-log_output\fR ] [\fB\-\-command\fR ] [\fB\-\-pipe\fR] [\fB\-\-help\fR] [\fB\-\-version\fR] +.B openocd \fR[\fB\-fsdlchv\fR] [\fB\-\-file\fR ] [\fB\-\-search\fR ] [\fB\-\-debug\fR ] [\fB\-\-log_output\fR ] [\fB\-\-command\fR ] [\fB\-\-help\fR] [\fB\-\-version\fR] .SH "DESCRIPTION" .B OpenOCD is an on\-chip debugging, in\-system programming and boundary\-scan -testing tool for various ARM and MIPS systems. +testing tool for various microcontrollers and other embedded devices. .PP -The debugger uses an IEEE 1149\-1 compliant JTAG TAP bus master to access -on\-chip debug functionality available on ARM based microcontrollers or -system-on-chip solutions. For MIPS systems the EJTAG interface is supported. +Various different types of debug adapters as well as transport protocols like +JTAG and SWD are supported by OpenOCD, please check the \fIopenocd\fR info page +for the complete list. .PP User interaction is realized through a telnet command line interface, a gdb (the GNU debugger) remote protocol server, and a simplified RPC connection that can be used to interface with OpenOCD's Jim Tcl engine. -.PP -OpenOCD supports various different types of JTAG interfaces/programmers, -please check the \fIopenocd\fR info page for the complete list. .SH "OPTIONS" .TP .B "\-f, \-\-file " @@ -68,8 +65,6 @@ Note that you will need to explicitly invoke .I init if the command requires access to a target or flash. .TP -.B "\-p, \-\-pipe" -Use pipes when talking to gdb. .TP .B "\-h, \-\-help" Show a help text and exit. @@ -82,8 +77,6 @@ Please report any bugs on the mailing list at .SH "LICENCE" .B OpenOCD is covered by the GNU General Public License (GPL), version 2 or later. -.SH "SEE ALSO" -.BR jtag (1) .PP The full documentation for .B openocd From 990869f7ec8dbb91f14f9edde6f02dc30fd18b8e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 21 Jun 2024 14:32:45 +0200 Subject: [PATCH 0868/1312] openocd: build: prevent old clone to fail on git submodules Working on an old local git repository, the git sub-modules could have been set before last changes in .gitmodules. The script 'bootstrap' does not update the url of the repositories and this can cause the script to fail. Add 'git submodule sync' to the script to update the url of the repositories. While there, fuse 'git submodule init' and git submodule update' in a single command. Reported-by: Karl Hammar Change-Id: I61412f804dbbb7a843aa009139ddb4b8e71beefb Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8375 Tested-by: jenkins --- bootstrap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap b/bootstrap index cf6167fff6..7d4ca37bd8 100755 --- a/bootstrap +++ b/bootstrap @@ -38,8 +38,8 @@ if [ -n "$SKIP_SUBMODULE" ]; then echo "Skipping submodule setup" else echo "Setting up submodules" - git submodule init - git submodule update + git submodule sync + git submodule update --init fi if [ -x src/jtag/drivers/libjaylink/autogen.sh ]; then From 7957208cf6c50ddbbc4b6d687f8aa278604a363b Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Mon, 10 Apr 2023 11:17:17 +0800 Subject: [PATCH 0869/1312] openocd: fix some coding style Add space around math operators. Change-Id: I50fce3da283a78ba02bf70b6a752f7bf778d79f5 Signed-off-by: Mark Zhuang Reviewed-on: https://review.openocd.org/c/openocd/+/7585 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/em357.c | 2 +- src/target/xtensa/xtensa.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c index 043494c789..207346f10d 100644 --- a/src/flash/nor/em357.c +++ b/src/flash/nor/em357.c @@ -709,7 +709,7 @@ static int em357_probe(struct flash_bank *bank) em357_info->ppage_size = 4; - LOG_INFO("flash size = %d KiB", num_pages*page_size/1024); + LOG_INFO("flash size = %d KiB", num_pages * page_size / 1024); free(bank->sectors); diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 702b8fc6b8..54fcd2ad6d 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -540,7 +540,7 @@ static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint for (int32_t i = oplenw - 1; i > 0; i--) xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0 + i, - target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t)*i])); + target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t) * i])); /* Write DIR0EXEC last */ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0EXEC, From 4d99e77419e34fac62e36355e7205e929c712b5c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 9 Nov 2023 11:20:00 +0100 Subject: [PATCH 0870/1312] jtag/hla: Restructure commands Use a command group 'hla' with subcommands instead of individual commands with 'hla_' prefix. The old commands are still available to ensure backwards compatibility, but are marked as deprecated. Change-Id: I612e3cc080d308735932aea0f11001428eadc570 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8335 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 10 +++++----- src/jtag/hla/hla_interface.c | 23 +++++++++++++++++------ src/jtag/startup.tcl | 30 ++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 267430d1fc..a7c1e6d08b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3197,19 +3197,19 @@ versions of firmware where serial number is reset after first use. Suggest using ST firmware update utility to upgrade ST-LINK firmware even if current version reported is V2.J21.S4. -@deffn {Config Command} {hla_device_desc} description +@deffn {Config Command} {hla device_desc} description Currently Not Supported. @end deffn -@deffn {Config Command} {hla_layout} (@option{stlink}|@option{icdi}|@option{nulink}) +@deffn {Config Command} {hla layout} (@option{stlink}|@option{icdi}|@option{nulink}) Specifies the adapter layout to use. @end deffn -@deffn {Config Command} {hla_vid_pid} [vid pid]+ +@deffn {Config Command} {hla vid_pid} [vid pid]+ Pairs of vendor IDs and product IDs of the device. @end deffn -@deffn {Config Command} {hla_stlink_backend} (usb | tcp [port]) +@deffn {Config Command} {hla stlink_backend} (usb | tcp [port]) @emph{ST-Link only:} Choose between 'exclusive' USB communication (the default backend) or 'shared' mode using ST-Link TCP server (the default port is 7184). @@ -3218,7 +3218,7 @@ available from @url{https://www.st.com/en/development-tools/st-link-server.html, ST-LINK server software module}. @end deffn -@deffn {Command} {hla_command} command +@deffn {Command} {hla command} command Execute a custom adapter-specific command. The @var{command} string is passed as is to the underlying adapter layout handler. @end deffn diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index 6ac680128c..c73f6c8d39 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -319,37 +319,37 @@ COMMAND_HANDLER(interface_handle_hla_command) return ERROR_OK; } -static const struct command_registration hl_interface_command_handlers[] = { +static const struct command_registration hl_interface_subcommand_handlers[] = { { - .name = "hla_device_desc", + .name = "device_desc", .handler = &hl_interface_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the device description of the adapter", .usage = "description_string", }, { - .name = "hla_layout", + .name = "layout", .handler = &hl_interface_handle_layout_command, .mode = COMMAND_CONFIG, .help = "set the layout of the adapter", .usage = "layout_name", }, { - .name = "hla_vid_pid", + .name = "vid_pid", .handler = &hl_interface_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor and product ID of the adapter", .usage = "(vid pid)*", }, { - .name = "hla_stlink_backend", + .name = "stlink_backend", .handler = &hl_interface_handle_stlink_backend_command, .mode = COMMAND_CONFIG, .help = "select which ST-Link backend to use", .usage = "usb | tcp [port]", }, { - .name = "hla_command", + .name = "command", .handler = &interface_handle_hla_command, .mode = COMMAND_EXEC, .help = "execute a custom adapter-specific command", @@ -358,6 +358,17 @@ static const struct command_registration hl_interface_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration hl_interface_command_handlers[] = { + { + .name = "hla", + .mode = COMMAND_ANY, + .help = "perform hla management", + .chain = hl_interface_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + struct adapter_driver hl_adapter_driver = { .name = "hla", .transports = hl_transports, diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 41db38e4ac..2d8ebf0410 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -1126,6 +1126,36 @@ proc "cmsis_dap_usb" {args} { eval cmsis-dap usb $args } +lappend _telnet_autocomplete_skip "hla_layout" +proc "hla_layout" {layout} { + echo "DEPRECATED! use 'hla layout', not 'hla_layout'" + eval hla layout $layout +} + +lappend _telnet_autocomplete_skip "hla_device_desc" +proc "hla_device_desc" {desc} { + echo "DEPRECATED! use 'hla device_desc', not 'hla_device_desc'" + eval hla device_desc $desc +} + +lappend _telnet_autocomplete_skip "hla_vid_pid" +proc "hla_vid_pid" {args} { + echo "DEPRECATED! use 'hla vid_pid', not 'hla_vid_pid'" + eval hla vid_pid $args +} + +lappend _telnet_autocomplete_skip "hla_command" +proc "hla_command" {command} { + echo "DEPRECATED! use 'hla command', not 'hla_command'" + eval hla command $command +} + +lappend _telnet_autocomplete_skip "hla_stlink_backend" +proc "hla_stlink_backend" {args} { + echo "DEPRECATED! use 'hla stlink_backend', not 'hla_stlink_backend'" + eval hla stlink_backend $args +} + lappend _telnet_autocomplete_skip "kitprog_init_acquire_psoc" proc "kitprog_init_acquire_psoc" {} { echo "DEPRECATED! use 'kitprog init_acquire_psoc', not 'kitprog_init_acquire_psoc'" From ed80a182ceadbf7ecbc921241526335a6d5cc65e Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 14 Jun 2024 16:37:39 +0200 Subject: [PATCH 0871/1312] tcl: Replace 'hla_' prefix with 'hla' command group Change-Id: I99ec2dc7f300352d091cf9eb807a690901c33307 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8338 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/interface/nulink.cfg | 6 +++--- tcl/interface/stlink.cfg | 6 +++--- tcl/interface/ti-icdi.cfg | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tcl/interface/nulink.cfg b/tcl/interface/nulink.cfg index 2a4bc0b93b..48dc20e241 100644 --- a/tcl/interface/nulink.cfg +++ b/tcl/interface/nulink.cfg @@ -5,9 +5,9 @@ # adapter driver hla -hla_layout nulink -hla_device_desc "Nu-Link" -hla_vid_pid 0x0416 0x511b 0x0416 0x511c 0x0416 0x511d 0x0416 0x5200 0x0416 0x5201 +hla layout nulink +hla device_desc "Nu-Link" +hla vid_pid 0x0416 0x511b 0x0416 0x511c 0x0416 0x511d 0x0416 0x5200 0x0416 0x5201 # Only swd is supported transport select hla_swd diff --git a/tcl/interface/stlink.cfg b/tcl/interface/stlink.cfg index 8578bf2199..9b7f1f9ebf 100644 --- a/tcl/interface/stlink.cfg +++ b/tcl/interface/stlink.cfg @@ -6,9 +6,9 @@ # adapter driver hla -hla_layout stlink -hla_device_desc "ST-LINK" -hla_vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 +hla layout stlink +hla device_desc "ST-LINK" +hla vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 # Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2 # devices seem to have serial numbers with unreadable characters. ST-LINK/V2 diff --git a/tcl/interface/ti-icdi.cfg b/tcl/interface/ti-icdi.cfg index db4e1e0a04..c13d27e8b1 100644 --- a/tcl/interface/ti-icdi.cfg +++ b/tcl/interface/ti-icdi.cfg @@ -10,8 +10,8 @@ # adapter driver hla -hla_layout ti-icdi -hla_vid_pid 0x1cbe 0x00fd +hla layout ti-icdi +hla vid_pid 0x1cbe 0x00fd # Optionally specify the serial number of TI-ICDI devices, for when using # multiple devices. Serial numbers can be obtained using lsusb -v From df7a31f5367d61e4b61b990a0e265a786ba90fd4 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 4 Jun 2024 10:30:20 +0200 Subject: [PATCH 0872/1312] target: cortex_m: fix detection of STAR-MC1 device The detection of Cortex-M STAR-MC1 was introduced with [1], at a time when OpenOCD was only checking the field PartNo of the CPUID register. Later-on [2], OpenOCD extended the check to the field implementer of CPUID register. The value for ARM (0x41) implementer was used to all the Cortex-M, but no feedback for STAR-MC1 was available. A comment reporting the possible mismatch was added. As reported on OpenOCD mailing-list, the technical reference manual for STAR-MC1 is now available [3] and it reports the implementer as ARM China (0x63) [3]. Fix the STAR-MC1 implementer accordingly. Reported-by: Joseph Yiu Change-Id: I8ed1064a847b73065528ee7032be967b5c58b431 Signed-off-by: Antonio Borneo Link: [1] 7dc4be3157d6 ("target/arm: Add support with identify STAR-MC1") Fixes: [2] 05ee88915520 ("target/cortex_m: check core implementor field") Link: [3] https://www.armchina.com/download/Documents/Application-Notes/Technical-Reference-Manual?infoId=160 Reviewed-on: https://review.openocd.org/c/openocd/+/8316 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/arm.h | 1 + src/target/cortex_m.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/arm.h b/src/target/arm.h index 486666b5c6..999dc9ae7f 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -62,6 +62,7 @@ enum arm_arch { enum arm_implementor { ARM_IMPLEMENTOR_ARM = 0x41, ARM_IMPLEMENTOR_INFINEON = 0x49, + ARM_IMPLEMENTOR_ARM_CHINA = 0x63, ARM_IMPLEMENTOR_REALTEK = 0x72, }; diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index eb646e4726..847bb95188 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -45,7 +45,7 @@ */ enum cortex_m_impl_part { CORTEX_M_PARTNO_INVALID, - STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */ + STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM_CHINA, 0x132), CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20), CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21), CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23), From fbb16b05da3b87a5e305a73a5dcca9f1ccdd5885 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 4 Jun 2024 11:11:25 +0200 Subject: [PATCH 0873/1312] target: cortex_m: add detection for Cortex-M52 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Cortex-M52 to the list of known Cortex-M implementations to allow detection of the core. Values checked against the ARM document "Arm China Cortex®-M52 Processor Technical Reference Manual" 102776_0002_06_en. Reported-by: Joseph Yiu Change-Id: Id0bde8a0476f76799b7274835db9690f975e2dd6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8317 Tested-by: jenkins --- src/target/cortex_m.c | 6 ++++++ src/target/cortex_m.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 9b00a2796f..cf4e8dfb7f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -99,6 +99,12 @@ static const struct cortex_m_part_info cortex_m_parts[] = { .arch = ARM_ARCH_V8M, .flags = CORTEX_M_F_HAS_FPV5, }, + { + .impl_part = CORTEX_M52_PARTNO, + .name = "Cortex-M52", + .arch = ARM_ARCH_V8M, + .flags = CORTEX_M_F_HAS_FPV5, + }, { .impl_part = CORTEX_M55_PARTNO, .name = "Cortex-M55", diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 847bb95188..0c2995f3a7 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -55,6 +55,7 @@ enum cortex_m_impl_part { CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20), CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21), CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31), + CORTEX_M52_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM_CHINA, 0xD24), CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22), CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD23), INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0), From 6da4025167fdf77e975305422406d696abf7a024 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 4 Jun 2024 11:50:19 +0200 Subject: [PATCH 0874/1312] target: cortex_m: replace 'implementor' with 'implementer' ARM documentation for Cortex-M reports the field 'implementer' in the register CPUID. OpenOCD used the miss-spelled 'implementor'. Fix it! Change-Id: I854d223971ae7a49346e1f7491c2c0415f5e2c1d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8318 Tested-by: jenkins Reviewed-by: zapb --- src/target/arm.h | 12 ++++++------ src/target/cortex_m.c | 4 ++-- src/target/cortex_m.h | 40 ++++++++++++++++++++-------------------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/target/arm.h b/src/target/arm.h index 999dc9ae7f..0de322a5a1 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -58,12 +58,12 @@ enum arm_arch { ARM_ARCH_V8M, }; -/** Known ARM implementor IDs */ -enum arm_implementor { - ARM_IMPLEMENTOR_ARM = 0x41, - ARM_IMPLEMENTOR_INFINEON = 0x49, - ARM_IMPLEMENTOR_ARM_CHINA = 0x63, - ARM_IMPLEMENTOR_REALTEK = 0x72, +/** Known ARM implementer IDs */ +enum arm_implementer { + ARM_IMPLEMENTER_ARM = 0x41, + ARM_IMPLEMENTER_INFINEON = 0x49, + ARM_IMPLEMENTER_ARM_CHINA = 0x63, + ARM_IMPLEMENTER_REALTEK = 0x72, }; /** diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index cf4e8dfb7f..791a432427 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2612,8 +2612,8 @@ int cortex_m_examine(struct target *target) if (retval != ERROR_OK) return retval; - /* Inspect implementor/part to look for recognized cores */ - unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTOR_MASK | ARM_CPUID_PARTNO_MASK); + /* Inspect implementer/part to look for recognized cores */ + unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTER_MASK | ARM_CPUID_PARTNO_MASK); for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) { if (impl_part == cortex_m_parts[n].impl_part) { diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 0c2995f3a7..726fca2903 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -31,36 +31,36 @@ #define CPUID 0xE000ED00 -#define ARM_CPUID_IMPLEMENTOR_POS 24 -#define ARM_CPUID_IMPLEMENTOR_MASK (0xFF << ARM_CPUID_IMPLEMENTOR_POS) +#define ARM_CPUID_IMPLEMENTER_POS 24 +#define ARM_CPUID_IMPLEMENTER_MASK (0xFF << ARM_CPUID_IMPLEMENTER_POS) #define ARM_CPUID_PARTNO_POS 4 #define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS) -#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTOR_POS) & ARM_CPUID_IMPLEMENTOR_MASK) | \ +#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTER_POS) & ARM_CPUID_IMPLEMENTER_MASK) | \ (((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK)) /** Known Arm Cortex masked CPU Ids - * This includes the implementor and part number, but _not_ the revision or + * This includes the implementer and part number, but _not_ the revision or * patch fields. */ enum cortex_m_impl_part { CORTEX_M_PARTNO_INVALID, - STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM_CHINA, 0x132), - CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20), - CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21), - CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23), - CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24), - CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27), - CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60), - CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20), - CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21), - CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31), - CORTEX_M52_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM_CHINA, 0xD24), - CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22), - CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD23), - INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0), - REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20), - REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22), + STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM_CHINA, 0x132), + CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC20), + CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC21), + CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC23), + CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC24), + CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC27), + CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC60), + CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD20), + CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD21), + CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD31), + CORTEX_M52_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM_CHINA, 0xD24), + CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD22), + CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD23), + INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_INFINEON, 0xDB0), + REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_REALTEK, 0xd20), + REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_REALTEK, 0xd22), }; /* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */ From c322060fbda4a162b55acd3658388eb145b4c73f Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Tue, 14 May 2024 15:55:58 -0700 Subject: [PATCH 0875/1312] target/xtensa: flag additional write-only registers intsetN, intclearN (for LX8) mesrclr (for NX) Signed-off-by: Ian Thompson Change-Id: I0bb59728fcec761a71c4789189f733a10bad6375 Reviewed-on: https://review.openocd.org/c/openocd/+/8235 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/xtensa/xtensa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 54fcd2ad6d..8369cc4e5c 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3966,10 +3966,10 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) rptr->type = XT_REG_OTHER; } - /* Register flags */ + /* Register flags: includes intsetN, intclearN for LX8 */ if ((strcmp(rptr->name, "mmid") == 0) || (strcmp(rptr->name, "eraccess") == 0) || - (strcmp(rptr->name, "ddr") == 0) || (strcmp(rptr->name, "intset") == 0) || - (strcmp(rptr->name, "intclear") == 0)) + (strcmp(rptr->name, "ddr") == 0) || (strncmp(rptr->name, "intset", 6) == 0) || + (strncmp(rptr->name, "intclear", 8) == 0) || (strcmp(rptr->name, "mesrclr") == 0)) rptr->flags = XT_REGF_NOREAD; else rptr->flags = 0; From f09ccc817b76683b42dc6ad410adddee16a351ed Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 8 Jun 2024 11:33:35 +0200 Subject: [PATCH 0876/1312] flash/nor/nrf5: split chip and bank probes nrf5_auto_probe() always re-probed chip hardware to get flash geometry. Introduce nrf5_probe_chip() and move chip related probing to it. Save all flash parameters needed for bank setup to struct nrf5_info. Introduce nrf5_setup_bank() and move bank setup code to it. Call both chip probe and bank setup unconditionally from nrf5_probe(): in case of manual issuing 'flash probe' command, we should refresh actual values from the device. Call chip probe and bank setup only if not done before from nrf5_auto_probe(). Signed-off-by: Tomas Vanek Change-Id: Ib090a97fd7a41579b3d4f6e6634a5fdf93836c83 Reviewed-on: https://review.openocd.org/c/openocd/+/8322 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 104 ++++++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 32 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index f07433e674..3ad6a96288 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -117,20 +117,24 @@ struct nrf5_map { struct nrf5_info { unsigned int refcount; + bool chip_probed; struct nrf5_bank { struct nrf5_info *chip; bool probed; } bank[2]; + struct target *target; - /* chip identification stored in nrf5_probe() for use in nrf5_info() */ + /* chip identification stored in nrf5_probe_chip() + * for use in nrf5_info() and nrf5_setup_bank() */ bool ficr_info_valid; struct nrf52_ficr_info ficr_info; const struct nrf5_device_spec *spec; uint16_t hwid; enum nrf5_features features; - unsigned int flash_size_kb; + uint32_t flash_page_size; + uint32_t flash_num_sectors; unsigned int ram_size_kb; const struct nrf5_map *map; @@ -346,6 +350,16 @@ static bool nrf5_bank_is_probed(const struct flash_bank *bank) return nbank->probed; } +static bool nrf5_chip_is_probed(const struct flash_bank *bank) +{ + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); + + return chip->chip_probed; +} + static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank) { struct nrf5_info *chip = nbank->chip; @@ -709,8 +723,9 @@ static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) return ERROR_FAIL; + unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; command_print_sameline(cmd, "%s %ukB Flash, %ukB RAM", - chip_type_str, chip->flash_size_kb, chip->ram_size_kb); + chip_type_str, flash_size_kb, chip->ram_size_kb); return ERROR_OK; } @@ -838,7 +853,7 @@ static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size) return res; } -static int nrf5_probe(struct flash_bank *bank) +static int nrf5_probe_chip(struct flash_bank *bank) { int res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -968,9 +983,8 @@ static int nrf5_probe(struct flash_bank *bank) } /* The value stored in FICR CODEPAGESIZE is the number of bytes in one page of FLASH. */ - uint32_t flash_page_size; res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize, - &flash_page_size); + &chip->flash_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); return res; @@ -978,69 +992,95 @@ static int nrf5_probe(struct flash_bank *bank) /* Note the register name is misleading, * FICR CODESIZE is the number of pages in flash memory, not the number of bytes! */ - uint32_t num_sectors; res = target_read_u32(chip->target, ficr_base + ficr_offsets->codesize, - &num_sectors); + &chip->flash_num_sectors); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; } - chip->flash_size_kb = num_sectors * flash_page_size / 1024; + char chip_type_str[256]; + if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) + return ERROR_FAIL; + + unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; + const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid); + LOG_INFO("%s%s %ukB Flash, %ukB RAM", + device_is_unknown ? "Unknown device: " : "", + chip_type_str, + flash_size_kb, + chip->ram_size_kb); - if (!chip->bank[0].probed && !chip->bank[1].probed) { - char chip_type_str[256]; - if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) - return ERROR_FAIL; - const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid); - LOG_INFO("%s%s %ukB Flash, %ukB RAM", - device_is_unknown ? "Unknown device: " : "", - chip_type_str, - chip->flash_size_kb, - chip->ram_size_kb); - } + chip->chip_probed = true; + return ERROR_OK; +} - free(bank->sectors); +static int nrf5_setup_bank(struct flash_bank *bank) +{ + struct nrf5_bank *nbank = bank->driver_priv; + assert(nbank); + struct nrf5_info *chip = nbank->chip; + assert(chip); if (bank->base == chip->map->flash_base) { + unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; /* Sanity check */ - if (chip->spec && chip->flash_size_kb != chip->spec->flash_size_kb) + if (chip->spec && flash_size_kb != chip->spec->flash_size_kb) LOG_WARNING("Chip's reported Flash capacity does not match expected one"); - if (chip->ficr_info_valid && chip->flash_size_kb != chip->ficr_info.flash) + if (chip->ficr_info_valid && flash_size_kb != chip->ficr_info.flash) LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH"); - bank->num_sectors = num_sectors; - bank->size = num_sectors * flash_page_size; + bank->num_sectors = chip->flash_num_sectors; + bank->size = chip->flash_num_sectors * chip->flash_page_size; - bank->sectors = alloc_block_array(0, flash_page_size, num_sectors); + bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; chip->bank[0].probed = true; - } else { + } else if (bank->base == chip->map->uicr_base) { /* UICR bank */ bank->num_sectors = 1; - bank->size = flash_page_size; + bank->size = chip->flash_page_size; - bank->sectors = alloc_block_array(0, flash_page_size, num_sectors); + bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; bank->sectors[0].is_protected = 0; chip->bank[1].probed = true; + } else { + LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base); + return ERROR_FLASH_BANK_INVALID; } return ERROR_OK; } +static int nrf5_probe(struct flash_bank *bank) +{ + /* probe always reads actual info from the device */ + int res = nrf5_probe_chip(bank); + if (res != ERROR_OK) + return res; + + return nrf5_setup_bank(bank); +} + static int nrf5_auto_probe(struct flash_bank *bank) { if (nrf5_bank_is_probed(bank)) return ERROR_OK; - return nrf5_probe(bank); + if (!nrf5_chip_is_probed(bank)) { + int res = nrf5_probe_chip(bank); + if (res != ERROR_OK) + return res; + } + + return nrf5_setup_bank(bank); } @@ -1372,8 +1412,8 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) case NRF53NET_UICR_BASE: break; default: - LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); - return ERROR_FAIL; + LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base); + return ERROR_FLASH_BANK_INVALID; } chip = nrf5_get_chip(bank->target); From c97a8ff10d250ad98597054322fd727dc292a332 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 8 Jun 2024 11:59:29 +0200 Subject: [PATCH 0877/1312] flash/nor/nrf5: remove asserts on dereferenced pointers The driver code works reliably, no need to use assert() everywhere. Signed-off-by: Tomas Vanek Change-Id: Idb1942bfd31d370a74610b8a8836bc2e64370557 Reviewed-on: https://review.openocd.org/c/openocd/+/8324 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/nrf5.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 3ad6a96288..5cb552aa94 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -345,26 +345,19 @@ const struct flash_driver nrf5_flash, nrf51_flash; static bool nrf5_bank_is_probed(const struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); - return nbank->probed; } static bool nrf5_chip_is_probed(const struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); - return chip->chip_probed; } static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank) { struct nrf5_info *chip = nbank->chip; - assert(chip); - return nbank == &chip->bank[1]; } @@ -484,9 +477,7 @@ static int nrf51_protect_check_clenr0(struct flash_bank *bank) uint32_t clenr0; struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); res = target_read_u32(chip->target, NRF51_FICR_CLENR0, &clenr0); @@ -515,9 +506,7 @@ static int nrf51_protect_check_clenr0(struct flash_bank *bank) static int nrf52_protect_check_bprot(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 }; uint32_t bprot_reg = 0; @@ -542,9 +531,7 @@ static int nrf52_protect_check_bprot(struct flash_bank *bank) static int nrf5_protect_check(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); /* UICR cannot be write protected so just return early */ if (nrf5_bank_is_uicr(nbank)) @@ -568,9 +555,7 @@ static int nrf51_protect_clenr0(struct flash_bank *bank, int set, unsigned int f uint32_t clenr0, ppfc; struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); if (first != 0) { LOG_ERROR("Code region 0 must start at the beginning of the bank"); @@ -628,9 +613,7 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); /* UICR cannot be write protected so just bail out early */ if (nrf5_bank_is_uicr(nbank)) { @@ -715,9 +698,7 @@ static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsig static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); char chip_type_str[256]; if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) @@ -858,9 +839,7 @@ static int nrf5_probe_chip(struct flash_bank *bank) int res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); struct target *target = chip->target; chip->spec = NULL; @@ -1018,9 +997,7 @@ static int nrf5_probe_chip(struct flash_bank *bank) static int nrf5_setup_bank(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); if (bank->base == chip->map->flash_base) { unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; @@ -1254,9 +1231,7 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer, } struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); assert(offset % 4 == 0); assert(count % 4 == 0); @@ -1316,9 +1291,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, } struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); /* UICR CLENR0 based protection used on nRF51 prevents erase * absolutely silently. NVMC has no flag to indicate the protection @@ -1362,7 +1335,6 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, static void nrf5_free_driver_priv(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; if (!chip) return; @@ -1458,17 +1430,13 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) if (res != ERROR_OK) return res; - assert(bank); - if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); if (chip->features & NRF5_FEATURE_SERIES_51) { uint32_t ppfc; From 53b94fad58ab32b02531f13299968c41f49947fa Mon Sep 17 00:00:00 2001 From: Jan Matyas Date: Mon, 3 Jun 2024 10:23:02 +0200 Subject: [PATCH 0878/1312] binarybuffer: Fix str_to_buf() parsing function The function str_to_buf() was too benevolent and did not perform sufficient error checking on the input string being parsed. Especially: - Invalid numbers were silently ignored. - Out-of-range numbers were silently truncated. The following commands that use str_to_buf() were affected: - reg (when writing a register value) - set_reg - jtag drscan This pull request fixes that by: - Rewriting str_to_buf() to add the missing checks. - Adding function command_parse_str_to_buf() which can be used in command handlers. It parses the input numbers and provides user-readable error messages in case of parsing errors. Examples: jtag drscan 10 huh10 - Old behavior: The string "huh10" is silently converted to 10 and the command is then executed. No warning error or warning is shown to the user. - New behavior: Error message is shown: "'huh10' is not a valid number" reg pc 0x123456789 Assuming the "pc" is 32 bits wide: - Old behavior: The register value is silently truncated to 0x23456789 and the command is performed. - New behavior: Error message is shown to the user: "Number 0x123456789 exceeds 32 bits" Change-Id: I079e19cd153aec853a3c2eb66953024b8542d0f4 Signed-off-by: Jan Matyas Reviewed-on: https://review.openocd.org/c/openocd/+/8315 Tested-by: jenkins Reviewed-by: Marek Vrbka Reviewed-by: Antonio Borneo --- src/helper/binarybuffer.c | 158 ++++++++++++++++++++++++++------------ src/helper/binarybuffer.h | 17 +++- src/helper/command.c | 40 ++++++++++ src/helper/command.h | 11 +++ src/jtag/tcl.c | 5 +- src/target/target.c | 66 +++++++++------- 6 files changed, 216 insertions(+), 81 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 5f38b43ae1..3e09143c68 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -102,7 +102,6 @@ bool buf_cmp_mask(const void *_buf1, const void *_buf2, return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing); } - void *buf_set_ones(void *_buf, unsigned size) { uint8_t *buf = _buf; @@ -206,36 +205,75 @@ char *buf_to_hex_str(const void *_buf, unsigned buf_len) return str; } -/** identify radix, and skip radix-prefix (0, 0x or 0X) */ -static void str_radix_guess(const char **_str, unsigned *_str_len, - unsigned *_radix) +static bool str_has_hex_prefix(const char *s) +{ + /* Starts with "0x" or "0X" */ + return (s[0] == '0') && (s[1] == 'x' || s[1] == 'X'); +} + +static bool str_has_octal_prefix(const char *s) +{ + /* - starts with '0', + * - has at least two characters, and + * - the second character is not 'x' or 'X' */ + return (s[0] == '0') && (s[1] != '\0') && (s[1] != 'x') && (s[1] != 'X'); +} + +/** + * Try to identify the radix of the number by looking at its prefix. + * No further validation of the number is preformed. + */ +static unsigned int str_radix_guess(const char *str) +{ + assert(str); + + if (str_has_hex_prefix(str)) + return 16; + + if (str_has_octal_prefix(str)) + return 8; + + /* Otherwise assume a decadic number. */ + return 10; +} + +/** Strip leading "0x" or "0X" from hex numbers or "0" from octal numbers. */ +static void str_strip_number_prefix_if_present(const char **_str, unsigned int radix) { - unsigned radix = *_radix; - if (radix != 0) - return; + assert(radix == 16 || radix == 10 || radix == 8); + assert(_str); + const char *str = *_str; - unsigned str_len = *_str_len; - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { - radix = 16; + assert(str); + + if (radix == 16 && str_has_hex_prefix(str)) str += 2; - str_len -= 2; - } else if ((str[0] == '0') && (str_len != 1)) { - radix = 8; + else if (radix == 8 && str_has_octal_prefix(str)) str += 1; - str_len -= 1; - } else - radix = 10; + + /* No prefix to strip for radix == 10. */ + *_str = str; - *_str_len = str_len; - *_radix = radix; } -int str_to_buf(const char *str, unsigned str_len, - void *_buf, unsigned buf_len, unsigned radix) +int str_to_buf(const char *str, void *_buf, unsigned int buf_len, + unsigned int radix, unsigned int *_detected_radix) { - str_radix_guess(&str, &str_len, &radix); + assert(radix == 0 || radix == 8 || radix == 10 || radix == 16); + + if (radix == 0) + radix = str_radix_guess(str); - float factor; + if (_detected_radix) + *_detected_radix = radix; + + str_strip_number_prefix_if_present(&str, radix); + + const size_t str_len = strlen(str); + if (str_len == 0) + return ERROR_INVALID_NUMBER; + + float factor = 0.0; if (radix == 16) factor = 0.5; /* log(16) / log(256) = 0.5 */ else if (radix == 10) @@ -243,41 +281,69 @@ int str_to_buf(const char *str, unsigned str_len, else if (radix == 8) factor = 0.375; /* log(8) / log(256) = 0.375 */ else - return 0; + assert(false); - /* copy to zero-terminated buffer */ - char *charbuf = strndup(str, str_len); + const unsigned int b256_len = ceil_f_to_u32(str_len * factor); - /* number of digits in base-256 notation */ - unsigned b256_len = ceil_f_to_u32(str_len * factor); + /* Allocate a buffer for digits in base-256 notation */ uint8_t *b256_buf = calloc(b256_len, 1); + if (!b256_buf) { + LOG_ERROR("Unable to allocate memory"); + return ERROR_FAIL; + } - /* go through zero terminated buffer - * input digits (ASCII) */ - unsigned i; - for (i = 0; charbuf[i]; i++) { - uint32_t tmp = charbuf[i]; - if ((tmp >= '0') && (tmp <= '9')) + /* Go through the zero-terminated buffer + * of input digits (ASCII) */ + for (unsigned int i = 0; str[i]; i++) { + uint32_t tmp = str[i]; + if ((tmp >= '0') && (tmp <= '9')) { tmp = (tmp - '0'); - else if ((tmp >= 'a') && (tmp <= 'f')) + } else if ((tmp >= 'a') && (tmp <= 'f')) { tmp = (tmp - 'a' + 10); - else if ((tmp >= 'A') && (tmp <= 'F')) + } else if ((tmp >= 'A') && (tmp <= 'F')) { tmp = (tmp - 'A' + 10); - else - continue; /* skip characters other than [0-9,a-f,A-F] */ + } else { + /* Characters other than [0-9,a-f,A-F] are invalid */ + free(b256_buf); + return ERROR_INVALID_NUMBER; + } - if (tmp >= radix) - continue; /* skip digits invalid for the current radix */ + if (tmp >= radix) { + /* Encountered a digit that is invalid for the current radix */ + free(b256_buf); + return ERROR_INVALID_NUMBER; + } - /* base-256 digits */ - for (unsigned j = 0; j < b256_len; j++) { + /* Add the current digit (tmp) to the intermediate result + * in b256_buf (base-256 digits) */ + for (unsigned int j = 0; j < b256_len; j++) { tmp += (uint32_t)b256_buf[j] * radix; - b256_buf[j] = (uint8_t)(tmp & 0xFF); + b256_buf[j] = (uint8_t)(tmp & 0xFFu); tmp >>= 8; } + /* The b256_t buffer is large enough to contain the whole result. */ + assert(tmp == 0); } + /* The result must not contain more bits than buf_len. */ + /* Check the whole bytes: */ + for (unsigned int j = DIV_ROUND_UP(buf_len, 8); j < b256_len; j++) { + if (b256_buf[j] != 0x0) { + free(b256_buf); + return ERROR_NUMBER_EXCEEDS_BUFFER; + } + } + /* Check the partial byte: */ + if (buf_len % 8) { + const uint8_t mask = 0xFFu << (buf_len % 8); + if ((b256_buf[(buf_len / 8)] & mask) != 0x0) { + free(b256_buf); + return ERROR_NUMBER_EXCEEDS_BUFFER; + } + } + + /* Copy the digits to the output buffer */ uint8_t *buf = _buf; for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) { if (j < b256_len) @@ -286,14 +352,8 @@ int str_to_buf(const char *str, unsigned str_len, buf[j] = 0; } - /* mask out bits that don't belong to the buffer */ - if (buf_len % 8) - buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8)); - free(b256_buf); - free(charbuf); - - return i; + return ERROR_OK; } void bit_copy_queue_init(struct bit_copy_queue *q) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index 3446296817..441374330e 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -14,6 +14,9 @@ #include #include +#define ERROR_INVALID_NUMBER (-1700) +#define ERROR_NUMBER_EXCEEDS_BUFFER (-1701) + /** @file * Support functions to access arbitrary bits in a byte array */ @@ -189,8 +192,18 @@ void *buf_set_ones(void *buf, unsigned size); void *buf_set_buf(const void *src, unsigned src_start, void *dst, unsigned dst_start, unsigned len); -int str_to_buf(const char *str, unsigned len, - void *bin_buf, unsigned buf_size, unsigned radix); +/** + * Parse an unsigned number (provided as a zero-terminated string) + * into a bit buffer whose size is buf_len bits. + * @param str Input number, zero-terminated string + * @param _buf Output buffer, allocated by the caller + * @param buf_len Output buffer size in bits + * @param radix Base of the input number - 16, 10, 8 or 0. + * 0 means auto-detect the radix. + */ +int str_to_buf(const char *str, void *_buf, unsigned int buf_len, + unsigned int radix, unsigned int *_detected_radix); + char *buf_to_hex_str(const void *buf, unsigned size); /* read a uint32_t from a buffer in target memory endianness */ diff --git a/src/helper/command.c b/src/helper/command.c index a775c730b8..15a9b4a084 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -1360,6 +1360,46 @@ int command_parse_bool_arg(const char *in, bool *out) return ERROR_COMMAND_SYNTAX_ERROR; } +static const char *radix_to_str(unsigned int radix) +{ + switch (radix) { + case 16: return "hexadecimal"; + case 10: return "decadic"; + case 8: return "octal"; + } + assert(false); + return ""; +} + +COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len, + unsigned int radix) +{ + assert(str); + assert(buf); + + int ret = str_to_buf(str, buf, buf_len, radix, NULL); + if (ret == ERROR_OK) + return ret; + + /* Provide a clear error message to the user */ + if (ret == ERROR_INVALID_NUMBER) { + if (radix == 0) { + /* Any radix is accepted, so don't include it in the error message. */ + command_print(CMD, "'%s' is not a valid number", str); + } else { + /* Specific radix is required - tell the user what it is. */ + command_print(CMD, "'%s' is not a valid number (requiring %s number)", + str, radix_to_str(radix)); + } + } else if (ret == ERROR_NUMBER_EXCEEDS_BUFFER) { + command_print(CMD, "Number %s exceeds %u bits", str, buf_len); + } else { + command_print(CMD, "Could not parse number '%s'", str); + } + + return ERROR_COMMAND_ARGUMENT_INVALID; +} + COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label) { switch (CMD_ARGC) { diff --git a/src/helper/command.h b/src/helper/command.h index fc26dda81a..7a044e6191 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -517,6 +517,17 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); int command_parse_bool_arg(const char *in, bool *out); COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); +/** + * Parse a number (base 10, base 16 or base 8) and store the result + * into a bit buffer. + * + * In case of parsing error, a user-readable error message is produced. + * + * If radix = 0 is given, the function guesses the radix by looking at the number prefix. + */ +COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len, + unsigned int radix); + /** parses an on/off command argument */ #define COMMAND_PARSE_ON_OFF(in, out) \ COMMAND_PARSE_BOOL(in, out, "on", "off") diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 1a4c4b774e..e534134276 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -87,8 +87,11 @@ static COMMAND_HELPER(handle_jtag_command_drscan_fields, struct scan_field *fiel LOG_ERROR("Out of memory"); return ERROR_FAIL; } + fields[field_count].out_value = t; - str_to_buf(CMD_ARGV[i + 1], strlen(CMD_ARGV[i + 1]), t, bits, 0); + int ret = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[i + 1], t, bits, 0); + if (ret != ERROR_OK) + return ret; fields[field_count].in_value = t; field_count++; } diff --git a/src/target/target.c b/src/target/target.c index 1f4817d5c1..8ff665f474 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3128,11 +3128,18 @@ COMMAND_HANDLER(handle_reg_command) /* set register value */ if (CMD_ARGC == 2) { uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); - if (!buf) + if (!buf) { + LOG_ERROR("Failed to allocate memory"); return ERROR_FAIL; - str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); + } + + int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[1], buf, reg->size, 0); + if (retval != ERROR_OK) { + free(buf); + return retval; + } - int retval = reg->type->set(reg, buf); + retval = reg->type->set(reg, buf); if (retval != ERROR_OK) { LOG_ERROR("Could not write to register '%s'", reg->name); } else { @@ -4788,63 +4795,64 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc, return JIM_OK; } -static int target_jim_set_reg(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) +COMMAND_HANDLER(handle_set_reg_command) { - if (argc != 2) { - Jim_WrongNumArgs(interp, 1, argv, "dict"); - return JIM_ERR; - } + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; int tmp; #if JIM_VERSION >= 80 - Jim_Obj **dict = Jim_DictPairs(interp, argv[1], &tmp); + Jim_Obj **dict = Jim_DictPairs(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], &tmp); if (!dict) - return JIM_ERR; + return ERROR_FAIL; #else Jim_Obj **dict; - int ret = Jim_DictPairs(interp, argv[1], &dict, &tmp); + int ret = Jim_DictPairs(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], &dict, &tmp); if (ret != JIM_OK) - return ret; + return ERROR_FAIL; #endif const unsigned int length = tmp; - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - const struct target *target = get_current_target(cmd_ctx); + + const struct target *target = get_current_target(CMD_CTX); + assert(target); for (unsigned int i = 0; i < length; i += 2) { const char *reg_name = Jim_String(dict[i]); const char *reg_value = Jim_String(dict[i + 1]); - struct reg *reg = register_get_by_name(target->reg_cache, reg_name, - false); + struct reg *reg = register_get_by_name(target->reg_cache, reg_name, false); if (!reg || !reg->exist) { - Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name); - return JIM_ERR; + command_print(CMD, "unknown register '%s'", reg_name); + return ERROR_FAIL; } uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); - if (!buf) { LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; + return ERROR_FAIL; } - str_to_buf(reg_value, strlen(reg_value), buf, reg->size, 0); - int retval = reg->type->set(reg, buf); + int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, + reg_value, buf, reg->size, 0); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + + retval = reg->type->set(reg, buf); free(buf); if (retval != ERROR_OK) { - Jim_SetResultFormatted(interp, "failed to set '%s' to register '%s'", + command_print(CMD, "failed to set '%s' to register '%s'", reg_value, reg_name); - return JIM_ERR; + return retval; } } - return JIM_OK; + return ERROR_OK; } /** @@ -5584,7 +5592,7 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "set_reg", .mode = COMMAND_EXEC, - .jim_handler = target_jim_set_reg, + .handler = handle_set_reg_command, .help = "Set target register values", .usage = "dict", }, @@ -6719,7 +6727,7 @@ static const struct command_registration target_exec_command_handlers[] = { { .name = "set_reg", .mode = COMMAND_EXEC, - .jim_handler = target_jim_set_reg, + .handler = handle_set_reg_command, .help = "Set target register values", .usage = "dict", }, From 2992ec909588bebf89fe87e1db0aae0f51f0ff07 Mon Sep 17 00:00:00 2001 From: Jonathan Forrest Date: Wed, 1 May 2024 14:25:32 +1000 Subject: [PATCH 0879/1312] jtag/drivers/mpsse: Added FT4232HA Added FT4232HA varianet of FTDI's FT4232H which has a different bcd. Also added default PID/VID for the FT4243HA to contrib/60-openocd.rules. And added default PID/VIDs for FTDI's HP ICs to contrib/60-openocd.rules as this wasn't done previously. BugLink: https://sourceforge.net/p/openocd/tickets/410/ Change-Id: Ia84b566aa004332d3f7815a3d22ac37eee4f522a Signed-off-by: Jonathan Forrest Reviewed-on: https://review.openocd.org/c/openocd/+/8225 Tested-by: jenkins Reviewed-by: Antonio Borneo --- contrib/60-openocd.rules | 21 +++++++++++++++++++++ src/jtag/drivers/mpsse.c | 3 +++ src/jtag/drivers/mpsse.h | 1 + 3 files changed, 25 insertions(+) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index fe8b00cb7a..29f8d7a6d4 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -29,6 +29,27 @@ ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", # Original FT231XQ VID:PID ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", MODE="660", GROUP="plugdev", TAG+="uaccess" +# Original FT2233HP VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6040", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT4233HP VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6041", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT2232HP VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6042", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT4232HP VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6043", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT233HP VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6044", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT232HP VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6045", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT4232HA VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6048", MODE="660", GROUP="plugdev", TAG+="uaccess" + # DISTORTEC JTAG-lock-pick Tiny 2 ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="660", GROUP="plugdev", TAG+="uaccess" diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index f3499e3864..3decddb0e8 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -283,6 +283,9 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t vids[], c case 0x3300: ctx->type = TYPE_FT232HP; break; + case 0x3600: + ctx->type = TYPE_FT4232HA; + break; default: LOG_ERROR("unsupported FTDI chip type: 0x%04x", desc.bcdDevice); goto error; diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index e92a9bb56f..737560d956 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -30,6 +30,7 @@ enum ftdi_chip_type { TYPE_FT4232HP, TYPE_FT233HP, TYPE_FT232HP, + TYPE_FT4232HA, }; struct mpsse_ctx; From 44cfdef0a40d6c5d4514a927d9e46f5c2acc1586 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 14 Jun 2024 16:19:56 +0200 Subject: [PATCH 0880/1312] server/gdb: Restructure commands Use a command group 'gdb' with subcommands instead of individual commands with 'gdb_' prefix. The old commands are still available to ensure backwards compatibility, but are marked as deprecated. Change-Id: I037dc58554e589d5710cf46924e0a00f863aa300 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8336 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 58 +++++++++++++++++++------------------- src/server/gdb_server.c | 37 +++++++++++++++--------- src/server/startup.tcl | 54 +++++++++++++++++++++++++++++++++++ src/server/tcl_server.c | 2 +- src/server/telnet_server.c | 2 +- src/target/esirisc.c | 2 +- 6 files changed, 109 insertions(+), 46 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index a7c1e6d08b..58f1d04216 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -930,8 +930,8 @@ a board with an Atmel AT91SAM7X256 microcontroller: source [find interface/ftdi/signalyzer.cfg] # GDB can also flash my flash! -gdb_memory_map enable -gdb_flash_program enable +gdb memory_map enable +gdb flash_program enable source [find target/sam7x256.cfg] @end example @@ -940,8 +940,8 @@ Here is the command line equivalent of that configuration: @example openocd -f interface/ftdi/signalyzer.cfg \ - -c "gdb_memory_map enable" \ - -c "gdb_flash_program enable" \ + -c "gdb memory_map enable" \ + -c "gdb flash_program enable" \ -f target/sam7x256.cfg @end example @@ -2183,12 +2183,12 @@ In such cases, just specify the relevant port number as "disabled". You can request the operating system to select one of the available ports for the server by specifying the relevant port number as "0". -@anchor{gdb_port} -@deffn {Config Command} {gdb_port} [number] +@anchor{gdb port} +@deffn {Config Command} {gdb port} [number] @cindex GDB server Normally gdb listens to a TCP/IP port, but GDB can also communicate via pipes(stdin/out or named pipes). The name -"gdb_port" stuck because it covers probably more than 90% of +"gdb port" stuck because it covers probably more than 90% of the normal use cases. No arguments reports GDB port. "pipe" means listen to stdin @@ -2203,7 +2203,7 @@ Output pipe is the same name as input pipe, but with 'o' appended, e.g. /var/gdb, /var/gdbo. The GDB port for the first target will be the base port, the -second target will listen on gdb_port + 1, and so on. +second target will listen on port + 1, and so on. When not specified during the configuration stage, the port @var{number} defaults to 3333. When @var{number} is not a numeric value, incrementing it to compute @@ -2212,7 +2212,7 @@ the next port number does not work. In this case, specify the proper commands @command{target create} or @command{$target_name configure}. @xref{gdbportoverride,,option -gdb-port}. -Note: when using "gdb_port pipe", increasing the default remote timeout in +Note: when using "gdb port pipe", increasing the default remote timeout in gdb (with 'set remotetimeout') is recommended. An insufficient timeout may cause initialization to fail with "Unknown remote qXfer reply: OK". @end deffn @@ -2246,7 +2246,7 @@ The ones listed here are static and global. @xref{targetevents,,Target Events}, about configuring target-specific event handling. @anchor{gdbbreakpointoverride} -@deffn {Command} {gdb_breakpoint_override} [@option{hard}|@option{soft}|@option{disable}] +@deffn {Command} {gdb breakpoint_override} [@option{hard}|@option{soft}|@option{disable}] Force breakpoint type for gdb @command{break} commands. This option supports GDB GUIs which don't distinguish hard versus soft breakpoints, if the default OpenOCD and @@ -2255,41 +2255,41 @@ breakpoints if the memory map has been set up for flash regions. @end deffn @anchor{gdbflashprogram} -@deffn {Config Command} {gdb_flash_program} (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb flash_program} (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to program the flash memory when a vFlash packet is received. The default behaviour is @option{enable}. @end deffn -@deffn {Config Command} {gdb_memory_map} (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb memory_map} (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to send the memory configuration to GDB when requested. GDB will then know when to set hardware breakpoints, and program flash -using the GDB load command. @command{gdb_flash_program enable} must also be enabled +using the GDB load command. @command{gdb flash_program enable} must also be enabled for flash programming to work. Default behaviour is @option{enable}. -@xref{gdbflashprogram,,gdb_flash_program}. +@xref{gdbflashprogram,,gdb flash_program}. @end deffn -@deffn {Config Command} {gdb_report_data_abort} (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb report_data_abort} (@option{enable}|@option{disable}) Specifies whether data aborts cause an error to be reported by GDB memory read packets. The default behaviour is @option{disable}; use @option{enable} see these errors reported. @end deffn -@deffn {Config Command} {gdb_report_register_access_error} (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb report_register_access_error} (@option{enable}|@option{disable}) Specifies whether register accesses requested by GDB register read/write packets report errors or not. The default behaviour is @option{disable}; use @option{enable} see these errors reported. @end deffn -@deffn {Config Command} {gdb_target_description} (@option{enable}|@option{disable}) +@deffn {Config Command} {gdb target_description} (@option{enable}|@option{disable}) Set to @option{enable} to cause OpenOCD to send the target descriptions to gdb via qXfer:features:read packet. The default behaviour is @option{enable}. @end deffn -@deffn {Command} {gdb_save_tdesc} +@deffn {Command} {gdb save_tdesc} Saves the target description file to the local file system. The file name is @i{target_name}.xml. @@ -5198,11 +5198,11 @@ where it is a mandatory configuration for the target run control. for instruction on how to declare and control a CTI instance. @anchor{gdbportoverride} -@item @code{-gdb-port} @var{number} -- see command @command{gdb_port} for the +@item @code{-gdb-port} @var{number} -- @xref{gdb port,,command gdb port} for the possible values of the parameter @var{number}, which are not only numeric values. Use this option to override, for this target only, the global parameter set with -command @command{gdb_port}. -@xref{gdb_port,,command gdb_port}. +command @command{gdb port}. +@xref{gdb port,,command gdb port}. @item @code{-gdb-max-connections} @var{number} -- EXPERIMENTAL: set the maximum number of GDB connections that are allowed for the target. Default is 1. @@ -12417,7 +12417,7 @@ target remote localhost:3333 A pipe connection is typically started as follows: @example target extended-remote | \ - openocd -c "gdb_port pipe; log_output openocd.log" + openocd -c "gdb port pipe; log_output openocd.log" @end example This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout). Using this method has the advantage of GDB starting/stopping OpenOCD for the debug @@ -12501,7 +12501,7 @@ using @command{gdb -x filename}. By default the target memory map is sent to GDB. This can be disabled by the following OpenOCD configuration option: @example -gdb_memory_map disable +gdb memory_map disable @end example For this to function correctly a valid flash configuration must also be set in OpenOCD. For faster performance you should also configure a valid @@ -12509,8 +12509,8 @@ working area. Informing GDB of the memory map of the target will enable GDB to protect any flash areas of the target and use hardware breakpoints by default. This means -that the OpenOCD option @command{gdb_breakpoint_override} is not required when -using a memory map. @xref{gdbbreakpointoverride,,gdb_breakpoint_override}. +that the OpenOCD option @command{gdb breakpoint_override} is not required when +using a memory map. @xref{gdbbreakpointoverride,,gdb breakpoint_override}. To view the configured memory map in GDB, use the GDB command @option{info mem}. All other unassigned addresses within GDB are treated as RAM. @@ -12521,7 +12521,7 @@ This can be changed to the old behaviour by using the following GDB command set mem inaccessible-by-default off @end example -If @command{gdb_flash_program enable} is also used, GDB will be able to +If @command{gdb flash_program enable} is also used, GDB will be able to program any flash memory using the vFlash interface. GDB will look at the target memory map when a load command is given, if any @@ -12560,9 +12560,9 @@ $_TARGETNAME configure -event gdb-attach @{@} @end example If any of installed flash banks does not support probe on running target, -switch off gdb_memory_map: +switch off gdb memory_map: @example -gdb_memory_map disable +gdb memory_map disable @end example Ensure GDB is configured without interrupt-on-connect. @@ -12571,7 +12571,7 @@ Some GDB versions set it by default, some does not. set remote interrupt-on-connect off @end example -If you switched gdb_memory_map off, you may want to setup GDB memory map +If you switched gdb memory_map off, you may want to setup GDB memory map manually or issue @command{set mem inaccessible-by-default off} Now you can issue GDB command @command{target extended-remote ...} and inspect memory diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 58326f77be..2db3123a04 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1548,7 +1548,7 @@ static int gdb_read_memory_packet(struct connection *connection, * cmd = view%20audit-trail&database = gdb&pr = 2395 * * For now, the default is to fix up things to make current GDB versions work. - * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command. + * This can be overwritten using the "gdb report_data_abort <'enable'|'disable'>" command. */ memset(buffer, 0, len); retval = ERROR_OK; @@ -3938,7 +3938,7 @@ COMMAND_HANDLER(handle_gdb_sync_command) if (!current_gdb_connection) { command_print(CMD, - "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\""); + "gdb sync command can only be run from within gdb using \"monitor gdb sync\""); return ERROR_FAIL; } @@ -3947,7 +3947,6 @@ COMMAND_HANDLER(handle_gdb_sync_command) return ERROR_OK; } -/* daemon configuration command gdb_port */ COMMAND_HANDLER(handle_gdb_port_command) { int retval = CALL_COMMAND_HANDLER(server_pipe_command, &gdb_port); @@ -3994,7 +3993,6 @@ COMMAND_HANDLER(handle_gdb_report_register_access_error) return ERROR_OK; } -/* gdb_breakpoint_override */ COMMAND_HANDLER(handle_gdb_breakpoint_override_command) { if (CMD_ARGC == 0) { @@ -4071,9 +4069,9 @@ COMMAND_HANDLER(handle_gdb_save_tdesc_command) return retval; } -static const struct command_registration gdb_command_handlers[] = { +static const struct command_registration gdb_subcommand_handlers[] = { { - .name = "gdb_sync", + .name = "sync", .handler = handle_gdb_sync_command, .mode = COMMAND_ANY, .help = "next stepi will return immediately allowing " @@ -4082,7 +4080,7 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "" }, { - .name = "gdb_port", + .name = "port", .handler = handle_gdb_port_command, .mode = COMMAND_CONFIG, .help = "Normally gdb listens to a TCP/IP port. Each subsequent GDB " @@ -4095,35 +4093,35 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "[port_num]", }, { - .name = "gdb_memory_map", + .name = "memory_map", .handler = handle_gdb_memory_map_command, .mode = COMMAND_CONFIG, .help = "enable or disable memory map", .usage = "('enable'|'disable')" }, { - .name = "gdb_flash_program", + .name = "flash_program", .handler = handle_gdb_flash_program_command, .mode = COMMAND_CONFIG, .help = "enable or disable flash program", .usage = "('enable'|'disable')" }, { - .name = "gdb_report_data_abort", + .name = "report_data_abort", .handler = handle_gdb_report_data_abort_command, .mode = COMMAND_CONFIG, .help = "enable or disable reporting data aborts", .usage = "('enable'|'disable')" }, { - .name = "gdb_report_register_access_error", + .name = "report_register_access_error", .handler = handle_gdb_report_register_access_error, .mode = COMMAND_CONFIG, .help = "enable or disable reporting register access errors", .usage = "('enable'|'disable')" }, { - .name = "gdb_breakpoint_override", + .name = "breakpoint_override", .handler = handle_gdb_breakpoint_override_command, .mode = COMMAND_ANY, .help = "Display or specify type of breakpoint " @@ -4131,14 +4129,14 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "('hard'|'soft'|'disable')" }, { - .name = "gdb_target_description", + .name = "target_description", .handler = handle_gdb_target_description_command, .mode = COMMAND_CONFIG, .help = "enable or disable target description", .usage = "('enable'|'disable')" }, { - .name = "gdb_save_tdesc", + .name = "save_tdesc", .handler = handle_gdb_save_tdesc_command, .mode = COMMAND_EXEC, .help = "Save the target description file", @@ -4147,6 +4145,17 @@ static const struct command_registration gdb_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration gdb_command_handlers[] = { + { + .name = "gdb", + .mode = COMMAND_ANY, + .help = "GDB commands", + .chain = gdb_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + int gdb_register_commands(struct command_context *cmd_ctx) { gdb_port = strdup("3333"); diff --git a/src/server/startup.tcl b/src/server/startup.tcl index 1d30b1dd37..93f718927d 100644 --- a/src/server/startup.tcl +++ b/src/server/startup.tcl @@ -41,3 +41,57 @@ proc _telnet_autocomplete_helper pattern { return [lsort $cmds] } + +lappend _telnet_autocomplete_skip "gdb_sync" +proc "gdb_sync" {} { + echo "DEPRECATED! use 'gdb sync', not 'gdb_sync'" + eval gdb sync +} + +lappend _telnet_autocomplete_skip "gdb_port" +proc "gdb_port" {args} { + echo "DEPRECATED! use 'gdb port', not 'gdb_port'" + eval gdb port $args +} + +lappend _telnet_autocomplete_skip "gdb_memory_map" +proc "gdb_memory_map" {state} { + echo "DEPRECATED! use 'gdb memory_map', not 'gdb_memory_map'" + eval gdb memory_map $state +} + +lappend _telnet_autocomplete_skip "gdb_flash_program" +proc "gdb_flash_program" {state} { + echo "DEPRECATED! use 'gdb flash_program', not 'gdb_flash_program'" + eval gdb flash_program $state +} + +lappend _telnet_autocomplete_skip "gdb_report_data_abort" +proc "gdb_report_data_abort" {state} { + echo "DEPRECATED! use 'gdb report_data_abort', not 'gdb_report_data_abort'" + eval gdb report_data_abort $state +} + +lappend _telnet_autocomplete_skip "gdb_report_register_access_error" +proc "gdb_report_register_access_error" {state} { + echo "DEPRECATED! use 'gdb report_register_access_error', not 'gdb_report_register_access_error'" + eval gdb report_register_access_error $state +} + +lappend _telnet_autocomplete_skip "gdb_breakpoint_override" +proc "gdb_breakpoint_override" {override} { + echo "DEPRECATED! use 'gdb breakpoint_override', not 'gdb_breakpoint_override'" + eval gdb breakpoint_override $override +} + +lappend _telnet_autocomplete_skip "gdb_target_description" +proc "gdb_target_description" {state} { + echo "DEPRECATED! use 'gdb target_description', not 'gdb_target_description'" + eval gdb target_description $state +} + +lappend _telnet_autocomplete_skip "gdb_save_tdesc" +proc "gdb_save_tdesc" {} { + echo "DEPRECATED! use 'gdb save_tdesc', not 'gdb_save_tdesc'" + eval gdb save_tdesc +} diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index 16cbedc76c..06a7096d8c 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -330,7 +330,7 @@ static const struct command_registration tcl_command_handlers[] = { .mode = COMMAND_CONFIG, .help = "Specify port on which to listen " "for incoming Tcl syntax. " - "Read help on 'gdb_port'.", + "Read help on 'gdb port'.", .usage = "[port_num]", }, { diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 938bc5b062..72171cb3f5 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -992,7 +992,7 @@ static const struct command_registration telnet_command_handlers[] = { .mode = COMMAND_CONFIG, .help = "Specify port on which to listen " "for incoming telnet connections. " - "Read help on 'gdb_port'.", + "Read help on 'gdb port'.", .usage = "[port_num]", }, COMMAND_REGISTRATION_DONE diff --git a/src/target/esirisc.c b/src/target/esirisc.c index 0f76b5982e..14d34ff04b 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -483,7 +483,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea * The default linker scripts provided by the eSi-RISC toolchain do * not specify attributes on memory regions, which results in * incorrect application of software breakpoints by GDB. Targets - * must be configured with `gdb_breakpoint_override hard` as + * must be configured with `gdb breakpoint_override hard` as * software breakpoints are not supported. */ if (breakpoint->type != BKPT_HARD) From b764fc2a4dda2dacba7e9d3dd901fc6b8b1ad34b Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 14 Jun 2024 16:28:38 +0200 Subject: [PATCH 0881/1312] tcl: Replace 'gdb_' prefix with 'gdb' command group Change-Id: I0490b4c112c1a922bf77a4b37df2a630a8f6cea1 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8337 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/actux3.cfg | 2 +- tcl/board/mini2440.cfg | 2 +- tcl/board/mini6410.cfg | 2 +- tcl/board/or1k_generic.cfg | 2 +- tcl/interface/vdebug.cfg | 2 +- tcl/target/esi32xx.cfg | 2 +- tcl/target/esp_common.cfg | 2 +- tcl/target/omap4430.cfg | 2 +- tcl/target/omap4460.cfg | 2 +- tcl/target/omapl138.cfg | 2 +- tcl/target/rp2040.cfg | 2 +- tcl/target/u8500.cfg | 4 ++-- tcl/target/xtensa.cfg | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tcl/board/actux3.cfg b/tcl/board/actux3.cfg index edb529c889..7c2ce06773 100644 --- a/tcl/board/actux3.cfg +++ b/tcl/board/actux3.cfg @@ -50,7 +50,7 @@ reset init # setup to debug u-boot in flash proc uboot_debug {} { - gdb_breakpoint_override hard + gdb breakpoint_override hard xscale vector_catch 0xFF xscale vector_table low 1 0xe59ff018 diff --git a/tcl/board/mini2440.cfg b/tcl/board/mini2440.cfg index 85d9a35b9a..5642cb1ab8 100644 --- a/tcl/board/mini2440.cfg +++ b/tcl/board/mini2440.cfg @@ -128,7 +128,7 @@ reset_config trst_and_srst # GDB Setup #------------------------------------------------------------------------- - gdb_breakpoint_override hard + gdb breakpoint_override hard #------------------------------------------------ # ARM SPECIFIC diff --git a/tcl/board/mini6410.cfg b/tcl/board/mini6410.cfg index 18f9e8d25a..276e7180ea 100644 --- a/tcl/board/mini6410.cfg +++ b/tcl/board/mini6410.cfg @@ -95,7 +95,7 @@ adapter srst delay 100 jtag_ntrst_delay 100 reset_config trst_and_srst -gdb_breakpoint_override hard +gdb breakpoint_override hard targets nand device $_CHIPNAME.flash s3c6400 $_CHIPNAME.cpu diff --git a/tcl/board/or1k_generic.cfg b/tcl/board/or1k_generic.cfg index 915a0de249..b6cf3a0978 100644 --- a/tcl/board/or1k_generic.cfg +++ b/tcl/board/or1k_generic.cfg @@ -22,7 +22,7 @@ poll_period 1 adapter speed 3000 # Enable the target description feature -gdb_target_description enable +gdb target_description enable # Add a new register in the cpu register list. This register will be # included in the generated target descriptor file. diff --git a/tcl/interface/vdebug.cfg b/tcl/interface/vdebug.cfg index 7350bb9a91..116ac8a758 100644 --- a/tcl/interface/vdebug.cfg +++ b/tcl/interface/vdebug.cfg @@ -22,7 +22,7 @@ vdebug server $_VDEBUGHOST:$_VDEBUGPORT # example config listen on all interfaces, disable tcl/telnet server bindto 0.0.0.0 -#gdb_port 3333 +#gdb port 3333 #telnet_port disabled tcl_port disabled diff --git a/tcl/target/esi32xx.cfg b/tcl/target/esi32xx.cfg index a8b0823dac..d29c636cfa 100644 --- a/tcl/target/esi32xx.cfg +++ b/tcl/target/esi32xx.cfg @@ -35,4 +35,4 @@ reset_config none # The default linker scripts provided by the eSi-RISC toolchain do not # specify attributes on memory regions, which results in incorrect # application of software breakpoints by GDB. -gdb_breakpoint_override hard +gdb breakpoint_override hard diff --git a/tcl/target/esp_common.cfg b/tcl/target/esp_common.cfg index ac8cd6a198..e9a188f9f6 100644 --- a/tcl/target/esp_common.cfg +++ b/tcl/target/esp_common.cfg @@ -181,7 +181,7 @@ proc configure_esp_xtensa_default_settings { } { $_TARGETNAME_0 xtensa smpbreak BreakIn BreakOut } - gdb_breakpoint_override hard + gdb breakpoint_override hard if { [info exists _FLASH_VOLTAGE] } { $_TARGETNAME_0 $_CHIPNAME flashbootstrap $_FLASH_VOLTAGE diff --git a/tcl/target/omap4430.cfg b/tcl/target/omap4430.cfg index a448550f67..4bc7fe1bf7 100644 --- a/tcl/target/omap4430.cfg +++ b/tcl/target/omap4430.cfg @@ -128,4 +128,4 @@ $_CHIPNAME.m30 configure -event reset-assert { } $_CHIPNAME.m31 configure -event reset-assert { } # Soft breakpoints don't currently work due to broken cache handling -gdb_breakpoint_override hard +gdb breakpoint_override hard diff --git a/tcl/target/omap4460.cfg b/tcl/target/omap4460.cfg index bbc824b2af..85ba96c51f 100644 --- a/tcl/target/omap4460.cfg +++ b/tcl/target/omap4460.cfg @@ -128,4 +128,4 @@ $_CHIPNAME.m30 configure -event reset-assert { } $_CHIPNAME.m31 configure -event reset-assert { } # Soft breakpoints don't currently work due to broken cache handling -gdb_breakpoint_override hard +gdb breakpoint_override hard diff --git a/tcl/target/omapl138.cfg b/tcl/target/omapl138.cfg index 2d670b98a3..78c456d5c0 100644 --- a/tcl/target/omapl138.cfg +++ b/tcl/target/omapl138.cfg @@ -64,5 +64,5 @@ arm7_9 dcc_downloads enable etm config $_TARGETNAME 16 normal full etb etb config $_TARGETNAME $_CHIPNAME.etb -gdb_breakpoint_override hard +gdb breakpoint_override hard arm7_9 dbgrq enable diff --git a/tcl/target/rp2040.cfg b/tcl/target/rp2040.cfg index de76b4e29c..5e78c69310 100644 --- a/tcl/target/rp2040.cfg +++ b/tcl/target/rp2040.cfg @@ -96,7 +96,7 @@ if { $_USE_CORE == 1 } { set _FLASH_TARGET $_TARGETNAME_0 } # Backup the work area. The flash probe runs an algorithm on the target CPU. -# The flash is probed during gdb connect if gdb_memory_map is enabled (by default). +# The flash is probed during gdb connect if gdb memory_map is enabled (by default). $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup 1 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME rp2040_flash 0x10000000 0 0 0 $_FLASH_TARGET diff --git a/tcl/target/u8500.cfg b/tcl/target/u8500.cfg index 417fdd18f2..932ef8c20d 100644 --- a/tcl/target/u8500.cfg +++ b/tcl/target/u8500.cfg @@ -144,7 +144,7 @@ proc enable_apetap {} { tcl_port 5555 telnet_port 4444 -gdb_port 3333 +gdb port 3333 if { [info exists CHIPNAME] } { global _CHIPNAME @@ -319,7 +319,7 @@ global _MAXSPEED adapter speed $_MAXSPEED -gdb_breakpoint_override hard +gdb breakpoint_override hard set mem inaccessible-by-default-off jtag_ntrst_delay 100 diff --git a/tcl/target/xtensa.cfg b/tcl/target/xtensa.cfg index 561131d842..c277673e47 100644 --- a/tcl/target/xtensa.cfg +++ b/tcl/target/xtensa.cfg @@ -67,4 +67,4 @@ if { $_XTENSA_NUM_CORES == 1 } { $_TARGETNAME configure -event reset-assert-post { soft_reset_halt } } -gdb_report_register_access_error enable +gdb report_register_access_error enable From 73b15194eaf0c6d1a52e82d05c3d6771d89c9886 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 17 Jun 2024 09:12:34 +0200 Subject: [PATCH 0882/1312] server/tcl: Restructure commands Use a command group 'tcl' with subcommands instead of individual commands with 'tcl_' prefix. The old commands are still available to ensure backwards compatibility, but are marked as deprecated. Change-Id: I1efd8a0e2c1403833f8cb656510a54d5ab0b2740 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8344 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 10 +++++----- src/server/startup.tcl | 18 ++++++++++++++++++ src/server/tcl_server.c | 19 +++++++++++++++---- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 58f1d04216..7169ef08b5 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2217,7 +2217,7 @@ gdb (with 'set remotetimeout') is recommended. An insufficient timeout may cause initialization to fail with "Unknown remote qXfer reply: OK". @end deffn -@deffn {Config Command} {tcl_port} [number] +@deffn {Config Command} {tcl port} [number] Specify or query the port used for a simplified RPC connection that can be used by clients to issue TCL commands and get the output from the Tcl engine. @@ -10588,7 +10588,7 @@ the destination of the trace data: @item @option{external} -- configure TPIU/SWO to let user capture trace output externally, either with an additional UART or with a logic analyzer (default); @item @option{-} -- configure TPIU/SWO and debug adapter to gather trace data -and forward it to @command{tcl_trace} command; +and forward it to @command{tcl trace} command; @item @option{:}@var{port} -- configure TPIU/SWO and debug adapter to gather trace data, open a TCP server at port @var{port} and send the trace data to each connected client; @@ -12776,7 +12776,7 @@ OpenOCD provides a simple RPC server that allows to run arbitrary Tcl commands and receive the results. To access it, your application needs to connect to a configured TCP port -(see @command{tcl_port}). Then it can pass any string to the +(see @command{tcl port}). Then it can pass any string to the interpreter terminating it with @code{0x1a} and wait for the return value (it will be terminated with @code{0x1a} as well). This can be repeated as many times as desired without reopening the connection. @@ -12802,7 +12802,7 @@ type target_state state [state-name] type target_reset mode [reset-mode] @end verbatim -@deffn {Command} {tcl_notifications} [on/off] +@deffn {Command} {tcl notifications} [on/off] Toggle output of target notifications to the current Tcl RPC server. Only available from the Tcl RPC server. Defaults to off. @@ -12821,7 +12821,7 @@ Target trace data is emitted as a Tcl associative array in the following format. type target_trace data [trace-data-hex-encoded] @end verbatim -@deffn {Command} {tcl_trace} [on/off] +@deffn {Command} {tcl trace} [on/off] Toggle output of target trace data to the current Tcl RPC server. Only available from the Tcl RPC server. Defaults to off. diff --git a/src/server/startup.tcl b/src/server/startup.tcl index 93f718927d..ebfb0562e9 100644 --- a/src/server/startup.tcl +++ b/src/server/startup.tcl @@ -95,3 +95,21 @@ proc "gdb_save_tdesc" {} { echo "DEPRECATED! use 'gdb save_tdesc', not 'gdb_save_tdesc'" eval gdb save_tdesc } + +lappend _telnet_autocomplete_skip "tcl_port" +proc "tcl_port" {args} { + echo "DEPRECATED! use 'tcl port' not 'tcl_port'" + eval tcl port $args +} + +lappend _telnet_autocomplete_skip "tcl_notifications" +proc "tcl_notifications" {state} { + echo "DEPRECATED! use 'tcl notifications' not 'tcl_notifications'" + eval tcl notifications $state +} + +lappend _telnet_autocomplete_skip "tcl_trace" +proc "tcl_trace" {state} { + echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'" + eval tcl trace $state +} diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index 06a7096d8c..16cc55e29b 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -323,9 +323,9 @@ COMMAND_HANDLER(handle_tcl_trace_command) } } -static const struct command_registration tcl_command_handlers[] = { +static const struct command_registration tcl_subcommand_handlers[] = { { - .name = "tcl_port", + .name = "port", .handler = handle_tcl_port_command, .mode = COMMAND_CONFIG, .help = "Specify port on which to listen " @@ -334,14 +334,14 @@ static const struct command_registration tcl_command_handlers[] = { .usage = "[port_num]", }, { - .name = "tcl_notifications", + .name = "notifications", .handler = handle_tcl_notifications_command, .mode = COMMAND_EXEC, .help = "Target Notification output", .usage = "[on|off]", }, { - .name = "tcl_trace", + .name = "trace", .handler = handle_tcl_trace_command, .mode = COMMAND_EXEC, .help = "Target trace output", @@ -350,6 +350,17 @@ static const struct command_registration tcl_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration tcl_command_handlers[] = { + { + .name = "tcl", + .mode = COMMAND_ANY, + .help = "tcl command group", + .usage = "", + .chain = tcl_subcommand_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + int tcl_register_commands(struct command_context *cmd_ctx) { tcl_port = strdup("6666"); From 40a6af6eda6e12768ab4341de10f78140f925e25 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 17 Jun 2024 16:39:10 +0200 Subject: [PATCH 0883/1312] tcl: Replace 'tcl_' prefix with 'tcl' command group Change-Id: Iee1e84a87d07172aa6b0adfb7b85fb465cefb979 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8345 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/interface/vdebug.cfg | 2 +- tcl/target/u8500.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/interface/vdebug.cfg b/tcl/interface/vdebug.cfg index 116ac8a758..9097c33dac 100644 --- a/tcl/interface/vdebug.cfg +++ b/tcl/interface/vdebug.cfg @@ -24,7 +24,7 @@ vdebug server $_VDEBUGHOST:$_VDEBUGPORT bindto 0.0.0.0 #gdb port 3333 #telnet_port disabled -tcl_port disabled +tcl port disabled # transaction batching: 0 - no batching, 1 - (default) wr, 2 - rw vdebug batching 1 diff --git a/tcl/target/u8500.cfg b/tcl/target/u8500.cfg index 932ef8c20d..b87d2613a8 100644 --- a/tcl/target/u8500.cfg +++ b/tcl/target/u8500.cfg @@ -142,7 +142,7 @@ proc enable_apetap {} { } } -tcl_port 5555 +tcl port 5555 telnet_port 4444 gdb port 3333 From 812fad02fee0627d917b7ba746947f06244ed3b1 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 16 May 2024 15:49:37 -0500 Subject: [PATCH 0884/1312] tcl/board: Add am62p/am62a7/j722s native swd configuration Direct memory driver swd native configuration for am62a7, am62p and J722S SoCs. All three share common memory map for the debug address map, so there is a strong reuse. However, introduce board file specific to the board to allow users to directly get started. Change-Id: I5609925a2e9918fd4c91d9fd40fbee98de27fdbc Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8283 Tested-by: jenkins Reviewed-by: Vaishnav M A Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- tcl/board/ti_am62a7_swd_native.cfg | 22 ++++++++++++++++++++++ tcl/board/ti_am62p_swd_native.cfg | 22 ++++++++++++++++++++++ tcl/board/ti_j722s_swd_native.cfg | 23 +++++++++++++++++++++++ tcl/target/ti_k3.cfg | 10 ++++++++++ 4 files changed, 77 insertions(+) create mode 100644 tcl/board/ti_am62a7_swd_native.cfg create mode 100644 tcl/board/ti_am62p_swd_native.cfg create mode 100644 tcl/board/ti_j722s_swd_native.cfg diff --git a/tcl/board/ti_am62a7_swd_native.cfg b/tcl/board/ti_am62a7_swd_native.cfg new file mode 100644 index 0000000000..99fc0b0b38 --- /dev/null +++ b/tcl/board/ti_am62a7_swd_native.cfg @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments AM62A7 +# Link: https://www.ti.com/product/AM62A7 +# +# This configuration file is used as a self hosted debug configuration that +# works on every AM62A7 platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside AM62A7 and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC am62a7 +} + +source [find target/ti_k3.cfg] diff --git a/tcl/board/ti_am62p_swd_native.cfg b/tcl/board/ti_am62p_swd_native.cfg new file mode 100644 index 0000000000..fa549f3585 --- /dev/null +++ b/tcl/board/ti_am62p_swd_native.cfg @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments am62p +# Link: https://www.ti.com/product/AM62P +# +# This configuration file is used as a self hosted debug configuration that +# works on every AM62P platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside AM62P and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC am62p +} + +source [find target/ti_k3.cfg] diff --git a/tcl/board/ti_j722s_swd_native.cfg b/tcl/board/ti_j722s_swd_native.cfg new file mode 100644 index 0000000000..bbe0d508c8 --- /dev/null +++ b/tcl/board/ti_j722s_swd_native.cfg @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2024 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments J722S/AM67/TDA4VEN +# Link: https://www.ti.com/product/AM67 +# Link: https://www.ti.com/product/TDA4VEN-Q1 +# +# This configuration file is used as a self hosted debug configuration that +# works on every J722S platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside J722S and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC j722s +} + +source [find target/ti_k3.cfg] diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index ebea821793..2ae0f75b80 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -209,6 +209,16 @@ switch $_soc { # Sysctrl power-ap unlock offsets set _sysctrl_ap_unlock_offsets {0xf0 0x78} + # Setup DMEM access descriptions + # DAPBUS (Debugger) description + set _dmem_base_address 0x740002000 + set _dmem_ap_address_offset 0x100 + set _dmem_max_aps 10 + # Emulated AP description + set _dmem_emu_base_address 0x760000000 + set _dmem_emu_base_address_map_to 0x1d500000 + set _dmem_emu_ap_list 1 + # Overrides for am62p if { "$_soc" == "am62p" } { set _K3_DAP_TAPID 0x0bb9d02f From 7f2d3e2925833c952ee73fb178c8fdee637c844e Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Tue, 31 Oct 2023 20:51:48 +0300 Subject: [PATCH 0885/1312] rtos/hwthread: derive threadid from SMP index As defined in `target/target.h`, `coreid` is the index of the target on the TAP, so, if an SMP group includes targets from multiple TAPs, it can not be used as the base for `threadid`. Change-Id: Ied7cfa42197aaf4908ef6628c6436f28d4856ebe Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/7957 Tested-by: jenkins Reviewed-by: Mark Zhuang Reviewed-by: Antonio Borneo --- src/rtos/hwthread.c | 53 +++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 937d01b874..748e71c3dc 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -33,7 +33,18 @@ static int hwthread_write_buffer(struct rtos *rtos, target_addr_t address, static inline threadid_t threadid_from_target(const struct target *target) { - return target->coreid + 1; + if (!target->smp) + return 1; + + threadid_t threadid = 1; + struct target_list *head; + foreach_smp_target(head, target->smp_targets) { + if (target == head->target) + return threadid; + ++threadid; + } + assert(0 && "Target is not found in it's own SMP group!"); + return -1; } const struct rtos_type hwthread_rtos = { @@ -54,14 +65,13 @@ struct hwthread_params { int dummy_param; }; -static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num) +static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num, threadid_t tid) { char tmp_str[HW_THREAD_NAME_STR_SIZE]; - threadid_t tid = threadid_from_target(curr); memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE); - /* thread-id is the core-id of this core inside the SMP group plus 1 */ + /* thread-id is the index of this core inside the SMP group plus 1 */ rtos->thread_details[thread_num].threadid = tid; /* create the thread name */ rtos->thread_details[thread_num].exists = true; @@ -123,9 +133,8 @@ static int hwthread_update_threads(struct rtos *rtos) if (!target_was_examined(curr)) continue; - threadid_t tid = threadid_from_target(curr); - - hwthread_fill_thread(rtos, curr, threads_found); + threadid_t tid = threads_found + 1; + hwthread_fill_thread(rtos, curr, threads_found, tid); /* find an interesting thread to set as current */ switch (current_reason) { @@ -182,8 +191,8 @@ static int hwthread_update_threads(struct rtos *rtos) threads_found++; } } else { - hwthread_fill_thread(rtos, target, threads_found); - current_thread = threadid_from_target(target); + current_thread = 1; + hwthread_fill_thread(rtos, target, threads_found, current_thread); threads_found++; } @@ -206,19 +215,17 @@ static int hwthread_smp_init(struct target *target) return hwthread_update_threads(target->rtos); } -static struct target *hwthread_find_thread(struct target *target, int64_t thread_id) +static struct target *hwthread_find_thread(struct target *target, threadid_t thread_id) { - /* Find the thread with that thread_id */ - if (!target) - return NULL; - if (target->smp) { - struct target_list *head; - foreach_smp_target(head, target->smp_targets) { - if (thread_id == threadid_from_target(head->target)) - return head->target; - } - } else if (thread_id == threadid_from_target(target)) { + /* Find the thread with that thread_id (index in SMP group plus 1)*/ + if (!(target && target->smp)) return target; + struct target_list *head; + threadid_t tid = 1; + foreach_smp_target(head, target->smp_targets) { + if (thread_id == tid) + return head->target; + ++tid; } return NULL; } @@ -297,7 +304,7 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, } if (!target_was_examined(curr)) { - LOG_ERROR("Target %d hasn't been examined yet.", curr->coreid); + LOG_TARGET_ERROR(curr, "Target hasn't been examined yet."); return ERROR_FAIL; } @@ -382,9 +389,9 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac return ERROR_FAIL; } target->rtos->current_thread = current_threadid; - } else - if (current_threadid == 0 || current_threadid == -1) + } else if (current_threadid == 0 || current_threadid == -1) { target->rtos->current_thread = threadid_from_target(target); + } target->rtos->current_threadid = current_threadid; From 6554d176e926e1e46b90e1b00d1b3ed1bd20b9ff Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Fri, 3 Dec 2021 13:16:50 +0100 Subject: [PATCH 0886/1312] flash/stm32l4x: support STM32U59/U5Ax devices STM32U59/U5Ax devices are similar to U57/U58x devices with 2 flash banks up to 2 MB each while at there update STM32U57x/U58x revisions Change-Id: I7e5c1700acf8c9fda34f660c9274bfd8bcb1381b Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/6875 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/stm32l4x.c | 29 ++++++++++++++++++++++++++--- src/flash/nor/stm32l4x.h | 1 + 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 039938512b..b6fa3d6515 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -120,6 +120,12 @@ * http://www.st.com/resource/en/reference_manual/dm00346336.pdf */ +/* STM32U5xxx series for reference. + * + * RM0456 (STM32U5xx) + * http://www.st.com/resource/en/reference_manual/dm00477635.pdf + */ + /* Erase time can be as high as 25ms, 10x this and assume it's toast... */ #define FLASH_ERASE_TIMEOUT 250 @@ -346,7 +352,11 @@ static const struct stm32l4_rev stm32g49_g4axx_revs[] = { static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, - { 0x2001, "X" }, { 0x3000, "C" }, + { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, +}; + +static const struct stm32l4_rev stm32u59_u5axx_revs[] = { + { 0x3001, "X" }, }; static const struct stm32l4_rev stm32wba5x_revs[] = { @@ -574,6 +584,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = DEVID_STM32U59_U5AXX, + .revs = stm32u59_u5axx_revs, + .num_revs = ARRAY_SIZE(stm32u59_u5axx_revs), + .device_str = "STM32U59/U5Axx", + .max_flash_size_kb = 4096, + .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0BFA07A0, + .otp_base = 0x0BFA0000, + .otp_size = 512, + }, { .id = DEVID_STM32U57_U58XX, .revs = stm32u57_u58xx_revs, @@ -2000,9 +2022,10 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; + case DEVID_STM32U59_U5AXX: case DEVID_STM32U57_U58XX: - /* if flash size is max (2M) the device is always dual bank - * otherwise check DUALBANK + /* if flash size is more than 1M the device is always dual bank + * otherwise check DUALBANK bit */ page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 3dc0909554..95b6c84a61 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -102,6 +102,7 @@ #define DEVID_STM32L4P_L4QXX 0x471 #define DEVID_STM32L55_L56XX 0x472 #define DEVID_STM32G49_G4AXX 0x479 +#define DEVID_STM32U59_U5AXX 0x481 #define DEVID_STM32U57_U58XX 0x482 #define DEVID_STM32WBA5X 0x492 #define DEVID_STM32WB1XX 0x494 From 052a4a69b5098e23efaf4ef993a3f0c44d605943 Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Fri, 28 Apr 2023 17:06:56 +0100 Subject: [PATCH 0887/1312] flash/stm32l4x: support STM32U53/U54x devices STM32U53/U54x devices are similar to U57/U58x devices with 2 flash banks up to 256 KB each Change-Id: I774ef0df4dddac5f06bbfc2e6c3fc2e628d2249e Signed-off-by: FBOSTM Signed-off-by: Tarek BOCHKATI Reviewed-on: https://review.openocd.org/c/openocd/+/7515 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/stm32l4x.c | 33 ++++++++++++++++++++++++++++++--- src/flash/nor/stm32l4x.h | 1 + 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index b6fa3d6515..bb6e9ef04a 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -350,6 +350,10 @@ static const struct stm32l4_rev stm32g49_g4axx_revs[] = { { 0x1000, "A" }, }; +static const struct stm32l4_rev stm32u53_u54xx_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, +}; + static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, @@ -428,6 +432,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = DEVID_STM32U53_U54XX, + .revs = stm32u53_u54xx_revs, + .num_revs = ARRAY_SIZE(stm32u53_u54xx_revs), + .device_str = "STM32U535/U545", + .max_flash_size_kb = 512, + .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0BFA07A0, + .otp_base = 0x0BFA0000, + .otp_size = 512, + }, { .id = DEVID_STM32G05_G06XX, .revs = stm32g05_g06xx_revs, @@ -2022,11 +2038,22 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; - case DEVID_STM32U59_U5AXX: + case DEVID_STM32U53_U54XX: case DEVID_STM32U57_U58XX: - /* if flash size is more than 1M the device is always dual bank - * otherwise check DUALBANK bit + case DEVID_STM32U59_U5AXX: + /* according to RM0456 Rev 4, Chapter 7.3.1 and 7.9.13 + * U53x/U54x have 512K max flash size: + * 512K variants are always in DUAL BANK mode + * 256K and 128K variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set + * U57x/U58x have 2M max flash size: + * 2M variants are always in DUAL BANK mode + * 1M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set + * U59x/U5Ax have 4M max flash size: + * 4M variants are always in DUAL BANK mode + * 2M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set + * Note: flash banks are always contiguous */ + page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 95b6c84a61..5f3bc26576 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -89,6 +89,7 @@ #define DEVID_STM32L43_L44XX 0x435 #define DEVID_STM32C01XX 0x443 #define DEVID_STM32C03XX 0x453 +#define DEVID_STM32U53_U54XX 0x455 #define DEVID_STM32G05_G06XX 0x456 #define DEVID_STM32G07_G08XX 0x460 #define DEVID_STM32L49_L4AXX 0x461 From 5b7b77349c11e0a8f4b0967f31d65dde6ee01457 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 13 Jul 2024 19:14:39 +0200 Subject: [PATCH 0888/1312] cortex_m: fix scan-build false positive Scan-build is unable to detect that 'target->dbg_msg_enabled' does not change across the function cortex_m_fast_read_all_regs(). It incorrectly assumes that it can be false at the first check (so 'dcrdr' get not assigned) and it is true later on (when 'dcrdr' get used). This triggers a false positive: src/target/cortex_m.c:338:12: warning: 3rd function call argument is an uninitialized value [core.CallAndMessage] retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr); Use a local variable for 'target->dbg_msg_enabled' so scan-build can track it as not modified. While there, change the type of 'target->dbg_msg_enabled' to boolean as there is no reason to use uint32_t. Change-Id: Icaf1a1b2dea8bc55108182ea440708ab76396cd7 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8391 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/cortex_m.c | 5 +++-- src/target/target.c | 2 +- src/target/target.h | 2 +- src/target/target_request.c | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 791a432427..3b95b648ef 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -279,7 +279,8 @@ static int cortex_m_fast_read_all_regs(struct target *target) /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ - if (target->dbg_msg_enabled) { + bool dbg_msg_enabled = target->dbg_msg_enabled; + if (dbg_msg_enabled) { retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr); if (retval != ERROR_OK) return retval; @@ -332,7 +333,7 @@ static int cortex_m_fast_read_all_regs(struct target *target) if (retval != ERROR_OK) return retval; - if (target->dbg_msg_enabled) { + if (dbg_msg_enabled) { /* restore DCB_DCRDR - this needs to be in a separate * transaction otherwise the emulated DCC channel breaks */ retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr); diff --git a/src/target/target.c b/src/target/target.c index 8ff665f474..bd2638f2d0 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5813,7 +5813,7 @@ static int target_create(struct jim_getopt_info *goi) } target->dbgmsg = NULL; - target->dbg_msg_enabled = 0; + target->dbg_msg_enabled = false; target->endianness = TARGET_ENDIAN_UNKNOWN; diff --git a/src/target/target.h b/src/target/target.h index 03db3950ce..d3077f5716 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -160,7 +160,7 @@ struct target { struct watchpoint *watchpoints; /* list of watchpoints */ struct trace *trace_info; /* generic trace information */ struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */ - uint32_t dbg_msg_enabled; /* debug message status */ + bool dbg_msg_enabled; /* debug message status */ void *arch_info; /* architecture specific information */ void *private_config; /* pointer to target specific config data (for jim_configure hook) */ struct target *next; /* next target in list */ diff --git a/src/target/target_request.c b/src/target/target_request.c index 72c84216fa..bccae07b42 100644 --- a/src/target/target_request.c +++ b/src/target/target_request.c @@ -164,7 +164,7 @@ static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target (*p)->next = NULL; /* enable callback */ - target->dbg_msg_enabled = 1; + target->dbg_msg_enabled = true; return ERROR_OK; } @@ -225,7 +225,7 @@ int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *ta free(c); if (!*p) { /* disable callback */ - target->dbg_msg_enabled = 0; + target->dbg_msg_enabled = false; } return ERROR_OK; } else From 4c6646f10a55efccf7a076667ebeb18b45c1d6e0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jul 2024 10:46:48 +0200 Subject: [PATCH 0889/1312] doc: fix makeinfo warning Build returns a makeinfo warning: openocd.texi:5201: warning: `.' or `,' must follow @xref, not f Add a dummy ',' after '@xref{..}' to silent the warning. Fixes: 44cfdef0a40d ("server/gdb: Restructure commands") Change-Id: Ic0bff8fc9b54942ebb72762816686ea7c7881345 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8392 Tested-by: jenkins Reviewed-by: zapb --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 7169ef08b5..a8a1892db8 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5198,7 +5198,7 @@ where it is a mandatory configuration for the target run control. for instruction on how to declare and control a CTI instance. @anchor{gdbportoverride} -@item @code{-gdb-port} @var{number} -- @xref{gdb port,,command gdb port} for the +@item @code{-gdb-port} @var{number} -- @xref{gdb port,,command gdb port}, for the possible values of the parameter @var{number}, which are not only numeric values. Use this option to override, for this target only, the global parameter set with command @command{gdb port}. From 2cbfd141e8aa3e8c36ea2d9a68d8d3e2c4d3df36 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 18 Jul 2024 14:51:01 +0200 Subject: [PATCH 0890/1312] jep106: update to revision JEP106BJ.01 July 2024 Change-Id: Iebab3f6a3b1f6d82f955997fd4e691c55d01c767 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8406 Tested-by: jenkins --- src/helper/jep106.inc | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 958dc4ea4d..b74cda85fe 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -8,9 +8,7 @@ * identification code list, please visit the JEDEC website at www.jedec.org . */ -/* This file is aligned to revision JEP106BI January 2024. */ - -/* "NXP (Philips)" is reported below, while missing since JEP106BG */ +/* This file is aligned to revision JEP106BJ.01 July 2024. */ [0][0x01 - 1] = "AMD", [0][0x02 - 1] = "AMI", @@ -30,7 +28,7 @@ [0][0x10 - 1] = "NEC", [0][0x11 - 1] = "RCA", [0][0x12 - 1] = "Raytheon", -[0][0x13 - 1] = "Conexant (Rockwell)", +[0][0x13 - 1] = "Synaptics", [0][0x14 - 1] = "Seeq", [0][0x15 - 1] = "NXP (Philips)", [0][0x16 - 1] = "Synertek", @@ -1045,7 +1043,7 @@ [8][0x17 - 1] = "Axell Corporation", [8][0x18 - 1] = "Essencore Limited", [8][0x19 - 1] = "Phytium", -[8][0x1a - 1] = "Xi'an UniIC Semiconductors Co Ltd", +[8][0x1a - 1] = "UniIC Semiconductors Co Ltd", [8][0x1b - 1] = "Ambiq Micro", [8][0x1c - 1] = "eveRAM Technology Inc", [8][0x1d - 1] = "Infomax", @@ -1452,7 +1450,7 @@ [11][0x34 - 1] = "Acacia Communications", [11][0x35 - 1] = "Beijinjinshengyihe Technology Co Ltd", [11][0x36 - 1] = "Zyzyx", -[11][0x37 - 1] = "T-HEAD Semiconductor Co Ltd", +[11][0x37 - 1] = "C-SKY Microsystems Co Ltd", [11][0x38 - 1] = "Shenzhen Hystou Technology Co Ltd", [11][0x39 - 1] = "Syzexion", [11][0x3a - 1] = "Kembona", @@ -1938,4 +1936,31 @@ [15][0x22 - 1] = "SkyeChip", [15][0x23 - 1] = "Guangzhou Kaishile Trading Co Ltd", [15][0x24 - 1] = "Jing Pai Digital Technology (Shenzhen) Co", +[15][0x25 - 1] = "Memoritek", +[15][0x26 - 1] = "Zhejiang Hikstor Technology Co Ltd", +[15][0x27 - 1] = "Memoritek PTE Ltd", +[15][0x28 - 1] = "Longsailing Semiconductor Co Ltd", +[15][0x29 - 1] = "LX Semicon", +[15][0x2a - 1] = "Shenzhen Techwinsemi Technology Co Ltd", +[15][0x2b - 1] = "AOC", +[15][0x2c - 1] = "GOEPEL Electronic GmbH", +[15][0x2d - 1] = "Shenzhen G-Bong Technology Co Ltd", +[15][0x2e - 1] = "Openedges Technology Inc", +[15][0x2f - 1] = "EA Semi Shangahi Limited", +[15][0x30 - 1] = "EMBCORF", +[15][0x31 - 1] = "Shenzhen MicroBT Electronics Technology", +[15][0x32 - 1] = "Shanghai Simor Chip Semiconductor Co", +[15][0x33 - 1] = "Xllbyte", +[15][0x34 - 1] = "Guangzhou Maidite Electronics Co Ltd.", +[15][0x35 - 1] = "Zhejiang Changchun Technology Co Ltd", +[15][0x36 - 1] = "Beijing Cloud Security Technology Co Ltd", +[15][0x37 - 1] = "SSTC Technology and Distribution Inc", +[15][0x38 - 1] = "Shenzhen Panmin Technology Co Ltd", +[15][0x39 - 1] = "ITE Tech Inc", +[15][0x3a - 1] = "Beijing Zettastone Technology Co Ltd", +[15][0x3b - 1] = "Powerchip Micro Device", +[15][0x3c - 1] = "Shenzhen Ysemi Computing Co Ltd", +[15][0x3d - 1] = "Shenzhen Titan Micro Electronics Co Ltd", +[15][0x3e - 1] = "Shenzhen Macroflash Technology Co Ltd", +[15][0x3f - 1] = "Advantech Group", /* EOF */ From 16c114c05891509054079e8d5d82905f1690a7a8 Mon Sep 17 00:00:00 2001 From: Grant Ramsay Date: Tue, 25 Jun 2024 16:52:59 +1200 Subject: [PATCH 0891/1312] flash/startup.tcl: Tidy flash program preverify documentation Remove the hyphen from "pre-verify" in usage text. Add preverify to the help text and procedure comment Change-Id: I6d96e78ca84d99929300d461e435f5b4ce07b5db Signed-off-by: Grant Ramsay Reviewed-on: https://review.openocd.org/c/openocd/+/8376 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/startup.tcl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl index 654f201a4e..0dd84efacc 100644 --- a/src/flash/startup.tcl +++ b/src/flash/startup.tcl @@ -5,7 +5,7 @@ # # program utility proc # usage: program filename -# optional args: verify, reset, exit and address +# optional args: preverify, verify, reset, exit and address # lappend _telnet_autocomplete_skip program_error @@ -101,8 +101,8 @@ proc program {filename args} { return } -add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional" -add_usage_text program " \[address\] \[pre-verify\] \[verify\] \[reset\] \[exit\]" +add_help_text program "write an image to flash, address is only required for binary images. preverify, verify, reset, exit are optional" +add_usage_text program " \[address\] \[preverify\] \[verify\] \[reset\] \[exit\]" # stm32[f0x|f3x] uses the same flash driver as the stm32f1x proc stm32f0x args { eval stm32f1x $args } From a8a0b4c50768fb8bbcbd1683d020a31ad2bb0cad Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 2 Jul 2024 17:14:22 +0200 Subject: [PATCH 0892/1312] configure: Use pkg-config for jimtcl The jimtcl project supports pkg-config, use it for a simpler configuration of compiler and linker flags and to enforce the minimum required package version. Since the jimtcl pkg-config file is not available on all systems, use AC_CHECK_HEADER() as fallback. Change-Id: I6fdcc818a8fdd205a126b0a46356434dbe890226 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8383 Reviewed-by: Antonio Borneo Tested-by: jenkins --- Makefile.am | 2 ++ configure.ac | 10 ++++++++++ src/Makefile.am | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/Makefile.am b/Makefile.am index 647b571cfa..2230e628f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,8 @@ AM_CPPFLAGS = $(HOST_CPPFLAGS)\ if INTERNAL_JIMTCL AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \ -I$(top_builddir)/jimtcl +else +AM_CPPFLAGS += $(JIMTCL_CFLAGS) endif EXTRA_DIST += \ BUGS \ diff --git a/configure.ac b/configure.ac index becc531b0d..b7aed245e6 100644 --- a/configure.ac +++ b/configure.ac @@ -594,6 +594,15 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ ], [ AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.]) ]) +], [ + PKG_CHECK_MODULES([JIMTCL], [jimtcl >= 0.79], [ + have_jimtcl_pkg_config=yes + ], [ + have_jimtcl_pkg_config=no + AC_CHECK_HEADER([jim.h], [], [ + AC_MSG_ERROR([jimtcl is required but not found via pkg-config and system includes]) + ]) + ]) ]) AS_IF([test "x$build_remote_bitbang" = "xyes"], [ @@ -781,6 +790,7 @@ AM_CONDITIONAL([DMEM], [test "x$build_dmem" = "xyes"]) AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"]) AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"]) +AM_CONDITIONAL([HAVE_JIMTCL_PKG_CONFIG], [test "x$have_jimtcl_pkg_config" = "xyes"]) AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"]) # Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h? diff --git a/src/Makefile.am b/src/Makefile.am index 6d79cd6311..4d1c1a2509 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,8 +17,12 @@ bin_PROGRAMS += %D%/openocd if INTERNAL_JIMTCL %C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a else +if HAVE_JIMTCL_PKG_CONFIG +%C%_openocd_LDADD += $(JIMTCL_LIBS) +else %C%_openocd_LDADD += -ljim endif +endif %C%_libopenocd_la_CPPFLAGS = From 1b5c137e434b0c21ee62c1e684fdfb43e63263d3 Mon Sep 17 00:00:00 2001 From: Marek Kraus Date: Sat, 20 Jul 2024 16:29:19 +0200 Subject: [PATCH 0893/1312] tcl/target: add initial Bouffalo Lab BL702 chip series support Adds initial support for the BL702 series of chips, BL702, BL704 and BL706. No flash bank support yet. File name bl702.tcl was chosen over bl70x.tcl, because Bouffalo Lab uses bl702 to mark the whole series in many of their tools. The ndmreset bit in the RISC-V Debug Module isn't implemented correctly, so it doesn't trigger a system reset as it should. To solve this problem, the software reset is implemented in the reset-assert-pre hook, which uses best reset method I could find. What is not reset is the GLB core, which handles GPIOs, pinmux, etc. The reset mechanism has been extensively tested, and works correctly for both "reset run" and "reset halt", which the latter halts very early in the BootROM. Change-Id: I5ced6eb3902d1b9d9c1bba56f817ec5dc3493cb0 Signed-off-by: Marek Kraus Reviewed-on: https://review.openocd.org/c/openocd/+/8407 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/bl702.cfg | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tcl/target/bl702.cfg diff --git a/tcl/target/bl702.cfg b/tcl/target/bl702.cfg new file mode 100644 index 0000000000..6d4a048d90 --- /dev/null +++ b/tcl/target/bl702.cfg @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Bouffalo Labs BL702, BL704 and BL706 target +# +# https://en.bouffalolab.com/product/?type=detail&id=8 +# +# Default JTAG pins: (if not changed by eFuse configuration) +# TMS - GPIO0 +# TDI - GPIO1 +# TCK - GPIO2 +# TDO - GPIO9 +# + +source [find mem_helper.tcl] + +transport select jtag + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME bl702 +} + +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000e05 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME + +riscv set_mem_access sysbus + +$_TARGETNAME configure -work-area-phys 0x22020000 -work-area-size 0x10000 -work-area-backup 1 + +# Internal RC ticks on 32 MHz, so this speed should be safe to use. +adapter speed 4000 + +$_TARGETNAME configure -event reset-assert-pre { + halt + + # Switch clock to internal RC32M + # In HBN_GLB, set ROOT_CLK_SEL = 0 + mmw 0x4000f030 0x0 0x00000003 + # Wait for clock switch + sleep 10 + + # GLB_REG_BCLK_DIS_FALSE + mww 0x40000ffc 0x0 + + # HCLK is RC32M, so BCLK/HCLK doesn't need divider + # In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0 + mmw 0x40000000 0x0 0x00FFFF00 + # Wait for clock to stabilize + sleep 10 + + # Do reset + # In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET + mmw 0x40000018 0x0 0x00000007 + # In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1 + mmw 0x40000018 0x6 0x0 +} From 13f9f29fa8ba9ad5a73a3bcf56708c47988e2c96 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 21 Jul 2024 13:00:08 +0200 Subject: [PATCH 0894/1312] checkpatch: extend checks to TCL, Makefile.am and configure.ac files The script, originally written for Linux code, skips several tests on files whose name's extension is not in Perl list '(h|c|s|S|sh|dtsi|dts)$'. This causes such tests to not be executed on OpenOCD TCL files and on Makefile.am and configure.ac. Modify the script to include the OpenOCD files in the list. Change-Id: I17c96bf32ee40d9390e60996e176e4e927c00197 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8408 Reviewed-by: Marek Kraus Tested-by: jenkins --- tools/scripts/checkpatch.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl index 9dda61cde0..26589beab0 100755 --- a/tools/scripts/checkpatch.pl +++ b/tools/scripts/checkpatch.pl @@ -3769,7 +3769,11 @@ sub process { } # check we are in a valid source file if not then ignore this hunk + if (!$OpenOCD) { next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); + } else { # !$OpenOCD + next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts|tcl|cfg|ac|am)$/); + } # !$OpenOCD # check for using SPDX-License-Identifier on the wrong line number if ($realline != $checklicenseline && From 4c77f942e1aba702cf49f70512e8f517db26825a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 21 Jul 2024 13:04:36 +0200 Subject: [PATCH 0895/1312] tcl: fix minor typos and repeated words Detected with checkpatch. Change-Id: Id306928496cf70bbe7ff065bf726bc7dceadce26 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8409 Tested-by: jenkins Reviewed-by: zapb --- tcl/board/at91sam9g20-ek.cfg | 4 ++-- tcl/board/netgear-wg102.cfg | 2 +- tcl/target/allwinner_v3s.cfg | 2 +- tcl/target/ampere_emag.cfg | 2 +- tcl/target/icepick.cfg | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tcl/board/at91sam9g20-ek.cfg b/tcl/board/at91sam9g20-ek.cfg index 4740471c89..22a38a7089 100644 --- a/tcl/board/at91sam9g20-ek.cfg +++ b/tcl/board/at91sam9g20-ek.cfg @@ -43,7 +43,7 @@ proc read_register {register} { proc at91sam9g20_reset_start { } { - # Make sure that the the jtag is running slow, since there are a number of different ways the board + # Make sure that the jtag is running slow, since there are a number of different ways the board # can be configured coming into this state that can cause communication problems with the jtag # adapter. Also since this call can be made following a "reset init" where fast memory accesses # are enabled, need to temporarily shut this down so that the RSTC_MR register can be written at slower @@ -202,7 +202,7 @@ proc at91sam9g20_reset_init { } { mww 0xffffea00 0x3 mww 0x20000000 0 - # Signal normal mode using the SDRAMC_MR register and follow with a zero value write the the starting + # Signal normal mode using the SDRAMC_MR register and follow with a zero value write the starting # memory location for the SDRAM. mww 0xffffea00 0x0 diff --git a/tcl/board/netgear-wg102.cfg b/tcl/board/netgear-wg102.cfg index 15f9c118af..0a7dad5ab2 100644 --- a/tcl/board/netgear-wg102.cfg +++ b/tcl/board/netgear-wg102.cfg @@ -27,7 +27,7 @@ $_TARGETNAME configure -event reset-init { # 0x00003800 - 0x07 << FLASHCTL_WST2_S # FLASHCTL_AC_8M 0x00060000 - Size of flash # FLASHCTL_E 0x00080000 - Flash bank enable (added) - # FLASHCTL_WP 0x04000000 - write protect. If used, CFI mode wont work!! + # FLASHCTL_WP 0x04000000 - write protect. If used, CFI mode won't work!! # FLASHCTL_MWx16 0x10000000 - 16bit mode. Do not use it!! # FLASHCTL_MWx8 0x00000000 - 8bit mode. mww 0xb8400000 0x000d3ce1 diff --git a/tcl/target/allwinner_v3s.cfg b/tcl/target/allwinner_v3s.cfg index 437bd956df..6c3435ed74 100644 --- a/tcl/target/allwinner_v3s.cfg +++ b/tcl/target/allwinner_v3s.cfg @@ -28,7 +28,7 @@ # UART2_TX PB0 Per default disabled # UART2_RX PB1 Per default disabled # -# JTAG is enabled by default after power on on listed JTAG_* pins. So far the +# JTAG is enabled by default after power-on on listed JTAG_* pins. So far the # boot sequence is: # Time Action # 0000ms Power ON diff --git a/tcl/target/ampere_emag.cfg b/tcl/target/ampere_emag.cfg index 0b0bd9e88d..fd68fcd482 100644 --- a/tcl/target/ampere_emag.cfg +++ b/tcl/target/ampere_emag.cfg @@ -8,7 +8,7 @@ # # Configure defaults for target -# Can be overriden in board configuration file +# Can be overridden in board configuration file # if { [info exists CHIPNAME] } { diff --git a/tcl/target/icepick.cfg b/tcl/target/icepick.cfg index 5509532111..e5d5706f02 100644 --- a/tcl/target/icepick.cfg +++ b/tcl/target/icepick.cfg @@ -6,7 +6,7 @@ # # Utilities for TI ICEpick-C/D used in most TI SoCs -# Details about the ICEPick are available in the the TRM for each SoC +# Details about the ICEPick are available in the TRM for each SoC # and http://processors.wiki.ti.com/index.php/ICEPICK # create "constants" From 5543bb4a90cd49940817a70a82c996df68d60282 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 21 Jul 2024 13:06:58 +0200 Subject: [PATCH 0896/1312] doc: Makefile.am: add SPDX license Add the SPDX tag line. Change-Id: Iffe73faaf20614f9e5237b7afba3c580dfa03a9e Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8410 Tested-by: jenkins --- doc/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/Makefile.am b/doc/Makefile.am index 67592038d5..17d051ff87 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + info_TEXINFOS += %D%/openocd.texi %C%_openocd_TEXINFOS = %D%/fdl.texi From 882749dd2f4afe3758daf40d8b501c1af5166fa8 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 21 Jul 2024 13:07:47 +0200 Subject: [PATCH 0897/1312] uncrustify.cfg: add SPDX license Add the SPDX tag line. Change-Id: I701580948a0cacdb7fe31d91ed730e848da9b0ba Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8411 Reviewed-by: zapb Tested-by: jenkins --- uncrustify.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/uncrustify.cfg b/uncrustify.cfg index 07d097818a..593bcc2adf 100644 --- a/uncrustify.cfg +++ b/uncrustify.cfg @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + tok_split_gte=false utf8_byte=false utf8_force=false From 632df9e5cbf27f8c5f5d2633918af53c6b80d970 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 17 Jul 2024 15:11:46 +0200 Subject: [PATCH 0898/1312] jtag: Use bool data type for 'jtag_verify' Change-Id: Iae46e45c7523252eee44224e6b9b3b1484aaeb35 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8401 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index c84d5aa3d3..c8f20b73c6 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -88,7 +88,7 @@ static enum reset_types jtag_reset_config = RESET_NONE; tap_state_t cmd_queue_cur_state = TAP_RESET; static bool jtag_verify_capture_ir = true; -static int jtag_verify = 1; +static bool jtag_verify = true; /* how long the OpenOCD should wait before attempting JTAG communication after reset lines *deasserted (in ms) */ From 4fac13827feaf95554a54719278fbd890df40c67 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 17 Jul 2024 16:48:14 +0200 Subject: [PATCH 0899/1312] jtag: Use 'unsigned int' for 'abs_chain_position' Change-Id: I1ac0a6a86f820b051619aa132754a69b8f8e0ab9 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8402 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/core.c | 4 ++-- src/jtag/jtag.h | 4 ++-- src/jtag/tcl.c | 2 +- src/target/riscv/riscv-013.c | 4 ++-- src/target/xtensa/xtensa_chip.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index c8f20b73c6..939199462e 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -212,7 +212,7 @@ unsigned jtag_tap_count_enabled(void) /** Append a new TAP to the chain of all taps. */ static void jtag_tap_add(struct jtag_tap *t) { - unsigned jtag_num_taps = 0; + unsigned int jtag_num_taps = 0; struct jtag_tap **tap = &__jtag_all_taps; while (*tap) { @@ -1471,7 +1471,7 @@ void jtag_tap_init(struct jtag_tap *tap) jtag_register_event_callback(&jtag_reset_callback, tap); jtag_tap_add(tap); - LOG_DEBUG("Created Tap: %s @ abs position %d, " + LOG_DEBUG("Created Tap: %s @ abs position %u, " "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name, tap->abs_chain_position, tap->ir_length, (unsigned) tap->ir_capture_value, diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 470ae18334..46ab584d92 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -102,7 +102,7 @@ struct jtag_tap { char *chip; char *tapname; char *dotted_name; - int abs_chain_position; + unsigned int abs_chain_position; /** Is this TAP disabled after JTAG reset? */ bool disabled_after_reset; /** Is this TAP currently enabled? */ @@ -150,7 +150,7 @@ struct jtag_tap *jtag_all_taps(void); const char *jtag_tap_name(const struct jtag_tap *tap); struct jtag_tap *jtag_tap_by_string(const char *dotted_name); struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj); -struct jtag_tap *jtag_tap_by_position(unsigned abs_position); +struct jtag_tap *jtag_tap_by_position(unsigned int abs_position); struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p); unsigned jtag_tap_count_enabled(void); unsigned jtag_tap_count(void); diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index e534134276..7e4d6725ab 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -814,7 +814,7 @@ COMMAND_HANDLER(handle_scan_chain_command) expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length); command_print(CMD, - "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x", + "%2u %-18s %c 0x%08x %s %5d 0x%02x 0x%02x", tap->abs_chain_position, tap->dotted_name, tap->enabled ? 'Y' : 'n', diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 2f4a8fe2e6..0aa82031cd 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -132,7 +132,7 @@ typedef enum { typedef struct { struct list_head list; - int abs_chain_position; + unsigned int abs_chain_position; /* The number of harts connected to this DM. */ int hart_count; @@ -236,7 +236,7 @@ static dm013_info_t *get_dm(struct target *target) if (info->dm) return info->dm; - int abs_chain_position = target->tap->abs_chain_position; + unsigned int abs_chain_position = target->tap->abs_chain_position; dm013_info_t *entry; dm013_info_t *dm = NULL; diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index ac4a49ccf4..ce6d35cabf 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -103,7 +103,7 @@ static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp) LOG_DEBUG("DAP: ap_num %" PRId64 " DAP %p\n", pc->ap_num, pc->dap); } else { xtensa_chip_dm_cfg.tap = target->tap; - LOG_DEBUG("JTAG: %s:%s pos %d", target->tap->chip, target->tap->tapname, + LOG_DEBUG("JTAG: %s:%s pos %u", target->tap->chip, target->tap->tapname, target->tap->abs_chain_position); } From 42450345dd0cc2eb9fb18d8f794a6b57107bb242 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 17 Jul 2024 16:59:51 +0200 Subject: [PATCH 0900/1312] jtag: Use 'unsigned int' for 'ir_length' This patch modifies as little code as possible in order to simplify the review. Data types that are affected by these changes will be modified in following patches. Change-Id: I83921d70e017095d63547e0bc9fe61779191d9d0 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8403 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/core.c | 4 ++-- src/jtag/jtag.h | 2 +- src/jtag/tcl.c | 12 ++++++------ src/target/avrt.c | 2 +- src/target/lakemont.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index 939199462e..9aa755769b 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1396,7 +1396,7 @@ static int jtag_validate_ircapture(void) && tap->ir_length < JTAG_IRLEN_MAX) { tap->ir_length++; } - LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %d " + LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %u " "-expected-id 0x%08" PRIx32 "\"", tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode); } @@ -1472,7 +1472,7 @@ void jtag_tap_init(struct jtag_tap *tap) jtag_tap_add(tap); LOG_DEBUG("Created Tap: %s @ abs position %u, " - "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name, + "irlen %u, capture: 0x%x mask: 0x%x", tap->dotted_name, tap->abs_chain_position, tap->ir_length, (unsigned) tap->ir_capture_value, (unsigned) tap->ir_capture_mask); diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 46ab584d92..76bfdf157b 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -107,7 +107,7 @@ struct jtag_tap { bool disabled_after_reset; /** Is this TAP currently enabled? */ bool enabled; - int ir_length; /**< size of instruction register */ + unsigned int ir_length; /**< size of instruction register */ uint32_t ir_capture_value; uint8_t *expected; /**< Capture-IR expected value */ uint32_t ir_capture_mask; diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 7e4d6725ab..4bfbeeb420 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -448,11 +448,11 @@ static COMMAND_HELPER(handle_jtag_newtap_args, struct jtag_tap *tap) if (!CMD_ARGC) return ERROR_COMMAND_ARGUMENT_INVALID; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tap->ir_length); + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], tap->ir_length); CMD_ARGC--; CMD_ARGV++; - if (tap->ir_length > (int)(8 * sizeof(tap->ir_capture_value))) - LOG_WARNING("%s: huge IR length %d", tap->dotted_name, tap->ir_length); + if (tap->ir_length > (8 * sizeof(tap->ir_capture_value))) + LOG_WARNING("%s: huge IR length %u", tap->dotted_name, tap->ir_length); break; case NTAP_OPT_IRMASK: @@ -814,13 +814,13 @@ COMMAND_HANDLER(handle_scan_chain_command) expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length); command_print(CMD, - "%2u %-18s %c 0x%08x %s %5d 0x%02x 0x%02x", + "%2u %-18s %c 0x%08x %s %5u 0x%02x 0x%02x", tap->abs_chain_position, tap->dotted_name, tap->enabled ? 'Y' : 'n', (unsigned int)(tap->idcode), expected_id, - (unsigned int)(tap->ir_length), + tap->ir_length, (unsigned int)(expected), (unsigned int)(expected_mask)); @@ -972,7 +972,7 @@ COMMAND_HANDLER(handle_irscan_command) if (retval != ERROR_OK) goto error_return; - int field_size = tap->ir_length; + unsigned int field_size = tap->ir_length; fields[i].num_bits = field_size; uint8_t *v = calloc(1, DIV_ROUND_UP(field_size, 8)); if (!v) { diff --git a/src/target/avrt.c b/src/target/avrt.c index 61bef329fe..ccce7e5e52 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -153,7 +153,7 @@ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, LOG_ERROR("invalid tap"); return ERROR_FAIL; } - if (ir_len != tap->ir_length) { + if ((unsigned int)ir_len != tap->ir_length) { LOG_ERROR("invalid ir_len"); return ERROR_FAIL; } diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 6c0964bfaa..1fcd6426ae 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -224,10 +224,10 @@ static int irscan(struct target *t, uint8_t *out, if (ir_len != t->tap->ir_length) { retval = ERROR_FAIL; if (t->tap->enabled) - LOG_ERROR("%s tap enabled but tap irlen=%d", + LOG_ERROR("%s tap enabled but tap irlen=%u", __func__, t->tap->ir_length); else - LOG_ERROR("%s tap not enabled and irlen=%d", + LOG_ERROR("%s tap not enabled and irlen=%u", __func__, t->tap->ir_length); return retval; } From 0847a4d7fb9809a9bb36ba0965f43cb9d43ca2f3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 17 Jul 2024 17:35:42 +0200 Subject: [PATCH 0901/1312] jtag/commands: Use 'unsigned int' data type This patch modifies as little code as possible in order to simplify the review. Data types that are affected by these changes will be addresses in following patches. While at it, apply coding style fixes if these are not too extensive. Change-Id: Ie048b3d472f546fecb6733f17f9d0f17fda40187 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8404 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/commands.c | 20 ++++++--------- src/jtag/commands.h | 10 ++++---- src/jtag/core.c | 10 ++++---- src/jtag/drivers/amt_jtagaccel.c | 2 +- src/jtag/drivers/angie.c | 11 ++++---- src/jtag/drivers/arm-jtag-ew.c | 20 ++++++--------- src/jtag/drivers/bitbang.c | 21 +++++++--------- src/jtag/drivers/bitq.c | 19 ++++++-------- src/jtag/drivers/buspirate.c | 29 +++++++++------------- src/jtag/drivers/cmsis_dap.c | 18 +++++++------- src/jtag/drivers/driver.c | 8 +++--- src/jtag/drivers/ft232r.c | 18 ++++++-------- src/jtag/drivers/ftdi.c | 23 ++++++++--------- src/jtag/drivers/gw16012.c | 7 +++--- src/jtag/drivers/jlink.c | 27 +++++++++----------- src/jtag/drivers/jtag_dpi.c | 10 ++++---- src/jtag/drivers/jtag_vpi.c | 12 ++++----- src/jtag/drivers/opendous.c | 20 ++++++--------- src/jtag/drivers/openjtag.c | 10 +++++--- src/jtag/drivers/osbdm.c | 12 ++++----- src/jtag/drivers/rlink.c | 10 +++----- src/jtag/drivers/ulink.c | 11 ++++---- src/jtag/drivers/usb_blaster/usb_blaster.c | 18 ++++++-------- src/jtag/drivers/usbprog.c | 14 +++++------ src/jtag/drivers/vdebug.c | 20 +++++++-------- src/jtag/drivers/vsllink.c | 20 +++++++-------- src/jtag/drivers/xds110.c | 12 ++++----- src/jtag/drivers/xlnx-pcie-xvc.c | 11 ++++---- src/jtag/jtag.h | 6 ++--- src/jtag/minidriver.h | 6 ++--- src/target/esirisc_jtag.c | 5 ++-- 31 files changed, 201 insertions(+), 239 deletions(-) diff --git a/src/jtag/commands.c b/src/jtag/commands.c index a60684c880..c679c56c5c 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -166,10 +166,9 @@ void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src) enum scan_type jtag_scan_type(const struct scan_command *cmd) { - int i; int type = 0; - for (i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].in_value) type |= SCAN_IN; if (cmd->fields[i].out_value) @@ -182,10 +181,9 @@ enum scan_type jtag_scan_type(const struct scan_command *cmd) int jtag_scan_size(const struct scan_command *cmd) { int bit_count = 0; - int i; /* count bits in scan command */ - for (i = 0; i < cmd->num_fields; i++) + for (unsigned int i = 0; i < cmd->num_fields; i++) bit_count += cmd->fields[i].num_bits; return bit_count; @@ -194,18 +192,17 @@ int jtag_scan_size(const struct scan_command *cmd) int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) { int bit_count = 0; - int i; bit_count = jtag_scan_size(cmd); *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8)); bit_count = 0; - LOG_DEBUG_IO("%s num_fields: %i", + LOG_DEBUG_IO("%s num_fields: %u", cmd->ir_scan ? "IRSCAN" : "DRSCAN", cmd->num_fields); - for (i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].out_value) { if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) { char *char_buf = buf_to_hex_str(cmd->fields[i].out_value, @@ -213,14 +210,14 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits); - LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, + LOG_DEBUG("fields[%u].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf); free(char_buf); } buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); } else { - LOG_DEBUG_IO("fields[%i].out_value[%i]: NULL", + LOG_DEBUG_IO("fields[%u].out_value[%i]: NULL", i, cmd->fields[i].num_bits); } @@ -234,14 +231,13 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) { - int i; int bit_count = 0; int retval; /* we return ERROR_OK, unless a check fails, or a handler reports a problem */ retval = ERROR_OK; - for (i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { /* if neither in_value nor in_handler * are specified we don't have to examine this field */ @@ -256,7 +252,7 @@ int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) ? DEBUG_JTAG_IOZ : num_bits); - LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", + LOG_DEBUG("fields[%u].in_value[%i]: 0x%s", i, num_bits, char_buf); free(char_buf); } diff --git a/src/jtag/commands.h b/src/jtag/commands.h index 825907733f..885e6a3608 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -36,7 +36,7 @@ struct scan_command { /** instruction/not data scan */ bool ir_scan; /** number of fields in *fields array */ - int num_fields; + unsigned int num_fields; /** pointer to an array of data scan fields */ struct scan_field *fields; /** state in which JTAG commands should finish */ @@ -50,14 +50,14 @@ struct statemove_command { struct pathmove_command { /** number of states in *path */ - int num_states; + unsigned int num_states; /** states that have to be passed */ tap_state_t *path; }; struct runtest_command { /** number of cycles to spend in Run-Test/Idle state */ - int num_cycles; + unsigned int num_cycles; /** state in which JTAG commands should finish */ tap_state_t end_state; }; @@ -65,7 +65,7 @@ struct runtest_command { struct stableclocks_command { /** number of clock cycles that should be sent */ - int num_cycles; + unsigned int num_cycles; }; @@ -100,7 +100,7 @@ struct sleep_command { */ struct tms_command { /** How many bits should be clocked out. */ - unsigned num_bits; + unsigned int num_bits; /** The bits to clock out; the LSB is bit 0 of bits[0]. */ const uint8_t *bits; }; diff --git a/src/jtag/core.c b/src/jtag/core.c index 9aa755769b..a8190dd23c 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -514,7 +514,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) return retval; } -void jtag_add_pathmove(int num_states, const tap_state_t *path) +void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path) { tap_state_t cur_state = cmd_queue_cur_state; @@ -525,7 +525,7 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) return; } - for (int i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == TAP_RESET) { LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences"); jtag_set_error(ERROR_JTAG_STATE_INVALID); @@ -589,14 +589,14 @@ int jtag_add_statemove(tap_state_t goal_state) return ERROR_OK; } -void jtag_add_runtest(int num_cycles, tap_state_t state) +void jtag_add_runtest(unsigned int num_cycles, tap_state_t state) { jtag_prelude(state); jtag_set_error(interface_jtag_add_runtest(num_cycles, state)); } -void jtag_add_clocks(int num_cycles) +void jtag_add_clocks(unsigned int num_cycles) { if (!tap_is_state_stable(cmd_queue_cur_state)) { LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"", @@ -960,7 +960,7 @@ int default_interface_jtag_execute_queue(void) LOG_DEBUG_IO("JTAG %s SCAN to %s", cmd->cmd.scan->ir_scan ? "IR" : "DR", tap_state_name(cmd->cmd.scan->end_state)); - for (int i = 0; i < cmd->cmd.scan->num_fields; i++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) { struct scan_field *field = cmd->cmd.scan->fields + i; if (field->out_value) { char *str = buf_to_hex_str(field->out_value, field->num_bits); diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index b28ce62ffb..489cb24713 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -203,7 +203,7 @@ static void amt_jtagaccel_state_move(void) tap_set_state(end_state); } -static void amt_jtagaccel_runtest(int num_cycles) +static void amt_jtagaccel_runtest(unsigned int num_cycles) { int i = 0; uint8_t aw_scan_tms_5; diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 81dd1af82a..47628fef74 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -1836,15 +1836,17 @@ static int angie_reset(int trst, int srst) */ static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd) { - int ret, i, num_states, batch_size, state_count; + int ret, state_count; tap_state_t *path; uint8_t tms_sequence; - num_states = cmd->cmd.pathmove->num_states; + unsigned int num_states = cmd->cmd.pathmove->num_states; path = cmd->cmd.pathmove->path; state_count = 0; while (num_states > 0) { + unsigned int batch_size; + tms_sequence = 0; /* Determine batch size */ @@ -1853,7 +1855,7 @@ static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd) else batch_size = num_states; - for (i = 0; i < batch_size; i++) { + for (unsigned int i = 0; i < batch_size; i++) { if (tap_state_transition(tap_get_state(), false) == path[state_count]) { /* Append '0' transition: clear bit 'i' in tms_sequence */ buf_set_u32(&tms_sequence, i, 1, 0x0); @@ -1908,14 +1910,13 @@ static int angie_queue_sleep(struct angie *device, struct jtag_command *cmd) static int angie_queue_stableclocks(struct angie *device, struct jtag_command *cmd) { int ret; - unsigned int num_cycles; if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("JTAG_STABLECLOCKS: state not stable"); return ERROR_FAIL; } - num_cycles = cmd->cmd.stableclocks->num_cycles; + unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles; /* TMS stays either high (Test Logic Reset state) or low (all other states) */ if (tap_get_state() == TAP_RESET) diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index 4c50c54c9b..aaed16db6e 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -44,8 +44,8 @@ static uint8_t usb_out_buffer[ARMJTAGEW_OUT_BUFFER_SIZE]; /* Queue command functions */ static void armjtagew_end_state(tap_state_t state); static void armjtagew_state_move(void); -static void armjtagew_path_move(int num_states, tap_state_t *path); -static void armjtagew_runtest(int num_cycles); +static void armjtagew_path_move(unsigned int num_states, tap_state_t *path); +static void armjtagew_runtest(unsigned int num_cycles); static void armjtagew_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, @@ -95,7 +95,7 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); @@ -111,7 +111,7 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -279,11 +279,9 @@ static void armjtagew_state_move(void) tap_set_state(tap_get_end_state()); } -static void armjtagew_path_move(int num_states, tap_state_t *path) +static void armjtagew_path_move(unsigned int num_states, tap_state_t *path) { - int i; - - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { /* * TODO: The ARM-JTAG-EW hardware delays TDI with 3 TCK cycles when in RTCK mode. * Either handle that here, or update the documentation with examples @@ -305,10 +303,8 @@ static void armjtagew_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void armjtagew_runtest(int num_cycles) +static void armjtagew_runtest(unsigned int num_cycles) { - int i; - tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ @@ -318,7 +314,7 @@ static void armjtagew_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) armjtagew_tap_append_step(0, 0); /* finish in end_state */ diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 3d839e65de..e41659263c 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -33,7 +33,7 @@ * this function checks the current stable state to decide on the value of TMS * to use. */ -static int bitbang_stableclocks(int num_cycles); +static int bitbang_stableclocks(unsigned int num_cycles); static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk); @@ -95,7 +95,7 @@ static int bitbang_execute_tms(struct jtag_command *cmd) unsigned num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; - LOG_DEBUG_IO("TMS: %d bits", num_bits); + LOG_DEBUG_IO("TMS: %u bits", num_bits); int tms = 0; for (unsigned i = 0; i < num_bits; i++) { @@ -113,7 +113,7 @@ static int bitbang_execute_tms(struct jtag_command *cmd) static int bitbang_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; int tms = 0; @@ -147,10 +147,8 @@ static int bitbang_path_move(struct pathmove_command *cmd) return ERROR_OK; } -static int bitbang_runtest(int num_cycles) +static int bitbang_runtest(unsigned int num_cycles) { - int i; - tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ @@ -161,7 +159,7 @@ static int bitbang_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { if (bitbang_interface->write(0, 0, 0) != ERROR_OK) return ERROR_FAIL; if (bitbang_interface->write(1, 0, 0) != ERROR_OK) @@ -179,13 +177,12 @@ static int bitbang_runtest(int num_cycles) return ERROR_OK; } -static int bitbang_stableclocks(int num_cycles) +static int bitbang_stableclocks(unsigned int num_cycles) { int tms = (tap_get_state() == TAP_RESET ? 1 : 0); - int i; /* send num_cycles clocks onto the cable */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { if (bitbang_interface->write(1, tms, 0) != ERROR_OK) return ERROR_FAIL; if (bitbang_interface->write(0, tms, 0) != ERROR_OK) @@ -319,7 +316,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); bitbang_end_state(cmd->cmd.runtest->end_state); @@ -343,7 +340,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) return ERROR_FAIL; break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK) diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c index 2e5cca2a49..6816b9b86f 100644 --- a/src/jtag/drivers/bitq.c +++ b/src/jtag/drivers/bitq.c @@ -18,7 +18,7 @@ struct bitq_interface *bitq_interface; /* low level bit queue interface */ /* state of input queue */ struct bitq_state { struct jtag_command *cmd; /* command currently processed */ - int field_idx; /* index of field currently being processed */ + unsigned int field_idx; /* index of field currently being processed */ int bit_pos; /* position of bit currently being processed */ int status; /* processing status */ }; @@ -108,9 +108,7 @@ static void bitq_state_move(tap_state_t new_state) static void bitq_path_move(struct pathmove_command *cmd) { - int i; - - for (i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) bitq_io(0, 0, 0); else if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) @@ -127,16 +125,14 @@ static void bitq_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void bitq_runtest(int num_cycles) +static void bitq_runtest(unsigned int num_cycles) { - int i; - /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) bitq_state_move(TAP_IDLE); /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) bitq_io(0, 0, 0); /* finish in end_state */ @@ -190,13 +186,12 @@ static void bitq_scan_field(struct scan_field *field, int do_pause) static void bitq_scan(struct scan_command *cmd) { - int i; - if (cmd->ir_scan) bitq_state_move(TAP_IRSHIFT); else bitq_state_move(TAP_DRSHIFT); + unsigned int i; for (i = 0; i < cmd->num_fields - 1; i++) bitq_scan_field(&cmd->fields[i], 0); @@ -226,7 +221,7 @@ int bitq_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); bitq_end_state(cmd->cmd.runtest->end_state); bitq_runtest(cmd->cmd.runtest->num_cycles); break; @@ -238,7 +233,7 @@ int bitq_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); bitq_path_move(cmd->cmd.pathmove); break; diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index 3b03337c94..b01a796442 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -27,11 +27,11 @@ static int buspirate_reset(int trst, int srst); static void buspirate_end_state(tap_state_t state); static void buspirate_state_move(void); -static void buspirate_path_move(int num_states, tap_state_t *path); -static void buspirate_runtest(int num_cycles); +static void buspirate_path_move(unsigned int num_states, tap_state_t *path); +static void buspirate_runtest(unsigned int num_cycles); static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); -static void buspirate_stableclocks(int num_cycles); +static void buspirate_stableclocks(unsigned int num_cycles); #define CMD_UNKNOWN 0x00 #define CMD_PORT_MODE 0x01 @@ -162,7 +162,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest ->end_state)); @@ -180,7 +180,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue) buspirate_state_move(); break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove ->path[cmd->cmd.pathmove @@ -210,7 +210,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue) jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_STABLECLOCKS: - LOG_DEBUG_IO("stable clock %i cycles", cmd->cmd.stableclocks->num_cycles); + LOG_DEBUG_IO("stable clock %u cycles", cmd->cmd.stableclocks->num_cycles); buspirate_stableclocks(cmd->cmd.stableclocks->num_cycles); break; default: @@ -580,11 +580,9 @@ static void buspirate_state_move(void) tap_set_state(tap_get_end_state()); } -static void buspirate_path_move(int num_states, tap_state_t *path) +static void buspirate_path_move(unsigned int num_states, tap_state_t *path) { - int i; - - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), false) == path[i]) { buspirate_tap_append(0, 0); } else if (tap_state_transition(tap_get_state(), true) @@ -604,10 +602,8 @@ static void buspirate_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void buspirate_runtest(int num_cycles) +static void buspirate_runtest(unsigned int num_cycles) { - int i; - tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ @@ -616,7 +612,7 @@ static void buspirate_runtest(int num_cycles) buspirate_state_move(); } - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) buspirate_tap_append(0, 0); LOG_DEBUG_IO("runtest: cur_state %s end_state %s", @@ -658,14 +654,13 @@ static void buspirate_scan(bool ir_scan, enum scan_type type, buspirate_state_move(); } -static void buspirate_stableclocks(int num_cycles) +static void buspirate_stableclocks(unsigned int num_cycles) { - int i; int tms = (tap_get_state() == TAP_RESET ? 1 : 0); buspirate_tap_make_space(0, num_cycles); - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) buspirate_tap_append(tms, 0); } diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index d7367d8137..243b01c63b 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -1752,7 +1752,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) LOG_DEBUG("discarding trailing empty field"); } - if (cmd->cmd.scan->num_fields == 0) { + if (!cmd->cmd.scan->num_fields) { LOG_DEBUG("empty scan, doing nothing"); return; } @@ -1774,9 +1774,9 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) struct scan_field *field = cmd->cmd.scan->fields; unsigned scan_size = 0; - for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %d bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -1872,16 +1872,16 @@ static void cmsis_dap_execute_pathmove(struct jtag_command *cmd) cmsis_dap_pathmove(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); } -static void cmsis_dap_stableclocks(int num_cycles) +static void cmsis_dap_stableclocks(unsigned int num_cycles) { uint8_t tms = tap_get_state() == TAP_RESET; /* TODO: Perform optimizations? */ /* Execute num_cycles. */ - for (int i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) cmsis_dap_add_tms_sequence(&tms, 1); } -static void cmsis_dap_runtest(int num_cycles) +static void cmsis_dap_runtest(unsigned int num_cycles) { tap_state_t saved_end_state = tap_get_end_state(); @@ -1901,7 +1901,7 @@ static void cmsis_dap_runtest(int num_cycles) static void cmsis_dap_execute_runtest(struct jtag_command *cmd) { - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); cmsis_dap_end_state(cmd->cmd.runtest->end_state); @@ -1910,13 +1910,13 @@ static void cmsis_dap_execute_runtest(struct jtag_command *cmd) static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd) { - LOG_DEBUG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + LOG_DEBUG_IO("stableclocks %u cycles", cmd->cmd.runtest->num_cycles); cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles); } static void cmsis_dap_execute_tms(struct jtag_command *cmd) { - LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits); + LOG_DEBUG_IO("TMS: %u bits", cmd->cmd.tms->num_bits); cmsis_dap_cmd_dap_swj_sequence(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits); } diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index e52816d3ab..2aad4a0c13 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -259,7 +259,7 @@ int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state return ERROR_OK; } -int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) +int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -272,13 +272,13 @@ int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) cmd->cmd.pathmove->num_states = num_states; cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states); - for (int i = 0; i < num_states; i++) + for (unsigned int i = 0; i < num_states; i++) cmd->cmd.pathmove->path[i] = path[i]; return ERROR_OK; } -int interface_jtag_add_runtest(int num_cycles, tap_state_t state) +int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t state) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -294,7 +294,7 @@ int interface_jtag_add_runtest(int num_cycles, tap_state_t state) return ERROR_OK; } -int interface_jtag_add_clocks(int num_cycles) +int interface_jtag_add_clocks(unsigned int num_cycles) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index 766f6ddb5d..a4d072cd77 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -657,7 +657,7 @@ static int syncbb_execute_tms(struct jtag_command *cmd) unsigned num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; - LOG_DEBUG_IO("TMS: %d bits", num_bits); + LOG_DEBUG_IO("TMS: %u bits", num_bits); int tms = 0; for (unsigned i = 0; i < num_bits; i++) { @@ -672,7 +672,7 @@ static int syncbb_execute_tms(struct jtag_command *cmd) static void syncbb_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; int tms = 0; @@ -702,9 +702,8 @@ static void syncbb_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void syncbb_runtest(int num_cycles) +static void syncbb_runtest(unsigned int num_cycles) { - int i; tap_state_t saved_end_state = tap_get_end_state(); @@ -715,7 +714,7 @@ static void syncbb_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { ft232r_write(0, 0, 0); ft232r_write(1, 0, 0); } @@ -735,13 +734,12 @@ static void syncbb_runtest(int num_cycles) * this function checks the current stable state to decide on the value of TMS * to use. */ -static void syncbb_stableclocks(int num_cycles) +static void syncbb_stableclocks(unsigned int num_cycles) { int tms = (tap_get_state() == TAP_RESET ? 1 : 0); - int i; /* send num_cycles clocks onto the cable */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { ft232r_write(1, tms, 0); ft232r_write(0, tms, 0); } @@ -832,7 +830,7 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); syncbb_end_state(cmd->cmd.runtest->end_state); @@ -854,7 +852,7 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); syncbb_path_move(cmd->cmd.pathmove); diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 661300506c..4f253fa6d9 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -311,10 +311,9 @@ static void ftdi_end_state(tap_state_t state) static void ftdi_execute_runtest(struct jtag_command *cmd) { - int i; uint8_t zero = 0; - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); @@ -322,7 +321,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd) move_to_state(TAP_IDLE); /* TODO: Reuse ftdi_execute_stableclocks */ - i = cmd->cmd.runtest->num_cycles; + unsigned int i = cmd->cmd.runtest->num_cycles; while (i > 0) { /* there are no state transitions in this code, so omit state tracking */ unsigned this_len = i > 7 ? 7 : i; @@ -335,7 +334,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd) if (tap_get_state() != tap_get_end_state()) move_to_state(tap_get_end_state()); - LOG_DEBUG_IO("runtest: %i, end in %s", + LOG_DEBUG_IO("runtest: %u, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(tap_get_end_state())); } @@ -358,7 +357,7 @@ static void ftdi_execute_statemove(struct jtag_command *cmd) */ static void ftdi_execute_tms(struct jtag_command *cmd) { - LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits); + LOG_DEBUG_IO("TMS: %u bits", cmd->cmd.tms->num_bits); /* TODO: Missing tap state tracking, also missing from ft2232.c! */ mpsse_clock_tms_cs_out(mpsse_ctx, @@ -372,9 +371,9 @@ static void ftdi_execute_tms(struct jtag_command *cmd) static void ftdi_execute_pathmove(struct jtag_command *cmd) { tap_state_t *path = cmd->cmd.pathmove->path; - int num_states = cmd->cmd.pathmove->num_states; + unsigned int num_states = cmd->cmd.pathmove->num_states; - LOG_DEBUG_IO("pathmove: %i states, current: %s end: %s", num_states, + LOG_DEBUG_IO("pathmove: %u states, current: %s end: %s", num_states, tap_state_name(tap_get_state()), tap_state_name(path[num_states-1])); @@ -432,7 +431,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd) LOG_DEBUG_IO("discarding trailing empty field"); } - if (cmd->cmd.scan->num_fields == 0) { + if (!cmd->cmd.scan->num_fields) { LOG_DEBUG_IO("empty scan, doing nothing"); return; } @@ -450,9 +449,9 @@ static void ftdi_execute_scan(struct jtag_command *cmd) struct scan_field *field = cmd->cmd.scan->fields; unsigned scan_size = 0; - for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %d bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -576,7 +575,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd) /* this is only allowed while in a stable state. A check for a stable * state was done in jtag_add_clocks() */ - int num_cycles = cmd->cmd.stableclocks->num_cycles; + unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles; /* 7 bits of either ones or zeros. */ uint8_t tms = tap_get_state() == TAP_RESET ? 0x7f : 0x00; @@ -590,7 +589,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd) num_cycles -= this_len; } - LOG_DEBUG_IO("clocks %i while in %s", + LOG_DEBUG_IO("clocks %u while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name(tap_get_state())); } diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index a4c6fd0f00..d0fe43fdb1 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -185,10 +185,9 @@ static void gw16012_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void gw16012_runtest(int num_cycles) +static void gw16012_runtest(unsigned int num_cycles) { tap_state_t saved_end_state = tap_get_end_state(); - int i; /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -196,7 +195,7 @@ static void gw16012_runtest(int num_cycles) gw16012_state_move(); } - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { gw16012_control(0x0); /* single-bit mode */ gw16012_data(0x0); /* TMS cycle with TMS low */ } @@ -292,7 +291,7 @@ static int gw16012_execute_queue(struct jtag_command *cmd_queue) gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); gw16012_end_state(cmd->cmd.runtest->end_state); gw16012_runtest(cmd->cmd.runtest->num_cycles); diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 1874557dcd..ff39167359 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -80,9 +80,9 @@ static struct device_config tmp_config; /* Queue command functions */ static void jlink_end_state(tap_state_t state); static void jlink_state_move(void); -static void jlink_path_move(int num_states, tap_state_t *path); -static void jlink_stableclocks(int num_cycles); -static void jlink_runtest(int num_cycles); +static void jlink_path_move(unsigned int num_states, tap_state_t *path); +static void jlink_stableclocks(unsigned int num_cycles); +static void jlink_runtest(unsigned int num_cycles); static void jlink_reset(int trst, int srst); static int jlink_reset_safe(int trst, int srst); static int jlink_swd_run_queue(void); @@ -140,7 +140,7 @@ static void jlink_execute_statemove(struct jtag_command *cmd) static void jlink_execute_pathmove(struct jtag_command *cmd) { - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -159,7 +159,7 @@ static void jlink_execute_scan(struct jtag_command *cmd) LOG_DEBUG("discarding trailing empty field"); } - if (cmd->cmd.scan->num_fields == 0) { + if (!cmd->cmd.scan->num_fields) { LOG_DEBUG("empty scan, doing nothing"); return; } @@ -181,9 +181,9 @@ static void jlink_execute_scan(struct jtag_command *cmd) struct scan_field *field = cmd->cmd.scan->fields; unsigned scan_size = 0; - for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %d bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -885,12 +885,11 @@ static void jlink_state_move(void) tap_set_state(tap_get_end_state()); } -static void jlink_path_move(int num_states, tap_state_t *path) +static void jlink_path_move(unsigned int num_states, tap_state_t *path) { - int i; uint8_t tms = 0xff; - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) jlink_clock_data(NULL, 0, NULL, 0, NULL, 0, 1); else if (path[i] == tap_state_transition(tap_get_state(), true)) @@ -907,17 +906,15 @@ static void jlink_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void jlink_stableclocks(int num_cycles) +static void jlink_stableclocks(unsigned int num_cycles) { - int i; - uint8_t tms = tap_get_state() == TAP_RESET; /* Execute num_cycles. */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1); } -static void jlink_runtest(int num_cycles) +static void jlink_runtest(unsigned int num_cycles) { tap_state_t saved_end_state = tap_get_end_state(); diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c index 285f96e4bf..046186a619 100644 --- a/src/jtag/drivers/jtag_dpi.c +++ b/src/jtag/drivers/jtag_dpi.c @@ -163,7 +163,7 @@ static int jtag_dpi_scan(struct scan_command *cmd) return ret; } -static int jtag_dpi_runtest(int cycles) +static int jtag_dpi_runtest(unsigned int num_cycles) { char buf[20]; uint8_t *data_buf = last_ir_buf, *read_scan; @@ -189,7 +189,7 @@ static int jtag_dpi_runtest(int cycles) return ERROR_FAIL; } snprintf(buf, sizeof(buf), "ib %d\n", num_bits); - while (cycles > 0) { + while (num_cycles > 0) { ret = write_sock(buf, strlen(buf)); if (ret != ERROR_OK) { LOG_ERROR("write_sock() fail, file %s, line %d", @@ -209,7 +209,7 @@ static int jtag_dpi_runtest(int cycles) goto out; } - cycles -= num_bits + 6; + num_cycles -= num_bits + 6; } out: @@ -217,9 +217,9 @@ static int jtag_dpi_runtest(int cycles) return ret; } -static int jtag_dpi_stableclocks(int cycles) +static int jtag_dpi_stableclocks(unsigned int num_cycles) { - return jtag_dpi_runtest(cycles); + return jtag_dpi_runtest(num_cycles); } static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue) diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 9dec0d19df..5745a2cd0d 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -254,7 +254,7 @@ static int jtag_vpi_path_move(struct pathmove_command *cmd) memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8)); - for (int i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) buf_set_u32(trans, i, 1, 1); tap_set_state(cmd->path[i]); @@ -440,7 +440,7 @@ static int jtag_vpi_scan(struct scan_command *cmd) return ERROR_OK; } -static int jtag_vpi_runtest(int cycles, tap_state_t state) +static int jtag_vpi_runtest(unsigned int num_cycles, tap_state_t state) { int retval; @@ -448,23 +448,21 @@ static int jtag_vpi_runtest(int cycles, tap_state_t state) if (retval != ERROR_OK) return retval; - retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT); + retval = jtag_vpi_queue_tdi(NULL, num_cycles, NO_TAP_SHIFT); if (retval != ERROR_OK) return retval; return jtag_vpi_state_move(state); } -static int jtag_vpi_stableclocks(int cycles) +static int jtag_vpi_stableclocks(unsigned int num_cycles) { uint8_t tms_bits[4]; - int cycles_remain = cycles; + unsigned int cycles_remain = num_cycles; int nb_bits; int retval; const int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8; - assert(cycles >= 0); - /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */ memset(&tms_bits, (tap_get_state() == TAP_RESET) ? 0xff : 0x00, sizeof(tms_bits)); diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index 81b74d40ec..e828d46d04 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -106,8 +106,8 @@ static int opendous_quit(void); /* Queue command functions */ static void opendous_end_state(tap_state_t state); static void opendous_state_move(void); -static void opendous_path_move(int num_states, tap_state_t *path); -static void opendous_runtest(int num_cycles); +static void opendous_path_move(unsigned int num_states, tap_state_t *path); +static void opendous_runtest(unsigned int num_cycles); static void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void opendous_reset(int trst, int srst); @@ -248,7 +248,7 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); if (cmd->cmd.runtest->end_state != -1) @@ -265,7 +265,7 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -419,11 +419,9 @@ void opendous_state_move(void) tap_set_state(tap_get_end_state()); } -void opendous_path_move(int num_states, tap_state_t *path) +void opendous_path_move(unsigned int num_states, tap_state_t *path) { - int i; - - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) opendous_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) @@ -440,10 +438,8 @@ void opendous_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -void opendous_runtest(int num_cycles) +void opendous_runtest(unsigned int num_cycles) { - int i; - tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ @@ -453,7 +449,7 @@ void opendous_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) opendous_tap_append_step(0, 0); /* finish in end_state */ diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index ea78ca8fd6..0ae885e871 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -760,15 +760,17 @@ static void openjtag_execute_runtest(struct jtag_command *cmd) if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 || cmd->cmd.runtest->num_cycles) { uint8_t command; - int cycles = cmd->cmd.runtest->num_cycles; + unsigned int num_cycles = cmd->cmd.runtest->num_cycles; do { + const unsigned int num_cycles_cmd = MIN(num_cycles, 16); + command = 7; - command |= (((cycles > 16 ? 16 : cycles) - 1) & 0x0F) << 4; + command |= ((num_cycles_cmd - 1) & 0x0F) << 4; openjtag_add_byte(command); - cycles -= 16; - } while (cycles > 0); + num_cycles -= num_cycles_cmd; + } while (num_cycles > 0); } tap_set_end_state(end_state); diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index 8d4fc90d88..c41a0e13c5 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -381,7 +381,7 @@ static int osbdm_quit(void) static int osbdm_add_pathmove( struct queue *queue, tap_state_t *path, - int num_states) + unsigned int num_states) { assert(num_states <= 32); @@ -392,7 +392,7 @@ static int osbdm_add_pathmove( } uint32_t tms = 0; - for (int i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), 1) == path[i]) { tms |= (1 << i); } else if (tap_state_transition(tap_get_state(), 0) == path[i]) { @@ -451,7 +451,7 @@ static int osbdm_add_statemove( static int osbdm_add_stableclocks( struct queue *queue, - int count) + unsigned int count) { if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("BUG: current state (%s) is not stable", @@ -489,7 +489,7 @@ static int osbdm_add_tms( static int osbdm_add_scan( struct queue *queue, struct scan_field *fields, - int num_fields, + unsigned int num_fields, tap_state_t end_state, bool ir_scan) { @@ -508,7 +508,7 @@ static int osbdm_add_scan( /* Add scan */ tap_set_end_state(end_state); - for (int idx = 0; idx < num_fields; idx++) { + for (unsigned int idx = 0; idx < num_fields; idx++) { struct sequence *next = queue_add_tail(queue, fields[idx].num_bits); if (!next) { LOG_ERROR("Can't allocate bit sequence"); @@ -536,7 +536,7 @@ static int osbdm_add_scan( static int osbdm_add_runtest( struct queue *queue, - int num_cycles, + unsigned int num_cycles, tap_state_t end_state) { if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK) diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index afdf16e587..f4a4fcba94 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -869,7 +869,7 @@ static void rlink_state_move(void) static void rlink_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; int tms = 0; @@ -896,10 +896,8 @@ static void rlink_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void rlink_runtest(int num_cycles) +static void rlink_runtest(unsigned int num_cycles) { - int i; - tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in RTI */ @@ -909,7 +907,7 @@ static void rlink_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) tap_state_queue_append(0); /* finish in end_state */ @@ -1323,7 +1321,7 @@ static int rlink_execute_queue(struct jtag_command *cmd_queue) rlink_state_move(); break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); rlink_path_move(cmd->cmd.pathmove); diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 0fe8989b9d..ad3bc6e37e 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -1701,15 +1701,17 @@ static int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd) */ static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd) { - int ret, i, num_states, batch_size, state_count; + int ret, state_count; tap_state_t *path; uint8_t tms_sequence; - num_states = cmd->cmd.pathmove->num_states; + unsigned int num_states = cmd->cmd.pathmove->num_states; path = cmd->cmd.pathmove->path; state_count = 0; while (num_states > 0) { + unsigned int batch_size; + tms_sequence = 0; /* Determine batch size */ @@ -1718,7 +1720,7 @@ static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd) else batch_size = num_states; - for (i = 0; i < batch_size; i++) { + for (unsigned int i = 0; i < batch_size; i++) { if (tap_state_transition(tap_get_state(), false) == path[state_count]) { /* Append '0' transition: clear bit 'i' in tms_sequence */ buf_set_u32(&tms_sequence, i, 1, 0x0); @@ -1774,14 +1776,13 @@ static int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd) static int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd) { int ret; - unsigned num_cycles; if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("JTAG_STABLECLOCKS: state not stable"); return ERROR_FAIL; } - num_cycles = cmd->cmd.stableclocks->num_cycles; + unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles; /* TMS stays either high (Test Logic Reset state) or low (all other states) */ if (tap_get_state() == TAP_RESET) diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index c84055c4a1..53dd158f66 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -474,11 +474,9 @@ static void ublast_tms(struct tms_command *cmd) */ static void ublast_path_move(struct pathmove_command *cmd) { - int i; - - LOG_DEBUG_IO("(num_states=%d, last_state=%d)", + LOG_DEBUG_IO("(num_states=%u, last_state=%d)", cmd->num_states, cmd->path[cmd->num_states - 1]); - for (i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) ublast_clock_tms(0); if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) @@ -675,19 +673,19 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) ublast_idle_clock(); } -static void ublast_runtest(int cycles, tap_state_t state) +static void ublast_runtest(unsigned int num_cycles, tap_state_t state) { - LOG_DEBUG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state); + LOG_DEBUG_IO("%s(cycles=%u, end_state=%d)", __func__, num_cycles, state); ublast_state_move(TAP_IDLE, 0); - ublast_queue_tdi(NULL, cycles, SCAN_OUT); + ublast_queue_tdi(NULL, num_cycles, SCAN_OUT); ublast_state_move(state, 0); } -static void ublast_stableclocks(int cycles) +static void ublast_stableclocks(unsigned int num_cycles) { - LOG_DEBUG_IO("%s(cycles=%i)", __func__, cycles); - ublast_queue_tdi(NULL, cycles, SCAN_OUT); + LOG_DEBUG_IO("%s(cycles=%u)", __func__, num_cycles); + ublast_queue_tdi(NULL, num_cycles, SCAN_OUT); } /** diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index 2d666d0728..6e3b3ba242 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -37,7 +37,7 @@ static void usbprog_end_state(tap_state_t state); static void usbprog_state_move(void); static void usbprog_path_move(struct pathmove_command *cmd); -static void usbprog_runtest(int num_cycles); +static void usbprog_runtest(unsigned int num_cycles); static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size); #define UNKNOWN_COMMAND 0x00 @@ -101,7 +101,7 @@ static int usbprog_execute_queue(struct jtag_command *cmd_queue) usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); usbprog_end_state(cmd->cmd.runtest->end_state); @@ -113,7 +113,7 @@ static int usbprog_execute_queue(struct jtag_command *cmd_queue) usbprog_state_move(); break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); usbprog_path_move(cmd->cmd.pathmove); @@ -189,7 +189,7 @@ static void usbprog_state_move(void) static void usbprog_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; /* There may be queued transitions, and before following a specified @@ -222,10 +222,8 @@ static void usbprog_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void usbprog_runtest(int num_cycles) +static void usbprog_runtest(unsigned int num_cycles) { - int i; - /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { usbprog_end_state(TAP_IDLE); @@ -241,7 +239,7 @@ static void usbprog_runtest(int num_cycles) /* LOG_INFO("NUM CYCLES %i",num_cycles); */ } - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { usbprog_write(1, 0, 0); usbprog_write(0, 0, 0); } diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index f1fc4535f3..31f50b5616 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -931,11 +931,11 @@ static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush) static int vdebug_jtag_path_move(struct pathmove_command *cmd, uint8_t f_flush) { uint8_t tms[DIV_ROUND_UP(cmd->num_states, 8)]; - LOG_DEBUG_IO("path num states %d", cmd->num_states); + LOG_DEBUG_IO("path num states %u", cmd->num_states); memset(tms, 0, DIV_ROUND_UP(cmd->num_states, 8)); - for (uint8_t i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) buf_set_u32(tms, i, 1, 1); tap_set_state(cmd->path[i]); @@ -971,9 +971,9 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) uint8_t tms_post = tap_get_tms_path(state, cmd->end_state); uint8_t num_post = tap_get_tms_path_len(state, cmd->end_state); int num_bits = jtag_scan_size(cmd); - LOG_DEBUG_IO("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x", + LOG_DEBUG_IO("scan len:%d fields:%u ir/!dr:%d state cur:%x end:%x", num_bits, cmd->num_fields, cmd->ir_scan, cur, cmd->end_state); - for (int i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { uint8_t cur_num_pre = i == 0 ? num_pre : 0; uint8_t cur_tms_pre = i == 0 ? tms_pre : 0; uint8_t cur_num_post = i == cmd->num_fields - 1 ? num_post : 0; @@ -992,24 +992,24 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) return rc; } -static int vdebug_jtag_runtest(int cycles, tap_state_t state, uint8_t f_flush) +static int vdebug_jtag_runtest(unsigned int num_cycles, tap_state_t state, uint8_t f_flush) { tap_state_t cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); - LOG_DEBUG_IO("idle len:%d state cur:%x end:%x", cycles, cur, state); - int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, cycles, NULL, 0, 0, NULL, f_flush); + LOG_DEBUG_IO("idle len:%u state cur:%x end:%x", num_cycles, cur, state); + int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, num_cycles, NULL, 0, 0, NULL, f_flush); if (cur != state) tap_set_state(state); return rc; } -static int vdebug_jtag_stableclocks(int num, uint8_t f_flush) +static int vdebug_jtag_stableclocks(unsigned int num_cycles, uint8_t f_flush) { - LOG_DEBUG("stab len:%d state cur:%x", num, tap_get_state()); + LOG_DEBUG("stab len:%u state cur:%x", num_cycles, tap_get_state()); - return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num, NULL, 0, 0, NULL, f_flush); + return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num_cycles, NULL, 0, 0, NULL, f_flush); } static int vdebug_sleep(int us) diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 34525d5468..ca142177ec 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -43,10 +43,10 @@ static struct pending_scan_result /* Queue command functions */ static void vsllink_end_state(tap_state_t state); static void vsllink_state_move(void); -static void vsllink_path_move(int num_states, tap_state_t *path); +static void vsllink_path_move(unsigned int num_states, tap_state_t *path); static void vsllink_tms(int num_bits, const uint8_t *bits); -static void vsllink_runtest(int num_cycles); -static void vsllink_stableclocks(int num_cycles, int tms); +static void vsllink_runtest(unsigned int num_cycles); +static void vsllink_stableclocks(unsigned int num_cycles, int tms); static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static int vsllink_reset(int trst, int srst); @@ -98,7 +98,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); @@ -115,7 +115,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); @@ -161,7 +161,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_STABLECLOCKS: - LOG_DEBUG_IO("add %d clocks", + LOG_DEBUG_IO("add %u clocks", cmd->cmd.stableclocks->num_cycles); switch (tap_get_state()) { @@ -371,9 +371,9 @@ static void vsllink_state_move(void) tap_set_state(tap_get_end_state()); } -static void vsllink_path_move(int num_states, tap_state_t *path) +static void vsllink_path_move(unsigned int num_states, tap_state_t *path) { - for (int i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) vsllink_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) @@ -397,7 +397,7 @@ static void vsllink_tms(int num_bits, const uint8_t *bits) vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0); } -static void vsllink_stableclocks(int num_cycles, int tms) +static void vsllink_stableclocks(unsigned int num_cycles, int tms) { while (num_cycles > 0) { vsllink_tap_append_step(tms, 0); @@ -405,7 +405,7 @@ static void vsllink_stableclocks(int num_cycles, int tms) } } -static void vsllink_runtest(int num_cycles) +static void vsllink_runtest(unsigned int num_cycles) { tap_state_t saved_end_state = tap_get_end_state(); diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index 11fbaaab2a..f252087744 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -1669,7 +1669,6 @@ static void xds110_execute_tlr_reset(struct jtag_command *cmd) static void xds110_execute_pathmove(struct jtag_command *cmd) { - uint32_t i; uint32_t num_states; uint8_t *path; @@ -1685,7 +1684,7 @@ static void xds110_execute_pathmove(struct jtag_command *cmd) } /* Convert requested path states into XDS API states */ - for (i = 0; i < num_states; i++) + for (unsigned int i = 0; i < num_states; i++) path[i] = (uint8_t)xds_jtag_state[cmd->cmd.pathmove->path[i]]; if (xds110.firmware >= OCD_FIRMWARE_VERSION) { @@ -1704,7 +1703,6 @@ static void xds110_execute_pathmove(struct jtag_command *cmd) static void xds110_queue_scan(struct jtag_command *cmd) { - int i; uint32_t offset; uint32_t total_fields; uint32_t total_bits; @@ -1715,7 +1713,7 @@ static void xds110_queue_scan(struct jtag_command *cmd) /* Calculate the total number of bits to scan */ total_bits = 0; total_fields = 0; - for (i = 0; i < cmd->cmd.scan->num_fields; i++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) { total_fields++; total_bits += (uint32_t)cmd->cmd.scan->fields[i].num_bits; } @@ -1756,7 +1754,7 @@ static void xds110_queue_scan(struct jtag_command *cmd) buffer = &xds110.txn_requests[xds110.txn_request_size]; /* Clear data out buffer to default value of all zeros */ memset((void *)buffer, 0x00, total_bytes); - for (i = 0; i < cmd->cmd.scan->num_fields; i++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) { if (cmd->cmd.scan->fields[i].out_value) { /* Copy over data to scan out into request buffer */ bit_copy(buffer, offset, cmd->cmd.scan->fields[i].out_value, 0, @@ -1775,7 +1773,7 @@ static void xds110_queue_scan(struct jtag_command *cmd) static void xds110_queue_runtest(struct jtag_command *cmd) { - uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles; + uint32_t clocks = cmd->cmd.stableclocks->num_cycles; uint8_t end_state = (uint8_t)xds_jtag_state[cmd->cmd.runtest->end_state]; /* Check if new request would be too large to fit */ @@ -1794,7 +1792,7 @@ static void xds110_queue_runtest(struct jtag_command *cmd) static void xds110_queue_stableclocks(struct jtag_command *cmd) { - uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles; + uint32_t clocks = cmd->cmd.stableclocks->num_cycles; /* Check if new request would be too large to fit */ if ((xds110.txn_request_size + 1 + sizeof(clocks) + 1) > MAX_DATA_BLOCK) diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index 233ade3f88..b5c7e2fd69 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -128,7 +128,7 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd) size_t write; int err; - LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + LOG_DEBUG("stableclocks %u cycles", cmd->cmd.runtest->num_cycles); while (left) { write = MIN(XLNX_XVC_MAX_BITS, left); @@ -167,7 +167,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) { int err = ERROR_OK; - LOG_DEBUG("runtest %i cycles, end in %i", + LOG_DEBUG("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); @@ -200,16 +200,15 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) { - size_t num_states = cmd->cmd.pathmove->num_states; + unsigned int num_states = cmd->cmd.pathmove->num_states; tap_state_t *path = cmd->cmd.pathmove->path; int err = ERROR_OK; - size_t i; - LOG_DEBUG("pathmove: %i states, end in %i", + LOG_DEBUG("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) { err = xlnx_pcie_xvc_transact(1, 1, 0, NULL); } else if (path[i] == tap_state_transition(tap_get_state(), true)) { diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 76bfdf157b..520b5b8c08 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -436,7 +436,7 @@ void jtag_add_tlr(void); * - ERROR_JTAG_TRANSITION_INVALID -- The path includes invalid * state transitions. */ -void jtag_add_pathmove(int num_states, const tap_state_t *path); +void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path); /** * jtag_add_statemove() moves from the current state to @a goal_state. @@ -459,7 +459,7 @@ int jtag_add_statemove(tap_state_t goal_state); * via TAP_IDLE. * @param endstate The final state. */ -void jtag_add_runtest(int num_cycles, tap_state_t endstate); +void jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate); /** * A reset of the TAP state machine can be requested. @@ -495,7 +495,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state t); * first checks that the state in which the clocks are to be issued is * stable, then queues up num_cycles clocks for transmission. */ -void jtag_add_clocks(int num_cycles); +void jtag_add_clocks(unsigned int num_cycles); /** * For software FIFO implementations, the queued commands can be executed diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h index a40cffa2bd..45b0bf619d 100644 --- a/src/jtag/minidriver.h +++ b/src/jtag/minidriver.h @@ -51,8 +51,8 @@ int interface_jtag_add_plain_dr_scan( tap_state_t endstate); int interface_jtag_add_tlr(void); -int interface_jtag_add_pathmove(int num_states, const tap_state_t *path); -int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate); +int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path); +int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate); int interface_add_tms_seq(unsigned num_bits, const uint8_t *bits, enum tap_state state); @@ -67,7 +67,7 @@ int interface_add_tms_seq(unsigned num_bits, */ int interface_jtag_add_reset(int trst, int srst); int interface_jtag_add_sleep(uint32_t us); -int interface_jtag_add_clocks(int num_cycles); +int interface_jtag_add_clocks(unsigned int num_cycles); int interface_jtag_execute_queue(void); /** diff --git a/src/target/esirisc_jtag.c b/src/target/esirisc_jtag.c index 1ec1726e5c..5960e26cb4 100644 --- a/src/target/esirisc_jtag.c +++ b/src/target/esirisc_jtag.c @@ -58,11 +58,12 @@ static int esirisc_jtag_get_padding(void) return padding; } -static int esirisc_jtag_count_bits(int num_fields, struct scan_field *fields) +static int esirisc_jtag_count_bits(unsigned int num_fields, + struct scan_field *fields) { int bit_count = 0; - for (int i = 0; i < num_fields; ++i) + for (unsigned int i = 0; i < num_fields; ++i) bit_count += fields[i].num_bits; return bit_count; From 9ef59daef00fbf79985c2f4801c55e6116d475d3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 21 Jul 2024 17:43:08 +0200 Subject: [PATCH 0902/1312] target/avrt: Remove unused parameter 'rti' Change-Id: Ib6957b89190188f5c15fadc3d4036709f19a6cea Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8412 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/avrt.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/target/avrt.c b/src/target/avrt.c index ccce7e5e52..8886a46778 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -31,10 +31,10 @@ static int avr_assert_reset(struct target *target); static int avr_deassert_reset(struct target *target); /* IR and DR functions */ -static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti); -static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti); -static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti); -static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti); +static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len); +static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len); +static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len); +static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len); struct target_type avr_target = { .name = "avr", @@ -137,17 +137,17 @@ static int avr_deassert_reset(struct target *target) int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out, int len) { - return mcu_write_dr_u32(tap, dr_in, dr_out, len, 1); + return mcu_write_dr_u32(tap, dr_in, dr_out, len); } int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out) { - return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN, 1); + return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN); } /* IR and DR functions */ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, - int ir_len, int rti) + int ir_len) { if (!tap) { LOG_ERROR("invalid tap"); @@ -166,7 +166,7 @@ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, } static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, - int dr_len, int rti) + int dr_len) { if (!tap) { LOG_ERROR("invalid tap"); @@ -181,27 +181,27 @@ static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, } static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, - uint8_t ir_out, int ir_len, int rti) + uint8_t ir_out, int ir_len) { if (ir_len > 8) { LOG_ERROR("ir_len overflow, maximum is 8"); return ERROR_FAIL; } - mcu_write_ir(tap, ir_in, &ir_out, ir_len, rti); + mcu_write_ir(tap, ir_in, &ir_out, ir_len); return ERROR_OK; } static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in, - uint32_t dr_out, int dr_len, int rti) + uint32_t dr_out, int dr_len) { if (dr_len > 32) { LOG_ERROR("dr_len overflow, maximum is 32"); return ERROR_FAIL; } - mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len, rti); + mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len); return ERROR_OK; } From 7d56407ba7b43fddbbce412de2d1eddb51c46bfa Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 21 Jul 2024 20:28:17 +0200 Subject: [PATCH 0903/1312] jtag: Use 'unsigned int' for 'scan_field.num_bits' This patch modifies as little code as possible in order to simplify the review. Data types that are affected by these changes will be addresses in following patches. While at it, apply coding style fixes if these are not too extensive. Change-Id: Idcbbbbbea2705512201eb326c3e6cef110dbc674 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8413 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/commands.c | 8 ++++---- src/jtag/core.c | 6 +++--- src/jtag/drivers/bitq.c | 9 ++++----- src/jtag/drivers/cmsis_dap.c | 4 ++-- src/jtag/drivers/ftdi.c | 2 +- src/jtag/drivers/jlink.c | 2 +- src/jtag/jtag.h | 2 +- src/target/riscv/batch.c | 4 ++-- src/target/riscv/riscv-011.c | 2 +- src/target/riscv/riscv-013.c | 2 +- 10 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/jtag/commands.c b/src/jtag/commands.c index c679c56c5c..a15af68dbc 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -210,14 +210,14 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits); - LOG_DEBUG("fields[%u].out_value[%i]: 0x%s", i, + LOG_DEBUG("fields[%u].out_value[%u]: 0x%s", i, cmd->fields[i].num_bits, char_buf); free(char_buf); } buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); } else { - LOG_DEBUG_IO("fields[%u].out_value[%i]: NULL", + LOG_DEBUG_IO("fields[%u].out_value[%u]: NULL", i, cmd->fields[i].num_bits); } @@ -242,7 +242,7 @@ int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) * are specified we don't have to examine this field */ if (cmd->fields[i].in_value) { - int num_bits = cmd->fields[i].num_bits; + const unsigned int num_bits = cmd->fields[i].num_bits; uint8_t *captured = buf_set_buf(buffer, bit_count, malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits); @@ -252,7 +252,7 @@ int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) ? DEBUG_JTAG_IOZ : num_bits); - LOG_DEBUG("fields[%u].in_value[%i]: 0x%s", + LOG_DEBUG("fields[%u].in_value[%u]: 0x%s", i, num_bits, char_buf); free(char_buf); } diff --git a/src/jtag/core.c b/src/jtag/core.c index a8190dd23c..261de98612 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -964,12 +964,12 @@ int default_interface_jtag_execute_queue(void) struct scan_field *field = cmd->cmd.scan->fields + i; if (field->out_value) { char *str = buf_to_hex_str(field->out_value, field->num_bits); - LOG_DEBUG_IO(" %db out: %s", field->num_bits, str); + LOG_DEBUG_IO(" %ub out: %s", field->num_bits, str); free(str); } if (field->in_value) { char *str = buf_to_hex_str(field->in_value, field->num_bits); - LOG_DEBUG_IO(" %db in: %s", field->num_bits, str); + LOG_DEBUG_IO(" %ub in: %s", field->num_bits, str); free(str); } } @@ -1337,7 +1337,7 @@ static int jtag_validate_ircapture(void) int retval; /* when autoprobing, accommodate huge IR lengths */ - int total_ir_length = 0; + unsigned int total_ir_length = 0; for (tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) { if (tap->ir_length == 0) total_ir_length += JTAG_IRLEN_MAX; diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c index 6816b9b86f..ef870e6486 100644 --- a/src/jtag/drivers/bitq.c +++ b/src/jtag/drivers/bitq.c @@ -19,7 +19,7 @@ struct bitq_interface *bitq_interface; /* low level bit queue interface */ struct bitq_state { struct jtag_command *cmd; /* command currently processed */ unsigned int field_idx; /* index of field currently being processed */ - int bit_pos; /* position of bit currently being processed */ + unsigned int bit_pos; /* position of bit currently being processed */ int status; /* processing status */ }; static struct bitq_state bitq_in_state; @@ -142,11 +142,10 @@ static void bitq_runtest(unsigned int num_cycles) static void bitq_scan_field(struct scan_field *field, int do_pause) { - int bit_cnt; int tdo_req; const uint8_t *out_ptr; - uint8_t out_mask; + uint8_t out_mask; if (field->in_value) tdo_req = 1; @@ -155,7 +154,7 @@ static void bitq_scan_field(struct scan_field *field, int do_pause) if (!field->out_value) { /* just send zeros and request data from TDO */ - for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) + for (unsigned int i = 0; i < (field->num_bits - 1); i++) bitq_io(0, 0, tdo_req); bitq_io(do_pause, 0, tdo_req); @@ -163,7 +162,7 @@ static void bitq_scan_field(struct scan_field *field, int do_pause) /* send data, and optionally request TDO */ out_mask = 0x01; out_ptr = field->out_value; - for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) { + for (unsigned int i = 0; i < (field->num_bits - 1); i++) { bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req); if (out_mask == 0x80) { out_mask = 0x01; diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 243b01c63b..a6dcfcd3d2 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -1772,11 +1772,11 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) cmsis_dap_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; - unsigned scan_size = 0; + unsigned int scan_size = 0; for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %u/%u %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %u bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 4f253fa6d9..82117f12c1 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -451,7 +451,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd) for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %u/%u %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %u bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index ff39167359..21a5da8875 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -183,7 +183,7 @@ static void jlink_execute_scan(struct jtag_command *cmd) for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %u/%u %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %u bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 520b5b8c08..f0a0fe5e15 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -86,7 +86,7 @@ extern tap_state_t cmd_queue_cur_state; */ struct scan_field { /** The number of bits this field specifies */ - int num_bits; + unsigned int num_bits; /** A pointer to value to be scanned into the device */ const uint8_t *out_value; /** A pointer to a 32-bit memory location for data scanned out */ diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index d39967e4df..d4bdadf170 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -211,12 +211,12 @@ void dump_field(int idle, const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, __PRETTY_FUNCTION__, - "%db %s %08x @%02x -> %s %08x @%02x; %di", + "%ub %s %08x @%02x -> %s %08x @%02x; %di", field->num_bits, op_string[out_op], out_data, out_address, status_string[in_op], in_data, in_address, idle); } else { log_printf_lf(LOG_LVL_DEBUG, - __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?; %di", + __FILE__, __LINE__, __PRETTY_FUNCTION__, "%ub %s %08x @%02x -> ?; %di", field->num_bits, op_string[out_op], out_data, out_address, idle); } } diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index be296cdd8c..565721c28b 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -412,7 +412,7 @@ static void dump_field(const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", - "%db %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x", + "%ub %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x", field->num_bits, op_string[out_op], out_interrupt, out_haltnot, out_data, out_address, diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 0aa82031cd..dbf9aad1d9 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -389,7 +389,7 @@ static void dump_field(int idle, const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", - "%db %s %08x @%02x -> %s %08x @%02x; %di", + "%ub %s %08x @%02x -> %s %08x @%02x; %di", field->num_bits, op_string[out_op], out_data, out_address, status_string[in_op], in_data, in_address, idle); From 2b6d63a44da445f601f53b1bf40c97199987cfc2 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 22 Jul 2024 09:30:42 +0200 Subject: [PATCH 0904/1312] jtag: Use 'unsigned int' data type This patch modifies as little code as possible in order to simplify the review. Data types that are affected by these changes will be addresses in following patches. While at it, apply coding style fixes if these are not too extensive. Change-Id: I364467b88f193f8387623a19e6994ef77899d117 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8414 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/commands.c | 8 ++-- src/jtag/commands.h | 2 +- src/jtag/core.c | 80 +++++++++++++++++++-------------------- src/jtag/drivers/vdebug.c | 4 +- src/jtag/jtag.h | 24 ++++++------ src/jtag/tcl.c | 4 +- 6 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/jtag/commands.c b/src/jtag/commands.c index a15af68dbc..1bca4e8df3 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -178,9 +178,9 @@ enum scan_type jtag_scan_type(const struct scan_command *cmd) return type; } -int jtag_scan_size(const struct scan_command *cmd) +unsigned int jtag_scan_size(const struct scan_command *cmd) { - int bit_count = 0; + unsigned int bit_count = 0; /* count bits in scan command */ for (unsigned int i = 0; i < cmd->num_fields; i++) @@ -191,9 +191,7 @@ int jtag_scan_size(const struct scan_command *cmd) int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) { - int bit_count = 0; - - bit_count = jtag_scan_size(cmd); + unsigned int bit_count = jtag_scan_size(cmd); *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8)); bit_count = 0; diff --git a/src/jtag/commands.h b/src/jtag/commands.h index 885e6a3608..29fa8426ee 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -157,7 +157,7 @@ struct jtag_command *jtag_command_queue_get(void); void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src); enum scan_type jtag_scan_type(const struct scan_command *cmd); -int jtag_scan_size(const struct scan_command *cmd); +unsigned int jtag_scan_size(const struct scan_command *cmd); int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd); int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer); diff --git a/src/jtag/core.c b/src/jtag/core.c index 261de98612..9eae5e74ba 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -39,7 +39,7 @@ #include "server/ipdbg.h" /** The number of JTAG queue flushes (for profiling and debugging purposes). */ -static int jtag_flush_queue_count; +static unsigned int jtag_flush_queue_count; /* Sleep this # of ms after flushing the queue */ static int jtag_flush_queue_sleep; @@ -92,10 +92,10 @@ static bool jtag_verify = true; /* how long the OpenOCD should wait before attempting JTAG communication after reset lines *deasserted (in ms) */ -static int adapter_nsrst_delay; /* default to no nSRST delay */ -static int jtag_ntrst_delay;/* default to no nTRST delay */ -static int adapter_nsrst_assert_width; /* width of assertion */ -static int jtag_ntrst_assert_width; /* width of assertion */ +static unsigned int adapter_nsrst_delay; /* default to no nSRST delay */ +static unsigned int jtag_ntrst_delay;/* default to no nTRST delay */ +static unsigned int adapter_nsrst_assert_width; /* width of assertion */ +static unsigned int jtag_ntrst_assert_width; /* width of assertion */ /** * Contains a single callback along with a pointer that will be passed @@ -186,10 +186,10 @@ struct jtag_tap *jtag_all_taps(void) return __jtag_all_taps; }; -unsigned jtag_tap_count(void) +unsigned int jtag_tap_count(void) { struct jtag_tap *t = jtag_all_taps(); - unsigned n = 0; + unsigned int n = 0; while (t) { n++; t = t->next_tap; @@ -197,10 +197,10 @@ unsigned jtag_tap_count(void) return n; } -unsigned jtag_tap_count_enabled(void) +unsigned int jtag_tap_count_enabled(void) { struct jtag_tap *t = jtag_all_taps(); - unsigned n = 0; + unsigned int n = 0; while (t) { if (t->enabled) n++; @@ -499,7 +499,7 @@ void jtag_add_tlr(void) * * @todo Update naming conventions to stop assuming everything is JTAG. */ -int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) +int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state state) { int retval; @@ -567,12 +567,12 @@ int jtag_add_statemove(tap_state_t goal_state) /* nothing to do */; else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) { - unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); - unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state); + unsigned int tms_bits = tap_get_tms_path(cur_state, goal_state); + unsigned int tms_count = tap_get_tms_path_len(cur_state, goal_state); tap_state_t moves[8]; assert(tms_count < ARRAY_SIZE(moves)); - for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) { + for (unsigned int i = 0; i < tms_count; i++, tms_bits >>= 1) { bool bit = tms_bits & 1; cur_state = tap_state_transition(cur_state, bit); @@ -1029,7 +1029,7 @@ void jtag_execute_queue_noclear(void) } } -int jtag_get_flush_queue_count(void) +unsigned int jtag_get_flush_queue_count(void) { return jtag_flush_queue_count; } @@ -1081,7 +1081,7 @@ void jtag_sleep(uint32_t us) /* a larger IR length than we ever expect to autoprobe */ #define JTAG_IRLEN_MAX 60 -static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) +static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned int num_idcode) { struct scan_field field = { .num_bits = num_idcode * 32, @@ -1090,7 +1090,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod }; /* initialize to the end of chain ID value */ - for (unsigned i = 0; i < num_idcode; i++) + for (unsigned int i = 0; i < num_idcode; i++) buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG); jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); @@ -1098,12 +1098,12 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod return jtag_execute_queue(); } -static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count) +static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned int count) { uint8_t zero_check = 0x0; uint8_t one_check = 0xff; - for (unsigned i = 0; i < count * 4; i++) { + for (unsigned int i = 0; i < count * 4; i++) { zero_check |= idcodes[i]; one_check &= idcodes[i]; } @@ -1158,7 +1158,8 @@ static bool jtag_idcode_is_final(uint32_t idcode) * with the JTAG chain earlier, gives more helpful/explicit error messages. * Returns TRUE iff garbage was found. */ -static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max) +static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned int count, + unsigned int max) { bool triggered = false; for (; count < max - 31; count += 32) { @@ -1185,26 +1186,26 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) uint32_t idcode = tap->idcode & mask; /* Loop over the expected identification codes and test for a match */ - for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) { - uint32_t expected = tap->expected_ids[ii] & mask; + for (unsigned int i = 0; i < tap->expected_ids_cnt; i++) { + uint32_t expected = tap->expected_ids[i] & mask; if (idcode == expected) return true; /* treat "-expected-id 0" as a "don't-warn" wildcard */ - if (tap->expected_ids[ii] == 0) + if (tap->expected_ids[i] == 0) return true; } /* If none of the expected ids matched, warn */ jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED", tap->dotted_name, tap->idcode); - for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) { + for (unsigned int i = 0; i < tap->expected_ids_cnt; i++) { char msg[32]; - snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt); + snprintf(msg, sizeof(msg), "expected %u of %u", i + 1, tap->expected_ids_cnt); jtag_examine_chain_display(LOG_LVL_ERROR, msg, - tap->dotted_name, tap->expected_ids[ii]); + tap->dotted_name, tap->expected_ids[i]); } return false; } @@ -1215,7 +1216,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) static int jtag_examine_chain(void) { int retval; - unsigned max_taps = jtag_tap_count(); + unsigned int max_taps = jtag_tap_count(); /* Autoprobe up to this many. */ if (max_taps < JTAG_MAX_AUTO_TAPS) @@ -1243,9 +1244,9 @@ static int jtag_examine_chain(void) /* Point at the 1st predefined tap, if any */ struct jtag_tap *tap = jtag_tap_next_enabled(NULL); - unsigned bit_count = 0; - unsigned autocount = 0; - for (unsigned i = 0; i < max_taps; i++) { + unsigned int bit_count = 0; + unsigned int autocount = 0; + for (unsigned int i = 0; i < max_taps; i++) { assert(bit_count < max_taps * 32); uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32); @@ -1445,8 +1446,8 @@ static int jtag_validate_ircapture(void) void jtag_tap_init(struct jtag_tap *tap) { - unsigned ir_len_bits; - unsigned ir_len_bytes; + unsigned int ir_len_bits; + unsigned int ir_len_bytes; /* if we're autoprobing, cope with potentially huge ir_length */ ir_len_bits = tap->ir_length ? tap->ir_length : JTAG_IRLEN_MAX; @@ -1749,37 +1750,36 @@ int jtag_get_srst(void) return jtag_srst == 1; } -void jtag_set_nsrst_delay(unsigned delay) +void jtag_set_nsrst_delay(unsigned int delay) { adapter_nsrst_delay = delay; } -unsigned jtag_get_nsrst_delay(void) +unsigned int jtag_get_nsrst_delay(void) { return adapter_nsrst_delay; } -void jtag_set_ntrst_delay(unsigned delay) +void jtag_set_ntrst_delay(unsigned int delay) { jtag_ntrst_delay = delay; } -unsigned jtag_get_ntrst_delay(void) +unsigned int jtag_get_ntrst_delay(void) { return jtag_ntrst_delay; } - -void jtag_set_nsrst_assert_width(unsigned delay) +void jtag_set_nsrst_assert_width(unsigned int delay) { adapter_nsrst_assert_width = delay; } -unsigned jtag_get_nsrst_assert_width(void) +unsigned int jtag_get_nsrst_assert_width(void) { return adapter_nsrst_assert_width; } -void jtag_set_ntrst_assert_width(unsigned delay) +void jtag_set_ntrst_assert_width(unsigned int delay) { jtag_ntrst_assert_width = delay; } -unsigned jtag_get_ntrst_assert_width(void) +unsigned int jtag_get_ntrst_assert_width(void) { return jtag_ntrst_assert_width; } diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index 31f50b5616..691e576e53 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -970,8 +970,8 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) uint8_t num_pre = tap_get_tms_path_len(cur, state); uint8_t tms_post = tap_get_tms_path(state, cmd->end_state); uint8_t num_post = tap_get_tms_path_len(state, cmd->end_state); - int num_bits = jtag_scan_size(cmd); - LOG_DEBUG_IO("scan len:%d fields:%u ir/!dr:%d state cur:%x end:%x", + const unsigned int num_bits = jtag_scan_size(cmd); + LOG_DEBUG_IO("scan len:%u fields:%u ir/!dr:%d state cur:%x end:%x", num_bits, cmd->num_fields, cmd->ir_scan, cur, cmd->end_state); for (unsigned int i = 0; i < cmd->num_fields; i++) { uint8_t cur_num_pre = i == 0 ? num_pre : 0; diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index f0a0fe5e15..b9d37b32ae 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -152,8 +152,8 @@ struct jtag_tap *jtag_tap_by_string(const char *dotted_name); struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj); struct jtag_tap *jtag_tap_by_position(unsigned int abs_position); struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p); -unsigned jtag_tap_count_enabled(void); -unsigned jtag_tap_count(void); +unsigned int jtag_tap_count_enabled(void); +unsigned int jtag_tap_count(void); /* * - TRST_ASSERTED triggers two sets of callbacks, after operations to @@ -229,17 +229,17 @@ enum reset_types { enum reset_types jtag_get_reset_config(void); void jtag_set_reset_config(enum reset_types type); -void jtag_set_nsrst_delay(unsigned delay); -unsigned jtag_get_nsrst_delay(void); +void jtag_set_nsrst_delay(unsigned int delay); +unsigned int jtag_get_nsrst_delay(void); -void jtag_set_ntrst_delay(unsigned delay); -unsigned jtag_get_ntrst_delay(void); +void jtag_set_ntrst_delay(unsigned int delay); +unsigned int jtag_get_ntrst_delay(void); -void jtag_set_nsrst_assert_width(unsigned delay); -unsigned jtag_get_nsrst_assert_width(void); +void jtag_set_nsrst_assert_width(unsigned int delay); +unsigned int jtag_get_nsrst_assert_width(void); -void jtag_set_ntrst_assert_width(unsigned delay); -unsigned jtag_get_ntrst_assert_width(void); +void jtag_set_ntrst_assert_width(unsigned int delay); +unsigned int jtag_get_ntrst_assert_width(void); /** @returns The current state of TRST. */ int jtag_get_trst(void); @@ -488,7 +488,7 @@ void jtag_add_reset(int req_tlr_or_trst, int srst); void jtag_add_sleep(uint32_t us); -int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state t); +int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state t); /** * Function jtag_add_clocks @@ -523,7 +523,7 @@ int jtag_execute_queue(void); void jtag_execute_queue_noclear(void); /** @returns the number of times the scan queue has been flushed */ -int jtag_get_flush_queue_count(void); +unsigned int jtag_get_flush_queue_count(void); /** Report Tcl event to all TAPs */ void jtag_notify_event(enum jtag_event); diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 4bfbeeb420..10a7dd3f84 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -212,8 +212,8 @@ COMMAND_HANDLER(handle_jtag_flush_count) if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; - int count = jtag_get_flush_queue_count(); - command_print_sameline(CMD, "%d", count); + const unsigned int count = jtag_get_flush_queue_count(); + command_print_sameline(CMD, "%u", count); return ERROR_OK; } From fc0ec6cf0bf257e9304f9b57d4db8a22957e3755 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 22 Jul 2024 17:56:55 +0200 Subject: [PATCH 0905/1312] adapter/jlink: Use COMMAND_PARSE_* instead of sscanf() While at it, apply some coding style fixes. Change-Id: I77a6917a045af733ebe9211ca338952dbd49c89b Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8416 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/jlink.c | 83 +++++++++++++++------------------------- 1 file changed, 31 insertions(+), 52 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 21a5da8875..f9b500e6bf 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -961,23 +961,18 @@ static int jlink_reset_safe(int trst, int srst) COMMAND_HANDLER(jlink_usb_command) { - int tmp; - if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { - command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; - } + unsigned int tmp; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], tmp); - if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) { + if (tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } usb_address = tmp; - use_usb_address = true; return ERROR_OK; @@ -1035,38 +1030,35 @@ COMMAND_HANDLER(jlink_handle_free_memory_command) COMMAND_HANDLER(jlink_handle_jlink_jtag_command) { - int tmp; - int version; - if (!CMD_ARGC) { + unsigned int version; + switch (jtag_command_version) { - case JAYLINK_JTAG_VERSION_2: - version = 2; - break; - case JAYLINK_JTAG_VERSION_3: - version = 3; - break; - default: - return ERROR_FAIL; + case JAYLINK_JTAG_VERSION_2: + version = 2; + break; + case JAYLINK_JTAG_VERSION_3: + version = 3; + break; + default: + return ERROR_FAIL; } - command_print(CMD, "JTAG command version: %i", version); + command_print(CMD, "JTAG command version: %u", version); } else if (CMD_ARGC == 1) { - if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { - command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; - } + uint8_t tmp; + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], tmp); switch (tmp) { - case 2: - jtag_command_version = JAYLINK_JTAG_VERSION_2; - break; - case 3: - jtag_command_version = JAYLINK_JTAG_VERSION_3; - break; - default: - command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; + case 2: + jtag_command_version = JAYLINK_JTAG_VERSION_2; + break; + case 3: + jtag_command_version = JAYLINK_JTAG_VERSION_3; + break; + default: + command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } } else { return ERROR_COMMAND_SYNTAX_ERROR; @@ -1077,9 +1069,6 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) COMMAND_HANDLER(jlink_handle_target_power_command) { - int ret; - int enable; - if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -1089,16 +1078,10 @@ COMMAND_HANDLER(jlink_handle_target_power_command) return ERROR_OK; } - if (!strcmp(CMD_ARGV[0], "on")) { - enable = true; - } else if (!strcmp(CMD_ARGV[0], "off")) { - enable = false; - } else { - command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_FAIL; - } + bool enable; + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); - ret = jaylink_set_target_power(devh, enable); + int ret = jaylink_set_target_power(devh, enable); if (ret != JAYLINK_OK) { command_print(CMD, "jaylink_set_target_power() failed: %s", @@ -1407,8 +1390,6 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, COMMAND_HANDLER(jlink_handle_config_usb_address_command) { - uint8_t tmp; - if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { command_print(CMD, "Reading configuration is not supported by the " "device"); @@ -1418,10 +1399,8 @@ COMMAND_HANDLER(jlink_handle_config_usb_address_command) if (!CMD_ARGC) { show_config_usb_address(CMD); } else if (CMD_ARGC == 1) { - if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) { - command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; - } + uint8_t tmp; + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], tmp); if (tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD, "Invalid USB address: %u", tmp); @@ -1880,7 +1859,7 @@ static const struct command_registration jlink_subcommand_handlers[] = { .handler = &jlink_handle_target_power_command, .mode = COMMAND_EXEC, .help = "set the target power supply", - .usage = "" + .usage = "<0|1|on|off>" }, { .name = "freemem", From 4cab20b599885885cdcba850af6b57310e695412 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 24 Jul 2024 20:39:57 +0200 Subject: [PATCH 0906/1312] adapter/jlink: Allow to determine the target power state Change-Id: I0b4f543e0ba0e48c43f78e32e4fa41d7dec9d7b8 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8417 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/jlink.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index f9b500e6bf..a94f3a4aba 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -1069,7 +1069,7 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) COMMAND_HANDLER(jlink_handle_target_power_command) { - if (CMD_ARGC != 1) + if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) { @@ -1078,6 +1078,20 @@ COMMAND_HANDLER(jlink_handle_target_power_command) return ERROR_OK; } + if (!CMD_ARGC) { + uint32_t state; + int ret = jaylink_get_hardware_info(devh, JAYLINK_HW_INFO_TARGET_POWER, + &state); + + if (ret != JAYLINK_OK) { + command_print(CMD, "Failed to retrieve target power state"); + return ERROR_FAIL; + } + + command_print(CMD, "%d", (bool)state); + return ERROR_OK; + } + bool enable; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); @@ -1859,7 +1873,7 @@ static const struct command_registration jlink_subcommand_handlers[] = { .handler = &jlink_handle_target_power_command, .mode = COMMAND_EXEC, .help = "set the target power supply", - .usage = "<0|1|on|off>" + .usage = "[0|1|on|off]" }, { .name = "freemem", From 5b3d503e2e62d98ef107813af82bd573bda41239 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 24 Jul 2024 20:56:38 +0200 Subject: [PATCH 0907/1312] doc: Add 'jlink targetpower' command Change-Id: I7e6c9e75f3c70675a3ea55fd5f0d7de1a35f2c4b Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8418 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index a8a1892db8..fa0ffc7315 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2958,6 +2958,11 @@ Display free device internal memory. Set the JTAG command version to be used. Without argument, show the actual JTAG command version. @end deffn +@deffn {Command} {jlink targetpower} [@option{0}|@option{1}|@option{on}|@option{off}] +Switch the 5@ V target power supply on or off. +Without argument, show the state of the target power supply. +The target power supply is usually connected to pin 19 of the 20-pin connector. +@end deffn @deffn {Command} {jlink config} Display the device configuration. @end deffn From d5adab697fd8b65934acc2ffef105e9ab9804bcf Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 21 Apr 2024 20:00:28 +0200 Subject: [PATCH 0908/1312] target/breakpoints: Fix 'orig_instr' output The 'orig_instr' information of software breakpoints is incorrect because buf_to_hex_str() expects the length of the buffer to be converted in bits and not bytes. Change-Id: I9a9ed383a8c25200d461b899749d5259ee4c6e3d Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8218 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/target.c b/src/target/target.c index bd2638f2d0..b6159c72b7 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3921,7 +3921,7 @@ static int handle_bp_command_list(struct command_invocation *cmd) while (breakpoint) { if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_hex_str(breakpoint->orig_instr, - breakpoint->length); + breakpoint->length * 8); command_print(cmd, "Software breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, orig_instr=0x%s", breakpoint->address, breakpoint->length, From b9224c0c0f2a3d1ec52aab6ca985d1affa9a18b9 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 15 Apr 2024 21:02:43 +0200 Subject: [PATCH 0909/1312] transport: Remove echo in transport selection Do not echo the selected transport to avoid stray and confusing messages in the output of OpenOCD. For example, the "swd" line here: Open On-Chip Debugger 0.12.0+dev-00559-ge02f6c1b9-dirty Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html swd Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections While at it, fix some small documentation style issues. Change-Id: Ie85426c441289bbaa35615dbb7b53f0b5c46cfc0 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8217 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 16 +++++++--------- src/transport/transport.c | 2 -- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index fa0ffc7315..794762fa2d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3693,20 +3693,18 @@ displays the names of the transports supported by this version of OpenOCD. @end deffn -@deffn {Command} {transport select} @option{transport_name} +@deffn {Command} {transport select} [transport_name] Select which of the supported transports to use in this OpenOCD session. When invoked with @option{transport_name}, attempts to select the named -transport. The transport must be supported by the debug adapter +transport. The transport must be supported by the debug adapter hardware and by the version of OpenOCD you are using (including the adapter's driver). - -If no transport has been selected and no @option{transport_name} is -provided, @command{transport select} auto-selects the first transport -supported by the debug adapter. - -@command{transport select} always returns the name of the session's selected -transport, if any. +When invoked with no transport name: +@itemize @minus +@item if no transport has been selected yet, it auto-selects the first transport supported by the debug adapter +@item it returns the name of the session's selected transport +@end itemize @end deffn @subsection JTAG Transport diff --git a/src/transport/transport.c b/src/transport/transport.c index 81d3d583bc..bf306e7314 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -278,7 +278,6 @@ COMMAND_HANDLER(handle_transport_select) if (session) { if (!strcmp(session->name, CMD_ARGV[0])) { LOG_WARNING("Transport \"%s\" was already selected", session->name); - command_print(CMD, "%s", session->name); return ERROR_OK; } command_print(CMD, "Can't change session's transport after the initial selection was made"); @@ -301,7 +300,6 @@ COMMAND_HANDLER(handle_transport_select) int retval = transport_select(CMD_CTX, CMD_ARGV[0]); if (retval != ERROR_OK) return retval; - command_print(CMD, "%s", session->name); return ERROR_OK; } } From efe90221979458960618a5a5c8f90b116e91f011 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 24 Jun 2024 16:26:46 +0200 Subject: [PATCH 0910/1312] server/telnet: Always allow 'exit' command The telnet 'exit' command is only available in the execution phase of OpenOCD. Thus, a telnet session cannot be closed via 'exit' if OpenOCD is started with 'noinit'. Make the 'exit' command always available. Change-Id: I14447ecde63e579f1c523d606f048ad29cc84a35 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8379 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/server/telnet_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 72171cb3f5..02d450fbdf 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -982,7 +982,7 @@ static const struct command_registration telnet_command_handlers[] = { { .name = "exit", .handler = handle_exit_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .usage = "", .help = "exit telnet session", }, From ac63cd00d792331914db0b6edd3f427c30eec3fa Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 2 Aug 2024 19:45:09 +0200 Subject: [PATCH 0911/1312] tcl/interface/raspberrypi5-gpiod: fix string match pattern escaping Use correct TCL syntax and save string map operation. Change-Id: Ic2a522bd57cf6610b7df1d9cddd0fbdc2076ed62 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8426 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/interface/raspberrypi5-gpiod.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tcl/interface/raspberrypi5-gpiod.cfg b/tcl/interface/raspberrypi5-gpiod.cfg index f3fdde0f20..9624ad5114 100644 --- a/tcl/interface/raspberrypi5-gpiod.cfg +++ b/tcl/interface/raspberrypi5-gpiod.cfg @@ -19,8 +19,7 @@ proc read_file { name } { } set pcie_aspm [read_file /sys/module/pcie_aspm/parameters/policy] -# escaping [ ] characters in string match pattern does not work in Jim-Tcl -if {![string match "**" [string map { "\[" < "\]" > } $pcie_aspm]]} { +if {![string match {*\[performance\]*} $pcie_aspm]} { echo "Warn : Switch PCIe power saving off or the first couple of pulses gets clocked as fast as 20 MHz" echo "Warn : Issue 'echo performance | sudo tee /sys/module/pcie_aspm/parameters/policy'" } From a414ffaf65171bf2d1ed289397befca3cbf8b967 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 12 Aug 2024 13:39:36 +0200 Subject: [PATCH 0912/1312] doc: document command 'ms' Add documentation for the commands 'ms'. Change-Id: I247adce1c586c4f4cd36d044d48298c370635e67 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8432 Tested-by: jenkins --- doc/openocd.texi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 794762fa2d..c786382768 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9621,6 +9621,12 @@ Add or replace help text on the given @var{command_name}. Add or replace usage text on the given @var{command_name}. @end deffn +@deffn {Command} {ms} +Returns current time since the Epoch in ms +(See: @url{https://en.wikipedia.org/wiki/Epoch_(computing)}). +Useful to compute delays in TCL. +@end deffn + @node Architecture and Core Commands @chapter Architecture and Core Commands @cindex Architecture Specific Commands From ea859e1cd042578ea17994b56ac15be216eefe4a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jul 2024 11:28:49 +0200 Subject: [PATCH 0913/1312] helper: command: drop radix parameter from command_parse_str_to_buf() Commit 53b94fad58ab ("binarybuffer: Fix str_to_buf() parsing function") introduces the helper command_parse_str_to_buf() to parse as number a string on TCL command-line. The parameter 'radix' can specify the base (decimal, octal, hexadecimal, or auto-detected). TCL is supposed to use decimal numbers by default, while octal and hexadecimal numbers must be prefixed respectively with '0' and '0x' (or '0X'). This would require the helper to always run auto-detection of the base, thus always set the 'radix' parameter to zero. This makes the parameter useless. Keeping the 'radix' parameter can open the door to future abuse of TCL syntax, E.g. a command can require an octal value without the mandatory TCL '0' prefix; the octal value cannot be the result of TCL expression. To prevent any future abuse of the 'radix' parameter, drop it. Change-Id: I88855bd83b4e08e8fdcf86a2fa5ef3269dd4ad57 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8393 Tested-by: jenkins Reviewed-by: Jan Matyas --- src/helper/command.c | 25 +++---------------------- src/helper/command.h | 8 +++----- src/jtag/tcl.c | 2 +- src/target/target.c | 5 ++--- 4 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 15a9b4a084..b5dd927f25 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -1360,37 +1360,18 @@ int command_parse_bool_arg(const char *in, bool *out) return ERROR_COMMAND_SYNTAX_ERROR; } -static const char *radix_to_str(unsigned int radix) -{ - switch (radix) { - case 16: return "hexadecimal"; - case 10: return "decadic"; - case 8: return "octal"; - } - assert(false); - return ""; -} - -COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len, - unsigned int radix) +COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len) { assert(str); assert(buf); - int ret = str_to_buf(str, buf, buf_len, radix, NULL); + int ret = str_to_buf(str, buf, buf_len, 0, NULL); if (ret == ERROR_OK) return ret; /* Provide a clear error message to the user */ if (ret == ERROR_INVALID_NUMBER) { - if (radix == 0) { - /* Any radix is accepted, so don't include it in the error message. */ - command_print(CMD, "'%s' is not a valid number", str); - } else { - /* Specific radix is required - tell the user what it is. */ - command_print(CMD, "'%s' is not a valid number (requiring %s number)", - str, radix_to_str(radix)); - } + command_print(CMD, "'%s' is not a valid number", str); } else if (ret == ERROR_NUMBER_EXCEEDS_BUFFER) { command_print(CMD, "Number %s exceeds %u bits", str, buf_len); } else { diff --git a/src/helper/command.h b/src/helper/command.h index 7a044e6191..b224bd0221 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -519,14 +519,12 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); /** * Parse a number (base 10, base 16 or base 8) and store the result - * into a bit buffer. + * into a bit buffer. Use the prefixes '0' and '0x' for base 8 and 16, + * otherwise defaults to base 10. * * In case of parsing error, a user-readable error message is produced. - * - * If radix = 0 is given, the function guesses the radix by looking at the number prefix. */ -COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len, - unsigned int radix); +COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len); /** parses an on/off command argument */ #define COMMAND_PARSE_ON_OFF(in, out) \ diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 10a7dd3f84..624b4e4c2a 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -89,7 +89,7 @@ static COMMAND_HELPER(handle_jtag_command_drscan_fields, struct scan_field *fiel } fields[field_count].out_value = t; - int ret = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[i + 1], t, bits, 0); + int ret = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[i + 1], t, bits); if (ret != ERROR_OK) return ret; fields[field_count].in_value = t; diff --git a/src/target/target.c b/src/target/target.c index b6159c72b7..09396d8780 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3133,7 +3133,7 @@ COMMAND_HANDLER(handle_reg_command) return ERROR_FAIL; } - int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[1], buf, reg->size, 0); + int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[1], buf, reg->size); if (retval != ERROR_OK) { free(buf); return retval; @@ -4835,8 +4835,7 @@ COMMAND_HANDLER(handle_set_reg_command) return ERROR_FAIL; } - int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, - reg_value, buf, reg->size, 0); + int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, reg_value, buf, reg->size); if (retval != ERROR_OK) { free(buf); return retval; From 8a3efbf21fda2ac673c401f8b9ec82d300c2af29 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jul 2024 12:09:15 +0200 Subject: [PATCH 0914/1312] binarybuffer: simplify the prototype of str_to_buf() With 'radix' always zero and '_detected_radix' always NULL, drop the two parameters and simplify str_to_buf(). While there: - drop some redundant assert(), - drop the re-check for the base prefix, - simplify str_strip_number_prefix_if_present() and rename it, as the prefix MUST be present, - fix a minor typo, - update the doxygen description of str_to_buf(). Change-Id: I1abdc8ec0587b23881953d3094101c04d5bb1c58 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8394 Tested-by: jenkins Reviewed-by: Jan Matyas --- src/helper/binarybuffer.c | 42 ++++++++++++++------------------------- src/helper/binarybuffer.h | 9 ++++----- src/helper/command.c | 2 +- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 3e09143c68..da6e10bab7 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -225,49 +225,37 @@ static bool str_has_octal_prefix(const char *s) */ static unsigned int str_radix_guess(const char *str) { - assert(str); - if (str_has_hex_prefix(str)) return 16; if (str_has_octal_prefix(str)) return 8; - /* Otherwise assume a decadic number. */ + /* Otherwise assume a decimal number. */ return 10; } /** Strip leading "0x" or "0X" from hex numbers or "0" from octal numbers. */ -static void str_strip_number_prefix_if_present(const char **_str, unsigned int radix) +static const char *str_strip_number_prefix(const char *str, unsigned int radix) { - assert(radix == 16 || radix == 10 || radix == 8); - assert(_str); - - const char *str = *_str; - assert(str); - - if (radix == 16 && str_has_hex_prefix(str)) - str += 2; - else if (radix == 8 && str_has_octal_prefix(str)) - str += 1; - - /* No prefix to strip for radix == 10. */ - - *_str = str; + switch (radix) { + case 16: + return str + 2; + case 8: + return str + 1; + case 10: + default: + return str; + } } -int str_to_buf(const char *str, void *_buf, unsigned int buf_len, - unsigned int radix, unsigned int *_detected_radix) +int str_to_buf(const char *str, void *_buf, unsigned int buf_len) { - assert(radix == 0 || radix == 8 || radix == 10 || radix == 16); - - if (radix == 0) - radix = str_radix_guess(str); + assert(str); - if (_detected_radix) - *_detected_radix = radix; + unsigned int radix = str_radix_guess(str); - str_strip_number_prefix_if_present(&str, radix); + str = str_strip_number_prefix(str, radix); const size_t str_len = strlen(str); if (str_len == 0) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index 441374330e..6cff86bd92 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -194,15 +194,14 @@ void *buf_set_buf(const void *src, unsigned src_start, /** * Parse an unsigned number (provided as a zero-terminated string) - * into a bit buffer whose size is buf_len bits. + * into a bit buffer whose size is buf_len bits. The base of the + * number is detected between decimal, hexadecimal and octal. * @param str Input number, zero-terminated string * @param _buf Output buffer, allocated by the caller * @param buf_len Output buffer size in bits - * @param radix Base of the input number - 16, 10, 8 or 0. - * 0 means auto-detect the radix. + * @returns Error on invalid or overflowing number */ -int str_to_buf(const char *str, void *_buf, unsigned int buf_len, - unsigned int radix, unsigned int *_detected_radix); +int str_to_buf(const char *str, void *_buf, unsigned int buf_len); char *buf_to_hex_str(const void *buf, unsigned size); diff --git a/src/helper/command.c b/src/helper/command.c index b5dd927f25..907869325d 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -1365,7 +1365,7 @@ COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned in assert(str); assert(buf); - int ret = str_to_buf(str, buf, buf_len, 0, NULL); + int ret = str_to_buf(str, buf, buf_len); if (ret == ERROR_OK) return ret; From bee5999a447880dda271926bbbd7d49dc5f4fbe9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jul 2024 12:31:53 +0200 Subject: [PATCH 0915/1312] binarybuffer: str_to_buf(): rename buf_len as buf_bitsize The name 'buf_len' is misleading, as it usually refers to the byte length of a buffer. Here we use it for the length in bits. Rename it as 'buf_bitsize'. While there, fix checkpatch error by changing the index type to 'unsigned int'. Change-Id: I78855ed79a346d996d9c0100d94d14c64a36b228 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8395 Tested-by: jenkins Reviewed-by: Jan Matyas --- src/helper/binarybuffer.c | 14 +++++++------- src/helper/binarybuffer.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index da6e10bab7..dd1449276a 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -249,7 +249,7 @@ static const char *str_strip_number_prefix(const char *str, unsigned int radix) } } -int str_to_buf(const char *str, void *_buf, unsigned int buf_len) +int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize) { assert(str); @@ -314,18 +314,18 @@ int str_to_buf(const char *str, void *_buf, unsigned int buf_len) assert(tmp == 0); } - /* The result must not contain more bits than buf_len. */ + /* The result must not contain more bits than buf_bitsize. */ /* Check the whole bytes: */ - for (unsigned int j = DIV_ROUND_UP(buf_len, 8); j < b256_len; j++) { + for (unsigned int j = DIV_ROUND_UP(buf_bitsize, 8); j < b256_len; j++) { if (b256_buf[j] != 0x0) { free(b256_buf); return ERROR_NUMBER_EXCEEDS_BUFFER; } } /* Check the partial byte: */ - if (buf_len % 8) { - const uint8_t mask = 0xFFu << (buf_len % 8); - if ((b256_buf[(buf_len / 8)] & mask) != 0x0) { + if (buf_bitsize % 8) { + const uint8_t mask = 0xFFu << (buf_bitsize % 8); + if ((b256_buf[(buf_bitsize / 8)] & mask) != 0x0) { free(b256_buf); return ERROR_NUMBER_EXCEEDS_BUFFER; } @@ -333,7 +333,7 @@ int str_to_buf(const char *str, void *_buf, unsigned int buf_len) /* Copy the digits to the output buffer */ uint8_t *buf = _buf; - for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) { + for (unsigned int j = 0; j < DIV_ROUND_UP(buf_bitsize, 8); j++) { if (j < b256_len) buf[j] = b256_buf[j]; else diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index 6cff86bd92..103a48c5c5 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -198,10 +198,10 @@ void *buf_set_buf(const void *src, unsigned src_start, * number is detected between decimal, hexadecimal and octal. * @param str Input number, zero-terminated string * @param _buf Output buffer, allocated by the caller - * @param buf_len Output buffer size in bits + * @param buf_bitsize Output buffer size in bits * @returns Error on invalid or overflowing number */ -int str_to_buf(const char *str, void *_buf, unsigned int buf_len); +int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize); char *buf_to_hex_str(const void *buf, unsigned size); From bfd3110e59f5b13c075823c654f1a51cfcd66d4d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 14 Jul 2024 14:59:34 +0200 Subject: [PATCH 0916/1312] binarybuffer: str_to_buf(): simplify it and fix scan-build error The function str_to_buf() can be simplified by writing directly the intermediate results in the output buffer. Such simplification improves the readability and also makes scan-build happy, as it does not trigger anymore the warning: src/helper/binarybuffer.c:328:8: warning: Use of memory allocated with size zero [unix.Malloc] if ((b256_buf[(buf_len / 8)] & mask) != 0x0) { Change-Id: I1cef9a1ec5ff0e5841ba582610f273e89e7a81da Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8396 Reviewed-by: Jan Matyas Tested-by: jenkins --- src/helper/binarybuffer.c | 99 ++++++++++----------------------------- 1 file changed, 26 insertions(+), 73 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index dd1449276a..509f24f0b3 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -175,19 +175,6 @@ uint32_t flip_u32(uint32_t value, unsigned int num) return c; } -static int ceil_f_to_u32(float x) -{ - if (x < 0) /* return zero for negative numbers */ - return 0; - - uint32_t y = x; /* cut off fraction */ - - if ((x - y) > 0.0) /* if there was a fractional part, increase by one */ - y++; - - return y; -} - char *buf_to_hex_str(const void *_buf, unsigned buf_len) { unsigned len_bytes = DIV_ROUND_UP(buf_len, 8); @@ -252,7 +239,10 @@ static const char *str_strip_number_prefix(const char *str, unsigned int radix) int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize) { assert(str); + assert(_buf); + assert(buf_bitsize > 0); + uint8_t *buf = _buf; unsigned int radix = str_radix_guess(str); str = str_strip_number_prefix(str, radix); @@ -261,86 +251,49 @@ int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize) if (str_len == 0) return ERROR_INVALID_NUMBER; - float factor = 0.0; - if (radix == 16) - factor = 0.5; /* log(16) / log(256) = 0.5 */ - else if (radix == 10) - factor = 0.41524; /* log(10) / log(256) = 0.41524 */ - else if (radix == 8) - factor = 0.375; /* log(8) / log(256) = 0.375 */ - else - assert(false); - - const unsigned int b256_len = ceil_f_to_u32(str_len * factor); - - /* Allocate a buffer for digits in base-256 notation */ - uint8_t *b256_buf = calloc(b256_len, 1); - if (!b256_buf) { - LOG_ERROR("Unable to allocate memory"); - return ERROR_FAIL; - } + const size_t buf_len = DIV_ROUND_UP(buf_bitsize, 8); + memset(buf, 0, buf_len); /* Go through the zero-terminated buffer * of input digits (ASCII) */ - for (unsigned int i = 0; str[i]; i++) { - uint32_t tmp = str[i]; - if ((tmp >= '0') && (tmp <= '9')) { - tmp = (tmp - '0'); - } else if ((tmp >= 'a') && (tmp <= 'f')) { - tmp = (tmp - 'a' + 10); - } else if ((tmp >= 'A') && (tmp <= 'F')) { - tmp = (tmp - 'A' + 10); + for (; *str; str++) { + unsigned int tmp; + const char c = *str; + + if ((c >= '0') && (c <= '9')) { + tmp = c - '0'; + } else if ((c >= 'a') && (c <= 'f')) { + tmp = c - 'a' + 10; + } else if ((c >= 'A') && (c <= 'F')) { + tmp = c - 'A' + 10; } else { /* Characters other than [0-9,a-f,A-F] are invalid */ - free(b256_buf); return ERROR_INVALID_NUMBER; } - if (tmp >= radix) { - /* Encountered a digit that is invalid for the current radix */ - free(b256_buf); + /* Error on invalid digit for current radix */ + if (tmp >= radix) return ERROR_INVALID_NUMBER; - } - /* Add the current digit (tmp) to the intermediate result - * in b256_buf (base-256 digits) */ - for (unsigned int j = 0; j < b256_len; j++) { - tmp += (uint32_t)b256_buf[j] * radix; - b256_buf[j] = (uint8_t)(tmp & 0xFFu); + /* Add the current digit (tmp) to the intermediate result in buf */ + for (unsigned int j = 0; j < buf_len; j++) { + tmp += buf[j] * radix; + buf[j] = tmp & 0xFFu; tmp >>= 8; } - /* The b256_t buffer is large enough to contain the whole result. */ - assert(tmp == 0); - } - - /* The result must not contain more bits than buf_bitsize. */ - /* Check the whole bytes: */ - for (unsigned int j = DIV_ROUND_UP(buf_bitsize, 8); j < b256_len; j++) { - if (b256_buf[j] != 0x0) { - free(b256_buf); + /* buf should be large enough to contain the whole result. */ + if (tmp != 0) return ERROR_NUMBER_EXCEEDS_BUFFER; - } } - /* Check the partial byte: */ + + /* Check the partial most significant byte */ if (buf_bitsize % 8) { const uint8_t mask = 0xFFu << (buf_bitsize % 8); - if ((b256_buf[(buf_bitsize / 8)] & mask) != 0x0) { - free(b256_buf); + if ((buf[buf_len - 1] & mask) != 0x0) return ERROR_NUMBER_EXCEEDS_BUFFER; - } - } - - /* Copy the digits to the output buffer */ - uint8_t *buf = _buf; - for (unsigned int j = 0; j < DIV_ROUND_UP(buf_bitsize, 8); j++) { - if (j < b256_len) - buf[j] = b256_buf[j]; - else - buf[j] = 0; } - free(b256_buf); return ERROR_OK; } From ceae51ad74ba3a16be3e7ee2df4743a6df3cd097 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 1 Aug 2024 10:43:41 +0200 Subject: [PATCH 0917/1312] checkpatch: only report error on hit The Linux checkpatch script used by OpenOCD reports hits either as error, warning and check. Such classification is meaningful for Linux maintainers, but for OpenOCD Jenkins they are all considered as errors. Having such classification in the checkpatch report by Jenkins is misleading for developers that expect 'warnings' to be probably ignored by maintainers, while having no idea what 'checks' means. This patch flattens all the checkpatch reports to 'error' only. Checkpatch can trigger false positives. OpenOCD uses the tag Checkpatch-ignore: in the commit message to prevent Jenkins to report the error, as described in HACKING. Change-Id: I1d3164ba1f725c0763dfe362192ffa669b3856e6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8424 Reviewed-by: Karl Palsson Tested-by: jenkins --- tools/scripts/checkpatch.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl index 26589beab0..a2f89eac89 100755 --- a/tools/scripts/checkpatch.pl +++ b/tools/scripts/checkpatch.pl @@ -2384,6 +2384,10 @@ sub show_type { sub report { my ($level, $type, $msg) = @_; + # OpenOCD specific: Begin: Flatten ERROR, WARNING and CHECK as ERROR + $level = 'ERROR'; + # OpenOCD specific: End + if (!show_type($type) || (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { return 0; @@ -7638,9 +7642,15 @@ sub process { print report_dump(); if ($summary && !($clean == 1 && $quiet == 1)) { print "$filename " if ($summary_file); + if (!$OpenOCD) { print "total: $cnt_error errors, $cnt_warn warnings, " . (($check)? "$cnt_chk checks, " : "") . "$cnt_lines lines checked\n"; + } # $OpenOCD + # OpenOCD specific: Begin: Report total as errors + my $total = $cnt_error + $cnt_warn + $cnt_chk; + print "total: $total errors, $cnt_lines lines checked\n"; + # OpenOCD specific: End } if ($quiet == 0) { From 16429f6252c0d4b985d882e53ff476fe42fa0125 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 1 Aug 2024 09:22:02 +0200 Subject: [PATCH 0918/1312] target/arm_cti: Use suitable data types While at it, fix some small coding style issues. Change-Id: Ifb8e78b55d29a06d69a3ce71d12d0040777aef13 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8423 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_cti.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 7637ad0158..0ea853e493 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -196,9 +196,7 @@ static const struct { static int cti_find_reg_offset(const char *name) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(cti_names); i++) { + for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) { if (!strcmp(name, cti_names[i].label)) return cti_names[i].offset; } @@ -227,7 +225,7 @@ COMMAND_HANDLER(handle_cti_dump) struct adiv5_ap *ap = cti->ap; int retval = ERROR_OK; - for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++) + for (size_t i = 0; (retval == ERROR_OK) && (i < ARRAY_SIZE(cti_names)); i++) retval = mem_ap_read_u32(ap, cti->spot.base + cti_names[i].offset, cti_names[i].p_val); @@ -237,7 +235,7 @@ COMMAND_HANDLER(handle_cti_dump) if (retval != ERROR_OK) return JIM_ERR; - for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++) + for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32, cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val); @@ -323,7 +321,6 @@ COMMAND_HANDLER(handle_cti_ack) int retval = arm_cti_ack_events(cti, 1 << event); - if (retval != ERROR_OK) return retval; @@ -437,6 +434,7 @@ static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti) return JIM_OK; } + static int cti_create(struct jim_getopt_info *goi) { struct command_context *cmd_ctx; @@ -538,7 +536,6 @@ COMMAND_HANDLER(cti_handle_names) return ERROR_OK; } - static const struct command_registration cti_subcommand_handlers[] = { { .name = "create", From d3f50ea9145aa6cbe9232ab29736aebbd60763cd Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 7 Jun 2024 14:42:58 +0200 Subject: [PATCH 0919/1312] target: arm_adi_v5: add more CoreSight P/N Add part numbers for: - Cortex-A65AE, - Cortex-M52, - Cortex-M55, - Cortex-R52+, - STAR-MC1. Change-Id: I6282768896dd727e803a071139816494470744f1 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8319 Tested-by: jenkins --- src/target/arm_adi_v5.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 9129acecf9..8a97d7a524 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1453,11 +1453,13 @@ static const struct dap_part_nums { { ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", }, { ARM_ID, 0x4b5, "Cortex-R5 ROM", "(ROM Table)", }, { ARM_ID, 0x4b8, "Cortex-R52 ROM", "(ROM Table)", }, + { ARM_ID, 0x4bd, "Cortex-R52+ ROM", "(ROM Table)", }, { ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", }, { ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", }, { ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", }, { ARM_ID, 0x4c7, "Cortex-M7 PPB ROM", "(Private Peripheral Bus ROM Table)", }, { ARM_ID, 0x4c8, "Cortex-M7 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c9, "STAR ROM", "(ROM Table)", }, { ARM_ID, 0x4e0, "Cortex-A35 ROM", "(v7 Memory Map ROM Table)", }, { ARM_ID, 0x4e4, "Cortex-A76 ROM", "(ROM Table)", }, { ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", }, @@ -1499,6 +1501,7 @@ static const struct dap_part_nums { { ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9b6, "Cortex-R52 PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", }, + { ARM_ID, 0x9bb, "Cortex-R52+ PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", }, { ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", }, @@ -1533,6 +1536,10 @@ static const struct dap_part_nums { { ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0c, "Neoverse N1", "(Debug Unit)", }, { ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd16, "Cortex-R52+ Debug", "(Debug Unit)", }, + { ARM_ID, 0xd21, "STAR Debug", "(Debug Unit)", }, + { ARM_ID, 0xd22, "Cortex-M55 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd43, "Cortex-A65AE Debug", "(Debug Unit)", }, { ARM_ID, 0xd49, "Neoverse N2", "(Debug Unit)", }, { 0x017, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ { 0x017, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ @@ -1552,6 +1559,9 @@ static const struct dap_part_nums { { 0x1eb, 0x211, "Tegra 210 ROM", "(ROM Table)", }, { 0x1eb, 0x302, "Denver Debug", "(Debug Unit)", }, { 0x1eb, 0x402, "Denver PMU", "(Performance Monitor Unit)", }, + { 0x575, 0x132, "STAR SCS", "(System Control Space)", }, + { 0x575, 0x4d2, "Cortex-M52 ROM", "(ROM Table)", }, + { 0x575, 0xd24, "Cortex-M52 Debug", "(Debug Unit)", }, }; static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, unsigned int part_num) From 7eb9a48f2d53a773d822b7a2b93f53c09acb48d9 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 30 Jul 2024 18:03:33 -0700 Subject: [PATCH 0920/1312] arm_adi_v5: Also clear sticky overrun bit on init Some targets start up with the sticky overrun bit set. On such targets we need to clear it in order to avoid subsequent incorrect reads. Change-Id: I3e939a9e092de6fcea9494d3179a3386aa1701d2 Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/8420 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/arm_adi_v5.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 8a97d7a524..3a5afc605a 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -795,11 +795,12 @@ int dap_dp_init(struct adiv5_dap *dap) dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; /* - * This write operation clears the sticky error bit in jtag mode only and - * is ignored in swd mode. It also powers-up system and debug domains in - * both jtag and swd modes, if not done before. + * This write operation clears the sticky error and overrun bits in jtag + * mode only and is ignored in swd mode. It also powers-up system and + * debug domains in both jtag and swd modes, if not done before. */ - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat | SSTICKYERR); + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, + dap->dp_ctrl_stat | SSTICKYERR | SSTICKYORUN); if (retval != ERROR_OK) return retval; From fc1e73b9cf4264350f445479a5a08833582e0cc3 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 31 Jul 2024 19:02:42 -0700 Subject: [PATCH 0921/1312] arm_cti: Clean up the list of CTI registers Reduce the amount of boilerplate by moving cti_regs into its only user, making it a local variable and removing the now-redundant p_val pointer. Change-Id: I778cc1e960532fae1ac1a952c6ff19c54e578a5f Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/8421 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/arm_cti.c | 64 +++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 0ea853e493..422513e3ec 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -157,41 +157,38 @@ int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel) return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel)); } -static uint32_t cti_regs[28]; - static const struct { uint32_t offset; const char *label; - uint32_t *p_val; } cti_names[] = { - { CTI_CTR, "CTR", &cti_regs[0] }, - { CTI_GATE, "GATE", &cti_regs[1] }, - { CTI_INEN0, "INEN0", &cti_regs[2] }, - { CTI_INEN1, "INEN1", &cti_regs[3] }, - { CTI_INEN2, "INEN2", &cti_regs[4] }, - { CTI_INEN3, "INEN3", &cti_regs[5] }, - { CTI_INEN4, "INEN4", &cti_regs[6] }, - { CTI_INEN5, "INEN5", &cti_regs[7] }, - { CTI_INEN6, "INEN6", &cti_regs[8] }, - { CTI_INEN7, "INEN7", &cti_regs[9] }, - { CTI_INEN8, "INEN8", &cti_regs[10] }, - { CTI_OUTEN0, "OUTEN0", &cti_regs[11] }, - { CTI_OUTEN1, "OUTEN1", &cti_regs[12] }, - { CTI_OUTEN2, "OUTEN2", &cti_regs[13] }, - { CTI_OUTEN3, "OUTEN3", &cti_regs[14] }, - { CTI_OUTEN4, "OUTEN4", &cti_regs[15] }, - { CTI_OUTEN5, "OUTEN5", &cti_regs[16] }, - { CTI_OUTEN6, "OUTEN6", &cti_regs[17] }, - { CTI_OUTEN7, "OUTEN7", &cti_regs[18] }, - { CTI_OUTEN8, "OUTEN8", &cti_regs[19] }, - { CTI_TRIN_STATUS, "TRIN", &cti_regs[20] }, - { CTI_TROUT_STATUS, "TROUT", &cti_regs[21] }, - { CTI_CHIN_STATUS, "CHIN", &cti_regs[22] }, - { CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] }, - { CTI_APPSET, "APPSET", &cti_regs[24] }, - { CTI_APPCLEAR, "APPCLR", &cti_regs[25] }, - { CTI_APPPULSE, "APPPULSE", &cti_regs[26] }, - { CTI_INACK, "INACK", &cti_regs[27] }, + { CTI_CTR, "CTR" }, + { CTI_GATE, "GATE" }, + { CTI_INEN0, "INEN0" }, + { CTI_INEN1, "INEN1" }, + { CTI_INEN2, "INEN2" }, + { CTI_INEN3, "INEN3" }, + { CTI_INEN4, "INEN4" }, + { CTI_INEN5, "INEN5" }, + { CTI_INEN6, "INEN6" }, + { CTI_INEN7, "INEN7" }, + { CTI_INEN8, "INEN8" }, + { CTI_OUTEN0, "OUTEN0" }, + { CTI_OUTEN1, "OUTEN1" }, + { CTI_OUTEN2, "OUTEN2" }, + { CTI_OUTEN3, "OUTEN3" }, + { CTI_OUTEN4, "OUTEN4" }, + { CTI_OUTEN5, "OUTEN5" }, + { CTI_OUTEN6, "OUTEN6" }, + { CTI_OUTEN7, "OUTEN7" }, + { CTI_OUTEN8, "OUTEN8" }, + { CTI_TRIN_STATUS, "TRIN" }, + { CTI_TROUT_STATUS, "TROUT" }, + { CTI_CHIN_STATUS, "CHIN" }, + { CTI_CHOU_STATUS, "CHOUT" }, + { CTI_APPSET, "APPSET" }, + { CTI_APPCLEAR, "APPCLR" }, + { CTI_APPPULSE, "APPPULSE" }, + { CTI_INACK, "INACK" }, }; static int cti_find_reg_offset(const char *name) @@ -224,10 +221,11 @@ COMMAND_HANDLER(handle_cti_dump) struct arm_cti *cti = CMD_DATA; struct adiv5_ap *ap = cti->ap; int retval = ERROR_OK; + uint32_t values[ARRAY_SIZE(cti_names)]; for (size_t i = 0; (retval == ERROR_OK) && (i < ARRAY_SIZE(cti_names)); i++) retval = mem_ap_read_u32(ap, - cti->spot.base + cti_names[i].offset, cti_names[i].p_val); + cti->spot.base + cti_names[i].offset, &values[i]); if (retval == ERROR_OK) retval = dap_run(ap->dap); @@ -237,7 +235,7 @@ COMMAND_HANDLER(handle_cti_dump) for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32, - cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val); + cti_names[i].label, cti_names[i].offset, values[i]); return JIM_OK; } From 941fa8538f2ad491f365a3818caa7534aaf29ea3 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 31 Jul 2024 19:05:06 -0700 Subject: [PATCH 0922/1312] arm_cti: Add CTIDEVCTL to register list This is useful for setting a reset catch on a CPU that is being brought out of reset. Change-Id: Id8fe9bc3f75fd170f207f470a9f3b0faba7f24c1 Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/8422 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_cti.c | 1 + src/target/arm_cti.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 422513e3ec..97d1fb34bf 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -189,6 +189,7 @@ static const struct { { CTI_APPCLEAR, "APPCLR" }, { CTI_APPPULSE, "APPPULSE" }, { CTI_INACK, "INACK" }, + { CTI_DEVCTL, "DEVCTL" }, }; static int cti_find_reg_offset(const char *name) diff --git a/src/target/arm_cti.h b/src/target/arm_cti.h index cfcde65608..1513f0254a 100644 --- a/src/target/arm_cti.h +++ b/src/target/arm_cti.h @@ -39,6 +39,7 @@ #define CTI_CHIN_STATUS 0x138 #define CTI_CHOU_STATUS 0x13C #define CTI_GATE 0x140 +#define CTI_DEVCTL 0x150 #define CTI_UNLOCK 0xFB0 #define CTI_CHNL(x) (1 << x) From 0bf3373e808a097fdf50fc04f987c26b35ddf09d Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 31 Jul 2024 09:35:03 +0200 Subject: [PATCH 0923/1312] target/breakpoints: Use 'unsigned int' for length Change-Id: I233efb5b18de5f043fdc976807437db0a94236d1 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/7056 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/breakpoints.c | 18 +++++++++--------- src/target/breakpoints.h | 13 +++++++------ src/target/target.c | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index c39a980570..2fbb69e07a 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -38,7 +38,7 @@ static int bpwp_unique_id; static int breakpoint_add_internal(struct target *target, target_addr_t address, - uint32_t length, + unsigned int length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; @@ -101,7 +101,7 @@ static int breakpoint_add_internal(struct target *target, static int context_breakpoint_add_internal(struct target *target, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; @@ -151,7 +151,7 @@ static int context_breakpoint_add_internal(struct target *target, static int hybrid_breakpoint_add_internal(struct target *target, target_addr_t address, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; @@ -207,7 +207,7 @@ static int hybrid_breakpoint_add_internal(struct target *target, int breakpoint_add(struct target *target, target_addr_t address, - uint32_t length, + unsigned int length, enum breakpoint_type type) { if (target->smp) { @@ -233,7 +233,7 @@ int breakpoint_add(struct target *target, int context_breakpoint_add(struct target *target, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { if (target->smp) { @@ -255,7 +255,7 @@ int context_breakpoint_add(struct target *target, int hybrid_breakpoint_add(struct target *target, target_addr_t address, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { if (target->smp) { @@ -500,7 +500,7 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) } static int watchpoint_add_internal(struct target *target, target_addr_t address, - uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) + unsigned int length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; @@ -556,7 +556,7 @@ static int watchpoint_add_internal(struct target *target, target_addr_t address, } LOG_TARGET_DEBUG(target, "added %s watchpoint at " TARGET_ADDR_FMT - " of length 0x%8.8" PRIx32 " (WPID: %d)", + " of length 0x%8.8x (WPID: %d)", watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, (*watchpoint_p)->length, @@ -566,7 +566,7 @@ static int watchpoint_add_internal(struct target *target, target_addr_t address, } int watchpoint_add(struct target *target, target_addr_t address, - uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) + unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) { if (target->smp) { struct target_list *head; diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 64c0ce2a5a..0789267c7d 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -26,7 +26,7 @@ enum watchpoint_rw { struct breakpoint { target_addr_t address; uint32_t asid; - int length; + unsigned int length; enum breakpoint_type type; bool is_set; unsigned int number; @@ -40,7 +40,7 @@ struct breakpoint { struct watchpoint { target_addr_t address; - uint32_t length; + unsigned int length; uint64_t mask; uint64_t value; enum watchpoint_rw rw; @@ -52,11 +52,12 @@ struct watchpoint { int breakpoint_clear_target(struct target *target); int breakpoint_add(struct target *target, - target_addr_t address, uint32_t length, enum breakpoint_type type); + target_addr_t address, unsigned int length, enum breakpoint_type type); int context_breakpoint_add(struct target *target, - uint32_t asid, uint32_t length, enum breakpoint_type type); + uint32_t asid, unsigned int length, enum breakpoint_type type); int hybrid_breakpoint_add(struct target *target, - target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); + target_addr_t address, uint32_t asid, unsigned int length, + enum breakpoint_type type); int breakpoint_remove(struct target *target, target_addr_t address); int breakpoint_remove_all(struct target *target); @@ -70,7 +71,7 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int int watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, - target_addr_t address, uint32_t length, + target_addr_t address, unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask); int watchpoint_remove(struct target *target, target_addr_t address); int watchpoint_remove_all(struct target *target); diff --git a/src/target/target.c b/src/target/target.c index 09396d8780..b1a26f9e33 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3950,7 +3950,7 @@ static int handle_bp_command_list(struct command_invocation *cmd) } static int handle_bp_command_set(struct command_invocation *cmd, - target_addr_t addr, uint32_t asid, uint32_t length, int hw) + target_addr_t addr, uint32_t asid, unsigned int length, int hw) { struct target *target = get_current_target(cmd->ctx); int retval; @@ -4067,7 +4067,7 @@ COMMAND_HANDLER(handle_wp_command) while (watchpoint) { char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a')); command_print(CMD, "address: " TARGET_ADDR_FMT - ", len: 0x%8.8" PRIx32 + ", len: 0x%8.8x" ", r/w/a: %c, value: 0x%8.8" PRIx64 ", mask: 0x%8.8" PRIx64, watchpoint->address, From ff22f78d4605d7037a70fa36232986c7396f2946 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Thu, 4 Jul 2024 20:52:13 +0300 Subject: [PATCH 0924/1312] doc: document that breakpoints are disabled on step/resume OpenOCD disables breakpoints on step/resume if they match the current code position. This is a non-obvious behavior that should be documented Change-Id: Id762066569ec6452869a58dfcd9df88c8a14d6ab Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8388 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index c786382768..db787fdb2d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9273,11 +9273,19 @@ power consumption (because the CPU is needlessly clocked). @deffn {Command} {resume} [address] Resume the target at its current code position, or the optional @var{address} if it is provided. + +@b{NOTE:} targets are expected to temporary disable breakpoints +if they match the address of the current code position +or the @var{address} provided by user. @end deffn @deffn {Command} {step} [address] Single-step the target at its current code position, or the optional @var{address} if it is provided. + +@b{NOTE:} targets are expected to temporary disable breakpoints +if they match the address of the current code position +or the @var{address} provided by user. @end deffn @anchor{resetcommand} From 5cb184a732c998eed1d4e1a54c682d204f6f34d2 Mon Sep 17 00:00:00 2001 From: Richard Allen Date: Wed, 15 May 2024 12:29:05 -0500 Subject: [PATCH 0925/1312] target: fix profiler output on Windows Open output file in binary mode to disable EOL conversion on Windows (and sometimes cygwin depending on installation settings and path). Change-Id: I38276dd1af011ce5781b0264b7cbb08c32a1a2ad Signed-off-by: Richard Allen Reviewed-on: https://review.openocd.org/c/openocd/+/8278 Reviewed-by: Karl Palsson Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/target.c b/src/target/target.c index b1a26f9e33..9d1d2f5507 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4209,7 +4209,7 @@ static void write_gmon(uint32_t *samples, uint32_t sample_num, const char *filen uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms) { uint32_t i; - FILE *f = fopen(filename, "w"); + FILE *f = fopen(filename, "wb"); if (!f) return; write_string(f, "gmon"); From e7a060090ee82bc6904338df54740c4331926ec4 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Tue, 16 Jan 2024 13:52:56 +0000 Subject: [PATCH 0926/1312] rtt: default the ID to "SEGGER RTT" Instead of making people type this in all the time, just default to "SEGGER RTT" so more things work out of the box. Change-Id: I147142cf0a755e635d3f66e047be2eb5049cf511 Signed-off-by: Karl Palsson Reviewed-on: https://review.openocd.org/c/openocd/+/8354 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 5 +++-- src/rtt/tcl.c | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index db787fdb2d..dee4313015 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9541,11 +9541,12 @@ Channels are exposed via raw TCP/IP connections. One or more RTT servers can be assigned to each channel to make them accessible to an unlimited number of TCP/IP connections. -@deffn {Command} {rtt setup} address size ID +@deffn {Command} {rtt setup} address size [ID] Configure RTT for the currently selected target. Once RTT is started, OpenOCD searches for a control block with the identifier @var{ID} starting at the memory address @var{address} within the next @var{size} bytes. +ID defaults to the string "SEGGER RTT" @end deffn @deffn {Command} {rtt start} @@ -9588,7 +9589,7 @@ on the target device. @example resume -rtt setup 0x20000000 2048 "SEGGER RTT" +rtt setup 0x20000000 2048 rtt start rtt server start 9090 0 diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c index 2b8822fce8..bae71b6ce5 100644 --- a/src/rtt/tcl.c +++ b/src/rtt/tcl.c @@ -19,8 +19,14 @@ COMMAND_HANDLER(handle_rtt_setup_command) { struct rtt_source source; - if (CMD_ARGC != 3) + const char *DEFAULT_ID = "SEGGER RTT"; + const char *selected_id; + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; + if (CMD_ARGC == 2) + selected_id = DEFAULT_ID; + else + selected_id = CMD_ARGV[2]; source.find_cb = &target_rtt_find_control_block; source.read_cb = &target_rtt_read_control_block; @@ -38,7 +44,7 @@ COMMAND_HANDLER(handle_rtt_setup_command) rtt_register_source(source, get_current_target(CMD_CTX)); - if (rtt_setup(address, size, CMD_ARGV[2]) != ERROR_OK) + if (rtt_setup(address, size, selected_id) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; @@ -218,7 +224,7 @@ static const struct command_registration rtt_subcommand_handlers[] = { .handler = handle_rtt_setup_command, .mode = COMMAND_ANY, .help = "setup RTT", - .usage = "
" + .usage = "
[ID]" }, { .name = "start", From e09bb72da50c9a9878565af23ee8d5465c11526d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 5 Feb 2024 11:51:24 +0100 Subject: [PATCH 0927/1312] target/cortex_m: add DSCSR_CDSKEY bit definition Needed e.g. for flash drivers handling secure mode. Signed-off-by: Tomas Vanek Change-Id: If6cb49609140d06a73bcf2e446b6a634d6326e80 Reviewed-on: https://review.openocd.org/c/openocd/+/8435 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 726fca2903..144f24560c 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -150,6 +150,7 @@ struct cortex_m_part_info { #define VC_CORERESET BIT(0) /* DCB_DSCSR bit and field definitions */ +#define DSCSR_CDSKEY BIT(17) #define DSCSR_CDS BIT(16) /* NVIC registers */ From 4680d6ebdf142f9dd1acdc439d4e146ed36a290b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 25 Aug 2024 15:38:07 +0200 Subject: [PATCH 0928/1312] binarybuffer: str_to_buf(): align prefix to TCL syntax Integer values are interpreted by TCL as decimal, binary, octal or hexadecimal if prepended with '0d', '0b', '0o' or '0x' respectively. The case of '0' prefix has been interpreted as octal till TCL 8.6 but is interpreted as part of a decimal number by JimTCL and from TCL 9. Align str_to_buf() to latest TCL syntax by: - addding support for '0d', '0b' and '0o' prefix; - dropping support for '0' prefix. Change-Id: I708ef72146d75b7bf429df329a0269cf48700a44 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8465 Tested-by: jenkins Reviewed-by: Jan Matyas --- src/helper/binarybuffer.c | 79 ++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 509f24f0b3..423739a9d2 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -192,50 +192,12 @@ char *buf_to_hex_str(const void *_buf, unsigned buf_len) return str; } -static bool str_has_hex_prefix(const char *s) -{ - /* Starts with "0x" or "0X" */ - return (s[0] == '0') && (s[1] == 'x' || s[1] == 'X'); -} - -static bool str_has_octal_prefix(const char *s) -{ - /* - starts with '0', - * - has at least two characters, and - * - the second character is not 'x' or 'X' */ - return (s[0] == '0') && (s[1] != '\0') && (s[1] != 'x') && (s[1] != 'X'); -} - -/** - * Try to identify the radix of the number by looking at its prefix. - * No further validation of the number is preformed. +/* + * TCL standard prefix is '0b', '0o', '0d' or '0x' respectively for binary, + * octal, decimal or hexadecimal. + * The prefix '0' is interpreted by TCL <= 8.6 as octal, but is ignored and + * interpreted as part of a decimal number by JimTCL and by TCL >= 9. */ -static unsigned int str_radix_guess(const char *str) -{ - if (str_has_hex_prefix(str)) - return 16; - - if (str_has_octal_prefix(str)) - return 8; - - /* Otherwise assume a decimal number. */ - return 10; -} - -/** Strip leading "0x" or "0X" from hex numbers or "0" from octal numbers. */ -static const char *str_strip_number_prefix(const char *str, unsigned int radix) -{ - switch (radix) { - case 16: - return str + 2; - case 8: - return str + 1; - case 10: - default: - return str; - } -} - int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize) { assert(str); @@ -243,9 +205,34 @@ int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize) assert(buf_bitsize > 0); uint8_t *buf = _buf; - unsigned int radix = str_radix_guess(str); - - str = str_strip_number_prefix(str, radix); + unsigned int radix = 10; /* default when no prefix */ + + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': + radix = 2; + str += 2; + break; + case 'o': + case 'O': + radix = 8; + str += 2; + break; + case 'd': + case 'D': + radix = 10; + str += 2; + break; + case 'x': + case 'X': + radix = 16; + str += 2; + break; + default: + break; + } + } const size_t str_len = strlen(str); if (str_len == 0) From e01e180f6248590348bad5c354c6b4e0cf1a956a Mon Sep 17 00:00:00 2001 From: Marcus Nilsson Date: Mon, 6 May 2024 11:40:00 +0200 Subject: [PATCH 0929/1312] drivers/cmsis_dap: Fix buffer overflow in cmsis_dap_hid_open() Use mbstowcs() to get required length of wide character string and include space for terminating null wide character. Change-Id: I668de6f0acc9b3ec5aca033d870dd9ef354f9077 Signed-off-by: Marcus Nilsson Reviewed-on: https://review.openocd.org/c/openocd/+/8232 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- src/jtag/drivers/cmsis_dap_usb_hid.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 98ccc3e381..aeec685b9d 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -121,8 +121,12 @@ static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p break; if (cur_dev->serial_number) { - size_t len = (strlen(serial) + 1) * sizeof(wchar_t); - wchar_t *wserial = malloc(len); + size_t len = mbstowcs(NULL, serial, 0) + 1; + wchar_t *wserial = malloc(len * sizeof(wchar_t)); + if (!wserial) { + LOG_ERROR("unable to allocate serial number buffer"); + return ERROR_FAIL; + } mbstowcs(wserial, serial, len); if (wcscmp(wserial, cur_dev->serial_number) == 0) { From ca72d23c3b9df2ffa9e18cb5e3b4ccc2194ff329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Ho=C5=A1ek?= Date: Sun, 25 Aug 2024 13:54:15 +0200 Subject: [PATCH 0930/1312] doc: fix stm32l4x option_write usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stm32l4x option_write works like stm32h7x option_write, i.e. expects the value to write after reg_offset and optionally reg_mask after the value. Change-Id: I57fb4fb1dbf7f43fe063b48f4db2dd5f2ef0ade0 Signed-off-by: OndÅ™ej HoÅ¡ek Reviewed-on: https://review.openocd.org/c/openocd/+/8464 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index dee4313015..2e48d8e208 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8075,7 +8075,7 @@ The above example will read out the FLASH_OPTR register which contains the RDP option byte, Watchdog configuration, BOR level etc. @end deffn -@deffn {Command} {stm32l4x option_write} num reg_offset reg_mask +@deffn {Command} {stm32l4x option_write} num reg_offset value [reg_mask] Write an option byte register of the stm32l4x device. The @var{num} parameter is a value shown by @command{flash banks}, @var{reg_offset} is the register offset of the Option byte to write, and @var{reg_mask} is the mask From 7e271c91516ce106ceec6af952b9e02641b203cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Ho=C5=A1ek?= Date: Sun, 25 Aug 2024 23:50:07 +0200 Subject: [PATCH 0931/1312] flash/stm32l4x: option_write usage: mask is optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If no mask is given, the value in the option register is replaced completely. If a mask is set, only those bits that are set in the mask are transferred into the option register; the others remain unchanged. Change-Id: If488a10f92d7dcc0e0f192aef5e67c255fd529c3 Signed-off-by: OndÅ™ej HoÅ¡ek Reviewed-on: https://review.openocd.org/c/openocd/+/8466 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/stm32l4x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index bb6e9ef04a..9235dd7877 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -2622,7 +2622,7 @@ static const struct command_registration stm32l4_exec_command_handlers[] = { .name = "option_write", .handler = stm32l4_handle_option_write_command, .mode = COMMAND_EXEC, - .usage = "bank_id reg_offset value mask", + .usage = "bank_id reg_offset value [mask]", .help = "Write device option bit fields with provided value.", }, { From 324469da57f1b061674ac45a3b1f7fbc3b11fdfe Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 25 Aug 2024 22:51:22 -0400 Subject: [PATCH 0932/1312] cpld: update warning to suggest virtex2 refresh virtex2 refresh replaced virtex2 program, but the even older programming commands like xc6s_program still suggest the old, now-removed program command. This changes the warnings to suggest the command that is still there, and also adds some indication that you will need to use the .pld name instead of the .tap name. Change-Id: I292da62a95a9b414c69cdb1bba8a28dfd16a7336 Signed-off-by: Adam Novak Reviewed-on: https://review.openocd.org/c/openocd/+/8468 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Daniel Anselmi --- tcl/cpld/xilinx-xc6s.cfg | 4 ++-- tcl/cpld/xilinx-xc7.cfg | 2 +- tcl/cpld/xilinx-xcu.cfg | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tcl/cpld/xilinx-xc6s.cfg b/tcl/cpld/xilinx-xc6s.cfg index 92b2605774..862c4aa897 100644 --- a/tcl/cpld/xilinx-xc6s.cfg +++ b/tcl/cpld/xilinx-xc6s.cfg @@ -35,7 +35,7 @@ set XC6S_JSTART 0x0c set XC6S_BYPASS 0x3f proc xc6s_program {tap} { - echo "DEPRECATED! use 'virtex2 program ...' not 'xc6s_program'" + echo "DEPRECATED! use 'virtex2 refresh XXXX.pld' not 'xc6s_program'" global XC6S_JSHUTDOWN XC6S_JPROGRAM XC6S_JSTART XC6S_BYPASS irscan $tap $XC6S_JSHUTDOWN irscan $tap $XC6S_JPROGRAM @@ -45,7 +45,7 @@ proc xc6s_program {tap} { #xtp038 and xc3sprog approach proc xc6s_program_iprog {tap} { - echo "DEPRECATED! use 'virtex2 program ...' not 'xc6s_program_iprog'" + echo "DEPRECATED! use 'virtex2 refresh XXXX.pld' not 'xc6s_program_iprog'" global XC6S_JSHUTDOWN XC6S_JSTART XC6S_BYPASS XC6S_CFG_IN irscan $tap $XC6S_JSHUTDOWN runtest 16 diff --git a/tcl/cpld/xilinx-xc7.cfg b/tcl/cpld/xilinx-xc7.cfg index f5b0733749..6f8f4ae5cb 100644 --- a/tcl/cpld/xilinx-xc7.cfg +++ b/tcl/cpld/xilinx-xc7.cfg @@ -49,7 +49,7 @@ set XC7_JSTART 0x0c set XC7_BYPASS 0x3f proc xc7_program {tap} { - echo "DEPRECATED! use 'virtex2 program ...' not 'xc7_program'" + echo "DEPRECATED! use 'virtex2 refresh XXXX.pld' not 'xc7_program'" global XC7_JSHUTDOWN XC7_JPROGRAM XC7_JSTART XC7_BYPASS irscan $tap $XC7_JSHUTDOWN irscan $tap $XC7_JPROGRAM diff --git a/tcl/cpld/xilinx-xcu.cfg b/tcl/cpld/xilinx-xcu.cfg index 4d7f26c889..63a67da202 100644 --- a/tcl/cpld/xilinx-xcu.cfg +++ b/tcl/cpld/xilinx-xcu.cfg @@ -109,7 +109,7 @@ set XCU_JSTART 0x0c set XCU_BYPASS 0x3f proc xcu_program {tap} { - echo "DEPRECATED! use 'virtex2 program ...' not 'xcu_program'" + echo "DEPRECATED! use 'virtex2 refresh XXXX.pld' not 'xcu_program'" global XCU_JSHUTDOWN XCU_JPROGRAM XCU_JSTART XCU_BYPASS irscan $tap $XCU_JSHUTDOWN irscan $tap $XCU_JPROGRAM From f9b2a1a2bdfb6ff2f12281b2827b9c3b5278b41b Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Tue, 20 Aug 2024 16:07:17 +0300 Subject: [PATCH 0933/1312] jtag_vpi: fix signed/unsigned comparison jtag_vpi_stableclocks Change-Id: Id2b00fbc8ba627f4465c109fbde6e010faaff9d2 Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8462 Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/jtag_vpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 5745a2cd0d..a19060c2aa 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -461,7 +461,7 @@ static int jtag_vpi_stableclocks(unsigned int num_cycles) unsigned int cycles_remain = num_cycles; int nb_bits; int retval; - const int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8; + const unsigned int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8; /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */ memset(&tms_bits, (tap_get_state() == TAP_RESET) ? 0xff : 0x00, sizeof(tms_bits)); From 75b418faa7b9849a118c86ccac019d2d9ea235af Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 25 Aug 2024 22:36:29 -0400 Subject: [PATCH 0934/1312] tcl/board: Support for Digilent Anvyl board Support Digilent Anvyl board JTAG chain Change-Id: I6fb52284429af6c98c19411fc8bc3ab983dfa9b8 Signed-off-by: Adam Novak Reviewed-on: https://review.openocd.org/c/openocd/+/8467 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/digilent_anvyl.cfg | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tcl/board/digilent_anvyl.cfg diff --git a/tcl/board/digilent_anvyl.cfg b/tcl/board/digilent_anvyl.cfg new file mode 100644 index 0000000000..e820028779 --- /dev/null +++ b/tcl/board/digilent_anvyl.cfg @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Digilent Anvyl with Xilinx Spartan-6 FPGA +# https://digilent.com/reference/programmable-logic/anvyl/start +# Almost the same setup as the Digilent Nexys Video board or the Digilent HS1 +# adapter. +adapter driver ftdi +adapter speed 30000 + +ftdi device_desc "Digilent USB Device" +ftdi vid_pid 0x0403 0x6010 + +# channel 0 is the JTAG channel +# channel 1 is a user serial channel to pins on the FPGA +ftdi channel 0 + +# just TCK TDI TDO TMS, no reset +ftdi layout_init 0x0088 0x008b +reset_config none + +# Enable sampling on falling edge for high JTAG speeds. +ftdi tdo_sample_edge falling + +transport select jtag + +source [find cpld/xilinx-xc6s.cfg] +source [find cpld/jtagspi.cfg] From cbed09ee9bdbba27ca93f5883b79595f7e9d347d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Aug 2024 01:29:02 +0200 Subject: [PATCH 0935/1312] tcl/target: Make sure R-Car Gen3 _targets variable is global The _targets has to be global as it is accessed at the end of this file. This is already the case for setup_a5x {}, assure it is the same way for setup_crx{} . Without this change, the _targets at the end of this file is empty in case the Cortex-R is the boot core, fix this. Change-Id: I4979e3125ec7d93bbd56eee0096ae1d9c5f6a565 Signed-off-by: Marek Vasut Reviewed-on: https://review.openocd.org/c/openocd/+/8470 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/renesas_rcar_gen3.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/tcl/target/renesas_rcar_gen3.cfg b/tcl/target/renesas_rcar_gen3.cfg index 8dc0e7a0dd..73b3003a94 100644 --- a/tcl/target/renesas_rcar_gen3.cfg +++ b/tcl/target/renesas_rcar_gen3.cfg @@ -159,6 +159,7 @@ proc setup_a5x {core_name dbgbase ctibase num boot} { proc setup_crx {core_name dbgbase ctibase num boot} { global _CHIPNAME global _DAPNAME + global _targets for { set _core 0 } { $_core < $num } { incr _core } { set _TARGETNAME $_CHIPNAME.$core_name set _CTINAME $_TARGETNAME.cti From f0bad430df8e9fe0ff5323756a19ad2baa52e9f6 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Fri, 30 Aug 2024 22:45:07 +0300 Subject: [PATCH 0936/1312] rtos/hwthread: fix threadid generation Looks like 7f2d3e2925 introduced a regression by incorrectly assigning threads. The title of the commit message says that the intention was to "derive threadid from SMP index", this is not what happens, however. Instead threadid is assigned based on an index of all examined targets in an SMP group. This introduces two logical errors. *Error 1* Here is the code that assigns threads to harts: ``` foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; if (!target_was_examined(curr)) continue; threadid_t tid = threads_found + 1; hwthread_fill_thread(rtos, curr, threads_found, tid); ``` Now, imagine a situation when we have two targets: `target.A` and `target.B`. Let's assume that `target.A` is NOT examined (it could be under reset, for example). Then, according to the algorithm when assigning thread identifiers `target.B` will be assigned tid of 1. The respected inferior on GDB side will be called `Thread 1`. Now, imagine that `target.A` activates and succefully examined - OpenOCD will re-assign thread identifiers. And now on GDB side `Thread 1` will represent the state of `target.A`. Which is incorrect. *Error 2* The reverse mapping between `threadid` and targets does not take the state of targets into account. ``` static struct target * hwthread_find_thread(struct target *target, threadid_t thread_id) ... threadid_t tid = 1; foreach_smp_target(head, target->smp_targets) { if (thread_id == tid) head->target; ++tid; } ``` So the constructed mapping is incorrect. Since in example above `Thread 1` will get mapped to `target.A`. *Solution:* It seems that threadids should be assigned based on position of the thread in an smp group disregarding the target state. Change-Id: Ib93b7ed3bb03696afdf56a105b333e22b9ec69b5 Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8471 Reviewed-by: Antonio Borneo Reviewed-by: Mark Zhuang Tested-by: jenkins Reviewed-by: Evgeniy Naydanov --- src/rtos/hwthread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 748e71c3dc..4fe8419025 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -133,7 +133,7 @@ static int hwthread_update_threads(struct rtos *rtos) if (!target_was_examined(curr)) continue; - threadid_t tid = threads_found + 1; + threadid_t tid = threadid_from_target(curr); hwthread_fill_thread(rtos, curr, threads_found, tid); /* find an interesting thread to set as current */ From 0efedd7bd7e1531a47028d9b32e9406502a59ca7 Mon Sep 17 00:00:00 2001 From: Marcus Nilsson Date: Wed, 7 Aug 2024 11:24:04 +0200 Subject: [PATCH 0937/1312] drivers/jlink: Print serial numbers when multiple devices are connected When multiple jlink programmers are connected and no specific serial or USB location is specified, print out the detected serial numbers. Signed-off-by: Marcus Nilsson Change-Id: I280da2b85363f7054c5f466637120427cadcf7d1 Reviewed-on: https://review.openocd.org/c/openocd/+/8356 Reviewed-by: Mark Zhuang Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/jlink.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index a94f3a4aba..1b2fb4e304 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -564,6 +564,20 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { LOG_ERROR("Multiple devices found, specify the desired device"); + LOG_INFO("Found devices:"); + for (size_t i = 0; devs[i]; i++) { + uint32_t serial; + ret = jaylink_device_get_serial_number(devs[i], &serial); + if (ret == JAYLINK_ERR_NOT_AVAILABLE) { + continue; + } else if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_serial_number() failed: %s", + jaylink_strerror(ret)); + continue; + } + LOG_INFO("Device %zu serial: %" PRIu32, i, serial); + } + jaylink_free_devices(devs, true); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; From 6f9b1ee521203f0d43b7d84e671ba4e32bd3e599 Mon Sep 17 00:00:00 2001 From: Jun Yan Date: Sat, 31 Aug 2024 19:28:46 +0800 Subject: [PATCH 0938/1312] tcl/interface/ftdi: add support for Sipeed USB-JTAG/TTL Debugger Sipeed USB-JTAG/TTL Debugger is a compact FT2232D-based JTAG adapter. Change-Id: Ibc9075723f47cd9b49ba4bb39e3d292e7d80bed7 Signed-off-by: Jun Yan Reviewed-on: https://review.openocd.org/c/openocd/+/8472 Reviewed-by: Antonio Borneo Tested-by: jenkins --- .../ftdi/sipeed-usb-jtag-debugger.cfg | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tcl/interface/ftdi/sipeed-usb-jtag-debugger.cfg diff --git a/tcl/interface/ftdi/sipeed-usb-jtag-debugger.cfg b/tcl/interface/ftdi/sipeed-usb-jtag-debugger.cfg new file mode 100644 index 0000000000..8a804eca67 --- /dev/null +++ b/tcl/interface/ftdi/sipeed-usb-jtag-debugger.cfg @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Sipeed USB-JTAG/TTL RISC-V Debugger +# +# https://www.seeedstudio.com/Sipeed-USB-JTAG-TTL-RISC-V-Debugger-p-2910.html +# + +adapter driver ftdi +ftdi device_desc "Dual RS232" +ftdi vid_pid 0x0403 0x6010 +ftdi channel 0 + +# Every pin set as high impedance except TCK, TDI, TDO, TMS and RST +ftdi layout_init 0x0028 0x002b + +transport select jtag + +# nSRST defined on pin RST of the Debugger (pin ADBUS5 [AD5] on the FT2232D chip) +ftdi layout_signal nSRST -data 0x0020 -oe 0x0020 From d35399b00e5693d5b6f91208b0f52e5d710d086f Mon Sep 17 00:00:00 2001 From: daniellizewski Date: Fri, 23 Aug 2024 08:31:04 -0400 Subject: [PATCH 0939/1312] src/flash/nor/kinetis.c: Fixed flash bank write gap Flash banks created in kinetis_create_missing_banks did not populate bank->minimal_write_gap. The default value of 0 was interpreted as FLASH_WRITE_CONTINUOUS. This created unnecessary large padding if your binary had a gap in the populated flash. It also caused flash errors when loading with GDB because the erroneously padded pages were not erased first. Tested using an S32k148 using s32k.cfg. Change-Id: I9b7af698e29ac2c4f5fc8ecd82fa7f4b1a0d43f1 Signed-off-by: daniellizewski Reviewed-on: https://review.openocd.org/c/openocd/+/8463 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- src/flash/nor/kinetis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index fee36444e6..2d0a75334d 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -1038,6 +1038,7 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) bank->target = k_chip->target; bank->driver = &kinetis_flash; bank->default_padded_value = bank->erased_value = 0xff; + bank->minimal_write_gap = FLASH_WRITE_GAP_SECTOR; snprintf(name, sizeof(name), "%s.%s%s", base_name, class, num); From 1aa759dbb9dc1e3bc60ad5f86ddafc793c9d0e0b Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Fri, 29 Mar 2024 21:13:17 +0100 Subject: [PATCH 0940/1312] flash/nor: Update cc26xx flash driver to support cc13x2x7 This updates the flash driver to support more than one bank. This is required to support the cc1352p7 which has two banks. This only have been tested on a cc1352p7. The loader has been built using a gcc-arm-none-eabi-4_8-2014q3 toolchain. Change-Id: Ia813421ececd96d6e2fd4dae910ad60fcc3d3c88 Signed-off-by: Alexandre Bailon Reviewed-on: https://review.openocd.org/c/openocd/+/8192 Tested-by: jenkins Reviewed-by: Vaishnav M A Reviewed-by: Antonio Borneo --- contrib/loaders/flash/cc26xx/cc26x0_algo.inc | 490 +++++++++---------- contrib/loaders/flash/cc26xx/cc26x2_algo.inc | 486 +++++++++--------- contrib/loaders/flash/cc26xx/flash.c | 107 ++-- contrib/loaders/flash/cc26xx/flash.h | 40 ++ contrib/loaders/flash/cc26xx/hw_regs.h | 21 + 5 files changed, 614 insertions(+), 530 deletions(-) diff --git a/contrib/loaders/flash/cc26xx/cc26x0_algo.inc b/contrib/loaders/flash/cc26xx/cc26x0_algo.inc index 2246a36706..d20d9be44a 100644 --- a/contrib/loaders/flash/cc26xx/cc26x0_algo.inc +++ b/contrib/loaders/flash/cc26xx/cc26x0_algo.inc @@ -1,249 +1,248 @@ /* Autogenerated with ../../../../src/helper/bin2char.sh */ 0x08,0xb5,0x00,0xbf,0x00,0xbf,0x00,0xbf,0x00,0xbf,0xdf,0xf8,0x1c,0xd0,0x07,0x48, -0x07,0x49,0x4f,0xf0,0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb, -0x00,0xf0,0xa8,0xf9,0xfe,0xe7,0x00,0x00,0xf0,0x0e,0x00,0x20,0x54,0x13,0x00,0x20, -0x98,0x13,0x00,0x20,0x08,0xb5,0x07,0x4b,0x07,0x48,0x03,0x33,0x1b,0x1a,0x06,0x2b, -0x04,0xd9,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x5c,0xf8,0x08,0xbc,0x01,0xbc, -0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, -0x08,0x48,0x09,0x49,0x09,0x1a,0x89,0x10,0x08,0xb5,0xcb,0x0f,0x59,0x18,0x49,0x10, -0x04,0xd0,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x44,0xf8,0x08,0xbc,0x01,0xbc, -0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, -0x10,0xb5,0x08,0x4c,0x23,0x78,0x00,0x2b,0x09,0xd1,0xff,0xf7,0xcb,0xff,0x06,0x4b, +0x07,0x49,0x4f,0xf0,0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xff,0xf6, +0xfa,0xaf,0x00,0xf0,0x71,0xf9,0xfe,0xe7,0xe0,0x0e,0x00,0x20,0x44,0x13,0x00,0x20, +0x88,0x13,0x00,0x20,0x10,0xb5,0x07,0x4c,0x23,0x78,0x00,0x2b,0x07,0xd1,0x06,0x4b, 0x00,0x2b,0x02,0xd0,0x05,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbc, -0x01,0xbc,0x00,0x47,0x54,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20, -0x08,0xb5,0x0b,0x4b,0x00,0x2b,0x03,0xd0,0x0a,0x48,0x0b,0x49,0xaf,0xf3,0x00,0x80, -0x0a,0x48,0x03,0x68,0x00,0x2b,0x04,0xd1,0xff,0xf7,0xc2,0xff,0x08,0xbc,0x01,0xbc, -0x00,0x47,0x07,0x4b,0x00,0x2b,0xf7,0xd0,0x00,0xf0,0x0c,0xf8,0xf4,0xe7,0xc0,0x46, -0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20,0x58,0x13,0x00,0x20,0x4c,0x13,0x00,0x20, -0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xd4,0x30,0x9f,0xe5,0x00,0x00,0x53,0xe3, -0xc8,0x30,0x9f,0x05,0x03,0xd0,0xa0,0xe1,0x00,0x20,0x0f,0xe1,0x0f,0x00,0x12,0xe3, -0x15,0x00,0x00,0x0a,0xd1,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0xaa,0x4d,0xe2, -0x0a,0x30,0xa0,0xe1,0xd7,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2, -0xdb,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2,0xd2,0xf0,0x21,0xe3, -0x03,0xd0,0xa0,0xe1,0x02,0x3a,0x43,0xe2,0xd3,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1, -0x02,0x39,0x43,0xe2,0xff,0x30,0xc3,0xe3,0xff,0x3c,0xc3,0xe3,0x04,0x30,0x03,0xe5, -0x00,0x20,0x53,0xe9,0xc0,0x20,0x82,0xe3,0x02,0xf0,0x21,0xe1,0x01,0xa8,0x43,0xe2, -0x00,0x10,0xb0,0xe3,0x01,0xb0,0xa0,0xe1,0x01,0x70,0xa0,0xe1,0x5c,0x00,0x9f,0xe5, -0x5c,0x20,0x9f,0xe5,0x00,0x20,0x52,0xe0,0x01,0x30,0x8f,0xe2,0x13,0xff,0x2f,0xe1, -0x00,0xf0,0x42,0xfd,0x10,0x4b,0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x0f,0x4b, -0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00, -0x0d,0x48,0x00,0xf0,0x89,0xfc,0x00,0xf0,0xc3,0xfc,0x20,0x00,0x29,0x00,0x00,0xf0, -0xd1,0xf8,0x00,0xf0,0x8b,0xfc,0x7b,0x46,0x18,0x47,0x00,0x00,0x11,0x00,0x00,0xef, -0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x54,0x13,0x00,0x20,0x98,0x13,0x00,0x20,0x15,0x0b,0x00,0x20,0x70,0xb5,0x04,0x46, -0x0e,0x46,0x15,0x46,0x00,0x21,0x28,0x22,0x00,0xf0,0x0e,0xfd,0x26,0x61,0x65,0x62, -0x00,0x21,0x20,0x22,0x02,0x48,0x00,0xf0,0x07,0xfd,0x00,0x20,0x70,0xbd,0x00,0xbf, -0x70,0x13,0x00,0x20,0x10,0xb5,0x01,0x20,0x00,0xf0,0xac,0xf9,0x04,0x46,0x28,0xb9, -0x01,0x21,0x20,0x22,0x03,0x48,0x00,0xf0,0xf7,0xfc,0x01,0xe0,0x40,0xf2,0x01,0x14, -0x20,0x46,0x10,0xbd,0x70,0x13,0x00,0x20,0x01,0x39,0xf8,0xb5,0x04,0x0b,0x08,0x44, -0x05,0x0b,0x26,0x03,0xac,0x42,0x14,0xd8,0x0b,0x4f,0xe3,0x5d,0x6b,0xb9,0x30,0x46, -0x00,0xf0,0xfc,0xf8,0x38,0xb1,0x00,0x04,0x00,0xf4,0x7f,0x00,0x40,0xea,0x04,0x60, -0x40,0xf4,0x81,0x70,0xf8,0xbd,0x01,0x23,0xe3,0x55,0x01,0x34,0x06,0xf5,0x80,0x56, -0xe8,0xe7,0x00,0x20,0xf8,0xbd,0x00,0xbf,0x70,0x13,0x00,0x20,0x2d,0xe9,0xf0,0x4f, -0x0d,0x46,0x53,0x1e,0x85,0xb0,0x0b,0x44,0x02,0x90,0x4f,0xea,0x11,0x38,0x1b,0x0b, -0x16,0x46,0x23,0x48,0x00,0x21,0x20,0x22,0x01,0x93,0x4f,0xea,0x08,0x37,0x00,0xf0, -0xbb,0xfc,0x4f,0xf0,0x00,0x09,0xc5,0xf3,0x0b,0x0c,0x01,0x9b,0x98,0x45,0x33,0xd8, -0x74,0x19,0x07,0xf5,0x80,0x5a,0x54,0x45,0x98,0xbf,0x34,0x46,0xdf,0xf8,0x64,0xb0, -0x88,0xbf,0xc4,0xf3,0x0b,0x04,0x39,0x46,0x4f,0xf4,0x80,0x52,0x58,0x46,0x88,0xbf, -0x34,0x1b,0xcd,0xf8,0x0c,0xc0,0x00,0xf0,0x5f,0xfc,0xdd,0xf8,0x0c,0xc0,0x02,0x9b, -0x0b,0xeb,0x0c,0x00,0x03,0xeb,0x09,0x01,0x22,0x46,0x00,0xf0,0x55,0xfc,0x38,0x46, -0x4f,0xf4,0x80,0x51,0x08,0xf1,0x01,0x08,0xff,0xf7,0x9e,0xff,0x68,0xb9,0x39,0x46, -0x58,0x46,0x4f,0xf4,0x80,0x52,0x25,0x44,0x00,0xf0,0xae,0xf8,0x36,0x1b,0xc5,0xf3, -0x0b,0x0c,0xa1,0x44,0x57,0x46,0xc8,0xe7,0x00,0x20,0x05,0xb0,0xbd,0xe8,0xf0,0x8f, -0x70,0x13,0x00,0x20,0x00,0x3c,0x00,0x20,0xb2,0xf5,0x80,0x5f,0xf8,0xb5,0x07,0x46, -0x0e,0x46,0x15,0x46,0x0b,0xd8,0x08,0x46,0x11,0x46,0xff,0xf7,0x7d,0xff,0x04,0x46, -0x40,0xb9,0x38,0x46,0x31,0x46,0x2a,0x46,0x00,0xf0,0x8e,0xf8,0x02,0xe0,0x4f,0xf4, -0x82,0x70,0xf8,0xbd,0x20,0x46,0xf8,0xbd,0x08,0xb5,0x00,0xf0,0x85,0xf8,0x00,0x20, -0x08,0xbd,0x00,0x00,0xf8,0xb5,0x31,0x48,0x31,0x49,0x32,0x4a,0x32,0x4c,0xff,0xf7, -0x3d,0xff,0x00,0x23,0x23,0x60,0x22,0x68,0x2c,0x4f,0x14,0x23,0x03,0xfb,0x02,0x73, -0x08,0x33,0x5b,0x68,0x00,0x2b,0xf7,0xd0,0x2c,0x4b,0x1a,0x68,0x11,0x07,0xfb,0xd4, -0x2b,0x4d,0x2c,0x4e,0x2a,0x68,0x32,0x60,0x42,0xf0,0x33,0x02,0x2a,0x60,0x1a,0x68, -0x12,0x07,0xfc,0xd4,0x21,0x68,0x14,0x22,0x02,0xfb,0x01,0x73,0x98,0x68,0x13,0x46, -0x01,0x38,0x04,0x28,0x26,0xd8,0xdf,0xe8,0x00,0xf0,0x03,0x06,0x0e,0x16,0x1e,0x00, -0xff,0xf7,0x28,0xff,0x20,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, -0xff,0xf7,0xc2,0xff,0x18,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, -0xff,0xf7,0xa2,0xff,0x10,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, -0xff,0xf7,0x44,0xff,0x08,0xe0,0x4b,0x43,0xfa,0x18,0xf8,0x58,0x51,0x68,0xff,0xf7, -0x1b,0xff,0x01,0xe0,0x40,0xf2,0x05,0x10,0x33,0x68,0x2b,0x60,0x0b,0x4b,0x1b,0x68, -0x1b,0x07,0xfb,0xd4,0x22,0x68,0x14,0x23,0x03,0xfb,0x02,0x77,0xfb,0x68,0xf8,0x60, -0x00,0xb1,0xfe,0xe7,0x82,0xf0,0x01,0x02,0x22,0x60,0xa4,0xe7,0xd8,0x1b,0x00,0x20, -0x00,0x1c,0x00,0x20,0x00,0x2c,0x00,0x20,0x90,0x13,0x00,0x20,0x00,0x40,0x03,0x40, -0x04,0x40,0x03,0x40,0x94,0x13,0x00,0x20,0xfe,0xe7,0x00,0x00,0x08,0xb5,0x04,0x4b, -0x1b,0x68,0x5b,0x69,0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf, -0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42,0x08,0xb5,0x04,0x4b,0x1b,0x68,0x9b,0x69, -0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10, -0x84,0x04,0x60,0x42,0x10,0xb5,0x33,0x4b,0x33,0x48,0x1b,0x68,0x33,0x4a,0x13,0xf0, -0x02,0x0f,0x03,0x68,0x43,0xf0,0x02,0x03,0x03,0x60,0x13,0x68,0x01,0x68,0x19,0xd0, -0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x04,0x22,0xf0,0x01,0x02,0x22,0x43,0xc3,0xf3, -0xc0,0x11,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x11,0x42,0xea,0x81,0x12,0x02,0x60, -0x02,0x68,0xd4,0x07,0x03,0xd5,0x26,0x4a,0x12,0x68,0x50,0x07,0xfb,0xd5,0x03,0xf0, -0x07,0x03,0x18,0xe0,0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x24,0x22,0xf0,0x01,0x02, -0xc3,0xf3,0xc0,0x31,0x22,0x43,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x31,0x42,0xea, -0x81,0x12,0x02,0x60,0x02,0x68,0xd1,0x07,0x03,0xd5,0x19,0x4a,0x12,0x68,0x52,0x07, -0xfb,0xd5,0xc3,0xf3,0x02,0x23,0x4a,0xf6,0xaa,0x22,0x16,0x49,0x16,0x48,0x0a,0x60, -0x02,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4,0xe2,0x42,0x18,0xbf,0x43,0xf4, -0x80,0x73,0x13,0x43,0x03,0x60,0x45,0xf2,0xaa,0x53,0x0b,0x60,0x0f,0x4b,0x10,0x49, -0x01,0x22,0x1a,0x60,0x00,0x22,0x0a,0x60,0x1a,0x60,0x05,0x22,0xc3,0xf8,0x58,0x22, -0x4f,0xf0,0xff,0x32,0xc1,0xf8,0x8c,0x22,0xc1,0xf8,0x90,0x22,0x02,0x22,0xc3,0xf8, -0x58,0x22,0x10,0xbd,0x00,0x00,0x09,0x40,0x24,0x00,0x03,0x40,0x08,0x13,0x00,0x50, -0x1c,0x00,0x03,0x40,0x64,0x20,0x03,0x40,0xa8,0x20,0x03,0x40,0x30,0x20,0x03,0x40, -0x34,0x20,0x03,0x40,0x2d,0xe9,0xf8,0x4f,0xd4,0x4d,0x29,0x68,0x11,0xf0,0x01,0x01, -0x40,0xf0,0x95,0x81,0xdf,0xf8,0x90,0xe3,0x05,0x27,0xd1,0x4b,0xce,0xf8,0x00,0x70, -0x1b,0x68,0x4f,0xf4,0x40,0x72,0xc3,0xf3,0x03,0x23,0x01,0x33,0xb2,0xfb,0xf3,0xf3, -0xdf,0xf8,0x78,0xc3,0xdf,0xf8,0x78,0x83,0xdc,0xf8,0x00,0x20,0xd8,0xf8,0x00,0x40, -0x92,0xb2,0x5a,0x43,0xc2,0xf3,0x8f,0x16,0x22,0x0c,0x12,0x04,0x32,0x43,0xc8,0xf8, -0x00,0x20,0xc4,0x4a,0xc4,0x4c,0x12,0x68,0x26,0x68,0x5a,0x43,0xc3,0x4e,0x92,0x09, -0x22,0x60,0x32,0x68,0x54,0xf8,0x24,0x8c,0xc2,0xf3,0x07,0x42,0x5a,0x43,0x28,0xf0, -0xff,0x08,0xc2,0xf3,0x87,0x12,0xdf,0xf8,0x3c,0x93,0x42,0xea,0x08,0x02,0xdf,0xf8, -0x38,0x83,0x44,0xf8,0x24,0x2c,0xd9,0xf8,0x00,0xa0,0xd8,0xf8,0x00,0x20,0xca,0xf3, -0x07,0x4a,0x22,0xf0,0xff,0x02,0x4a,0xea,0x02,0x02,0xc8,0xf8,0x00,0x20,0xd9,0xf8, -0x00,0x20,0xdf,0xf8,0x18,0xa3,0x12,0x0e,0x5a,0x43,0xda,0xf8,0x00,0x80,0x92,0x00, -0x28,0xf4,0x7f,0x48,0x02,0xf4,0x7f,0x42,0x42,0xea,0x08,0x02,0xdf,0xf8,0x00,0x83, -0xca,0xf8,0x00,0x20,0xd8,0xf8,0x00,0x20,0xae,0xf5,0x09,0x7e,0x4f,0xea,0x12,0x6b, -0x0b,0xfb,0x03,0xfb,0xda,0xf8,0x04,0x20,0xcb,0xf3,0x8f,0x1b,0x12,0x0c,0x12,0x04, -0x4b,0xea,0x02,0x02,0xca,0xf8,0x04,0x20,0xd9,0xf8,0x00,0x20,0xc2,0xf3,0x07,0x22, -0x53,0x43,0x9f,0x4a,0x9b,0x00,0xd2,0xf8,0x00,0x90,0x03,0xf4,0x7f,0x43,0x29,0xf4, -0x7f,0x49,0x43,0xea,0x09,0x03,0xdf,0xf8,0xbc,0x92,0x13,0x60,0xd9,0xf8,0x00,0xa0, -0x52,0xf8,0x24,0x3c,0x4f,0xea,0x1a,0x6a,0x23,0xf4,0x7f,0x43,0x43,0xea,0x0a,0x23, -0x42,0xf8,0x24,0x3c,0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x24,0x3c,0xca,0xf3,0x07,0x4a, -0x23,0xf0,0xff,0x03,0x4a,0xea,0x03,0x03,0x42,0xf8,0x24,0x3c,0xd9,0xf8,0x00,0xa0, -0x52,0xf8,0x1c,0x3c,0x0a,0xf4,0x7f,0x4a,0x23,0xf4,0x7f,0x43,0x4a,0xea,0x03,0x03, -0x42,0xf8,0x1c,0x3c,0xd9,0xf8,0x00,0x90,0x52,0xf8,0x1c,0x3c,0x5f,0xfa,0x89,0xf9, -0x23,0xf0,0xff,0x03,0x49,0xea,0x03,0x03,0xdf,0xf8,0x5c,0x92,0x42,0xf8,0x1c,0x3c, -0x32,0x68,0xd9,0xf8,0x00,0x30,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43, -0xc9,0xf8,0x00,0x30,0xd8,0xf8,0x00,0x20,0xdf,0xf8,0x40,0x82,0x02,0xf4,0x70,0x42, -0xd8,0xf8,0x00,0x30,0x23,0xf4,0x70,0x43,0x13,0x43,0xc8,0xf8,0x00,0x30,0x32,0x68, -0x54,0xf8,0x24,0x3c,0x12,0x0e,0x23,0xf4,0x7f,0x43,0x43,0xea,0x02,0x23,0x44,0xf8, -0x24,0x3c,0x70,0x4b,0x1b,0x68,0x62,0x6a,0xc3,0xf3,0x0b,0x06,0x22,0xf4,0x7f,0x63, -0x23,0xf0,0x0f,0x03,0x33,0x43,0x6c,0x4e,0x63,0x62,0x32,0x68,0x63,0x6a,0x02,0xf4, -0x70,0x22,0x23,0xf4,0x70,0x23,0x13,0x43,0x63,0x62,0x68,0x4c,0x22,0x68,0xd8,0xf8, -0x58,0x30,0xc2,0xf3,0x83,0x42,0x23,0xf4,0x70,0x23,0x43,0xea,0x02,0x43,0xc8,0xf8, -0x58,0x30,0xdc,0xf8,0x00,0x30,0xd8,0xf8,0x58,0x20,0xc3,0xf3,0x0b,0x4c,0x22,0xf4, -0x7f,0x63,0x23,0xf0,0x0f,0x03,0x4c,0xea,0x03,0x03,0xc8,0xf8,0x58,0x30,0x23,0x68, -0xd8,0xf8,0x5c,0x20,0x4f,0xea,0xd3,0x5c,0x22,0xf0,0xff,0x73,0x23,0xf4,0x80,0x33, -0x43,0xea,0x0c,0x43,0xc8,0xf8,0x5c,0x30,0x33,0x68,0x55,0x4a,0x0f,0x33,0x03,0xf0, -0x0f,0x03,0x13,0x60,0x26,0x68,0x53,0x68,0xc6,0xf3,0x80,0x56,0x23,0xf4,0x00,0x03, -0x43,0xea,0xc6,0x53,0x53,0x60,0x53,0x68,0x4e,0x4e,0x43,0xf4,0x80,0x43,0x53,0x60, -0x02,0x23,0xce,0xf8,0x24,0x32,0x4a,0xf6,0xaa,0x23,0xdf,0xf8,0x74,0xc1,0xce,0xf8, -0x00,0x30,0xdc,0xf8,0x00,0x30,0x32,0x68,0x03,0xf0,0x0f,0x08,0x22,0xf4,0x7f,0x02, -0x42,0xea,0x08,0x42,0xc3,0xf3,0x03,0x23,0x42,0xea,0x03,0x53,0xdf,0xf8,0x54,0x81, -0x33,0x60,0xd8,0xf8,0x00,0x30,0x32,0x68,0xc3,0xf3,0x03,0x49,0x22,0xf0,0xff,0x02, -0x49,0xea,0x02,0x02,0xc3,0xf3,0x03,0x63,0x42,0xea,0x03,0x13,0x33,0x60,0xdc,0xf8, -0x00,0x60,0xdf,0xf8,0x34,0xc1,0x06,0xf4,0x70,0x22,0xdc,0xf8,0x00,0x30,0x23,0xf4, -0x7f,0x03,0x1a,0x43,0xc6,0xf3,0x03,0x63,0x42,0xea,0x03,0x53,0x32,0x4e,0xcc,0xf8, -0x00,0x30,0x32,0x68,0x5c,0xf8,0x08,0x3c,0xc2,0xf3,0x03,0x22,0x23,0xf0,0x0f,0x03, -0x13,0x43,0x4c,0xf8,0x08,0x3c,0xd8,0xf8,0x00,0x20,0xdc,0xf8,0x08,0x30,0x02,0xf4, -0xf8,0x52,0x23,0xf4,0xf8,0x53,0x13,0x43,0xcc,0xf8,0x08,0x30,0x32,0x68,0xdc,0xf8, -0x0c,0x30,0x12,0x0b,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43,0xcc,0xf8, -0x0c,0x30,0x32,0x68,0x21,0x4e,0xc2,0xf3,0x04,0x42,0x33,0x68,0x23,0xf0,0x1f,0x03, -0x13,0x43,0x33,0x60,0x22,0x68,0x1e,0x4c,0xc2,0xf3,0x01,0x42,0x23,0x68,0x23,0xf4, -0x40,0x13,0x43,0xea,0x02,0x53,0x23,0x60,0x45,0xf2,0xaa,0x53,0x19,0x4a,0xce,0xf8, -0x00,0x30,0x17,0x60,0x2b,0x68,0x43,0xf0,0x01,0x03,0x2b,0x60,0x11,0x60,0x16,0x4b, -0x16,0x4c,0x1b,0x68,0x16,0x4a,0x13,0xf0,0x02,0x0f,0x23,0x68,0x15,0x4d,0x43,0xf0, -0x02,0x03,0x23,0x60,0x13,0x68,0x21,0x68,0x59,0xd0,0x3f,0xe0,0x40,0x00,0x03,0x40, -0x00,0x20,0x03,0x40,0x8c,0x11,0x00,0x50,0x44,0x22,0x03,0x40,0x74,0x11,0x00,0x50, -0x34,0x22,0x03,0x40,0x84,0x11,0x00,0x50,0x80,0x11,0x00,0x50,0xb0,0x12,0x00,0x50, -0x78,0x22,0x03,0x40,0x84,0x20,0x03,0x40,0x98,0x11,0x00,0x50,0x98,0x20,0x03,0x40, -0xa8,0x20,0x03,0x40,0x3c,0x00,0x03,0x40,0x00,0x00,0x09,0x40,0x24,0x00,0x03,0x40, -0x08,0x13,0x00,0x50,0x1c,0x00,0x03,0x40,0x88,0x22,0x03,0x40,0x88,0x11,0x00,0x50, -0x40,0x22,0x03,0x40,0x78,0x11,0x00,0x50,0x24,0x22,0x03,0x40,0x28,0x22,0x03,0x40, -0x7c,0x11,0x00,0x50,0x70,0x11,0x00,0x50,0x1c,0x22,0x03,0x40,0x14,0x22,0x03,0x40, -0x90,0x11,0x00,0x50,0x94,0x11,0x00,0x50,0x88,0x20,0x03,0x40,0x21,0xf4,0xe1,0x72, -0xc3,0xf3,0xc1,0x46,0x22,0xf0,0x01,0x02,0xc3,0xf3,0xc0,0x51,0x32,0x43,0x42,0xea, -0x01,0x22,0xc3,0xf3,0x41,0x51,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd7,0x07, -0x02,0xd5,0x2a,0x68,0x56,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x43,0x16,0xe0,0xc3,0xf3, -0xc1,0x62,0xde,0x0f,0x42,0xea,0x06,0x26,0x21,0xf4,0xe1,0x72,0x22,0xf0,0x01,0x02, -0x32,0x43,0xc3,0xf3,0x41,0x71,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd4,0x07, -0x02,0xd5,0x2a,0x68,0x51,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x63,0x4a,0xf6,0xaa,0x22, -0x3a,0x49,0x3b,0x4c,0x0a,0x60,0x22,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4, -0xe2,0x42,0x18,0xbf,0x43,0xf4,0x80,0x73,0x13,0x43,0x23,0x60,0x45,0xf2,0xaa,0x53, -0x4f,0xf6,0xff,0x74,0x0b,0x60,0x33,0x4b,0x00,0x21,0x01,0x22,0x19,0x60,0x43,0xf8, -0x20,0x2c,0x31,0x4a,0x4f,0xf0,0x05,0x0e,0x14,0x60,0x30,0x4c,0x43,0xf8,0x20,0x1c, -0x02,0xf5,0xec,0x72,0x10,0x23,0xc4,0xf8,0x00,0xe0,0x13,0x60,0x2c,0x4b,0x15,0x26, -0x1e,0x60,0x02,0x26,0x26,0x60,0x2b,0x4e,0x37,0x68,0xc4,0xf8,0x00,0xe0,0xdf,0xf8, -0xb4,0xe0,0xce,0xf8,0x00,0x10,0xce,0xf8,0x04,0x10,0x18,0xb1,0x31,0x68,0x41,0xf4, -0x00,0x01,0x31,0x60,0x02,0x21,0x05,0x20,0x21,0x60,0x20,0x60,0x08,0x20,0x10,0x60, -0x15,0x22,0x1a,0x60,0x21,0x60,0x2b,0x68,0x9a,0x07,0xfc,0xd4,0x1e,0x4b,0x1b,0x68, -0x13,0xf0,0x10,0x0f,0x14,0xbf,0x04,0x25,0x00,0x25,0xff,0xf7,0x1b,0xfd,0x3b,0x02, -0x07,0xd4,0x05,0x23,0x23,0x60,0x33,0x68,0x23,0xf4,0x00,0x03,0x33,0x60,0x02,0x23, -0x23,0x60,0xbd,0xb9,0x15,0x4b,0x16,0x48,0x19,0x68,0x03,0xf5,0x10,0x53,0x04,0x33, -0x1a,0x68,0xc9,0xb2,0x02,0xf0,0x0f,0x02,0x51,0x43,0x1b,0x68,0x14,0x22,0x03,0xf0, -0x0f,0x03,0x9b,0x02,0xc3,0xeb,0x81,0x21,0x01,0xf6,0xd8,0x71,0xbd,0xe8,0xf8,0x4f, -0xff,0xf7,0xea,0xbc,0x28,0x46,0xbd,0xe8,0xf8,0x8f,0x00,0xbf,0x64,0x20,0x03,0x40, -0xa8,0x20,0x03,0x40,0x50,0x20,0x03,0x40,0x34,0x20,0x03,0x40,0x88,0x22,0x03,0x40, -0xb4,0x22,0x03,0x40,0x7c,0x22,0x03,0x40,0x54,0x20,0x03,0x40,0x2c,0x00,0x03,0x40, -0xf4,0x0e,0x00,0x20,0xc0,0x22,0x03,0x40,0x08,0xb5,0x01,0x1c,0x00,0x22,0x00,0x20, -0x00,0x23,0x00,0xf0,0xeb,0xf8,0x08,0xbc,0x02,0xbc,0x08,0x47,0x10,0xb5,0x00,0x21, -0x04,0x1c,0x00,0xf0,0x5d,0xf9,0x05,0x4b,0x18,0x68,0xc3,0x6b,0x00,0x2b,0x01,0xd0, -0x00,0xf0,0x06,0xf8,0x20,0x1c,0xff,0xf7,0xa7,0xfc,0xc0,0x46,0x0c,0x0f,0x00,0x20, -0x18,0x47,0xc0,0x46,0x38,0xb5,0x0a,0x4b,0x0a,0x4c,0xe4,0x1a,0xa4,0x10,0x0a,0xd0, -0x09,0x4a,0xa5,0x18,0xad,0x00,0xed,0x18,0x2b,0x68,0x01,0x3c,0x00,0xf0,0x0e,0xf8, -0x04,0x3d,0x00,0x2c,0xf8,0xd1,0x00,0xf0,0xcd,0xf9,0x38,0xbc,0x01,0xbc,0x00,0x47, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x3f,0x18,0x47,0xc0,0x46, -0x70,0xb5,0x10,0x4e,0x10,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, -0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x1d,0xf8,0xa5,0x42,0xf8,0xd1,0x00,0xf0, -0xab,0xf9,0x0a,0x4e,0x0a,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, -0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x0d,0xf8,0xa5,0x42,0xf8,0xd1,0x70,0xbc, -0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0x70,0xb5,0x0f,0x2a,0x34,0xd9,0x04,0x1c, -0x0c,0x43,0x0b,0x1c,0xa4,0x07,0x33,0xd1,0x15,0x1c,0x04,0x1c,0x10,0x3d,0x2d,0x09, -0x01,0x35,0x2d,0x01,0x49,0x19,0x1e,0x68,0x26,0x60,0x5e,0x68,0x66,0x60,0x9e,0x68, -0xa6,0x60,0xde,0x68,0x10,0x33,0xe6,0x60,0x10,0x34,0x99,0x42,0xf3,0xd1,0x0f,0x23, -0x45,0x19,0x13,0x40,0x03,0x2b,0x1d,0xd9,0x1c,0x1f,0x00,0x23,0xa4,0x08,0x01,0x34, -0xa4,0x00,0xce,0x58,0xee,0x50,0x04,0x33,0xa3,0x42,0xfa,0xd1,0xed,0x18,0xc9,0x18, -0x03,0x23,0x1a,0x40,0x05,0xd0,0x00,0x23,0xcc,0x5c,0xec,0x54,0x01,0x33,0x93,0x42, -0xfa,0xd1,0x70,0xbc,0x02,0xbc,0x08,0x47,0x05,0x1c,0x00,0x2a,0xf3,0xd1,0xf8,0xe7, -0x05,0x1c,0xf0,0xe7,0x1a,0x1c,0xf8,0xe7,0x70,0xb5,0x83,0x07,0x43,0xd0,0x54,0x1e, -0x00,0x2a,0x3d,0xd0,0x0d,0x06,0x2d,0x0e,0x03,0x1c,0x03,0x26,0x03,0xe0,0x62,0x1e, -0x00,0x2c,0x35,0xd0,0x14,0x1c,0x01,0x33,0x5a,0x1e,0x15,0x70,0x33,0x42,0xf6,0xd1, -0x03,0x2c,0x24,0xd9,0xff,0x25,0x0d,0x40,0x2a,0x02,0x15,0x43,0x2a,0x04,0x15,0x43, -0x0f,0x2c,0x11,0xd9,0x26,0x1c,0x10,0x3e,0x36,0x09,0x01,0x36,0x36,0x01,0x1a,0x1c, -0x9b,0x19,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,0x93,0x42,0xf8,0xd1, -0x0f,0x22,0x14,0x40,0x03,0x2c,0x0a,0xd9,0x26,0x1f,0xb6,0x08,0x01,0x36,0xb6,0x00, -0x1a,0x1c,0x9b,0x19,0x20,0xc2,0x93,0x42,0xfc,0xd1,0x03,0x22,0x14,0x40,0x00,0x2c, -0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,0x19,0x70,0x01,0x33,0xa3,0x42,0xfb,0xd1, -0x70,0xbc,0x02,0xbc,0x08,0x47,0x14,0x1c,0x03,0x1c,0xc9,0xe7,0xf8,0xb5,0x44,0x46, -0x5f,0x46,0x56,0x46,0x4d,0x46,0x9b,0x46,0x30,0x4b,0xf0,0xb4,0x1c,0x68,0xa4,0x23, -0x5b,0x00,0x05,0x1c,0xe0,0x58,0x0e,0x1c,0x90,0x46,0x00,0x28,0x4d,0xd0,0x43,0x68, -0x1f,0x2b,0x0f,0xdc,0x5c,0x1c,0x00,0x2d,0x23,0xd1,0x02,0x33,0x9b,0x00,0x44,0x60, -0x1e,0x50,0x00,0x20,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46,0xab,0x46,0xf8,0xbc, -0x02,0xbc,0x08,0x47,0x22,0x4b,0x00,0x2b,0x3c,0xd0,0xc8,0x20,0x40,0x00,0xaf,0xf3, -0x00,0x80,0x00,0x28,0x36,0xd0,0xa4,0x22,0x00,0x23,0x52,0x00,0xa1,0x58,0x43,0x60, -0x01,0x60,0xa0,0x50,0x40,0x32,0x83,0x50,0x04,0x32,0x83,0x50,0x01,0x24,0x00,0x2d, -0xdb,0xd0,0x9a,0x00,0x91,0x46,0x81,0x44,0x42,0x46,0x88,0x21,0x4f,0x46,0x7a,0x50, -0xc4,0x22,0x52,0x00,0x90,0x46,0x80,0x44,0x42,0x46,0x87,0x39,0x99,0x40,0x12,0x68, -0x0a,0x43,0x94,0x46,0x8a,0x46,0x42,0x46,0x61,0x46,0x11,0x60,0x84,0x22,0x49,0x46, -0x5f,0x46,0x52,0x00,0x8f,0x50,0x02,0x2d,0xbf,0xd1,0x02,0x1c,0x55,0x46,0x8d,0x32, -0xff,0x32,0x11,0x68,0x0d,0x43,0x15,0x60,0xb7,0xe7,0x20,0x1c,0x4d,0x30,0xff,0x30, -0xe0,0x50,0xac,0xe7,0x01,0x20,0x40,0x42,0xb4,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, -0x00,0x00,0x00,0x00,0x08,0xb5,0x04,0x4b,0x00,0x2b,0x02,0xd0,0x03,0x48,0xff,0xf7, -0x9b,0xfe,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x15,0x0b,0x00,0x20, -0xf0,0xb5,0x56,0x46,0x5f,0x46,0x4d,0x46,0x44,0x46,0xf0,0xb4,0x0e,0x1c,0x3f,0x4b, -0x1b,0x68,0x87,0xb0,0x03,0x93,0x49,0x33,0xff,0x33,0x01,0x90,0x04,0x93,0xa4,0x22, -0x03,0x9b,0x52,0x00,0x9f,0x58,0x00,0x2f,0x4d,0xd0,0x04,0x9b,0x98,0x46,0x00,0x23, -0x9b,0x46,0xc4,0x23,0x5b,0x00,0x9c,0x46,0xbc,0x44,0x63,0x46,0x02,0x93,0xc6,0x23, -0x5b,0x00,0x9a,0x46,0x7c,0x68,0xa5,0x00,0x7d,0x19,0xba,0x44,0x01,0x3c,0x08,0xd5, -0x27,0xe0,0x6b,0x1d,0xff,0x33,0x1b,0x68,0xb3,0x42,0x04,0xd0,0x04,0x3d,0x01,0x3c, -0x1f,0xd3,0x00,0x2e,0xf5,0xd1,0x7b,0x68,0x01,0x3b,0x6a,0x68,0xa3,0x42,0x3e,0xd0, -0x5b,0x46,0x6b,0x60,0x00,0x2a,0xf1,0xd0,0x7b,0x68,0x99,0x46,0x01,0x23,0xa3,0x40, -0x02,0x99,0x09,0x68,0x05,0x91,0x19,0x42,0x26,0xd1,0x00,0xf0,0x43,0xf8,0x7b,0x68, -0x4b,0x45,0xc4,0xd1,0x43,0x46,0x1b,0x68,0xbb,0x42,0xc0,0xd1,0x04,0x3d,0x01,0x3c, -0xdf,0xd2,0x1b,0x4b,0x00,0x2b,0x0e,0xd0,0x7b,0x68,0x00,0x2b,0x27,0xd1,0x3b,0x68, -0x00,0x2b,0x28,0xd0,0x42,0x46,0x38,0x1c,0x13,0x60,0xaf,0xf3,0x00,0x80,0x43,0x46, -0x1f,0x68,0x00,0x2f,0xb5,0xd1,0x07,0xb0,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46, -0xab,0x46,0xf0,0xbc,0x01,0xbc,0x00,0x47,0x51,0x46,0x09,0x68,0x19,0x42,0x08,0xd1, -0x2b,0x1c,0x84,0x33,0x19,0x68,0x01,0x98,0x00,0xf0,0x14,0xf8,0xcf,0xe7,0x7c,0x60, -0xc0,0xe7,0x2b,0x1c,0x84,0x33,0x18,0x68,0x00,0xf0,0x0c,0xf8,0xc7,0xe7,0x3b,0x68, -0xb8,0x46,0x1f,0x1c,0xdd,0xe7,0x00,0x23,0xfa,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, -0x00,0x00,0x00,0x00,0x10,0x47,0xc0,0x46,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc, -0x9e,0x46,0x70,0x47,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47, -0x00,0x00,0x00,0x00,0x24,0xf2,0xff,0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x28,0x15,0x00,0x20,0xff,0xff,0xff,0xc5,0xff,0xff,0xff,0xff,0xc5,0xff,0xff,0xff, -0xc5,0xc5,0xc5,0xff,0xc5,0xc5,0xc5,0xff,0x43,0x00,0x00,0x00,0x18,0x0f,0x00,0x20, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x12,0x00,0x20, -0x6c,0x12,0x00,0x20,0xd4,0x12,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0f,0x00,0x20, +0x01,0xbc,0x00,0x47,0x44,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0xd4,0x0e,0x00,0x20, +0x08,0xb5,0x09,0x4b,0x00,0x2b,0x03,0xd0,0x08,0x48,0x09,0x49,0xaf,0xf3,0x00,0x80, +0x08,0x48,0x03,0x68,0x00,0x2b,0x04,0xd0,0x07,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0, +0x0d,0xf8,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0xd4,0x0e,0x00,0x20, +0x48,0x13,0x00,0x20,0x3c,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46, +0xd8,0x30,0x9f,0xe5,0x00,0x00,0x53,0xe3,0xcc,0x30,0x9f,0x05,0x03,0xd0,0xa0,0xe1, +0x00,0x20,0x0f,0xe1,0x0f,0x00,0x12,0xe3,0x15,0x00,0x00,0x0a,0xd1,0xf0,0x21,0xe3, +0x03,0xd0,0xa0,0xe1,0x01,0xaa,0x4d,0xe2,0x0a,0x30,0xa0,0xe1,0xd7,0xf0,0x21,0xe3, +0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2,0xdb,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1, +0x01,0x3a,0x43,0xe2,0xd2,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x02,0x3a,0x43,0xe2, +0xd3,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x02,0x39,0x43,0xe2,0xff,0x30,0xc3,0xe3, +0xff,0x3c,0xc3,0xe3,0x04,0x30,0x03,0xe5,0x00,0x20,0x53,0xe9,0xc0,0x20,0x82,0xe3, +0x02,0xf0,0x21,0xe1,0x01,0xa8,0x43,0xe2,0x00,0x10,0xb0,0xe3,0x01,0xb0,0xa0,0xe1, +0x01,0x70,0xa0,0xe1,0x60,0x00,0x9f,0xe5,0x60,0x20,0x9f,0xe5,0x00,0x20,0x52,0xe0, +0x01,0x30,0x8f,0xe2,0x13,0xff,0x2f,0xe1,0x00,0xf0,0x44,0xfd,0x11,0x4b,0x00,0x2b, +0x01,0xd0,0xfe,0x46,0x9f,0x46,0x10,0x4b,0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46, +0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00,0x0e,0x48,0x00,0x28,0x02,0xd0,0x0e,0x48, +0x00,0xf0,0x24,0xfe,0x00,0xf0,0xbe,0xfc,0x20,0x00,0x29,0x00,0x00,0xf0,0xcc,0xf8, +0x00,0xf0,0xa4,0xfc,0x7b,0x46,0x18,0x47,0x11,0x00,0x00,0xef,0x00,0x00,0x08,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x13,0x00,0x20, +0x88,0x13,0x00,0x20,0xad,0x0d,0x00,0x20,0xc1,0x0d,0x00,0x20,0x70,0xb5,0x04,0x46, +0x0e,0x46,0x15,0x46,0x00,0x21,0x28,0x22,0x00,0xf0,0x0c,0xfd,0x26,0x61,0x65,0x62, +0x00,0x21,0x20,0x22,0x02,0x48,0x00,0xf0,0x05,0xfd,0x00,0x20,0x70,0xbd,0x00,0xbf, +0x60,0x13,0x00,0x20,0x10,0xb5,0x01,0x20,0x00,0xf0,0xba,0xf9,0x04,0x46,0x28,0xb9, +0x01,0x21,0x20,0x22,0x03,0x48,0x00,0xf0,0xf5,0xfc,0x01,0xe0,0x40,0xf2,0x01,0x14, +0x20,0x46,0x10,0xbd,0x60,0x13,0x00,0x20,0x01,0x39,0xf8,0xb5,0x04,0x0b,0x08,0x44, +0x07,0x0b,0x25,0x03,0xbc,0x42,0x14,0xd8,0x0b,0x4e,0xa3,0x5d,0x6b,0xb9,0x28,0x46, +0x00,0xf0,0xf8,0xf8,0x38,0xb1,0x00,0x04,0x00,0xf4,0x7f,0x00,0x40,0xea,0x04,0x60, +0x40,0xf4,0x81,0x70,0xf8,0xbd,0x01,0x23,0xa3,0x55,0x01,0x34,0x05,0xf5,0x80,0x55, +0xe8,0xe7,0x00,0x20,0xf8,0xbd,0x00,0xbf,0x60,0x13,0x00,0x20,0xb2,0xf5,0x80,0x5f, +0xf8,0xb5,0x07,0x46,0x0e,0x46,0x15,0x46,0x0b,0xd8,0x08,0x46,0x11,0x46,0xff,0xf7, +0xd3,0xff,0x04,0x46,0x40,0xb9,0x38,0x46,0x31,0x46,0x2a,0x46,0x00,0xf0,0xe0,0xf8, +0x02,0xe0,0x4f,0xf4,0x82,0x70,0xf8,0xbd,0x20,0x46,0xf8,0xbd,0x2d,0xe9,0xf0,0x4f, +0x53,0x1e,0x0b,0x44,0x1b,0x0b,0x85,0xb0,0x0c,0x46,0x0f,0x0b,0x83,0x46,0x15,0x46, +0x20,0x48,0x00,0x21,0x20,0x22,0x03,0x93,0x4f,0xea,0x07,0x38,0x00,0xf0,0xa2,0xfc, +0x4f,0xf0,0x00,0x0a,0xc4,0xf3,0x0b,0x03,0x03,0x9a,0x97,0x42,0x2e,0xd8,0x08,0xf5, +0x80,0x5c,0x2e,0x19,0xdf,0xf8,0x60,0x90,0x66,0x45,0x88,0xbf,0xc6,0xf3,0x0b,0x06, +0x41,0x46,0x4f,0xf4,0x80,0x52,0x48,0x46,0x8c,0xbf,0xc6,0xeb,0x05,0x06,0x2e,0x46, +0xcd,0xf8,0x04,0xc0,0x02,0x93,0x00,0xf0,0x41,0xfc,0x02,0x9b,0x0b,0xeb,0x0a,0x01, +0x09,0xeb,0x03,0x00,0x32,0x46,0x00,0xf0,0x39,0xfc,0x48,0x46,0x41,0x46,0x4f,0xf4, +0x80,0x52,0xff,0xf7,0xab,0xff,0x01,0x37,0xdd,0xf8,0x04,0xc0,0x38,0xb9,0x34,0x44, +0xc4,0xf3,0x0b,0x03,0xad,0x1b,0xb2,0x44,0xe0,0x46,0xcd,0xe7,0x00,0x20,0x05,0xb0, +0xbd,0xe8,0xf0,0x8f,0x60,0x13,0x00,0x20,0x00,0x3c,0x00,0x20,0x08,0xb5,0x00,0xf0, +0x87,0xf8,0x00,0x20,0x08,0xbd,0x00,0x00,0xf8,0xb5,0x32,0x48,0x32,0x49,0x33,0x4a, +0x33,0x4d,0xff,0xf7,0x43,0xff,0x00,0x23,0x2b,0x60,0x2a,0x68,0x2d,0x4c,0x14,0x23, +0x03,0xfb,0x02,0x43,0x08,0x33,0x5b,0x68,0x00,0x2b,0xf7,0xd0,0x2d,0x4b,0x1a,0x68, +0x19,0x46,0x12,0xf0,0x08,0x0f,0xf9,0xd1,0x2b,0x4e,0x2c,0x4f,0x33,0x68,0x3b,0x60, +0x43,0xf0,0x33,0x03,0x33,0x60,0x0a,0x68,0x12,0x07,0xfc,0xd4,0x2b,0x68,0x14,0x22, +0x02,0xfb,0x03,0x41,0x89,0x68,0x01,0x39,0x04,0x29,0x26,0xd8,0xdf,0xe8,0x01,0xf0, +0x03,0x06,0x0e,0x16,0x1e,0x00,0xff,0xf7,0x2d,0xff,0x20,0xe0,0x53,0x43,0xe2,0x18, +0x10,0x69,0xe1,0x58,0x52,0x68,0xff,0xf7,0xc1,0xff,0x18,0xe0,0x53,0x43,0xe2,0x18, +0x10,0x69,0xe1,0x58,0x52,0x68,0xff,0xf7,0x51,0xff,0x10,0xe0,0x53,0x43,0xe2,0x18, +0x10,0x69,0xe1,0x58,0x52,0x68,0xff,0xf7,0x61,0xff,0x08,0xe0,0x53,0x43,0xe2,0x18, +0xe0,0x58,0x51,0x68,0xff,0xf7,0x20,0xff,0x01,0xe0,0x40,0xf2,0x05,0x10,0x3b,0x68, +0x33,0x60,0x0c,0x4b,0x1b,0x68,0x1b,0x07,0xfb,0xd4,0x2b,0x68,0x14,0x22,0x02,0xfb, +0x03,0x44,0x10,0xb1,0xe3,0x68,0xe0,0x60,0xfe,0xe7,0xe2,0x68,0x83,0xf0,0x01,0x03, +0xe0,0x60,0xa1,0xe7,0xd8,0x1b,0x00,0x20,0x00,0x1c,0x00,0x20,0x00,0x2c,0x00,0x20, +0x80,0x13,0x00,0x20,0x00,0x40,0x03,0x40,0x04,0x40,0x03,0x40,0x84,0x13,0x00,0x20, +0xfe,0xe7,0x00,0x00,0x08,0xb5,0x04,0x4b,0x1b,0x68,0x5b,0x69,0x98,0x47,0x03,0x4b, +0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42, +0x08,0xb5,0x04,0x4b,0x1b,0x68,0x9b,0x69,0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60, +0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42,0x10,0xb5,0x3a,0x4b, +0x3a,0x4a,0x1b,0x68,0x13,0xf0,0x02,0x0f,0x39,0x4b,0x19,0x68,0x41,0xf0,0x02,0x01, +0x19,0x60,0x12,0x68,0x1a,0xd0,0x19,0x68,0xc2,0xf3,0xc1,0x04,0x21,0xf4,0xe1,0x71, +0x21,0xf0,0x01,0x01,0xc2,0xf3,0xc0,0x10,0x21,0x43,0x41,0xea,0x00,0x21,0xc2,0xf3, +0x41,0x10,0x41,0xea,0x80,0x11,0x19,0x60,0x1b,0x68,0xdc,0x07,0x03,0xd5,0x2d,0x4b, +0x1b,0x68,0x58,0x07,0xfb,0xd5,0x02,0xf0,0x07,0x03,0x19,0xe0,0x19,0x68,0xc2,0xf3, +0xc1,0x24,0x21,0xf4,0xe1,0x71,0x21,0xf0,0x01,0x01,0xc2,0xf3,0xc0,0x30,0x21,0x43, +0x41,0xea,0x00,0x21,0xc2,0xf3,0x41,0x30,0x41,0xea,0x80,0x11,0x19,0x60,0x1b,0x68, +0xd9,0x07,0x03,0xd5,0x1f,0x4b,0x1b,0x68,0x5b,0x07,0xfb,0xd5,0xc2,0xf3,0x02,0x23, +0x1d,0x4a,0x4a,0xf6,0xaa,0x21,0x11,0x60,0x1c,0x49,0x1b,0x03,0x08,0x68,0xb3,0xf5, +0xe0,0x4f,0x18,0xbf,0x43,0xf4,0x80,0x73,0x20,0xf4,0xe2,0x40,0x03,0x43,0x0b,0x60, +0x45,0xf2,0xaa,0x53,0x13,0x60,0x00,0x23,0x15,0x4a,0x12,0x68,0x02,0xf0,0x0f,0x02, +0x93,0x42,0x14,0x4a,0x15,0xd2,0x13,0x60,0x13,0x4a,0x14,0x48,0x01,0x21,0x11,0x60, +0x00,0x21,0x01,0x60,0x11,0x60,0x05,0x21,0xc2,0xf8,0x58,0x12,0x4f,0xf0,0xff,0x31, +0xc0,0xf8,0x8c,0x12,0xc0,0xf8,0x90,0x12,0x02,0x21,0xc2,0xf8,0x58,0x12,0x01,0x33, +0xe2,0xe7,0x00,0x23,0x13,0x60,0x10,0xbd,0x00,0x00,0x09,0x40,0x08,0x13,0x00,0x50, +0x24,0x00,0x03,0x40,0x1c,0x00,0x03,0x40,0x64,0x20,0x03,0x40,0xa8,0x20,0x03,0x40, +0x00,0x24,0x03,0x40,0x50,0x20,0x03,0x40,0x30,0x20,0x03,0x40,0x34,0x20,0x03,0x40, +0x2d,0xe9,0xf0,0x4f,0xc7,0x4b,0x85,0xb0,0x02,0x90,0x1b,0x68,0x4f,0xf0,0xfc,0x54, +0x23,0xf0,0x7f,0x43,0x01,0x93,0x00,0x22,0xc3,0x4b,0x1b,0x68,0x03,0xf0,0x0f,0x03, +0x9a,0x42,0x80,0xf0,0x58,0x82,0xc1,0x48,0x03,0x68,0x13,0xf0,0x01,0x03,0x03,0x93, +0x40,0xf0,0x75,0x81,0xdf,0xf8,0x6c,0xc3,0x4f,0xf0,0x05,0x0e,0xbc,0x4b,0xcc,0xf8, +0x00,0xe0,0x1b,0x68,0xdf,0xf8,0x60,0x83,0xc3,0xf3,0x03,0x23,0xd8,0xf8,0x00,0x60, +0x4f,0xf4,0x40,0x71,0x01,0x33,0xb1,0xfb,0xf3,0xf3,0xb6,0x4d,0xb6,0xb2,0x5e,0x43, +0x29,0x68,0xc6,0xf3,0x8f,0x16,0x09,0x0c,0x09,0x04,0x31,0x43,0x29,0x60,0xb2,0x49, +0x0d,0x68,0xb2,0x49,0x5d,0x43,0xad,0x09,0x0e,0x68,0x0d,0x60,0xb0,0x4d,0x2e,0x68, +0x51,0xf8,0x24,0x7c,0xc6,0xf3,0x07,0x46,0x5e,0x43,0x27,0xf0,0xff,0x07,0xc6,0xf3, +0x87,0x16,0x3e,0x43,0x41,0xf8,0x24,0x6c,0xaa,0x4f,0xab,0x4e,0xd6,0xf8,0x00,0xa0, +0xd7,0xf8,0x00,0x90,0xca,0xf3,0x07,0x4a,0x29,0xf0,0xff,0x09,0x4a,0xea,0x09,0x09, +0xc7,0xf8,0x00,0x90,0x37,0x68,0x4f,0xea,0x17,0x6a,0x0a,0xfb,0x03,0xfa,0xa3,0x4f, +0x4f,0xea,0x8a,0x0a,0xd7,0xf8,0x00,0x90,0x0a,0xf4,0x7f,0x4a,0x29,0xf4,0x7f,0x49, +0x4a,0xea,0x09,0x09,0xc7,0xf8,0x00,0x90,0xdf,0xf8,0xd0,0x92,0xdf,0xf8,0xd0,0xa2, +0xd9,0xf8,0x00,0x70,0x4f,0xea,0x17,0x6b,0x0b,0xfb,0x03,0xfb,0xda,0xf8,0x00,0x70, +0x3f,0x0c,0x3f,0x04,0x47,0xea,0x9b,0x17,0xca,0xf8,0x00,0x70,0x36,0x68,0xc6,0xf3, +0x07,0x26,0x73,0x43,0x92,0x4e,0x9b,0x00,0x37,0x68,0x03,0xf4,0x7f,0x43,0x27,0xf4, +0x7f,0x47,0x1f,0x43,0x37,0x60,0x8f,0x4b,0x8f,0x4e,0xd6,0xf8,0x00,0xa0,0x1f,0x68, +0x4f,0xea,0x1a,0x6a,0x27,0xf4,0x7f,0x47,0x47,0xea,0x0a,0x27,0x1f,0x60,0xd6,0xf8, +0x00,0xa0,0x1f,0x68,0xca,0xf3,0x07,0x4a,0x27,0xf0,0xff,0x07,0x4a,0xea,0x07,0x07, +0x1f,0x60,0xd6,0xf8,0x00,0xa0,0x9f,0x68,0x0a,0xf4,0x7f,0x4a,0x27,0xf4,0x7f,0x47, +0x4a,0xea,0x07,0x07,0x9f,0x60,0x37,0x68,0x9e,0x68,0xff,0xb2,0x26,0xf0,0xff,0x06, +0x3e,0x43,0x9e,0x60,0x2f,0x68,0xde,0x68,0x07,0xf4,0x70,0x47,0x26,0xf4,0x70,0x46, +0x3e,0x43,0xde,0x60,0xd9,0xf8,0x00,0x70,0x5e,0x68,0x07,0xf4,0x70,0x47,0x26,0xf4, +0x70,0x46,0x3e,0x43,0x5e,0x60,0x2d,0x68,0x51,0xf8,0x24,0x3c,0x2d,0x0e,0x23,0xf4, +0x7f,0x43,0x43,0xea,0x05,0x23,0x41,0xf8,0x24,0x3c,0x70,0x4b,0x1d,0x68,0x70,0x4b, +0xc5,0xf3,0x0b,0x05,0x19,0x68,0x21,0xf4,0x7f,0x61,0x21,0xf0,0x0f,0x01,0x29,0x43, +0x6c,0x4d,0x19,0x60,0x2e,0x68,0x19,0x68,0x06,0xf4,0x70,0x26,0x21,0xf4,0x70,0x21, +0x31,0x43,0x19,0x60,0x68,0x4b,0x69,0x49,0x1f,0x68,0x0e,0x68,0xc7,0xf3,0x83,0x47, +0x26,0xf4,0x70,0x26,0x46,0xea,0x07,0x46,0x0e,0x60,0xd8,0xf8,0x00,0x70,0x0e,0x68, +0xc7,0xf3,0x0b,0x47,0x26,0xf4,0x7f,0x66,0x26,0xf0,0x0f,0x06,0x3e,0x43,0x0e,0x60, +0x5f,0x4e,0x1f,0x68,0x31,0x68,0xff,0x0d,0x21,0xf0,0xff,0x71,0x21,0xf4,0x80,0x31, +0x41,0xea,0x07,0x41,0x31,0x60,0x2d,0x68,0x5a,0x49,0x0f,0x35,0x05,0xf0,0x0f,0x05, +0x0d,0x60,0x1e,0x68,0x4d,0x68,0xc6,0xf3,0x80,0x56,0x25,0xf4,0x00,0x05,0x45,0xea, +0xc6,0x55,0x4d,0x60,0x4d,0x68,0x54,0x4f,0x45,0xf4,0x80,0x45,0x4d,0x60,0x02,0x21, +0x52,0x4d,0xcc,0xf8,0x00,0x10,0x4a,0xf6,0xaa,0x21,0x29,0x60,0x50,0x49,0x3e,0x68, +0xd1,0xf8,0x00,0xc0,0x06,0xf0,0x0f,0x08,0x2c,0xf4,0x7f,0x0c,0x4c,0xea,0x08,0x4c, +0xc6,0xf3,0x03,0x26,0x4c,0xea,0x06,0x56,0x0e,0x60,0x4a,0x4e,0xd6,0xf8,0x00,0xc0, +0xd1,0xf8,0x00,0x80,0xcc,0xf3,0x03,0x49,0x28,0xf0,0xff,0x08,0x49,0xea,0x08,0x08, +0xcc,0xf3,0x03,0x6c,0x48,0xea,0x0c,0x1c,0xc1,0xf8,0x00,0xc0,0x3f,0x68,0xd1,0xf8, +0x04,0xc0,0x07,0xf4,0x70,0x28,0x2c,0xf4,0x7f,0x0c,0x4c,0xea,0x08,0x0c,0xc7,0xf3, +0x03,0x67,0x4c,0xea,0x07,0x57,0x4f,0x60,0x3b,0x49,0x3c,0x4f,0xd1,0xf8,0x00,0x80, +0xd7,0xf8,0x00,0xc0,0xc8,0xf3,0x03,0x28,0x2c,0xf0,0x0f,0x0c,0x48,0xea,0x0c,0x0c, +0xc7,0xf8,0x00,0xc0,0xd6,0xf8,0x00,0xc0,0x35,0x4e,0x0c,0xf4,0xf8,0x5c,0x37,0x68, +0x27,0xf4,0xf8,0x57,0x4c,0xea,0x07,0x07,0x37,0x60,0x0f,0x68,0xd6,0xf8,0x04,0xc0, +0x3f,0x0b,0x07,0xf4,0x70,0x47,0x2c,0xf4,0x70,0x4c,0x47,0xea,0x0c,0x07,0x77,0x60, +0x0f,0x68,0x2c,0x49,0xc7,0xf3,0x04,0x47,0x0e,0x68,0x26,0xf0,0x1f,0x06,0x3e,0x43, +0x0e,0x60,0x1e,0x68,0x28,0x4b,0xc6,0xf3,0x01,0x46,0x19,0x68,0x21,0xf4,0x40,0x11, +0x41,0xea,0x06,0x51,0x19,0x60,0x45,0xf2,0xaa,0x53,0x2b,0x60,0x23,0x4b,0xc3,0xf8, +0x00,0xe0,0x01,0x68,0x41,0xf0,0x01,0x01,0x01,0x60,0x03,0x99,0x19,0x60,0x20,0x4b, +0x48,0xe0,0x00,0xbf,0x14,0x24,0x03,0x40,0x00,0x24,0x03,0x40,0x40,0x00,0x03,0x40, +0x00,0x20,0x03,0x40,0x40,0x22,0x03,0x40,0x8c,0x11,0x00,0x50,0x44,0x22,0x03,0x40, +0x74,0x11,0x00,0x50,0x24,0x22,0x03,0x40,0x78,0x11,0x00,0x50,0x28,0x22,0x03,0x40, +0x34,0x22,0x03,0x40,0x10,0x22,0x03,0x40,0x70,0x11,0x00,0x50,0x84,0x11,0x00,0x50, +0x68,0x22,0x03,0x40,0x80,0x11,0x00,0x50,0xb0,0x12,0x00,0x50,0x6c,0x22,0x03,0x40, +0x70,0x22,0x03,0x40,0x78,0x22,0x03,0x40,0x90,0x11,0x00,0x50,0x64,0x20,0x03,0x40, +0x84,0x20,0x03,0x40,0x94,0x11,0x00,0x50,0x98,0x11,0x00,0x50,0x80,0x20,0x03,0x40, +0x90,0x20,0x03,0x40,0x98,0x20,0x03,0x40,0xa8,0x20,0x03,0x40,0x3c,0x00,0x03,0x40, +0x00,0x00,0x09,0x40,0x88,0x22,0x03,0x40,0x88,0x11,0x00,0x50,0x7c,0x11,0x00,0x50, +0x2c,0x22,0x03,0x40,0x62,0x49,0x1b,0x68,0x62,0x48,0x13,0xf0,0x02,0x0f,0x62,0x4b, +0x1d,0x68,0x45,0xf0,0x02,0x05,0x1d,0x60,0x09,0x68,0x19,0xd0,0x1d,0x68,0xc1,0xf3, +0xc1,0x47,0x25,0xf4,0xe1,0x75,0x25,0xf0,0x01,0x05,0xc1,0xf3,0xc0,0x56,0x3d,0x43, +0x45,0xea,0x06,0x25,0xc1,0xf3,0x41,0x56,0x45,0xea,0x86,0x15,0x1d,0x60,0x1b,0x68, +0xdd,0x07,0x02,0xd5,0x03,0x68,0x5b,0x07,0xfc,0xd5,0xc1,0xf3,0x02,0x43,0x17,0xe0, +0x1d,0x68,0xcf,0x0f,0xc1,0xf3,0xc1,0x66,0x25,0xf4,0xe1,0x75,0x46,0xea,0x07,0x26, +0x25,0xf0,0x01,0x05,0x35,0x43,0xc1,0xf3,0x41,0x76,0x45,0xea,0x86,0x15,0x1d,0x60, +0x1b,0x68,0xdf,0x07,0x02,0xd5,0x03,0x68,0x5e,0x07,0xfc,0xd5,0xc1,0xf3,0x02,0x63, +0x46,0x49,0x4a,0xf6,0xaa,0x25,0x0d,0x60,0x45,0x4d,0x1b,0x03,0x2e,0x68,0xb3,0xf5, +0xe0,0x4f,0x26,0xf4,0xe2,0x46,0x18,0xbf,0x43,0xf4,0x80,0x73,0x33,0x43,0x2b,0x60, +0x45,0xf2,0xaa,0x53,0x0b,0x60,0x3f,0x4b,0x01,0x21,0x1a,0x60,0x43,0xf8,0x20,0x1c, +0x3d,0x49,0x4f,0xf6,0xff,0x75,0x0d,0x60,0x3c,0x4f,0x00,0x25,0x43,0xf8,0x20,0x5c, +0x4f,0xf0,0x05,0x0e,0x03,0xf5,0x0e,0x73,0x10,0x21,0x39,0x4e,0xc3,0xf8,0x00,0xe0, +0x39,0x60,0x15,0x21,0x31,0x60,0x02,0x21,0x19,0x60,0x36,0x49,0xd1,0xf8,0x00,0xc0, +0xc3,0xf8,0x00,0xe0,0xdf,0xf8,0xdc,0xe0,0xce,0xf8,0x00,0x50,0xce,0xf8,0x04,0x50, +0x02,0x9d,0x1d,0xb1,0x0d,0x68,0x45,0xf4,0x00,0x05,0x0d,0x60,0xdf,0xf8,0xc8,0xe0, +0x02,0x25,0x1d,0x60,0xce,0xf8,0x00,0x40,0x4f,0xf0,0x05,0x0e,0xc3,0xf8,0x00,0xe0, +0x4f,0xf0,0x08,0x0e,0xc7,0xf8,0x00,0xe0,0x15,0x27,0x37,0x60,0x1d,0x60,0x05,0x68, +0xad,0x07,0x18,0xd5,0xfb,0xe7,0x24,0x4b,0x24,0x48,0x1a,0x68,0x03,0xf5,0x10,0x53, +0x04,0x33,0x19,0x68,0xd2,0xb2,0x01,0xf0,0x0f,0x01,0x1b,0x68,0x51,0x43,0x03,0xf0, +0x0f,0x03,0x9b,0x02,0xc3,0xeb,0x81,0x21,0x01,0xf6,0xd8,0x71,0x14,0x22,0xff,0xf7, +0xe7,0xfc,0x05,0x46,0x16,0xe0,0x1a,0x48,0x00,0x68,0x10,0xf0,0x10,0x0f,0x0c,0xbf, +0x00,0x25,0x04,0x25,0x1c,0xf4,0x00,0x0f,0x07,0xd1,0x05,0x20,0x18,0x60,0x08,0x68, +0x20,0xf4,0x00,0x00,0x08,0x60,0x02,0x21,0x19,0x60,0x01,0x99,0x0c,0x44,0x0d,0xb9, +0x01,0x32,0x71,0xe5,0xff,0xf7,0xda,0xfc,0x28,0x46,0x05,0xb0,0xbd,0xe8,0xf0,0x8f, +0x08,0x13,0x00,0x50,0x1c,0x00,0x03,0x40,0x24,0x00,0x03,0x40,0x64,0x20,0x03,0x40, +0xa8,0x20,0x03,0x40,0x50,0x20,0x03,0x40,0x34,0x20,0x03,0x40,0x0c,0x22,0x03,0x40, +0xb4,0x22,0x03,0x40,0x7c,0x22,0x03,0x40,0x2c,0x00,0x03,0x40,0xe4,0x0e,0x00,0x20, +0x54,0x20,0x03,0x40,0xc0,0x22,0x03,0x40,0x10,0x21,0x03,0x40,0x10,0xb5,0x00,0x21, +0x04,0x1c,0x00,0xf0,0xdf,0xf8,0x05,0x4b,0x18,0x68,0xc3,0x6b,0x00,0x2b,0x01,0xd0, +0x00,0xf0,0x06,0xf8,0x20,0x1c,0xff,0xf7,0x8b,0xfc,0xc0,0x46,0xfc,0x0e,0x00,0x20, +0x18,0x47,0xc0,0x46,0x70,0xb5,0x10,0x4e,0x10,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24, +0x00,0x2d,0x06,0xd0,0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x1d,0xf8,0xa5,0x42, +0xf8,0xd1,0x00,0xf0,0xdb,0xf9,0x0a,0x4e,0x0a,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24, +0x00,0x2d,0x06,0xd0,0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x0d,0xf8,0xa5,0x42, +0xf8,0xd1,0x70,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xf0,0xb5,0x0f,0x2a, +0x37,0xd9,0x03,0x1c,0x0b,0x43,0x9c,0x07,0x37,0xd1,0x16,0x1c,0x10,0x3e,0x36,0x09, +0x35,0x01,0x45,0x19,0x10,0x35,0x0c,0x1c,0x03,0x1c,0x27,0x68,0x1f,0x60,0x67,0x68, +0x5f,0x60,0xa7,0x68,0x9f,0x60,0xe7,0x68,0xdf,0x60,0x10,0x33,0x10,0x34,0xab,0x42, +0xf3,0xd1,0x73,0x1c,0x1b,0x01,0xc5,0x18,0xc9,0x18,0x0f,0x23,0x13,0x40,0x03,0x2b, +0x1d,0xd9,0x1c,0x1f,0xa4,0x08,0x01,0x34,0xa4,0x00,0x00,0x23,0xce,0x58,0xee,0x50, +0x04,0x33,0xa3,0x42,0xfa,0xd1,0xed,0x18,0xc9,0x18,0x03,0x23,0x1a,0x40,0x05,0xd0, +0x00,0x23,0xcc,0x5c,0xec,0x54,0x01,0x33,0x93,0x42,0xfa,0xd1,0xf0,0xbc,0x02,0xbc, +0x08,0x47,0x05,0x1c,0x00,0x2a,0xf3,0xd1,0xf8,0xe7,0x05,0x1c,0xf0,0xe7,0x1a,0x1c, +0xf8,0xe7,0xc0,0x46,0xf0,0xb5,0x83,0x07,0x4a,0xd0,0x54,0x1e,0x00,0x2a,0x44,0xd0, +0x0e,0x06,0x36,0x0e,0x03,0x1c,0x03,0x25,0x03,0xe0,0x62,0x1e,0x00,0x2c,0x3c,0xd0, +0x14,0x1c,0x01,0x33,0x5a,0x1e,0x16,0x70,0x2b,0x42,0xf6,0xd1,0x03,0x2c,0x2b,0xd9, +0xff,0x25,0x0d,0x40,0x2a,0x02,0x15,0x43,0x2a,0x04,0x15,0x43,0x0f,0x2c,0x15,0xd9, +0x27,0x1c,0x10,0x3f,0x3f,0x09,0x1e,0x1c,0x3a,0x01,0x10,0x36,0xb6,0x18,0x1a,0x1c, +0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,0xb2,0x42,0xf8,0xd1,0x01,0x37, +0x3f,0x01,0x0f,0x22,0xdb,0x19,0x14,0x40,0x03,0x2c,0x0d,0xd9,0x27,0x1f,0xbf,0x08, +0xba,0x00,0x1e,0x1d,0xb6,0x18,0x1a,0x1c,0x20,0xc2,0xb2,0x42,0xfc,0xd1,0x01,0x37, +0xbf,0x00,0x03,0x22,0xdb,0x19,0x14,0x40,0x00,0x2c,0x06,0xd0,0x0a,0x06,0x12,0x0e, +0x1c,0x19,0x1a,0x70,0x01,0x33,0xa3,0x42,0xfb,0xd1,0xf0,0xbc,0x02,0xbc,0x08,0x47, +0x14,0x1c,0x03,0x1c,0xc2,0xe7,0xc0,0x46,0x08,0xb5,0x04,0x4b,0x00,0x2b,0x02,0xd0, +0x03,0x48,0x00,0xf0,0x9b,0xf8,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00, +0xc1,0x0d,0x00,0x20,0xf0,0xb5,0x5f,0x46,0x56,0x46,0x4d,0x46,0x44,0x46,0xf0,0xb4, +0x43,0x4b,0x1b,0x68,0x85,0xb0,0x01,0x93,0x49,0x33,0xff,0x33,0x02,0x90,0x03,0x93, +0x0f,0x1c,0x01,0x98,0xa4,0x21,0x49,0x00,0x42,0x58,0x90,0x46,0x00,0x2a,0x4b,0xd0, +0x03,0x98,0x81,0x46,0x41,0x46,0x4e,0x68,0x74,0x1e,0x42,0xd4,0x45,0x46,0xa3,0x00, +0x88,0x35,0xed,0x18,0xc6,0x20,0xc4,0x23,0x01,0x36,0x5b,0x00,0x40,0x00,0xb6,0x00, +0x9b,0x46,0x82,0x46,0x46,0x44,0xc3,0x44,0xc2,0x44,0x08,0xe0,0x2b,0x1c,0x80,0x33, +0x1b,0x68,0xbb,0x42,0x05,0xd0,0x04,0x3d,0x04,0x3e,0x01,0x3c,0x29,0xd3,0x00,0x2f, +0xf4,0xd1,0x41,0x46,0x4a,0x68,0x01,0x3a,0x33,0x68,0xa2,0x42,0x30,0xd0,0x00,0x22, +0x32,0x60,0x00,0x2b,0xef,0xd0,0x40,0x46,0x59,0x46,0x40,0x68,0x01,0x22,0x09,0x68, +0xa2,0x40,0x00,0x90,0x11,0x42,0x20,0xd0,0x50,0x46,0x00,0x68,0x10,0x42,0x21,0xd1, +0x02,0x98,0x29,0x68,0x00,0xf0,0x40,0xf8,0x41,0x46,0x49,0x68,0x00,0x9a,0x91,0x42, +0xb7,0xd1,0x4a,0x46,0x12,0x68,0x42,0x45,0xb3,0xd1,0x04,0x3d,0x04,0x3e,0x01,0x3c, +0xd5,0xd2,0x18,0x4a,0x00,0x2a,0x11,0xd1,0x05,0xb0,0x3c,0xbc,0x90,0x46,0x99,0x46, +0xa2,0x46,0xab,0x46,0xf0,0xbc,0x01,0xbc,0x00,0x47,0x00,0xf0,0x25,0xf8,0xe3,0xe7, +0x4c,0x60,0xce,0xe7,0x28,0x68,0x00,0xf0,0x1f,0xf8,0xdd,0xe7,0x43,0x46,0x5b,0x68, +0x40,0x46,0x00,0x2b,0x0d,0xd1,0x03,0x68,0x00,0x2b,0x0e,0xd0,0x49,0x46,0x0b,0x60, +0xaf,0xf3,0x00,0x80,0x4b,0x46,0x1a,0x68,0x90,0x46,0x41,0x46,0x00,0x29,0x91,0xd1, +0xda,0xe7,0x03,0x68,0xc1,0x46,0x98,0x46,0xf7,0xe7,0x00,0x23,0xfa,0xe7,0xc0,0x46, +0xfc,0x0e,0x00,0x20,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0x08,0xb5,0x01,0x1c, +0x00,0x22,0x00,0x20,0x00,0x23,0x00,0xf0,0x1f,0xf8,0x08,0xbc,0x02,0xbc,0x08,0x47, +0x38,0xb5,0x0a,0x4b,0x0a,0x4d,0xed,0x1a,0xad,0x10,0x0a,0xd0,0x01,0x3d,0xac,0x00, +0xe4,0x18,0x00,0xe0,0x01,0x3d,0x23,0x68,0x00,0xf0,0x0c,0xf8,0x04,0x3c,0x00,0x2d, +0xf8,0xd1,0x00,0xf0,0x71,0xf8,0x38,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xf0,0xb5,0x4f,0x46,0x46,0x46,0xc0,0xb4, +0x98,0x46,0x2c,0x4b,0xa4,0x25,0x1b,0x68,0x6d,0x00,0x5c,0x59,0x83,0xb0,0x06,0x1c, +0x0f,0x1c,0x91,0x46,0x01,0x93,0x00,0x2c,0x46,0xd0,0x65,0x68,0x1f,0x2d,0x1a,0xdd, +0x25,0x4b,0x00,0x2b,0x02,0xd1,0x01,0x20,0x40,0x42,0x1c,0xe0,0xc8,0x20,0x40,0x00, +0xaf,0xf3,0x00,0x80,0x04,0x1e,0xf6,0xd0,0x00,0x25,0x45,0x60,0xa4,0x23,0x01,0x98, +0x5b,0x00,0xc0,0x58,0x01,0x99,0x20,0x60,0xcc,0x50,0xc4,0x23,0x5b,0x00,0xe5,0x50, +0xc6,0x23,0x5b,0x00,0xe5,0x50,0x00,0x2e,0x0c,0xd1,0x6b,0x1c,0x02,0x35,0xad,0x00, +0x63,0x60,0x2f,0x51,0x00,0x20,0x03,0xb0,0x0c,0xbc,0x90,0x46,0x99,0x46,0xf0,0xbc, +0x02,0xbc,0x08,0x47,0xab,0x00,0xe3,0x18,0x88,0x22,0x48,0x46,0x98,0x50,0xc4,0x20, +0x40,0x00,0x22,0x18,0x10,0x68,0x01,0x21,0xa9,0x40,0x08,0x43,0x10,0x60,0x84,0x22, +0x52,0x00,0x40,0x46,0x98,0x50,0x02,0x2e,0xdf,0xd1,0xc6,0x22,0x52,0x00,0xa3,0x18, +0x18,0x68,0x01,0x43,0x19,0x60,0xd8,0xe7,0x1c,0x1c,0x4d,0x34,0xff,0x34,0x5c,0x51, +0xb3,0xe7,0xc0,0x46,0xfc,0x0e,0x00,0x20,0x00,0x00,0x00,0x00,0xf8,0xb5,0xc0,0x46, +0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc, +0x9e,0x46,0x70,0x47,0x00,0x00,0x00,0x00,0xc8,0xf1,0xff,0x7f,0x01,0x00,0x00,0x00, +0x18,0x15,0x00,0x20,0xff,0xff,0xff,0xc5,0xff,0xff,0xff,0xff,0xc5,0xff,0xff,0xff, +0xc5,0xc5,0xc5,0xff,0xc5,0xc5,0xc5,0xff,0x43,0x00,0x00,0x00,0x08,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf4,0x11,0x00,0x20, +0x5c,0x12,0x00,0x20,0xc4,0x12,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0e,0x00,0x20, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -307,8 +306,9 @@ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x18,0x0f,0x00,0x20,0xc1,0x00,0x00,0x20,0x91,0x00,0x00,0x20,0x00,0x00,0x00,0x00, -0x95,0x0d,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x0f,0x00,0x20,0x61,0x00,0x00,0x20,0x35,0x00,0x00,0x20,0x00,0x00,0x00,0x00, +0x69,0x0c,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/cc26xx/cc26x2_algo.inc b/contrib/loaders/flash/cc26xx/cc26x2_algo.inc index 9adb919f4e..345079b08f 100644 --- a/contrib/loaders/flash/cc26xx/cc26x2_algo.inc +++ b/contrib/loaders/flash/cc26xx/cc26x2_algo.inc @@ -1,258 +1,257 @@ /* Autogenerated with ../../../../src/helper/bin2char.sh */ 0x08,0xb5,0x00,0xbf,0x00,0xbf,0x00,0xbf,0x00,0xbf,0xdf,0xf8,0x1c,0xd0,0x07,0x48, -0x07,0x49,0x4f,0xf0,0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb, -0x00,0xf0,0xa8,0xf9,0xfe,0xe7,0x00,0x00,0xf0,0x0e,0x00,0x20,0x54,0x13,0x00,0x20, -0xfc,0x13,0x00,0x20,0x08,0xb5,0x07,0x4b,0x07,0x48,0x03,0x33,0x1b,0x1a,0x06,0x2b, -0x04,0xd9,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x5c,0xf8,0x08,0xbc,0x01,0xbc, -0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, -0x08,0x48,0x09,0x49,0x09,0x1a,0x89,0x10,0x08,0xb5,0xcb,0x0f,0x59,0x18,0x49,0x10, -0x04,0xd0,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x44,0xf8,0x08,0xbc,0x01,0xbc, -0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, -0x10,0xb5,0x08,0x4c,0x23,0x78,0x00,0x2b,0x09,0xd1,0xff,0xf7,0xcb,0xff,0x06,0x4b, +0x07,0x49,0x4f,0xf0,0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xff,0xf6, +0xfa,0xaf,0x00,0xf0,0x71,0xf9,0xfe,0xe7,0xe8,0x0e,0x00,0x20,0x4c,0x13,0x00,0x20, +0xf4,0x13,0x00,0x20,0x10,0xb5,0x07,0x4c,0x23,0x78,0x00,0x2b,0x07,0xd1,0x06,0x4b, 0x00,0x2b,0x02,0xd0,0x05,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbc, -0x01,0xbc,0x00,0x47,0x54,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20, -0x08,0xb5,0x0b,0x4b,0x00,0x2b,0x03,0xd0,0x0a,0x48,0x0b,0x49,0xaf,0xf3,0x00,0x80, -0x0a,0x48,0x03,0x68,0x00,0x2b,0x04,0xd1,0xff,0xf7,0xc2,0xff,0x08,0xbc,0x01,0xbc, -0x00,0x47,0x07,0x4b,0x00,0x2b,0xf7,0xd0,0x00,0xf0,0x0c,0xf8,0xf4,0xe7,0xc0,0x46, -0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20,0x58,0x13,0x00,0x20,0x4c,0x13,0x00,0x20, -0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xd4,0x30,0x9f,0xe5,0x00,0x00,0x53,0xe3, -0xc8,0x30,0x9f,0x05,0x03,0xd0,0xa0,0xe1,0x00,0x20,0x0f,0xe1,0x0f,0x00,0x12,0xe3, -0x15,0x00,0x00,0x0a,0xd1,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0xaa,0x4d,0xe2, -0x0a,0x30,0xa0,0xe1,0xd7,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2, -0xdb,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2,0xd2,0xf0,0x21,0xe3, -0x03,0xd0,0xa0,0xe1,0x02,0x3a,0x43,0xe2,0xd3,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1, -0x02,0x39,0x43,0xe2,0xff,0x30,0xc3,0xe3,0xff,0x3c,0xc3,0xe3,0x04,0x30,0x03,0xe5, -0x00,0x20,0x53,0xe9,0xc0,0x20,0x82,0xe3,0x02,0xf0,0x21,0xe1,0x01,0xa8,0x43,0xe2, -0x00,0x10,0xb0,0xe3,0x01,0xb0,0xa0,0xe1,0x01,0x70,0xa0,0xe1,0x5c,0x00,0x9f,0xe5, -0x5c,0x20,0x9f,0xe5,0x00,0x20,0x52,0xe0,0x01,0x30,0x8f,0xe2,0x13,0xff,0x2f,0xe1, -0x00,0xf0,0x42,0xfd,0x10,0x4b,0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x0f,0x4b, -0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00, -0x0d,0x48,0x00,0xf0,0x89,0xfc,0x00,0xf0,0xc3,0xfc,0x20,0x00,0x29,0x00,0x00,0xf0, -0xd1,0xf8,0x00,0xf0,0x8b,0xfc,0x7b,0x46,0x18,0x47,0x00,0x00,0x11,0x00,0x00,0xef, -0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x54,0x13,0x00,0x20,0xfc,0x13,0x00,0x20,0x15,0x0b,0x00,0x20,0x70,0xb5,0x04,0x46, +0x01,0xbc,0x00,0x47,0x4c,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0xd8,0x0e,0x00,0x20, +0x08,0xb5,0x09,0x4b,0x00,0x2b,0x03,0xd0,0x08,0x48,0x09,0x49,0xaf,0xf3,0x00,0x80, +0x08,0x48,0x03,0x68,0x00,0x2b,0x04,0xd0,0x07,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0, +0x0d,0xf8,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0xd8,0x0e,0x00,0x20, +0x50,0x13,0x00,0x20,0x44,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46, +0xd8,0x30,0x9f,0xe5,0x00,0x00,0x53,0xe3,0xcc,0x30,0x9f,0x05,0x03,0xd0,0xa0,0xe1, +0x00,0x20,0x0f,0xe1,0x0f,0x00,0x12,0xe3,0x15,0x00,0x00,0x0a,0xd1,0xf0,0x21,0xe3, +0x03,0xd0,0xa0,0xe1,0x01,0xaa,0x4d,0xe2,0x0a,0x30,0xa0,0xe1,0xd7,0xf0,0x21,0xe3, +0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2,0xdb,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1, +0x01,0x3a,0x43,0xe2,0xd2,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x02,0x3a,0x43,0xe2, +0xd3,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x02,0x39,0x43,0xe2,0xff,0x30,0xc3,0xe3, +0xff,0x3c,0xc3,0xe3,0x04,0x30,0x03,0xe5,0x00,0x20,0x53,0xe9,0xc0,0x20,0x82,0xe3, +0x02,0xf0,0x21,0xe1,0x01,0xa8,0x43,0xe2,0x00,0x10,0xb0,0xe3,0x01,0xb0,0xa0,0xe1, +0x01,0x70,0xa0,0xe1,0x60,0x00,0x9f,0xe5,0x60,0x20,0x9f,0xe5,0x00,0x20,0x52,0xe0, +0x01,0x30,0x8f,0xe2,0x13,0xff,0x2f,0xe1,0x00,0xf0,0x46,0xfd,0x11,0x4b,0x00,0x2b, +0x01,0xd0,0xfe,0x46,0x9f,0x46,0x10,0x4b,0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46, +0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00,0x0e,0x48,0x00,0x28,0x02,0xd0,0x0e,0x48, +0x00,0xf0,0x26,0xfe,0x00,0xf0,0xc0,0xfc,0x20,0x00,0x29,0x00,0x00,0xf0,0xcc,0xf8, +0x00,0xf0,0xa6,0xfc,0x7b,0x46,0x18,0x47,0x11,0x00,0x00,0xef,0x00,0x00,0x08,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4c,0x13,0x00,0x20, +0xf4,0x13,0x00,0x20,0xb1,0x0d,0x00,0x20,0xc5,0x0d,0x00,0x20,0x70,0xb5,0x04,0x46, 0x0e,0x46,0x15,0x46,0x00,0x21,0x28,0x22,0x00,0xf0,0x0e,0xfd,0x26,0x61,0x65,0x62, 0x00,0x21,0x84,0x22,0x02,0x48,0x00,0xf0,0x07,0xfd,0x00,0x20,0x70,0xbd,0x00,0xbf, -0x70,0x13,0x00,0x20,0x10,0xb5,0x01,0x20,0x00,0xf0,0xac,0xf9,0x04,0x46,0x28,0xb9, +0x68,0x13,0x00,0x20,0x10,0xb5,0x01,0x20,0x00,0xf0,0xba,0xf9,0x04,0x46,0x28,0xb9, 0x01,0x21,0x84,0x22,0x03,0x48,0x00,0xf0,0xf7,0xfc,0x01,0xe0,0x40,0xf2,0x01,0x14, -0x20,0x46,0x10,0xbd,0x70,0x13,0x00,0x20,0x01,0x39,0xf8,0xb5,0x44,0x0b,0x08,0x44, -0x45,0x0b,0x66,0x03,0xac,0x42,0x14,0xd8,0x0b,0x4f,0xe3,0x5d,0x6b,0xb9,0x30,0x46, -0x00,0xf0,0xfc,0xf8,0x38,0xb1,0x00,0x04,0x00,0xf4,0x7f,0x00,0x40,0xea,0x04,0x60, -0x40,0xf4,0x81,0x70,0xf8,0xbd,0x01,0x23,0xe3,0x55,0x01,0x34,0x06,0xf5,0x00,0x56, -0xe8,0xe7,0x00,0x20,0xf8,0xbd,0x00,0xbf,0x70,0x13,0x00,0x20,0x2d,0xe9,0xf0,0x4f, -0x53,0x1e,0x85,0xb0,0x0b,0x44,0x02,0x90,0x0d,0x46,0x4f,0xea,0x51,0x38,0x5b,0x0b, -0x16,0x46,0x23,0x48,0x01,0x93,0x00,0x21,0x84,0x22,0x00,0xf0,0xbd,0xfc,0x4f,0xea, -0x48,0x37,0xc5,0xf3,0x0c,0x0c,0x4f,0xf0,0x00,0x09,0x01,0x9b,0x98,0x45,0x32,0xd8, -0x74,0x19,0xdf,0xf8,0x70,0xb0,0xcd,0xf8,0x0c,0xc0,0x07,0xf5,0x00,0x5a,0x54,0x45, -0x88,0xbf,0xc4,0xf3,0x0c,0x04,0x39,0x46,0x4f,0xf4,0x00,0x52,0x58,0x46,0x8c,0xbf, -0x34,0x1b,0x34,0x46,0x00,0xf0,0x60,0xfc,0xdd,0xf8,0x0c,0xc0,0x02,0x9b,0x0b,0xeb, -0x0c,0x00,0x03,0xeb,0x09,0x01,0x22,0x46,0x00,0xf0,0x56,0xfc,0x38,0x46,0x4f,0xf4, -0x00,0x51,0x08,0xf1,0x01,0x08,0xff,0xf7,0x9f,0xff,0x68,0xb9,0x39,0x46,0x58,0x46, -0x4f,0xf4,0x00,0x52,0x25,0x44,0x00,0xf0,0xaf,0xf8,0x36,0x1b,0xc5,0xf3,0x0c,0x0c, -0xa1,0x44,0x57,0x46,0xc9,0xe7,0x00,0x20,0x05,0xb0,0xbd,0xe8,0xf0,0x8f,0x00,0xbf, -0x70,0x13,0x00,0x20,0x00,0x60,0x00,0x20,0xb2,0xf5,0x00,0x5f,0xf8,0xb5,0x07,0x46, -0x0e,0x46,0x15,0x46,0x0b,0xd8,0x08,0x46,0x11,0x46,0xff,0xf7,0x7d,0xff,0x04,0x46, -0x40,0xb9,0x38,0x46,0x31,0x46,0x2a,0x46,0x00,0xf0,0x8e,0xf8,0x02,0xe0,0x4f,0xf4, -0x82,0x70,0xf8,0xbd,0x20,0x46,0xf8,0xbd,0x08,0xb5,0x00,0xf0,0x85,0xf8,0x00,0x20, -0x08,0xbd,0x00,0x00,0xf8,0xb5,0x31,0x48,0x31,0x49,0x32,0x4a,0x32,0x4c,0xff,0xf7, -0x3d,0xff,0x00,0x23,0x23,0x60,0x22,0x68,0x2c,0x4f,0x14,0x23,0x03,0xfb,0x02,0x73, -0x08,0x33,0x5b,0x68,0x00,0x2b,0xf7,0xd0,0x2c,0x4b,0x1a,0x68,0x11,0x07,0xfb,0xd4, -0x2b,0x4d,0x2c,0x4e,0x2a,0x68,0x32,0x60,0x42,0xf0,0x33,0x02,0x2a,0x60,0x1a,0x68, -0x12,0x07,0xfc,0xd4,0x21,0x68,0x14,0x22,0x02,0xfb,0x01,0x73,0x98,0x68,0x01,0x38, -0x13,0x46,0x04,0x28,0x26,0xd8,0xdf,0xe8,0x00,0xf0,0x03,0x06,0x0e,0x16,0x1e,0x00, -0xff,0xf7,0x28,0xff,0x20,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, -0xff,0xf7,0xc2,0xff,0x18,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, -0xff,0xf7,0xa2,0xff,0x10,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, -0xff,0xf7,0x44,0xff,0x08,0xe0,0x4b,0x43,0xfa,0x18,0xf8,0x58,0x51,0x68,0xff,0xf7, -0x1b,0xff,0x01,0xe0,0x40,0xf2,0x05,0x10,0x33,0x68,0x2b,0x60,0x0b,0x4b,0x1b,0x68, -0x1b,0x07,0xfb,0xd4,0x22,0x68,0x14,0x23,0x03,0xfb,0x02,0x77,0xfb,0x68,0xf8,0x60, -0x00,0xb1,0xfe,0xe7,0x82,0xf0,0x01,0x02,0x22,0x60,0xa4,0xe7,0xd8,0x1f,0x00,0x20, -0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x20,0xf4,0x13,0x00,0x20,0x00,0x40,0x03,0x40, -0x04,0x40,0x03,0x40,0xf8,0x13,0x00,0x20,0xfe,0xe7,0x00,0x00,0x08,0xb5,0x04,0x4b, -0x1b,0x68,0x5b,0x69,0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf, -0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42,0x08,0xb5,0x04,0x4b,0x1b,0x68,0x9b,0x69, -0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10, -0x84,0x04,0x60,0x42,0x10,0xb5,0x33,0x4b,0x33,0x48,0x1b,0x68,0x33,0x4a,0x13,0xf0, -0x02,0x0f,0x03,0x68,0x43,0xf0,0x02,0x03,0x03,0x60,0x13,0x68,0x01,0x68,0x19,0xd0, -0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x04,0x22,0xf0,0x01,0x02,0x22,0x43,0xc3,0xf3, -0xc0,0x11,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x11,0x42,0xea,0x81,0x12,0x02,0x60, -0x02,0x68,0xd4,0x07,0x03,0xd5,0x26,0x4a,0x12,0x68,0x50,0x07,0xfb,0xd5,0x03,0xf0, -0x07,0x03,0x18,0xe0,0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x24,0x22,0xf0,0x01,0x02, -0xc3,0xf3,0xc0,0x31,0x22,0x43,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x31,0x42,0xea, -0x81,0x12,0x02,0x60,0x02,0x68,0xd1,0x07,0x03,0xd5,0x19,0x4a,0x12,0x68,0x52,0x07, -0xfb,0xd5,0xc3,0xf3,0x02,0x23,0x17,0x49,0x17,0x48,0x4a,0xf6,0xaa,0x22,0x0a,0x60, -0x02,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4,0xe2,0x42,0x18,0xbf,0x43,0xf4, -0x80,0x73,0x13,0x43,0x03,0x60,0x45,0xf2,0xaa,0x53,0x0b,0x60,0x0f,0x4b,0x10,0x49, -0x01,0x22,0x1a,0x60,0x00,0x22,0x0a,0x60,0x1a,0x60,0x05,0x22,0xc3,0xf8,0x58,0x22, -0x4f,0xf0,0xff,0x32,0xc1,0xf8,0x8c,0x22,0xc1,0xf8,0x90,0x22,0x02,0x22,0xc3,0xf8, -0x58,0x22,0x10,0xbd,0x10,0x00,0x09,0x40,0x24,0x00,0x03,0x40,0x08,0x13,0x00,0x50, -0x1c,0x00,0x03,0x40,0x64,0x20,0x03,0x40,0xa8,0x20,0x03,0x40,0x30,0x20,0x03,0x40, -0x34,0x20,0x03,0x40,0x2d,0xe9,0xf8,0x4f,0xd4,0x4d,0x29,0x68,0x11,0xf0,0x01,0x01, -0x40,0xf0,0x95,0x81,0xdf,0xf8,0x90,0xe3,0xd1,0x4b,0xdf,0xf8,0x90,0xc3,0xdf,0xf8, -0x90,0x83,0xdf,0xf8,0x90,0x93,0x05,0x27,0xce,0xf8,0x00,0x70,0x1b,0x68,0xc3,0xf3, -0x03,0x23,0x4f,0xf4,0x40,0x72,0x01,0x33,0xb2,0xfb,0xf3,0xf3,0xdc,0xf8,0x00,0x20, -0xd8,0xf8,0x00,0x40,0x92,0xb2,0x5a,0x43,0xc2,0xf3,0x8f,0x16,0x22,0x0c,0x12,0x04, -0x32,0x43,0xc8,0xf8,0x00,0x20,0xc3,0x4a,0xc3,0x4c,0x12,0x68,0x26,0x68,0xc3,0x4e, -0x5a,0x43,0x92,0x09,0x22,0x60,0x32,0x68,0x54,0xf8,0x24,0x8c,0xc2,0xf3,0x07,0x42, -0x5a,0x43,0x28,0xf0,0xff,0x08,0xc2,0xf3,0x87,0x12,0x42,0xea,0x08,0x02,0xdf,0xf8, -0x38,0x83,0x44,0xf8,0x24,0x2c,0xd9,0xf8,0x00,0xa0,0xd8,0xf8,0x00,0x20,0xca,0xf3, -0x07,0x4a,0x22,0xf0,0xff,0x02,0x4a,0xea,0x02,0x02,0xc8,0xf8,0x00,0x20,0xd9,0xf8, -0x00,0x20,0xdf,0xf8,0x18,0xa3,0x12,0x0e,0xda,0xf8,0x00,0x80,0x5a,0x43,0x92,0x00, -0x28,0xf4,0x7f,0x48,0x02,0xf4,0x7f,0x42,0x42,0xea,0x08,0x02,0xdf,0xf8,0x00,0x83, -0xca,0xf8,0x00,0x20,0xd8,0xf8,0x00,0x20,0x4f,0xea,0x12,0x6b,0xda,0xf8,0x04,0x20, -0x0b,0xfb,0x03,0xfb,0x12,0x0c,0xcb,0xf3,0x8f,0x1b,0x12,0x04,0x4b,0xea,0x02,0x02, -0xca,0xf8,0x04,0x20,0xd9,0xf8,0x00,0x20,0xc2,0xf3,0x07,0x22,0x53,0x43,0xa0,0x4a, -0xd2,0xf8,0x00,0x90,0x9b,0x00,0x29,0xf4,0x7f,0x49,0x03,0xf4,0x7f,0x43,0x43,0xea, -0x09,0x03,0xdf,0xf8,0xc0,0x92,0x13,0x60,0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x24,0x3c, -0x4f,0xea,0x1a,0x6a,0x23,0xf4,0x7f,0x43,0x43,0xea,0x0a,0x23,0x42,0xf8,0x24,0x3c, -0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x24,0x3c,0xca,0xf3,0x07,0x4a,0x23,0xf0,0xff,0x03, -0x4a,0xea,0x03,0x03,0x42,0xf8,0x24,0x3c,0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x1c,0x3c, -0x0a,0xf4,0x7f,0x4a,0x23,0xf4,0x7f,0x43,0x4a,0xea,0x03,0x03,0x42,0xf8,0x1c,0x3c, -0xd9,0xf8,0x00,0x90,0x52,0xf8,0x1c,0x3c,0x5f,0xfa,0x89,0xf9,0x23,0xf0,0xff,0x03, -0x49,0xea,0x03,0x03,0xdf,0xf8,0x60,0x92,0x42,0xf8,0x1c,0x3c,0x32,0x68,0xd9,0xf8, -0x00,0x30,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43,0xc9,0xf8,0x00,0x30, -0xd8,0xf8,0x00,0x20,0xdf,0xf8,0x44,0x82,0xd8,0xf8,0x00,0x30,0x02,0xf4,0x70,0x42, -0x23,0xf4,0x70,0x43,0x13,0x43,0xc8,0xf8,0x00,0x30,0x32,0x68,0x54,0xf8,0x24,0x3c, -0x12,0x0e,0x23,0xf4,0x7f,0x43,0x43,0xea,0x02,0x23,0x44,0xf8,0x24,0x3c,0x71,0x4b, -0x1b,0x68,0x62,0x6a,0xc3,0xf3,0x0b,0x06,0x22,0xf4,0x7f,0x63,0x23,0xf0,0x0f,0x03, -0x33,0x43,0x6d,0x4e,0x63,0x62,0x32,0x68,0x63,0x6a,0x02,0xf4,0x70,0x22,0x23,0xf4, -0x70,0x23,0x13,0x43,0x63,0x62,0x69,0x4c,0x22,0x68,0xd8,0xf8,0x58,0x30,0xc2,0xf3, -0x83,0x42,0x23,0xf4,0x70,0x23,0x43,0xea,0x02,0x43,0xc8,0xf8,0x58,0x30,0xdc,0xf8, -0x00,0x30,0xd8,0xf8,0x58,0x20,0xc3,0xf3,0x0b,0x4c,0x22,0xf4,0x7f,0x63,0x23,0xf0, -0x0f,0x03,0x4c,0xea,0x03,0x03,0xc8,0xf8,0x58,0x30,0x23,0x68,0xd8,0xf8,0x5c,0x20, -0x4f,0xea,0xd3,0x5c,0x22,0xf0,0xff,0x73,0x23,0xf4,0x80,0x33,0x43,0xea,0x0c,0x43, -0xc8,0xf8,0x5c,0x30,0x33,0x68,0x56,0x4a,0xdf,0xf8,0xa4,0xc1,0x0f,0x33,0x03,0xf0, -0x0f,0x03,0x13,0x60,0x26,0x68,0x53,0x68,0xc6,0xf3,0x80,0x56,0x23,0xf4,0x00,0x03, -0x43,0xea,0xc6,0x53,0x53,0x60,0x53,0x68,0x4e,0x4e,0x43,0xf4,0x80,0x43,0x53,0x60, -0x02,0x23,0xce,0xf8,0x00,0x30,0xae,0xf5,0x09,0x7e,0x4a,0xf6,0xaa,0x23,0xce,0xf8, -0x00,0x30,0xdc,0xf8,0x00,0x30,0x32,0x68,0x03,0xf0,0x0f,0x08,0x22,0xf4,0x7f,0x02, -0x42,0xea,0x08,0x42,0xc3,0xf3,0x03,0x23,0x42,0xea,0x03,0x53,0xdf,0xf8,0x54,0x81, -0x33,0x60,0xd8,0xf8,0x00,0x30,0x32,0x68,0xc3,0xf3,0x03,0x49,0x22,0xf0,0xff,0x02, -0x49,0xea,0x02,0x02,0xc3,0xf3,0x03,0x63,0x42,0xea,0x03,0x13,0x33,0x60,0xdc,0xf8, -0x00,0x60,0xdf,0xf8,0x34,0xc1,0xdc,0xf8,0x00,0x30,0x06,0xf4,0x70,0x22,0x23,0xf4, -0x7f,0x03,0x1a,0x43,0xc6,0xf3,0x03,0x63,0x42,0xea,0x03,0x53,0x32,0x4e,0xcc,0xf8, -0x00,0x30,0x32,0x68,0x5c,0xf8,0x08,0x3c,0xc2,0xf3,0x03,0x22,0x23,0xf0,0x0f,0x03, -0x13,0x43,0x4c,0xf8,0x08,0x3c,0xd8,0xf8,0x00,0x20,0xdc,0xf8,0x08,0x30,0x02,0xf4, -0xf8,0x52,0x23,0xf4,0xf8,0x53,0x13,0x43,0xcc,0xf8,0x08,0x30,0x32,0x68,0xdc,0xf8, -0x0c,0x30,0x12,0x0b,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43,0xcc,0xf8, -0x0c,0x30,0x32,0x68,0x21,0x4e,0x33,0x68,0xc2,0xf3,0x04,0x42,0x23,0xf0,0x1f,0x03, -0x13,0x43,0x33,0x60,0x22,0x68,0x1e,0x4c,0x23,0x68,0xc2,0xf3,0x01,0x42,0x23,0xf4, -0x40,0x13,0x43,0xea,0x02,0x53,0x1b,0x4a,0x23,0x60,0x45,0xf2,0xaa,0x53,0xce,0xf8, -0x00,0x30,0x17,0x60,0x2b,0x68,0x43,0xf0,0x01,0x03,0x2b,0x60,0x11,0x60,0x16,0x4b, -0x16,0x4c,0x1b,0x68,0x16,0x4a,0x17,0x4d,0x13,0xf0,0x02,0x0f,0x23,0x68,0x43,0xf0, -0x02,0x03,0x23,0x60,0x13,0x68,0x21,0x68,0x59,0xd0,0x3f,0xe0,0x40,0x00,0x03,0x40, -0x00,0x20,0x03,0x40,0x8c,0x11,0x00,0x50,0x44,0x22,0x03,0x40,0x74,0x11,0x00,0x50, -0x34,0x22,0x03,0x40,0x84,0x11,0x00,0x50,0x80,0x11,0x00,0x50,0xb0,0x12,0x00,0x50, -0x78,0x22,0x03,0x40,0x84,0x20,0x03,0x40,0x98,0x11,0x00,0x50,0x98,0x20,0x03,0x40, -0xa8,0x20,0x03,0x40,0x3c,0x00,0x03,0x40,0x10,0x00,0x09,0x40,0x24,0x00,0x03,0x40, -0x08,0x13,0x00,0x50,0x1c,0x00,0x03,0x40,0x88,0x22,0x03,0x40,0x88,0x11,0x00,0x50, -0x40,0x22,0x03,0x40,0x78,0x11,0x00,0x50,0x24,0x22,0x03,0x40,0x28,0x22,0x03,0x40, -0x7c,0x11,0x00,0x50,0x70,0x11,0x00,0x50,0x1c,0x22,0x03,0x40,0x14,0x22,0x03,0x40, -0x90,0x11,0x00,0x50,0x94,0x11,0x00,0x50,0x88,0x20,0x03,0x40,0x21,0xf4,0xe1,0x72, -0xc3,0xf3,0xc1,0x46,0x22,0xf0,0x01,0x02,0xc3,0xf3,0xc0,0x51,0x32,0x43,0x42,0xea, -0x01,0x22,0xc3,0xf3,0x41,0x51,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd7,0x07, -0x02,0xd5,0x2a,0x68,0x56,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x43,0x16,0xe0,0xc3,0xf3, -0xc1,0x62,0xde,0x0f,0x42,0xea,0x06,0x26,0x21,0xf4,0xe1,0x72,0x22,0xf0,0x01,0x02, -0x32,0x43,0xc3,0xf3,0x41,0x71,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd4,0x07, -0x02,0xd5,0x2a,0x68,0x51,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x63,0x3b,0x49,0x3c,0x4c, -0x4a,0xf6,0xaa,0x22,0x0a,0x60,0x22,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4, -0xe2,0x42,0x18,0xbf,0x43,0xf4,0x80,0x73,0x13,0x43,0x23,0x60,0x45,0xf2,0xaa,0x53, -0x0b,0x60,0x34,0x4b,0x00,0x21,0x01,0x22,0x19,0x60,0x43,0xf8,0x20,0x2c,0x32,0x4a, -0x4f,0xf6,0xff,0x74,0x14,0x60,0x31,0x4c,0x43,0xf8,0x20,0x1c,0x02,0xf5,0xec,0x72, -0x4f,0xf0,0x05,0x0e,0x10,0x23,0xc4,0xf8,0x00,0xe0,0x13,0x60,0x2c,0x4b,0x15,0x26, -0x1e,0x60,0x02,0x26,0x26,0x60,0x2b,0x4e,0x37,0x68,0xc4,0xf8,0x00,0xe0,0xdf,0xf8, -0xb4,0xe0,0xce,0xf8,0x00,0x10,0xce,0xf8,0x04,0x10,0x18,0xb1,0x31,0x68,0x41,0xf4, -0x00,0x01,0x31,0x60,0x02,0x21,0x05,0x20,0x21,0x60,0x20,0x60,0x08,0x20,0x10,0x60, -0x15,0x22,0x1a,0x60,0x21,0x60,0x2b,0x68,0x9a,0x07,0xfc,0xd4,0x1e,0x4b,0x1b,0x68, -0x13,0xf0,0x10,0x0f,0x14,0xbf,0x04,0x25,0x00,0x25,0xff,0xf7,0x1b,0xfd,0x3b,0x02, -0x07,0xd4,0x05,0x23,0x23,0x60,0x33,0x68,0x23,0xf4,0x00,0x03,0x33,0x60,0x02,0x23, -0x23,0x60,0xc5,0xb9,0x15,0x4b,0x16,0x48,0x19,0x68,0x03,0xf5,0x10,0x53,0x04,0x33, -0x1a,0x68,0x1b,0x68,0x02,0xf0,0x0f,0x02,0xc9,0xb2,0x03,0xf0,0x0f,0x03,0x51,0x43, -0x9b,0x02,0xc3,0xeb,0x81,0x21,0x01,0xf5,0xfe,0x51,0x18,0x31,0x14,0x22,0xbd,0xe8, -0xf8,0x4f,0xff,0xf7,0xe9,0xbc,0x28,0x46,0xbd,0xe8,0xf8,0x8f,0x64,0x20,0x03,0x40, -0xa8,0x20,0x03,0x40,0x50,0x20,0x03,0x40,0x34,0x20,0x03,0x40,0x88,0x22,0x03,0x40, -0xb4,0x22,0x03,0x40,0x7c,0x22,0x03,0x40,0x54,0x20,0x03,0x40,0x2c,0x00,0x03,0x40, -0xf4,0x0e,0x00,0x20,0xc0,0x22,0x03,0x40,0x08,0xb5,0x01,0x1c,0x00,0x22,0x00,0x20, -0x00,0x23,0x00,0xf0,0xeb,0xf8,0x08,0xbc,0x02,0xbc,0x08,0x47,0x10,0xb5,0x00,0x21, -0x04,0x1c,0x00,0xf0,0x5d,0xf9,0x05,0x4b,0x18,0x68,0xc3,0x6b,0x00,0x2b,0x01,0xd0, -0x00,0xf0,0x06,0xf8,0x20,0x1c,0xff,0xf7,0xa7,0xfc,0xc0,0x46,0x0c,0x0f,0x00,0x20, -0x18,0x47,0xc0,0x46,0x38,0xb5,0x0a,0x4b,0x0a,0x4c,0xe4,0x1a,0xa4,0x10,0x0a,0xd0, -0x09,0x4a,0xa5,0x18,0xad,0x00,0xed,0x18,0x2b,0x68,0x01,0x3c,0x00,0xf0,0x0e,0xf8, -0x04,0x3d,0x00,0x2c,0xf8,0xd1,0x00,0xf0,0xcd,0xf9,0x38,0xbc,0x01,0xbc,0x00,0x47, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x3f,0x18,0x47,0xc0,0x46, -0x70,0xb5,0x10,0x4e,0x10,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, -0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x1d,0xf8,0xa5,0x42,0xf8,0xd1,0x00,0xf0, -0xab,0xf9,0x0a,0x4e,0x0a,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, -0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x0d,0xf8,0xa5,0x42,0xf8,0xd1,0x70,0xbc, -0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0x70,0xb5,0x0f,0x2a,0x34,0xd9,0x04,0x1c, -0x0c,0x43,0x0b,0x1c,0xa4,0x07,0x33,0xd1,0x15,0x1c,0x04,0x1c,0x10,0x3d,0x2d,0x09, -0x01,0x35,0x2d,0x01,0x49,0x19,0x1e,0x68,0x26,0x60,0x5e,0x68,0x66,0x60,0x9e,0x68, -0xa6,0x60,0xde,0x68,0x10,0x33,0xe6,0x60,0x10,0x34,0x99,0x42,0xf3,0xd1,0x0f,0x23, -0x45,0x19,0x13,0x40,0x03,0x2b,0x1d,0xd9,0x1c,0x1f,0x00,0x23,0xa4,0x08,0x01,0x34, -0xa4,0x00,0xce,0x58,0xee,0x50,0x04,0x33,0xa3,0x42,0xfa,0xd1,0xed,0x18,0xc9,0x18, -0x03,0x23,0x1a,0x40,0x05,0xd0,0x00,0x23,0xcc,0x5c,0xec,0x54,0x01,0x33,0x93,0x42, -0xfa,0xd1,0x70,0xbc,0x02,0xbc,0x08,0x47,0x05,0x1c,0x00,0x2a,0xf3,0xd1,0xf8,0xe7, -0x05,0x1c,0xf0,0xe7,0x1a,0x1c,0xf8,0xe7,0x70,0xb5,0x83,0x07,0x43,0xd0,0x54,0x1e, -0x00,0x2a,0x3d,0xd0,0x0d,0x06,0x2d,0x0e,0x03,0x1c,0x03,0x26,0x03,0xe0,0x62,0x1e, -0x00,0x2c,0x35,0xd0,0x14,0x1c,0x01,0x33,0x5a,0x1e,0x15,0x70,0x33,0x42,0xf6,0xd1, -0x03,0x2c,0x24,0xd9,0xff,0x25,0x0d,0x40,0x2a,0x02,0x15,0x43,0x2a,0x04,0x15,0x43, -0x0f,0x2c,0x11,0xd9,0x26,0x1c,0x10,0x3e,0x36,0x09,0x01,0x36,0x36,0x01,0x1a,0x1c, -0x9b,0x19,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,0x93,0x42,0xf8,0xd1, -0x0f,0x22,0x14,0x40,0x03,0x2c,0x0a,0xd9,0x26,0x1f,0xb6,0x08,0x01,0x36,0xb6,0x00, -0x1a,0x1c,0x9b,0x19,0x20,0xc2,0x93,0x42,0xfc,0xd1,0x03,0x22,0x14,0x40,0x00,0x2c, -0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,0x19,0x70,0x01,0x33,0xa3,0x42,0xfb,0xd1, -0x70,0xbc,0x02,0xbc,0x08,0x47,0x14,0x1c,0x03,0x1c,0xc9,0xe7,0xf8,0xb5,0x44,0x46, -0x5f,0x46,0x56,0x46,0x4d,0x46,0x9b,0x46,0x30,0x4b,0xf0,0xb4,0x1c,0x68,0xa4,0x23, -0x5b,0x00,0x05,0x1c,0xe0,0x58,0x0e,0x1c,0x90,0x46,0x00,0x28,0x4d,0xd0,0x43,0x68, -0x1f,0x2b,0x0f,0xdc,0x5c,0x1c,0x00,0x2d,0x23,0xd1,0x02,0x33,0x9b,0x00,0x44,0x60, -0x1e,0x50,0x00,0x20,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46,0xab,0x46,0xf8,0xbc, -0x02,0xbc,0x08,0x47,0x22,0x4b,0x00,0x2b,0x3c,0xd0,0xc8,0x20,0x40,0x00,0xaf,0xf3, -0x00,0x80,0x00,0x28,0x36,0xd0,0xa4,0x22,0x00,0x23,0x52,0x00,0xa1,0x58,0x43,0x60, -0x01,0x60,0xa0,0x50,0x40,0x32,0x83,0x50,0x04,0x32,0x83,0x50,0x01,0x24,0x00,0x2d, -0xdb,0xd0,0x9a,0x00,0x91,0x46,0x81,0x44,0x42,0x46,0x88,0x21,0x4f,0x46,0x7a,0x50, -0xc4,0x22,0x52,0x00,0x90,0x46,0x80,0x44,0x42,0x46,0x87,0x39,0x99,0x40,0x12,0x68, -0x0a,0x43,0x94,0x46,0x8a,0x46,0x42,0x46,0x61,0x46,0x11,0x60,0x84,0x22,0x49,0x46, -0x5f,0x46,0x52,0x00,0x8f,0x50,0x02,0x2d,0xbf,0xd1,0x02,0x1c,0x55,0x46,0x8d,0x32, -0xff,0x32,0x11,0x68,0x0d,0x43,0x15,0x60,0xb7,0xe7,0x20,0x1c,0x4d,0x30,0xff,0x30, -0xe0,0x50,0xac,0xe7,0x01,0x20,0x40,0x42,0xb4,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, -0x00,0x00,0x00,0x00,0x08,0xb5,0x04,0x4b,0x00,0x2b,0x02,0xd0,0x03,0x48,0xff,0xf7, -0x9b,0xfe,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x15,0x0b,0x00,0x20, -0xf0,0xb5,0x56,0x46,0x5f,0x46,0x4d,0x46,0x44,0x46,0xf0,0xb4,0x0e,0x1c,0x3f,0x4b, -0x1b,0x68,0x87,0xb0,0x03,0x93,0x49,0x33,0xff,0x33,0x01,0x90,0x04,0x93,0xa4,0x22, -0x03,0x9b,0x52,0x00,0x9f,0x58,0x00,0x2f,0x4d,0xd0,0x04,0x9b,0x98,0x46,0x00,0x23, -0x9b,0x46,0xc4,0x23,0x5b,0x00,0x9c,0x46,0xbc,0x44,0x63,0x46,0x02,0x93,0xc6,0x23, -0x5b,0x00,0x9a,0x46,0x7c,0x68,0xa5,0x00,0x7d,0x19,0xba,0x44,0x01,0x3c,0x08,0xd5, -0x27,0xe0,0x6b,0x1d,0xff,0x33,0x1b,0x68,0xb3,0x42,0x04,0xd0,0x04,0x3d,0x01,0x3c, -0x1f,0xd3,0x00,0x2e,0xf5,0xd1,0x7b,0x68,0x01,0x3b,0x6a,0x68,0xa3,0x42,0x3e,0xd0, -0x5b,0x46,0x6b,0x60,0x00,0x2a,0xf1,0xd0,0x7b,0x68,0x99,0x46,0x01,0x23,0xa3,0x40, -0x02,0x99,0x09,0x68,0x05,0x91,0x19,0x42,0x26,0xd1,0x00,0xf0,0x43,0xf8,0x7b,0x68, -0x4b,0x45,0xc4,0xd1,0x43,0x46,0x1b,0x68,0xbb,0x42,0xc0,0xd1,0x04,0x3d,0x01,0x3c, -0xdf,0xd2,0x1b,0x4b,0x00,0x2b,0x0e,0xd0,0x7b,0x68,0x00,0x2b,0x27,0xd1,0x3b,0x68, -0x00,0x2b,0x28,0xd0,0x42,0x46,0x38,0x1c,0x13,0x60,0xaf,0xf3,0x00,0x80,0x43,0x46, -0x1f,0x68,0x00,0x2f,0xb5,0xd1,0x07,0xb0,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46, -0xab,0x46,0xf0,0xbc,0x01,0xbc,0x00,0x47,0x51,0x46,0x09,0x68,0x19,0x42,0x08,0xd1, -0x2b,0x1c,0x84,0x33,0x19,0x68,0x01,0x98,0x00,0xf0,0x14,0xf8,0xcf,0xe7,0x7c,0x60, -0xc0,0xe7,0x2b,0x1c,0x84,0x33,0x18,0x68,0x00,0xf0,0x0c,0xf8,0xc7,0xe7,0x3b,0x68, -0xb8,0x46,0x1f,0x1c,0xdd,0xe7,0x00,0x23,0xfa,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, -0x00,0x00,0x00,0x00,0x10,0x47,0xc0,0x46,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc, -0x9e,0x46,0x70,0x47,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47, -0x00,0x00,0x00,0x00,0x24,0xf2,0xff,0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x8c,0x15,0x00,0x20,0xff,0xff,0xff,0xc5,0xff,0xff,0xff,0xff,0xc5,0xff,0xff,0xff, -0xc5,0xc5,0xc5,0xff,0xc5,0xc5,0xc5,0xff,0x43,0x00,0x00,0x00,0x18,0x0f,0x00,0x20, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x12,0x00,0x20, -0x6c,0x12,0x00,0x20,0xd4,0x12,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x46,0x10,0xbd,0x68,0x13,0x00,0x20,0x01,0x39,0xf8,0xb5,0x44,0x0b,0x08,0x44, +0x47,0x0b,0x65,0x03,0xbc,0x42,0x14,0xd8,0x0b,0x4e,0xa3,0x5d,0x6b,0xb9,0x28,0x46, +0x00,0xf0,0xf8,0xf8,0x38,0xb1,0x00,0x04,0x00,0xf4,0x7f,0x00,0x40,0xea,0x04,0x60, +0x40,0xf4,0x81,0x70,0xf8,0xbd,0x01,0x23,0xa3,0x55,0x01,0x34,0x05,0xf5,0x00,0x55, +0xe8,0xe7,0x00,0x20,0xf8,0xbd,0x00,0xbf,0x68,0x13,0x00,0x20,0xb2,0xf5,0x00,0x5f, +0xf8,0xb5,0x07,0x46,0x0e,0x46,0x15,0x46,0x0b,0xd8,0x08,0x46,0x11,0x46,0xff,0xf7, +0xd3,0xff,0x04,0x46,0x40,0xb9,0x38,0x46,0x31,0x46,0x2a,0x46,0x00,0xf0,0xe0,0xf8, +0x02,0xe0,0x4f,0xf4,0x82,0x70,0xf8,0xbd,0x20,0x46,0xf8,0xbd,0x2d,0xe9,0xf0,0x4f, +0x53,0x1e,0x85,0xb0,0x0b,0x44,0x5b,0x0b,0x0c,0x46,0x4f,0x0b,0x83,0x46,0x15,0x46, +0x20,0x48,0x03,0x93,0x00,0x21,0x84,0x22,0x00,0xf0,0xa6,0xfc,0x4f,0xea,0x47,0x38, +0xc4,0xf3,0x0c,0x03,0x4f,0xf0,0x00,0x0a,0x03,0x9a,0x97,0x42,0x2e,0xd8,0x08,0xf5, +0x00,0x5c,0x2e,0x19,0xdf,0xf8,0x60,0x90,0xcd,0xf8,0x04,0xc0,0x66,0x45,0x88,0xbf, +0xc6,0xf3,0x0c,0x06,0x41,0x46,0x4f,0xf4,0x00,0x52,0x48,0x46,0x8c,0xbf,0xc6,0xeb, +0x05,0x06,0x2e,0x46,0x02,0x93,0x00,0xf0,0x43,0xfc,0x02,0x9b,0x0b,0xeb,0x0a,0x01, +0x09,0xeb,0x03,0x00,0x32,0x46,0x00,0xf0,0x3b,0xfc,0x48,0x46,0x41,0x46,0x4f,0xf4, +0x00,0x52,0xff,0xf7,0xab,0xff,0x01,0x37,0xdd,0xf8,0x04,0xc0,0x38,0xb9,0x34,0x44, +0xc4,0xf3,0x0c,0x03,0xad,0x1b,0xb2,0x44,0xe0,0x46,0xcd,0xe7,0x00,0x20,0x05,0xb0, +0xbd,0xe8,0xf0,0x8f,0x68,0x13,0x00,0x20,0x00,0x60,0x00,0x20,0x08,0xb5,0x00,0xf0, +0x87,0xf8,0x00,0x20,0x08,0xbd,0x00,0x00,0xf8,0xb5,0x32,0x48,0x32,0x49,0x33,0x4a, +0x33,0x4d,0xff,0xf7,0x43,0xff,0x00,0x23,0x2b,0x60,0x2a,0x68,0x2d,0x4c,0x14,0x23, +0x03,0xfb,0x02,0x43,0x08,0x33,0x5b,0x68,0x00,0x2b,0xf7,0xd0,0x2d,0x4b,0x1a,0x68, +0x12,0xf0,0x08,0x0f,0x19,0x46,0xf9,0xd1,0x2b,0x4e,0x2c,0x4f,0x33,0x68,0x3b,0x60, +0x43,0xf0,0x33,0x03,0x33,0x60,0x0a,0x68,0x12,0x07,0xfc,0xd4,0x2b,0x68,0x14,0x22, +0x02,0xfb,0x03,0x41,0x89,0x68,0x01,0x39,0x04,0x29,0x26,0xd8,0xdf,0xe8,0x01,0xf0, +0x03,0x06,0x0e,0x16,0x1e,0x00,0xff,0xf7,0x2d,0xff,0x20,0xe0,0x53,0x43,0xe2,0x18, +0x10,0x69,0xe1,0x58,0x52,0x68,0xff,0xf7,0xc1,0xff,0x18,0xe0,0x53,0x43,0xe2,0x18, +0x10,0x69,0xe1,0x58,0x52,0x68,0xff,0xf7,0x51,0xff,0x10,0xe0,0x53,0x43,0xe2,0x18, +0x10,0x69,0xe1,0x58,0x52,0x68,0xff,0xf7,0x61,0xff,0x08,0xe0,0x53,0x43,0xe2,0x18, +0xe0,0x58,0x51,0x68,0xff,0xf7,0x20,0xff,0x01,0xe0,0x40,0xf2,0x05,0x10,0x3b,0x68, +0x33,0x60,0x0c,0x4b,0x1b,0x68,0x1b,0x07,0xfb,0xd4,0x2b,0x68,0x14,0x22,0x02,0xfb, +0x03,0x44,0x10,0xb1,0xe3,0x68,0xe0,0x60,0xfe,0xe7,0xe2,0x68,0xe0,0x60,0x83,0xf0, +0x01,0x03,0xa1,0xe7,0xd8,0x1f,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x20, +0xec,0x13,0x00,0x20,0x00,0x40,0x03,0x40,0x04,0x40,0x03,0x40,0xf0,0x13,0x00,0x20, +0xfe,0xe7,0x00,0x00,0x08,0xb5,0x04,0x4b,0x1b,0x68,0x5b,0x69,0x98,0x47,0x03,0x4b, +0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42, +0x08,0xb5,0x04,0x4b,0x1b,0x68,0x9b,0x69,0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60, +0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42,0x10,0xb5,0x3a,0x4b, +0x3a,0x4a,0x1b,0x68,0x13,0xf0,0x02,0x0f,0x39,0x4b,0x19,0x68,0x41,0xf0,0x02,0x01, +0x19,0x60,0x12,0x68,0x1a,0xd0,0x19,0x68,0x21,0xf4,0xe1,0x71,0xc2,0xf3,0xc1,0x04, +0x21,0xf0,0x01,0x01,0xc2,0xf3,0xc0,0x10,0x21,0x43,0x41,0xea,0x00,0x21,0xc2,0xf3, +0x41,0x10,0x41,0xea,0x80,0x11,0x19,0x60,0x1b,0x68,0xdc,0x07,0x03,0xd5,0x2d,0x4b, +0x1b,0x68,0x58,0x07,0xfb,0xd5,0x02,0xf0,0x07,0x03,0x19,0xe0,0x19,0x68,0x21,0xf4, +0xe1,0x71,0xc2,0xf3,0xc1,0x24,0x21,0xf0,0x01,0x01,0xc2,0xf3,0xc0,0x30,0x21,0x43, +0x41,0xea,0x00,0x21,0xc2,0xf3,0x41,0x30,0x41,0xea,0x80,0x11,0x19,0x60,0x1b,0x68, +0xd9,0x07,0x03,0xd5,0x1f,0x4b,0x1b,0x68,0x5b,0x07,0xfb,0xd5,0xc2,0xf3,0x02,0x23, +0x1d,0x4a,0x4a,0xf6,0xaa,0x21,0x11,0x60,0x1c,0x49,0x1b,0x03,0x08,0x68,0xb3,0xf5, +0xe0,0x4f,0x18,0xbf,0x43,0xf4,0x80,0x73,0x20,0xf4,0xe2,0x40,0x03,0x43,0x0b,0x60, +0x45,0xf2,0xaa,0x53,0x13,0x60,0x00,0x23,0x15,0x4a,0x12,0x68,0x02,0xf0,0x0f,0x02, +0x93,0x42,0x14,0x4a,0x15,0xd2,0x13,0x60,0x13,0x4a,0x14,0x48,0x01,0x21,0x11,0x60, +0x00,0x21,0x01,0x60,0x11,0x60,0x05,0x21,0xc2,0xf8,0x58,0x12,0x4f,0xf0,0xff,0x31, +0xc0,0xf8,0x8c,0x12,0xc0,0xf8,0x90,0x12,0x02,0x21,0xc2,0xf8,0x58,0x12,0x01,0x33, +0xe2,0xe7,0x00,0x23,0x13,0x60,0x10,0xbd,0x10,0x00,0x09,0x40,0x08,0x13,0x00,0x50, +0x24,0x00,0x03,0x40,0x1c,0x00,0x03,0x40,0x64,0x20,0x03,0x40,0xa8,0x20,0x03,0x40, +0x00,0x24,0x03,0x40,0x50,0x20,0x03,0x40,0x30,0x20,0x03,0x40,0x34,0x20,0x03,0x40, +0x2d,0xe9,0xf0,0x4f,0x85,0xb0,0xc8,0x4b,0x02,0x90,0x1b,0x68,0x23,0xf0,0x7f,0x43, +0x01,0x93,0x4f,0xf0,0xfc,0x54,0x00,0x22,0xc4,0x4b,0x1b,0x68,0x03,0xf0,0x0f,0x03, +0x9a,0x42,0x80,0xf0,0x5a,0x82,0xc2,0x48,0x03,0x68,0x13,0xf0,0x01,0x03,0x03,0x93, +0x40,0xf0,0x75,0x81,0xdf,0xf8,0x74,0xc3,0xbe,0x4b,0xdf,0xf8,0x74,0x83,0xbe,0x4d, +0x4f,0xf0,0x05,0x0e,0xcc,0xf8,0x00,0xe0,0x1b,0x68,0xd8,0xf8,0x00,0x60,0xc3,0xf3, +0x03,0x23,0x4f,0xf4,0x40,0x71,0x01,0x33,0xb1,0xfb,0xf3,0xf3,0x29,0x68,0xb6,0xb2, +0x5e,0x43,0x09,0x0c,0xc6,0xf3,0x8f,0x16,0x09,0x04,0x31,0x43,0x29,0x60,0xb3,0x49, +0x0d,0x68,0xb3,0x49,0x5d,0x43,0xad,0x09,0x0e,0x68,0x0d,0x60,0xb1,0x4d,0x2e,0x68, +0x51,0xf8,0x24,0x7c,0xc6,0xf3,0x07,0x46,0x5e,0x43,0x27,0xf0,0xff,0x07,0xc6,0xf3, +0x87,0x16,0x3e,0x43,0x41,0xf8,0x24,0x6c,0xab,0x4f,0xac,0x4e,0xd6,0xf8,0x00,0xa0, +0xd7,0xf8,0x00,0x90,0xca,0xf3,0x07,0x4a,0x29,0xf0,0xff,0x09,0x4a,0xea,0x09,0x09, +0xc7,0xf8,0x00,0x90,0x37,0x68,0x4f,0xea,0x17,0x6a,0xa5,0x4f,0x0a,0xfb,0x03,0xfa, +0xd7,0xf8,0x00,0x90,0x4f,0xea,0x8a,0x0a,0x0a,0xf4,0x7f,0x4a,0x29,0xf4,0x7f,0x49, +0x4a,0xea,0x09,0x09,0xc7,0xf8,0x00,0x90,0xdf,0xf8,0xd8,0x92,0xdf,0xf8,0xd8,0xa2, +0xd9,0xf8,0x00,0x70,0x4f,0xea,0x17,0x6b,0xda,0xf8,0x00,0x70,0x3f,0x0c,0x0b,0xfb, +0x03,0xfb,0x3f,0x04,0x47,0xea,0x9b,0x17,0xca,0xf8,0x00,0x70,0x36,0x68,0xc6,0xf3, +0x07,0x26,0x73,0x43,0x93,0x4e,0x37,0x68,0x9b,0x00,0x03,0xf4,0x7f,0x43,0x27,0xf4, +0x7f,0x47,0x1f,0x43,0x37,0x60,0x90,0x4b,0x90,0x4e,0xd6,0xf8,0x00,0xa0,0x1f,0x68, +0x4f,0xea,0x1a,0x6a,0x27,0xf4,0x7f,0x47,0x47,0xea,0x0a,0x27,0x1f,0x60,0xd6,0xf8, +0x00,0xa0,0x1f,0x68,0xca,0xf3,0x07,0x4a,0x27,0xf0,0xff,0x07,0x4a,0xea,0x07,0x07, +0x1f,0x60,0xd6,0xf8,0x00,0xa0,0x9f,0x68,0x0a,0xf4,0x7f,0x4a,0x27,0xf4,0x7f,0x47, +0x4a,0xea,0x07,0x07,0x9f,0x60,0x37,0x68,0x9e,0x68,0xff,0xb2,0x26,0xf0,0xff,0x06, +0x3e,0x43,0x9e,0x60,0x2f,0x68,0xde,0x68,0x07,0xf4,0x70,0x47,0x26,0xf4,0x70,0x46, +0x3e,0x43,0xde,0x60,0xd9,0xf8,0x00,0x70,0x5e,0x68,0x07,0xf4,0x70,0x47,0x26,0xf4, +0x70,0x46,0x3e,0x43,0x5e,0x60,0x2d,0x68,0x51,0xf8,0x24,0x3c,0x2d,0x0e,0x23,0xf4, +0x7f,0x43,0x43,0xea,0x05,0x23,0x41,0xf8,0x24,0x3c,0x71,0x4b,0x1d,0x68,0x71,0x4b, +0x19,0x68,0x21,0xf4,0x7f,0x61,0xc5,0xf3,0x0b,0x05,0x21,0xf0,0x0f,0x01,0x29,0x43, +0x6d,0x4d,0x19,0x60,0x2e,0x68,0x19,0x68,0x06,0xf4,0x70,0x26,0x21,0xf4,0x70,0x21, +0x31,0x43,0x19,0x60,0x69,0x4b,0x6a,0x49,0x1f,0x68,0x0e,0x68,0xc7,0xf3,0x83,0x47, +0x26,0xf4,0x70,0x26,0x46,0xea,0x07,0x46,0x0e,0x60,0xd8,0xf8,0x00,0x70,0x0e,0x68, +0x26,0xf4,0x7f,0x66,0xc7,0xf3,0x0b,0x47,0x26,0xf0,0x0f,0x06,0x3e,0x43,0x0e,0x60, +0x60,0x4e,0x1f,0x68,0x31,0x68,0x21,0xf0,0xff,0x71,0xff,0x0d,0x21,0xf4,0x80,0x31, +0x41,0xea,0x07,0x41,0x31,0x60,0x2d,0x68,0x5b,0x49,0x5c,0x4f,0x0f,0x35,0x05,0xf0, +0x0f,0x05,0x0d,0x60,0x1e,0x68,0x4d,0x68,0xc6,0xf3,0x80,0x56,0x25,0xf4,0x00,0x05, +0x45,0xea,0xc6,0x55,0x4d,0x60,0x4d,0x68,0x45,0xf4,0x80,0x45,0x4d,0x60,0x02,0x21, +0x53,0x4d,0xcc,0xf8,0x00,0x10,0x4a,0xf6,0xaa,0x21,0x29,0x60,0x51,0x49,0x3e,0x68, +0xd1,0xf8,0x00,0xc0,0x06,0xf0,0x0f,0x08,0x2c,0xf4,0x7f,0x0c,0x4c,0xea,0x08,0x4c, +0xc6,0xf3,0x03,0x26,0x4c,0xea,0x06,0x56,0x0e,0x60,0x4b,0x4e,0xd6,0xf8,0x00,0xc0, +0xd1,0xf8,0x00,0x80,0xcc,0xf3,0x03,0x49,0x28,0xf0,0xff,0x08,0x49,0xea,0x08,0x08, +0xcc,0xf3,0x03,0x6c,0x48,0xea,0x0c,0x1c,0xc1,0xf8,0x00,0xc0,0x3f,0x68,0xd1,0xf8, +0x04,0xc0,0x07,0xf4,0x70,0x28,0x2c,0xf4,0x7f,0x0c,0x4c,0xea,0x08,0x0c,0xc7,0xf3, +0x03,0x67,0x4c,0xea,0x07,0x57,0x4f,0x60,0x3c,0x49,0x3d,0x4f,0xd1,0xf8,0x00,0x80, +0xd7,0xf8,0x00,0xc0,0xc8,0xf3,0x03,0x28,0x2c,0xf0,0x0f,0x0c,0x48,0xea,0x0c,0x0c, +0xc7,0xf8,0x00,0xc0,0xd6,0xf8,0x00,0xc0,0x36,0x4e,0x37,0x68,0x0c,0xf4,0xf8,0x5c, +0x27,0xf4,0xf8,0x57,0x4c,0xea,0x07,0x07,0x37,0x60,0x0f,0x68,0xd6,0xf8,0x04,0xc0, +0x3f,0x0b,0x07,0xf4,0x70,0x47,0x2c,0xf4,0x70,0x4c,0x47,0xea,0x0c,0x07,0x77,0x60, +0x0f,0x68,0x2d,0x49,0x0e,0x68,0xc7,0xf3,0x04,0x47,0x26,0xf0,0x1f,0x06,0x3e,0x43, +0x0e,0x60,0x1e,0x68,0x29,0x4b,0x19,0x68,0xc6,0xf3,0x01,0x46,0x21,0xf4,0x40,0x11, +0x41,0xea,0x06,0x51,0x19,0x60,0x45,0xf2,0xaa,0x53,0x2b,0x60,0x24,0x4b,0xc3,0xf8, +0x00,0xe0,0x01,0x68,0x41,0xf0,0x01,0x01,0x01,0x60,0x03,0x99,0x19,0x60,0x21,0x4b, +0x21,0x49,0x1b,0x68,0x4a,0xe0,0x00,0xbf,0x14,0x24,0x03,0x40,0x00,0x24,0x03,0x40, +0x40,0x00,0x03,0x40,0x00,0x20,0x03,0x40,0x40,0x22,0x03,0x40,0x8c,0x11,0x00,0x50, +0x44,0x22,0x03,0x40,0x74,0x11,0x00,0x50,0x24,0x22,0x03,0x40,0x78,0x11,0x00,0x50, +0x28,0x22,0x03,0x40,0x34,0x22,0x03,0x40,0x10,0x22,0x03,0x40,0x70,0x11,0x00,0x50, +0x84,0x11,0x00,0x50,0x68,0x22,0x03,0x40,0x80,0x11,0x00,0x50,0xb0,0x12,0x00,0x50, +0x6c,0x22,0x03,0x40,0x70,0x22,0x03,0x40,0x78,0x22,0x03,0x40,0x90,0x11,0x00,0x50, +0x64,0x20,0x03,0x40,0x84,0x20,0x03,0x40,0x94,0x11,0x00,0x50,0x98,0x11,0x00,0x50, +0x80,0x20,0x03,0x40,0x90,0x20,0x03,0x40,0x98,0x20,0x03,0x40,0xa8,0x20,0x03,0x40, +0x3c,0x00,0x03,0x40,0x10,0x00,0x09,0x40,0x08,0x13,0x00,0x50,0x88,0x22,0x03,0x40, +0x88,0x11,0x00,0x50,0x7c,0x11,0x00,0x50,0x2c,0x22,0x03,0x40,0x62,0x48,0x13,0xf0, +0x02,0x0f,0x62,0x4b,0x1d,0x68,0x45,0xf0,0x02,0x05,0x1d,0x60,0x09,0x68,0x19,0xd0, +0x1d,0x68,0x25,0xf4,0xe1,0x75,0xc1,0xf3,0xc1,0x47,0x25,0xf0,0x01,0x05,0xc1,0xf3, +0xc0,0x56,0x3d,0x43,0x45,0xea,0x06,0x25,0xc1,0xf3,0x41,0x56,0x45,0xea,0x86,0x15, +0x1d,0x60,0x1b,0x68,0xdd,0x07,0x02,0xd5,0x03,0x68,0x5b,0x07,0xfc,0xd5,0xc1,0xf3, +0x02,0x43,0x17,0xe0,0x1d,0x68,0xcf,0x0f,0xc1,0xf3,0xc1,0x66,0x25,0xf4,0xe1,0x75, +0x46,0xea,0x07,0x26,0x25,0xf0,0x01,0x05,0x35,0x43,0xc1,0xf3,0x41,0x76,0x45,0xea, +0x86,0x15,0x1d,0x60,0x1b,0x68,0xdf,0x07,0x02,0xd5,0x03,0x68,0x5e,0x07,0xfc,0xd5, +0xc1,0xf3,0x02,0x63,0x46,0x49,0x47,0x4f,0x4a,0xf6,0xaa,0x25,0x0d,0x60,0x46,0x4d, +0x1b,0x03,0x2e,0x68,0xb3,0xf5,0xe0,0x4f,0x26,0xf4,0xe2,0x46,0x18,0xbf,0x43,0xf4, +0x80,0x73,0x33,0x43,0x2b,0x60,0x45,0xf2,0xaa,0x53,0x0b,0x60,0x3f,0x4b,0x40,0x4e, +0x1a,0x60,0x01,0x21,0x43,0xf8,0x20,0x1c,0x3e,0x49,0x4f,0xf6,0xff,0x75,0x0d,0x60, +0x00,0x25,0x43,0xf8,0x20,0x5c,0x03,0xf5,0x0e,0x73,0x4f,0xf0,0x05,0x0e,0x10,0x21, +0xc3,0xf8,0x00,0xe0,0x39,0x60,0x15,0x21,0x31,0x60,0x02,0x21,0x19,0x60,0x36,0x49, +0xd1,0xf8,0x00,0xc0,0xc3,0xf8,0x00,0xe0,0xdf,0xf8,0xdc,0xe0,0xce,0xf8,0x00,0x50, +0xce,0xf8,0x04,0x50,0x02,0x9d,0x1d,0xb1,0x0d,0x68,0x45,0xf4,0x00,0x05,0x0d,0x60, +0xdf,0xf8,0xc8,0xe0,0x02,0x25,0x1d,0x60,0xce,0xf8,0x00,0x40,0x4f,0xf0,0x05,0x0e, +0xc3,0xf8,0x00,0xe0,0x4f,0xf0,0x08,0x0e,0xc7,0xf8,0x00,0xe0,0x15,0x27,0x37,0x60, +0x1d,0x60,0x05,0x68,0xad,0x07,0x19,0xd5,0xfb,0xe7,0x24,0x4b,0x24,0x48,0x1a,0x68, +0x03,0xf5,0x10,0x53,0x04,0x33,0x19,0x68,0x1b,0x68,0xd2,0xb2,0x01,0xf0,0x0f,0x01, +0x03,0xf0,0x0f,0x03,0x51,0x43,0x9b,0x02,0xc3,0xeb,0x81,0x21,0x01,0xf5,0xfe,0x51, +0x18,0x31,0x14,0x22,0xff,0xf7,0xe4,0xfc,0x05,0x46,0x16,0xe0,0x19,0x48,0x00,0x68, +0x10,0xf0,0x10,0x0f,0x0c,0xbf,0x00,0x25,0x04,0x25,0x1c,0xf4,0x00,0x0f,0x07,0xd1, +0x05,0x20,0x18,0x60,0x08,0x68,0x20,0xf4,0x00,0x00,0x08,0x60,0x02,0x21,0x19,0x60, +0x01,0x99,0x0c,0x44,0x0d,0xb9,0x01,0x32,0x6e,0xe5,0xff,0xf7,0xd7,0xfc,0x28,0x46, +0x05,0xb0,0xbd,0xe8,0xf0,0x8f,0x00,0xbf,0x1c,0x00,0x03,0x40,0x24,0x00,0x03,0x40, +0x64,0x20,0x03,0x40,0x0c,0x22,0x03,0x40,0xa8,0x20,0x03,0x40,0x50,0x20,0x03,0x40, +0xb4,0x22,0x03,0x40,0x34,0x20,0x03,0x40,0x7c,0x22,0x03,0x40,0x2c,0x00,0x03,0x40, +0xec,0x0e,0x00,0x20,0x54,0x20,0x03,0x40,0xc0,0x22,0x03,0x40,0x10,0x21,0x03,0x40, +0x10,0xb5,0x00,0x21,0x04,0x1c,0x00,0xf0,0xdf,0xf8,0x05,0x4b,0x18,0x68,0xc3,0x6b, +0x00,0x2b,0x01,0xd0,0x00,0xf0,0x06,0xf8,0x20,0x1c,0xff,0xf7,0x89,0xfc,0xc0,0x46, +0x04,0x0f,0x00,0x20,0x18,0x47,0xc0,0x46,0x70,0xb5,0x10,0x4e,0x10,0x4d,0xad,0x1b, +0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0,0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0, +0x1d,0xf8,0xa5,0x42,0xf8,0xd1,0x00,0xf0,0xdb,0xf9,0x0a,0x4e,0x0a,0x4d,0xad,0x1b, +0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0,0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0, +0x0d,0xf8,0xa5,0x42,0xf8,0xd1,0x70,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46, +0xf0,0xb5,0x0f,0x2a,0x37,0xd9,0x03,0x1c,0x0b,0x43,0x9c,0x07,0x37,0xd1,0x16,0x1c, +0x10,0x3e,0x36,0x09,0x35,0x01,0x45,0x19,0x10,0x35,0x0c,0x1c,0x03,0x1c,0x27,0x68, +0x1f,0x60,0x67,0x68,0x5f,0x60,0xa7,0x68,0x9f,0x60,0xe7,0x68,0xdf,0x60,0x10,0x33, +0x10,0x34,0xab,0x42,0xf3,0xd1,0x73,0x1c,0x1b,0x01,0xc5,0x18,0xc9,0x18,0x0f,0x23, +0x13,0x40,0x03,0x2b,0x1d,0xd9,0x1c,0x1f,0xa4,0x08,0x01,0x34,0xa4,0x00,0x00,0x23, +0xce,0x58,0xee,0x50,0x04,0x33,0xa3,0x42,0xfa,0xd1,0xed,0x18,0xc9,0x18,0x03,0x23, +0x1a,0x40,0x05,0xd0,0x00,0x23,0xcc,0x5c,0xec,0x54,0x01,0x33,0x93,0x42,0xfa,0xd1, +0xf0,0xbc,0x02,0xbc,0x08,0x47,0x05,0x1c,0x00,0x2a,0xf3,0xd1,0xf8,0xe7,0x05,0x1c, +0xf0,0xe7,0x1a,0x1c,0xf8,0xe7,0xc0,0x46,0xf0,0xb5,0x83,0x07,0x4a,0xd0,0x54,0x1e, +0x00,0x2a,0x44,0xd0,0x0e,0x06,0x36,0x0e,0x03,0x1c,0x03,0x25,0x03,0xe0,0x62,0x1e, +0x00,0x2c,0x3c,0xd0,0x14,0x1c,0x01,0x33,0x5a,0x1e,0x16,0x70,0x2b,0x42,0xf6,0xd1, +0x03,0x2c,0x2b,0xd9,0xff,0x25,0x0d,0x40,0x2a,0x02,0x15,0x43,0x2a,0x04,0x15,0x43, +0x0f,0x2c,0x15,0xd9,0x27,0x1c,0x10,0x3f,0x3f,0x09,0x1e,0x1c,0x3a,0x01,0x10,0x36, +0xb6,0x18,0x1a,0x1c,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,0xb2,0x42, +0xf8,0xd1,0x01,0x37,0x3f,0x01,0x0f,0x22,0xdb,0x19,0x14,0x40,0x03,0x2c,0x0d,0xd9, +0x27,0x1f,0xbf,0x08,0xba,0x00,0x1e,0x1d,0xb6,0x18,0x1a,0x1c,0x20,0xc2,0xb2,0x42, +0xfc,0xd1,0x01,0x37,0xbf,0x00,0x03,0x22,0xdb,0x19,0x14,0x40,0x00,0x2c,0x06,0xd0, +0x0a,0x06,0x12,0x0e,0x1c,0x19,0x1a,0x70,0x01,0x33,0xa3,0x42,0xfb,0xd1,0xf0,0xbc, +0x02,0xbc,0x08,0x47,0x14,0x1c,0x03,0x1c,0xc2,0xe7,0xc0,0x46,0x08,0xb5,0x04,0x4b, +0x00,0x2b,0x02,0xd0,0x03,0x48,0x00,0xf0,0x9b,0xf8,0x08,0xbc,0x01,0xbc,0x00,0x47, +0x00,0x00,0x00,0x00,0xc5,0x0d,0x00,0x20,0xf0,0xb5,0x5f,0x46,0x56,0x46,0x4d,0x46, +0x44,0x46,0xf0,0xb4,0x43,0x4b,0x1b,0x68,0x85,0xb0,0x01,0x93,0x49,0x33,0xff,0x33, +0x02,0x90,0x03,0x93,0x0f,0x1c,0x01,0x98,0xa4,0x21,0x49,0x00,0x42,0x58,0x90,0x46, +0x00,0x2a,0x4b,0xd0,0x03,0x98,0x81,0x46,0x41,0x46,0x4e,0x68,0x74,0x1e,0x42,0xd4, +0x45,0x46,0xa3,0x00,0x88,0x35,0xed,0x18,0xc6,0x20,0xc4,0x23,0x01,0x36,0x5b,0x00, +0x40,0x00,0xb6,0x00,0x9b,0x46,0x82,0x46,0x46,0x44,0xc3,0x44,0xc2,0x44,0x08,0xe0, +0x2b,0x1c,0x80,0x33,0x1b,0x68,0xbb,0x42,0x05,0xd0,0x04,0x3d,0x04,0x3e,0x01,0x3c, +0x29,0xd3,0x00,0x2f,0xf4,0xd1,0x41,0x46,0x4a,0x68,0x01,0x3a,0x33,0x68,0xa2,0x42, +0x30,0xd0,0x00,0x22,0x32,0x60,0x00,0x2b,0xef,0xd0,0x40,0x46,0x59,0x46,0x40,0x68, +0x01,0x22,0x09,0x68,0xa2,0x40,0x00,0x90,0x11,0x42,0x20,0xd0,0x50,0x46,0x00,0x68, +0x10,0x42,0x21,0xd1,0x02,0x98,0x29,0x68,0x00,0xf0,0x40,0xf8,0x41,0x46,0x49,0x68, +0x00,0x9a,0x91,0x42,0xb7,0xd1,0x4a,0x46,0x12,0x68,0x42,0x45,0xb3,0xd1,0x04,0x3d, +0x04,0x3e,0x01,0x3c,0xd5,0xd2,0x18,0x4a,0x00,0x2a,0x11,0xd1,0x05,0xb0,0x3c,0xbc, +0x90,0x46,0x99,0x46,0xa2,0x46,0xab,0x46,0xf0,0xbc,0x01,0xbc,0x00,0x47,0x00,0xf0, +0x25,0xf8,0xe3,0xe7,0x4c,0x60,0xce,0xe7,0x28,0x68,0x00,0xf0,0x1f,0xf8,0xdd,0xe7, +0x43,0x46,0x5b,0x68,0x40,0x46,0x00,0x2b,0x0d,0xd1,0x03,0x68,0x00,0x2b,0x0e,0xd0, +0x49,0x46,0x0b,0x60,0xaf,0xf3,0x00,0x80,0x4b,0x46,0x1a,0x68,0x90,0x46,0x41,0x46, +0x00,0x29,0x91,0xd1,0xda,0xe7,0x03,0x68,0xc1,0x46,0x98,0x46,0xf7,0xe7,0x00,0x23, +0xfa,0xe7,0xc0,0x46,0x04,0x0f,0x00,0x20,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46, +0x08,0xb5,0x01,0x1c,0x00,0x22,0x00,0x20,0x00,0x23,0x00,0xf0,0x1f,0xf8,0x08,0xbc, +0x02,0xbc,0x08,0x47,0x38,0xb5,0x0a,0x4b,0x0a,0x4d,0xed,0x1a,0xad,0x10,0x0a,0xd0, +0x01,0x3d,0xac,0x00,0xe4,0x18,0x00,0xe0,0x01,0x3d,0x23,0x68,0x00,0xf0,0x0c,0xf8, +0x04,0x3c,0x00,0x2d,0xf8,0xd1,0x00,0xf0,0x71,0xf8,0x38,0xbc,0x01,0xbc,0x00,0x47, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xf0,0xb5,0x4f,0x46, +0x46,0x46,0xc0,0xb4,0x98,0x46,0x2c,0x4b,0xa4,0x25,0x1b,0x68,0x6d,0x00,0x5c,0x59, +0x83,0xb0,0x06,0x1c,0x0f,0x1c,0x91,0x46,0x01,0x93,0x00,0x2c,0x46,0xd0,0x65,0x68, +0x1f,0x2d,0x1a,0xdd,0x25,0x4b,0x00,0x2b,0x02,0xd1,0x01,0x20,0x40,0x42,0x1c,0xe0, +0xc8,0x20,0x40,0x00,0xaf,0xf3,0x00,0x80,0x04,0x1e,0xf6,0xd0,0x00,0x25,0x45,0x60, +0xa4,0x23,0x01,0x98,0x5b,0x00,0xc0,0x58,0x01,0x99,0x20,0x60,0xcc,0x50,0xc4,0x23, +0x5b,0x00,0xe5,0x50,0xc6,0x23,0x5b,0x00,0xe5,0x50,0x00,0x2e,0x0c,0xd1,0x6b,0x1c, +0x02,0x35,0xad,0x00,0x63,0x60,0x2f,0x51,0x00,0x20,0x03,0xb0,0x0c,0xbc,0x90,0x46, +0x99,0x46,0xf0,0xbc,0x02,0xbc,0x08,0x47,0xab,0x00,0xe3,0x18,0x88,0x22,0x48,0x46, +0x98,0x50,0xc4,0x20,0x40,0x00,0x22,0x18,0x10,0x68,0x01,0x21,0xa9,0x40,0x08,0x43, +0x10,0x60,0x84,0x22,0x52,0x00,0x40,0x46,0x98,0x50,0x02,0x2e,0xdf,0xd1,0xc6,0x22, +0x52,0x00,0xa3,0x18,0x18,0x68,0x01,0x43,0x19,0x60,0xd8,0xe7,0x1c,0x1c,0x4d,0x34, +0xff,0x34,0x5c,0x51,0xb3,0xe7,0xc0,0x46,0x04,0x0f,0x00,0x20,0x00,0x00,0x00,0x00, +0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47,0xf8,0xb5,0xc0,0x46, +0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47,0x00,0x00,0x00,0x00,0xc4,0xf1,0xff,0x7f, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x15,0x00,0x20,0xff,0xff,0xff,0xc5, +0xff,0xff,0xff,0xff,0xc5,0xff,0xff,0xff,0xc5,0xc5,0xc5,0xff,0xc5,0xc5,0xc5,0xff, +0x43,0x00,0x00,0x00,0x10,0x0f,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfc,0x11,0x00,0x20,0x64,0x12,0x00,0x20,0xcc,0x12,0x00,0x20, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0f,0x00,0x20, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x33,0xcd,0xab,0x34,0x12,0x6d,0xe6, -0xec,0xde,0x05,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0e,0x33,0xcd,0xab,0x34,0x12,0x6d,0xe6,0xec,0xde,0x05,0x00,0x0b,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -307,8 +306,9 @@ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x18,0x0f,0x00,0x20,0xc1,0x00,0x00,0x20,0x91,0x00,0x00,0x20,0x00,0x00,0x00,0x00, -0x95,0x0d,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x0f,0x00,0x20,0x61,0x00,0x00,0x20, +0x35,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x6d,0x0c,0x00,0x20,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/cc26xx/flash.c b/contrib/loaders/flash/cc26xx/flash.c index affd029553..641054943f 100644 --- a/contrib/loaders/flash/cc26xx/flash.c +++ b/contrib/loaders/flash/cc26xx/flash.c @@ -42,7 +42,7 @@ typedef uint32_t (*flash_sector_erase_pntr_t) (uint32_t); * ******************************************************************************/ static void issue_fsm_command(flash_state_command_t command); -static void enable_sectors_for_write(void); +static void enable_sectors_for_write(uint32_t); static uint32_t scale_cycle_values(uint32_t specified_timing, uint32_t scale_value); static void set_write_mode(void); @@ -80,42 +80,51 @@ uint32_t flash_bank_erase(bool force_precondition) uint32_t error_return; uint32_t sector_address; uint32_t reg_val; + uint32_t bank_no; + uint32_t top_bank_start_addr = (HWREG(FLASH_BASE + FLASH_O_FCFG_B1_START) & + FLASH_FCFG_B1_START_B1_START_ADDR_M) + >> FLASH_FCFG_B1_START_B1_START_ADDR_S; - /* Enable all sectors for erase. */ - enable_sectors_for_write(); + for (bank_no = 0; bank_no < flash_bank_count(); bank_no++) { + /* Enable all sectors for erase. */ + enable_sectors_for_write(bank_no); - /* Clear the Status register. */ - issue_fsm_command(FAPI_CLEAR_STATUS); + /* Clear the Status register. */ + issue_fsm_command(FAPI_CLEAR_STATUS); - /* Enable erase of all sectors and enable precondition if required. */ - reg_val = HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE); - HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; - HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0x00000000; - HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0x00000000; - if (force_precondition) - HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) |= - FLASH_FSM_ST_MACHINE_DO_PRECOND; - HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + /* Enable erase of all sectors and enable precondition if required. */ + reg_val = HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE); + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0x00000000; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0x00000000; + if (force_precondition) + HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) |= + FLASH_FSM_ST_MACHINE_DO_PRECOND; + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; - /* Issue the bank erase command to the FSM. */ - issue_fsm_command(FAPI_ERASE_BANK); + // Write address to FADDR register. + HWREG(FLASH_BASE + FLASH_O_FADDR) = ADDR_OFFSET + (bank_no * top_bank_start_addr); - /* Wait for erase to finish. */ - while (flash_check_fsm_for_ready() == FAPI_STATUS_FSM_BUSY) - ; + /* Issue the bank erase command to the FSM. */ + issue_fsm_command(FAPI_ERASE_BANK); - /* Update status. */ - error_return = flash_check_fsm_for_error(); + /* Wait for erase to finish. */ + while (flash_check_fsm_for_ready() == FAPI_STATUS_FSM_BUSY) + ; - /* Disable sectors for erase. */ - flash_disable_sectors_for_write(); + /* Update status. */ + error_return = flash_check_fsm_for_error(); - /* Set configured precondition mode since it may have been forced on. */ - if (!(reg_val & FLASH_FSM_ST_MACHINE_DO_PRECOND)) { - HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; - HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) &= - ~FLASH_FSM_ST_MACHINE_DO_PRECOND; - HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + /* Set configured precondition mode since it may have been forced on. */ + if (!(reg_val & FLASH_FSM_ST_MACHINE_DO_PRECOND)) { + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) &= + ~FLASH_FSM_ST_MACHINE_DO_PRECOND; + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + } + + if (error_return != FAPI_STATUS_SUCCESS) + break; } /* Program security data to default values in the customer configuration */ @@ -128,6 +137,9 @@ uint32_t flash_bank_erase(bool force_precondition) CCFG_SIZE_SECURITY); } + /* Disable sectors for erase. */ + flash_disable_sectors_for_write(); + /* Return status of operation. */ return error_return; } @@ -161,23 +173,34 @@ uint32_t flash_program(uint8_t *data_buffer, uint32_t address, uint32_t count) ******************************************************************************/ void flash_disable_sectors_for_write(void) { + uint32_t bank_no; + /* Configure flash back to read mode */ set_read_mode(); - /* Disable Level 1 Protection. */ - HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS; + for (bank_no = 0; bank_no < flash_bank_count(); bank_no++) { - /* Disable all sectors for erase and programming. */ - HWREG(FLASH_BASE + FLASH_O_FBSE) = 0x0000; + /* Select flash bank. */ + HWREG(FLASH_BASE + FLASH_O_FMAC) = bank_no; - /* Enable Level 1 Protection. */ - HWREG(FLASH_BASE + FLASH_O_FBPROT) = 0; + /* Disable Level 1 Protection. */ + HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS; - /* Protect sectors from sector erase. */ - HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; - HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0xFFFFFFFF; - HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0xFFFFFFFF; - HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + /* Disable all sectors for erase and programming. */ + HWREG(FLASH_BASE + FLASH_O_FBSE) = 0x0000; + + /* Enable Level 1 Protection. */ + HWREG(FLASH_BASE + FLASH_O_FBPROT) = 0; + + /* Protect sectors from sector erase. */ + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0xFFFFFFFF; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0xFFFFFFFF; + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + } + + // Select bank 0 + HWREG(FLASH_BASE + FLASH_O_FMAC) = 0x0; } /****************************************************************************** @@ -214,7 +237,7 @@ static void issue_fsm_command(flash_state_command_t command) * the FLASH_O_FSM_SECTOR1 register. * ******************************************************************************/ -static void enable_sectors_for_write(void) +static void enable_sectors_for_write(uint32_t bank_no) { /* Trim flash module for program/erase operation. */ trim_for_write(); @@ -223,7 +246,7 @@ static void enable_sectors_for_write(void) set_write_mode(); /* Select flash bank. */ - HWREG(FLASH_BASE + FLASH_O_FMAC) = 0x00; + HWREG(FLASH_BASE + FLASH_O_FMAC) = bank_no; /* Disable Level 1 Protection. */ HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS; diff --git a/contrib/loaders/flash/cc26xx/flash.h b/contrib/loaders/flash/cc26xx/flash.h index 07acf26f2a..21df89bd63 100644 --- a/contrib/loaders/flash/cc26xx/flash.h +++ b/contrib/loaders/flash/cc26xx/flash.h @@ -246,6 +246,46 @@ static inline uint32_t flash_check_fsm_for_ready(void) return FAPI_STATUS_FSM_READY; } +/****************************************************************************** + * + * Get the number of banks + * + * This function returns the number of bank of the flash. + * + * Returns the number of banks + * + ******************************************************************************/ +static inline uint32_t flash_bank_count(void) +{ + uint32_t bank_count; + + bank_count = (HWREG(FLASH_BASE + FLASH_O_FCFG_BANK) & + FLASH_FCFG_BANK_MAIN_NUM_BANK_M) >> + FLASH_FCFG_BANK_MAIN_NUM_BANK_S; + + return bank_count; +} + +/****************************************************************************** + * + * Get the size of the bank. + * + * This function returns the size of the main bank in number of bytes. + * + * Returns the flash size in number of bytes. + * + ******************************************************************************/ +static inline uint8_t flash_bank_width(void) +{ + uint8_t bank_width; + + bank_width = (uint8_t)(((HWREG(FLASH_BASE + FLASH_O_FCFG_BANK) & + FLASH_FCFG_BANK_MAIN_BANK_WIDTH_M) >> + FLASH_FCFG_BANK_MAIN_BANK_WIDTH_S) >> 3); + + return bank_width; +} + /****************************************************************************** * * Erase a flash sector. diff --git a/contrib/loaders/flash/cc26xx/hw_regs.h b/contrib/loaders/flash/cc26xx/hw_regs.h index 78c81be242..753db17c52 100644 --- a/contrib/loaders/flash/cc26xx/hw_regs.h +++ b/contrib/loaders/flash/cc26xx/hw_regs.h @@ -116,6 +116,10 @@ /* FMC Sequential Pump Information */ #define FLASH_O_FSEQPMP 0x000020A8 +#define FLASH_O_FADDR 0x00002110 + +#define FLASH_O_FWPWRITE0 0x00002120 + /* FMC FSM Command */ #define FLASH_O_FSM_CMD 0x0000220C @@ -179,9 +183,14 @@ /* FMC FSM Sector Erased 2 */ #define FLASH_O_FSM_SECTOR2 0x000022C4 +#define FLASH_O_FCFG_BANK 0x00002400 + /* FMC Flash Bank 0 Starting Address */ #define FLASH_O_FCFG_B0_START 0x00002410 +/* FMC Flash Bank 1 Starting Address */ +#define FLASH_O_FCFG_B1_START 0x00002414 + /* FMC Flash Bank 0 Sector Size 0 */ #define FLASH_O_FCFG_B0_SSIZE0 0x00002430 @@ -1353,4 +1362,16 @@ * 1: DCDC and GLDO are bypassed and an external regulator supplies VDDR */ #define AON_PMCTL_PWRCTL_EXT_REG_MODE 0x00000002 +/* Field: [3:0] MAIN_NUM_BANK */ +#define FLASH_FCFG_BANK_MAIN_NUM_BANK_M 0x0000000F +#define FLASH_FCFG_BANK_MAIN_NUM_BANK_S 0 + +/* Field: [23:0] B1_START_ADDR */ +#define FLASH_FCFG_B1_START_B1_START_ADDR_M 0x00FFFFFF +#define FLASH_FCFG_B1_START_B1_START_ADDR_S 0 + +/* Field: [15:4] MAIN_BANK_WIDTH */ +#define FLASH_FCFG_BANK_MAIN_BANK_WIDTH_M 0x0000FFF0 +#define FLASH_FCFG_BANK_MAIN_BANK_WIDTH_S 4 + #endif /* #ifndef OPENOCD_LOADERS_FLASH_CC26XX_HW_REGS_H */ From 13f1bcbe90c51ab9200a0d10de24111459b0e626 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Fri, 29 Mar 2024 21:14:29 +0100 Subject: [PATCH 0941/1312] tcl/target: Add support of CC1352P7 This adds support for TI CC13X2X7 / CC26X2X7 family. For further details, see https://www.ti.com/lit/ug/swcu192/swcu192.pdf. Change-Id: Ifd9b505716ddf0abbdd00f617e50a93a3d4fbe6a Signed-off-by: Alexandre Bailon Reviewed-on: https://review.openocd.org/c/openocd/+/8193 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Vaishnav M A --- tcl/target/ti_cc26x2x7.cfg | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tcl/target/ti_cc26x2x7.cfg diff --git a/tcl/target/ti_cc26x2x7.cfg b/tcl/target/ti_cc26x2x7.cfg new file mode 100644 index 0000000000..91c1a80596 --- /dev/null +++ b/tcl/target/ti_cc26x2x7.cfg @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Texas Instruments CC26x2 - ARM Cortex-M4 +# +# http://www.ti.com +# + +set CHIPNAME cc26x2x7 +set JRC_TAPID 0x1BB7702F +set WORKAREASIZE 0x7000 + +source [find target/ti_cc26x0.cfg] From 760dd1f3a8720e5e58b96e4920fd17bd8a1a7bf6 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Fri, 29 Mar 2024 21:14:54 +0100 Subject: [PATCH 0942/1312] tcl/boards: Add support of LP-CC1352P7 board This adds support of TI LP-CC1352P7 evaluation kit. For further details, see https://www.ti.com/tool/LP-CC1352P7. Change-Id: I4aba160dbf4920febb7897458d06450e7d134147 Signed-off-by: Alexandre Bailon Reviewed-on: https://review.openocd.org/c/openocd/+/8194 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Vaishnav M A --- tcl/board/ti_cc26x2x7_launchpad.cfg | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tcl/board/ti_cc26x2x7_launchpad.cfg diff --git a/tcl/board/ti_cc26x2x7_launchpad.cfg b/tcl/board/ti_cc26x2x7_launchpad.cfg new file mode 100644 index 0000000000..9e6e72e89c --- /dev/null +++ b/tcl/board/ti_cc26x2x7_launchpad.cfg @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# TI CC1352P7 LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter speed 5500 +transport select jtag +source [find target/ti_cc26x2x7.cfg] From e5a2001a3331dfc669f9969fd9a5f661579ccad9 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Sat, 3 Aug 2024 22:10:57 +0300 Subject: [PATCH 0943/1312] binarybuffer: add asserts for the number of requested bits for get/set functions Change-Id: Ieca5b4e690c9713ad60dc9d8c223c2d64822e2f5 Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8427 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Jan Matyas Reviewed-by: Antonio Borneo --- src/helper/binarybuffer.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index 103a48c5c5..df4199837f 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -34,6 +34,7 @@ static inline void buf_set_u32(uint8_t *_buffer, unsigned first, unsigned num, uint32_t value) { + assert(num >= 1 && num <= 32); uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -64,6 +65,7 @@ static inline void buf_set_u32(uint8_t *_buffer, static inline void buf_set_u64(uint8_t *_buffer, unsigned first, unsigned num, uint64_t value) { + assert(num >= 1 && num <= 64); uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -102,6 +104,7 @@ static inline void buf_set_u64(uint8_t *_buffer, static inline uint32_t buf_get_u32(const uint8_t *_buffer, unsigned first, unsigned num) { + assert(num >= 1 && num <= 32); const uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -131,6 +134,7 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer, static inline uint64_t buf_get_u64(const uint8_t *_buffer, unsigned first, unsigned num) { + assert(num >= 1 && num <= 64); const uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { From e5276bb945b518c7e9df5b7e069cc6bf45a96c35 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 1 Sep 2024 15:01:56 +0200 Subject: [PATCH 0944/1312] rtos: use target_buffer_get_u32() Simplify the code using the target endianness independent API. Change-Id: I39f720d0db9cf24eb41d7f359e4321bbc2045658 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8474 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/rtos/rtos_standard_stackings.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 5478080cf7..99cd1540f0 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -160,9 +160,7 @@ target_addr_t rtos_cortex_m_stack_align(struct target *target, new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size; - xpsr = (target->endianness == TARGET_LITTLE_ENDIAN) ? - le_to_h_u32(&stack_data[xpsr_offset]) : - be_to_h_u32(&stack_data[xpsr_offset]); + xpsr = target_buffer_get_u32(target, &stack_data[xpsr_offset]); if ((xpsr & ALIGN_NEEDED) != 0) { LOG_DEBUG("XPSR(0x%08" PRIx32 ") indicated stack alignment was necessary\r\n", xpsr); From 930ec2f439f2f7d81894a292f0df5a56f9ff0ce8 Mon Sep 17 00:00:00 2001 From: Richard Allen Date: Wed, 31 Jul 2024 20:53:52 -0500 Subject: [PATCH 0945/1312] target/espressif: add profiling function for ESP32-S3 Use the TRAX interface DEBUGPC if available. Otherwise use default stop-and-go profiling. ESP32-S3, before this patch: Internal: 8 samples/second FT2232H: 12 samples/second After this patch: Internal: 18ksamples/second FT2232H: 100ksamples/second Change-Id: I681f0bccf4263c1e24f38be511e3b3aec8bf4d60 Signed-off-by: Richard Allen Reviewed-on: https://review.openocd.org/c/openocd/+/8431 Reviewed-by: Erhan Kurubas Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Ian Thompson Reviewed-by: Yurii Shutkin --- src/target/espressif/esp32s3.c | 1 + src/target/espressif/esp_xtensa.c | 72 +++++++++++++++++++++++++ src/target/espressif/esp_xtensa.h | 3 ++ src/target/xtensa/xtensa_debug_module.h | 2 + 4 files changed, 78 insertions(+) diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 22e1630e16..2afb4b009e 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -421,4 +421,5 @@ struct target_type esp32s3_target = { .deinit_target = esp_xtensa_target_deinit, .commands = esp32s3_command_handlers, + .profiling = esp_xtensa_profiling, }; diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index 11895d23bb..9b57f345e4 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -179,3 +179,75 @@ int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *break return xtensa_breakpoint_remove(target, breakpoint); /* flash breakpoints will be handled in another patch */ } + +int esp_xtensa_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +{ + struct timeval timeout, now; + struct xtensa *xtensa = target_to_xtensa(target); + int retval = ERROR_OK; + int res; + + /* Vary samples per pass to avoid sampling a periodic function periodically */ + #define MIN_PASS 200 + #define MAX_PASS 1000 + + gettimeofday(&timeout, NULL); + timeval_add_time(&timeout, seconds, 0); + + uint8_t buf[sizeof(uint32_t) * MAX_PASS]; + + /* Capture one sample to verify the register is present and working */ + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf); + res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) { + LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go"); + return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); + } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) { + LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go"); + return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); + } + + LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can..."); + + /* Make sure the target is running */ + target_poll(target); + if (target->state == TARGET_HALTED) + retval = target_resume(target, 1, 0, 0, 0); + + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "Error while resuming target"); + return retval; + } + + uint32_t sample_count = 0; + + for (;;) { + uint32_t remaining = max_num_samples - sample_count; + uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS; + this_pass = this_pass > remaining ? remaining : this_pass; + for (uint32_t i = 0; i < this_pass; ++i) + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t)); + res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!"); + return res; + } + + for (uint32_t i = 0; i < this_pass; ++i) { + uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32); + samples[sample_count++] = sample32; + } + gettimeofday(&now, NULL); + if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) { + LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count); + break; + } + } + + *num_samples = sample_count; + return retval; + + #undef MIN_PASS + #undef MAX_PASS +} diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h index 00f67a3706..56c903f607 100644 --- a/src/target/espressif/esp_xtensa.h +++ b/src/target/espressif/esp_xtensa.h @@ -37,6 +37,9 @@ 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); +int esp_xtensa_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); + int esp_xtensa_on_halt(struct target *target); #endif /* OPENOCD_TARGET_ESP_XTENSA_H */ diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h index 495da2a646..8391a96382 100644 --- a/src/target/xtensa/xtensa_debug_module.h +++ b/src/target/xtensa/xtensa_debug_module.h @@ -75,6 +75,7 @@ enum xtensa_dm_reg { XDMREG_DELAYCNT, XDMREG_MEMADDRSTART, XDMREG_MEMADDREND, + XDMREG_DEBUGPC,/*Unsupported, undocumented, may not be present*/ XDMREG_EXTTIMELO, XDMREG_EXTTIMEHI, XDMREG_TRAXRSVD48, @@ -184,6 +185,7 @@ struct xtensa_dm_reg_offsets { { .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \ { .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \ { .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \ + { .nar = 0x0f, .apb = 0x003c }, /* XDMREG_DEBUGPC */ \ { .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \ { .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \ { .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \ From 1dc3d7e8febb8bdd74bdcbefeb0e0f7b54817f10 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 09:15:46 +0200 Subject: [PATCH 0946/1312] flash/nor/sfdp: expose SFDP_MAGIC in sfdp.h Could be handy for dummy transfer size detection. Signed-off-by: Tomas Vanek Change-Id: Ibb485218f6c2ff9066910bb58be0fc614b77add3 Reviewed-on: https://review.openocd.org/c/openocd/+/8438 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Andreas Bolsch --- src/flash/nor/sfdp.c | 1 - src/flash/nor/sfdp.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/sfdp.c b/src/flash/nor/sfdp.c index 5bfb541946..b411a3b639 100644 --- a/src/flash/nor/sfdp.c +++ b/src/flash/nor/sfdp.c @@ -12,7 +12,6 @@ #include "spi.h" #include "sfdp.h" -#define SFDP_MAGIC 0x50444653 #define SFDP_ACCESS_PROT 0xFF #define SFDP_BASIC_FLASH 0xFF00 #define SFDP_4BYTE_ADDR 0xFF84 diff --git a/src/flash/nor/sfdp.h b/src/flash/nor/sfdp.h index 1c9af326b3..7a7af9931f 100644 --- a/src/flash/nor/sfdp.h +++ b/src/flash/nor/sfdp.h @@ -7,6 +7,8 @@ #ifndef OPENOCD_FLASH_NOR_SFDP_H #define OPENOCD_FLASH_NOR_SFDP_H +#define SFDP_MAGIC 0x50444653 + /* per JESD216D 'addr' is *byte* based but must be word aligned, * 'buffer' is word based, word aligned and always little-endian encoded, * in the flash, 'addr_len' is 3 or 4, 'dummy' ***usually*** 8 From ea28f96aa99b3dd6cbed6143fda844427e71832a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 09:17:36 +0200 Subject: [PATCH 0947/1312] flash/nor/sfdp, stmqspi: use native type for buffer size Two different sizes uint8_t and uint32_t was used for this value without a good reason. Signed-off-by: Tomas Vanek Change-Id: I4bb60cc5397ffd0d37e7034e3930e62793140c8d Reviewed-on: https://review.openocd.org/c/openocd/+/8439 Reviewed-by: Andreas Bolsch Tested-by: jenkins --- src/flash/nor/sfdp.c | 2 +- src/flash/nor/sfdp.h | 2 +- src/flash/nor/stmqspi.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/sfdp.c b/src/flash/nor/sfdp.c index b411a3b639..917f1626fb 100644 --- a/src/flash/nor/sfdp.c +++ b/src/flash/nor/sfdp.c @@ -99,7 +99,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, goto err; for (k = 0; k < nph; k++) { - uint8_t words = (pheaders[k].revision >> 24) & 0xFF; + unsigned int words = (pheaders[k].revision >> 24) & 0xFF; uint16_t id = (((pheaders[k].ptr) >> 16) & 0xFF00) | (pheaders[k].revision & 0xFF); uint32_t ptr = pheaders[k].ptr & 0xFFFFFF; diff --git a/src/flash/nor/sfdp.h b/src/flash/nor/sfdp.h index 7a7af9931f..0d43519f65 100644 --- a/src/flash/nor/sfdp.h +++ b/src/flash/nor/sfdp.h @@ -18,7 +18,7 @@ * * buffer contents is supposed to be returned in ***host*** endianness */ typedef int (*read_sfdp_block_t)(struct flash_bank *bank, uint32_t addr, - uint32_t words, uint32_t *buffer); + unsigned int words, uint32_t *buffer); extern int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, read_sfdp_block_t read_sfdp_block); diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c index a1e1d34116..df58f6c55d 100644 --- a/src/flash/nor/stmqspi.c +++ b/src/flash/nor/stmqspi.c @@ -1807,7 +1807,7 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len) /* Read SFDP parameter block */ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, - uint32_t words, uint32_t *buffer) + unsigned int words, uint32_t *buffer) { struct target *target = bank->target; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; @@ -1848,7 +1848,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, } } - LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08" PRIx32 " dummy=%u", + LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08x dummy=%u", __func__, addr, words, *dummy); /* Abort any previous operation */ From 96924dda01b964799fc1a78524fc24d7bd2142dc Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Tue, 18 Jun 2024 12:15:21 +0800 Subject: [PATCH 0948/1312] target: add imx8mp and evk board support Have verified with JLink: openocd -f interface/jlink.cfg -f board/nxp_imx8mp-evk.cfg -c "gdb_breakpoint_override hard" Change-Id: I74f8766b8c5334ca5758c2672c283ff2405de4c3 Signed-off-by: Jiafei Pan Reviewed-on: https://review.openocd.org/c/openocd/+/8352 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/nxp_imx8mp-evk.cfg | 24 +++++++++++++++++ tcl/target/imx8mp.cfg | 52 ++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 tcl/board/nxp_imx8mp-evk.cfg create mode 100644 tcl/target/imx8mp.cfg diff --git a/tcl/board/nxp_imx8mp-evk.cfg b/tcl/board/nxp_imx8mp-evk.cfg new file mode 100644 index 0000000000..4e101d454f --- /dev/null +++ b/tcl/board/nxp_imx8mp-evk.cfg @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# configuration file for NXP IMX8M Plus EVK +# + +# only JTAG supported +transport select jtag + +# set a safe JTAG clock speed, can be overridden +adapter speed 1000 + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 70 + + +# board has an i.MX8MP with 4 Cortex-A55 cores +set CHIPNAME imx8mp +set CHIPCORES 4 + +# source SoC configuration +source [find target/imx8mp.cfg] diff --git a/tcl/target/imx8mp.cfg b/tcl/target/imx8mp.cfg new file mode 100644 index 0000000000..bddbcfd20e --- /dev/null +++ b/tcl/target/imx8mp.cfg @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# configuration file for NXP i.MX8M Plus SoCs +# +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME imx8m +} + +if { [info exists CHIPCORES] } { + set _cores $CHIPCORES +} else { + set _cores 1 +} + +# CoreSight Debug Access Port +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x5ba00477 +} + +# the DAP tap +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x0f \ + -expected-id $_DAP_TAPID + +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.a53 +set _CTINAME $_CHIPNAME.cti + +set DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000} +set CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000} + +for { set _core 0 } { $_core < $_cores } { incr _core } { + + cti create $_CTINAME.$_core -dap $_CHIPNAME.dap -ap-num 1 \ + -baseaddr [lindex $CTIBASE $_core] + + target create $_TARGETNAME.$_core aarch64 -dap $_CHIPNAME.dap \ + -dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core +} + +# declare the auxiliary Cortex-M7 core on AP #4 +target create ${_CHIPNAME}.m7 cortex_m -dap ${_CHIPNAME}.dap -ap-num 4 + +# AHB-AP for direct access to soc bus +target create ${_CHIPNAME}.ahb mem_ap -dap ${_CHIPNAME}.dap -ap-num 0 + +# default target is A53 core 0 +targets $_TARGETNAME.0 From 0261cd995888e83f6099f0d94a5e9a96a47bc609 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 2 Sep 2024 11:02:19 +0200 Subject: [PATCH 0949/1312] checkpatch: check for SPDX in linker scripts Current script does not enforces the check for the SPDX tag in the linker scripts. Add the extension '.ld' in the OpenOCD specific part. Change-Id: I1cb6bc52e9dd86d99a26393085c7e2c9e8bac11f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8475 Tested-by: jenkins --- tools/scripts/checkpatch.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl index a2f89eac89..59a3eed121 100755 --- a/tools/scripts/checkpatch.pl +++ b/tools/scripts/checkpatch.pl @@ -3730,6 +3730,8 @@ sub process { # OpenOCD specific: Begin } elsif ($realfile =~ /\.(am|cfg|tcl)$/) { $comment = '#'; + } elsif ($realfile =~ /\.(ld)$/) { + $comment = '/*'; # OpenOCD specific: End } From 84d196673e1d24898c588423870ea0f0ab39d9be Mon Sep 17 00:00:00 2001 From: liangzhen Date: Mon, 2 Sep 2024 20:21:48 +0800 Subject: [PATCH 0950/1312] tcl/target: Add SpacemiT Key Stone K1 config Add basic connection details with Key Stone K1 Change-Id: I3e51d4194cfd3b7fe8ae395e0aca0fa4799dfb73 Signed-off-by: liangzhen Reviewed-on: https://review.openocd.org/c/openocd/+/8361 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/spacemit-k1.cfg | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tcl/target/spacemit-k1.cfg diff --git a/tcl/target/spacemit-k1.cfg b/tcl/target/spacemit-k1.cfg new file mode 100644 index 0000000000..ef5d7833dd --- /dev/null +++ b/tcl/target/spacemit-k1.cfg @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# SpacemiT Key Stone K1 target +# +# https://www.spacemit.com/key-stone-k1 +# + +transport select jtag + +adapter speed 2000 + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME k1 +} + +if { [info exists CORES] } { + set _cores $CORES +} else { + set _cores 1 +} + +if { [info exists SECJTAG] } { + jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000E21 +} else { + jtag newtap pre unknown -irlen 1 -expected-id 0x00000000 -disable + jtag configure pre.unknown -event tap-enable "" + + jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000E21 -disable + jtag configure $_CHIPNAME.cpu -event tap-enable "" + + jtag newtap post unknown -irlen 9 -expected-id 0x08501C0D -ignore-version + + jtag configure post.unknown -event setup { + global _CHIPNAME + + irscan post.unknown 0x98 + drscan post.unknown 16 0xa + + jtag tapenable pre.unknown + jtag tapenable $_CHIPNAME.cpu + } +} + +set _TARGETNAME $_CHIPNAME.cpu +set DBGBASE {0x0 0x400} +set _smp_command "target smp" + +for { set _core 0 } { $_core < $_cores } { incr _core } { + target create $_TARGETNAME.$_core riscv -chain-position $_TARGETNAME \ + -coreid [expr {$_core % 4}] -dbgbase [lindex $DBGBASE [expr {$_core / 4}]] + + if { [expr {$_core % 4}] == 0 } { + $_TARGETNAME.$_core configure -rtos hwthread + } + + set _smp_command "$_smp_command $_TARGETNAME.$_core" +} + +eval $_smp_command + +set _SPEED 8000 + +$_TARGETNAME.0 configure -event examine-start { + adapter speed $_SPEED + puts [ adapter speed ] +} + +foreach t [target names] { + # $t riscv set_mem_access sysbus progbuf + $t riscv set_mem_access progbuf +} From a9ba96f94a31da50b7323fbb42ae749027b0357b Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Tue, 3 Sep 2024 14:32:42 -0700 Subject: [PATCH 0951/1312] doc/xtensa: update supported architecture list - Xtensa LX8 is fully supported in addition to prior LX and NX cores. Change-Id: I2f3f0a21ce1518b3ced6d241f0ab84c65af64423 Signed-off-by: Ian Thompson Reviewed-on: https://review.openocd.org/c/openocd/+/8362 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 2e48d8e208..e8a1f33b5f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11611,8 +11611,8 @@ on @url{https://www.nxp.com}. @subsection Xtensa Configuration Commands @deffn {Config Command} {xtensa xtdef} (@option{LX}|@option{NX}) -Configure the Xtensa target architecture. Currently, Xtensa support is limited -to LX6, LX7, and NX cores. +Configure the Xtensa target architecture to LX or NX. Currently, Xtensa LX support +is limited to LX6 and newer cores. @end deffn @deffn {Config Command} {xtensa xtopt} option value From 63ca9670321c1c057ee32e9925826f9f8c836005 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 3 Jul 2024 15:16:27 +0200 Subject: [PATCH 0952/1312] README: Use proper Markdown syntax The README file contains a mixture of Markdown and non-Markdown syntax. Refurbish the document and use only Markdown syntax according to the specification in [1]. [1] https://www.markdownguide.org/ Change-Id: If58f4e2971dc798a03a78841226804ab1f2d33c8 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8387 Reviewed-by: Antonio Borneo Tested-by: jenkins --- README | 140 +++++++++++++++++++++++++-------------------------------- 1 file changed, 60 insertions(+), 80 deletions(-) diff --git a/README b/README index 7d3f10def0..950c71f707 100644 --- a/README +++ b/README @@ -1,5 +1,4 @@ -Welcome to OpenOCD! -=================== +# Welcome to OpenOCD! OpenOCD provides on-chip programming and debugging support with a layered architecture of JTAG interface and TAP support including: @@ -26,33 +25,33 @@ This README file contains an overview of the following topics: - packaging tips. -============================ -Quickstart for the impatient -============================ +# Quickstart for the impatient If you have a popular board then just start OpenOCD with its config, e.g.: - openocd -f board/stm32f4discovery.cfg + openocd -f board/stm32f4discovery.cfg If you are connecting a particular adapter with some specific target, you need to source both the jtag interface and the target configs, e.g.: - openocd -f interface/ftdi/jtagkey2.cfg -c "transport select jtag" \ - -f target/ti_calypso.cfg +``` +openocd -f interface/ftdi/jtagkey2.cfg -c "transport select jtag" \ + -f target/ti_calypso.cfg +``` - openocd -f interface/stlink.cfg -c "transport select hla_swd" \ - -f target/stm32l0.cfg +``` +openocd -f interface/stlink.cfg -c "transport select hla_swd" \ + -f target/stm32l0.cfg +``` After OpenOCD startup, connect GDB with - (gdb) target extended-remote localhost:3333 + (gdb) target extended-remote localhost:3333 -===================== -OpenOCD Documentation -===================== +# OpenOCD Documentation In addition to the in-tree documentation, the latest manuals may be viewed online at the following URLs: @@ -71,35 +70,34 @@ by subscribing to the OpenOCD developer mailing list: openocd-devel@lists.sourceforge.net -Building the OpenOCD Documentation ----------------------------------- +## Building the OpenOCD Documentation By default the OpenOCD build process prepares documentation in the -"Info format" and installs it the standard way, so that "info openocd" +"Info format" and installs it the standard way, so that `info openocd` can access it. Additionally, the OpenOCD User's Guide can be produced in the following different formats: - # If PDFVIEWER is set, this creates and views the PDF User Guide. - make pdf && ${PDFVIEWER} doc/openocd.pdf +If `PDFVIEWER` is set, this creates and views the PDF User Guide. - # If HTMLVIEWER is set, this creates and views the HTML User Guide. - make html && ${HTMLVIEWER} doc/openocd.html/index.html + make pdf && ${PDFVIEWER} doc/openocd.pdf + +If `HTMLVIEWER` is set, this creates and views the HTML User Guide. + + make html && ${HTMLVIEWER} doc/openocd.html/index.html The OpenOCD Developer Manual contains information about the internal architecture and other details about the code: - # NB! make sure doxygen is installed, type doxygen --version - make doxygen && ${HTMLVIEWER} doxygen/index.html +Note: make sure doxygen is installed, type doxygen --version + make doxygen && ${HTMLVIEWER} doxygen/index.html -================== -Supported hardware -================== -JTAG adapters -------------- +# Supported hardware + +## JTAG adapters AM335x, ARM-JTAG-EW, ARM-USB-OCD, ARM-USB-TINY, AT91RM9200, axm0432, BCM2835, Bus Blaster, Buspirate, Cadence DPI, Cadence vdebug, Chameleon, CMSIS-DAP, @@ -116,8 +114,7 @@ sysfsgpio, Tigard, TI XDS110, TUMPA, Turtelizer, ULINK, USB-A9260, USB-Blaster, USB-JTAG, USBprog, VPACLink, VSLLink, Wiggler, XDS100v2, Xilinx XVC/PCIe, Xverve. -Debug targets -------------- +## Debug targets ARM: AArch64, ARM11, ARM7, ARM9, Cortex-A/R (v7-A/R), Cortex-M (ARMv{6/7/8}-M), FA526, Feroceon/Dragonite, XScale. @@ -125,8 +122,7 @@ ARCv2, AVR32, DSP563xx, DSP5680xx, EnSilica eSi-RISC, EJTAG (MIPS32, MIPS64), ESP32, ESP32-S2, ESP32-S3, Intel Quark, LS102x-SAP, RISC-V, ST STM8, Xtensa. -Flash drivers -------------- +## Flash drivers ADUC702x, AT91SAM, AT91SAM9 (NAND), ATH79, ATmega128RFA1, Atmel SAM, AVR, CFI, DSP5680xx, EFM32, EM357, eSi-RISC, eSi-TSMC, EZR32HG, FM3, FM4, Freedom E SPI, @@ -140,12 +136,9 @@ TI CC13xx, TI CC26xx, TI CC32xx, TI MSP432, Winner Micro w600, Xilinx XCF, XMC1xxx, XMC4xxx. -================== -Installing OpenOCD -================== +# Installing OpenOCD -A Note to OpenOCD Users ------------------------ +## A Note to OpenOCD Users If you would rather be working "with" OpenOCD rather than "on" it, your operating system or JTAG interface supplier may provide binaries for @@ -164,8 +157,7 @@ Users of these binary versions of OpenOCD must contact their Packager to ask for support or newer versions of the binaries; the OpenOCD developers do not support packages directly. -A Note to OpenOCD Packagers ---------------------------- +## A Note to OpenOCD Packagers You are a PACKAGER of OpenOCD if you: @@ -192,11 +184,9 @@ suggestions: - Use "ftdi" interface adapter driver for the FTDI-based devices. -================ -Building OpenOCD -================ +# Building OpenOCD -The INSTALL file contains generic instructions for running 'configure' +The INSTALL file contains generic instructions for running `configure` and compiling the OpenOCD source code. That file is provided by default for all GNU autotools packages. If you are not familiar with the GNU autotools, then you should read those instructions first. @@ -204,8 +194,7 @@ the GNU autotools, then you should read those instructions first. The remainder of this document tries to provide some instructions for those looking for a quick-install. -OpenOCD Dependencies --------------------- +## OpenOCD Dependencies GCC or Clang is currently required to build OpenOCD. The developers have begun to enforce strict code warnings (-Wall, -Werror, -Wextra, @@ -250,8 +239,7 @@ Optional development script checkpatch needs: - python - python-ply -Permissions delegation ----------------------- +## Permissions delegation Running OpenOCD with root/administrative permissions is strongly discouraged for security reasons. @@ -268,89 +256,81 @@ For parport adapters on Windows you need to run install_giveio.bat (it's also possible to use "ioperm" with Cygwin instead) to give ordinary users permissions for accessing the "LPT" registers directly. -Compiling OpenOCD ------------------ +## Compiling OpenOCD To build OpenOCD, use the following sequence of commands: - ./bootstrap (when building from the git repository) - ./configure [options] - make - sudo make install + ./bootstrap + ./configure [options] + make + sudo make install -The 'configure' step generates the Makefiles required to build +The `bootstrap` command is only necessary when building from the Git repository. The `configure` step generates the Makefiles required to build OpenOCD, usually with one or more options provided to it. The first 'make' step will build OpenOCD and place the final executable in -'./src/'. The final (optional) step, ``make install'', places all of +'./src/'. The final (optional) step, `make install`, places all of the files in the required location. -To see the list of all the supported options, run - ./configure --help +To see the list of all the supported options, run `./configure --help` -Cross-compiling Options ------------------------ +## Cross-compiling Options Cross-compiling is supported the standard autotools way, you just need to specify the cross-compiling target triplet in the --host option, e.g. for cross-building for Windows 32-bit with MinGW on Debian: - ./configure --host=i686-w64-mingw32 [options] + ./configure --host=i686-w64-mingw32 [options] To make pkg-config work nicely for cross-compiling, you might need an additional wrapper script as described at - https://autotools.io/pkgconfig/cross-compiling.html + https://autotools.io/pkgconfig/cross-compiling.html This is needed to tell pkg-config where to look for the target libraries that OpenOCD depends on. Alternatively, you can specify -*_CFLAGS and *_LIBS environment variables directly, see "./configure ---help" for the details. +`*_CFLAGS` and `*_LIBS` environment variables directly, see `./configure +--help` for the details. For a more or less complete script that does all this for you, see - contrib/cross-build.sh + contrib/cross-build.sh -Parallel Port Dongles ---------------------- +## Parallel Port Dongles If you want to access the parallel port using the PPDEV interface you -have to specify both --enable-parport AND --enable-parport-ppdev, since +have to specify both `--enable-parport` and `--enable-parport-ppdev`, since the later option is an option to the parport driver. -The same is true for the --enable-parport-giveio option, you have to -use both the --enable-parport AND the --enable-parport-giveio option +The same is true for the `--enable-parport-giveio` option, you have to +use both the `--enable-parport` and the `--enable-parport-giveio` option if you want to use giveio instead of ioperm parallel port access method. -========================== -Obtaining OpenOCD From GIT -========================== +# Obtaining OpenOCD From GIT You can download the current GIT version with a GIT client of your choice from the main repository: - git://git.code.sf.net/p/openocd/code + git://git.code.sf.net/p/openocd/code You may prefer to use a mirror: - http://repo.or.cz/r/openocd.git - git://repo.or.cz/openocd.git + http://repo.or.cz/r/openocd.git + git://repo.or.cz/openocd.git Using the GIT command line client, you might use the following command to set up a local copy of the current repository (make sure there is no directory called "openocd" in the current directory): - git clone git://git.code.sf.net/p/openocd/code openocd - -Then you can update that at your convenience using + git clone git://git.code.sf.net/p/openocd/code openocd - git pull +Then you can update that at your convenience using `git pull`. There is also a gitweb interface, which you can use either to browse the repository or to download arbitrary snapshots using HTTP: - http://repo.or.cz/w/openocd.git + http://repo.or.cz/w/openocd.git Snapshots are compressed tarballs of the source tree, about 1.3 MBytes each at this writing. From fd7b66c5eb038185b72953821204ec9bb8ce49d1 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Thu, 12 Sep 2024 20:12:05 +0100 Subject: [PATCH 0953/1312] binarybuffer: Fix inverted return value in buf_cmp This is the fast path for when there is a mismatch in the leading whole bytes, which means we should return true to indicate not equal like all the other cases here and in the surrounding functions. Otherwise we'll incorrectly report _buf1 == _buf2 if and only if there are mismatches in the leading whole bytes. This was introduced during the refactor and optimisation referenced below. The only in-tree caller of this is jtag_check_value_inner, which will just fail to catch some errors. However, downstream in riscv-openocd it gets used in the riscv target to determine whether an IR scan is needed to select the debug module, and with an IRLEN >= 8 this breaks resetting if the encoding for the DMI isn't all-ones in its leading whole bytes (to match BYPASS), since it will believe they are the same and not do an IR scan, failing (with "At least one TAP shouldn't be in BYPASS mode") in the subsequent DR scan due to the TAP still being recorded as having bypass set (and really having an instruction of either BYPASS or IDCODE). Fixes: e4ee891759b0 ("improve buf_cmp and buf_cmp_mask helpers") Change-Id: Ic4f7ed094429abc4c06a775eb847a8b3ddf2e2d6 Signed-off-by: Jessica Clarke Reviewed-on: https://review.openocd.org/c/openocd/+/8489 Reviewed-by: Antonio Borneo Reviewed-by: Evgeniy Naydanov Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/helper/binarybuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 423739a9d2..c25383dc61 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -74,7 +74,7 @@ bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size) unsigned last = size / 8; if (memcmp(_buf1, _buf2, last) != 0) - return false; + return true; unsigned trailing = size % 8; if (!trailing) From b14f63e0045557118a5296e6049a3642011bf431 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 1 Aug 2024 15:48:25 -0700 Subject: [PATCH 0954/1312] aarch64: Invalidate caches on reset When a target is reset we must invalidate register caches in order to avoid showing stale register values or writing them back to registers. Use EDPRSR.SR to detect a previous reset, and EDPRSR.R to detect a current reset state. Change-Id: Ia1e97d7154cf7789d392274eee475733086a835b Signed-off-by: Peter Collingbourne Reviewed-on: https://review.openocd.org/c/openocd/+/8425 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/aarch64.c | 49 +++++++++++++++++++++++++++++++++----------- src/target/armv8.h | 2 ++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 6a70b2ddf8..f0d486f58e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -193,6 +193,20 @@ static int aarch64_mmu_modify(struct target *target, int enable) return retval; } +static int aarch64_read_prsr(struct target *target, uint32_t *prsr) +{ + struct armv8_common *armv8 = target_to_armv8(target); + int retval; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRSR, prsr); + if (retval != ERROR_OK) + return retval; + + armv8->sticky_reset |= *prsr & PRSR_SR; + return ERROR_OK; +} + /* * Basic debug access, very low level assumes state is saved */ @@ -213,8 +227,7 @@ static int aarch64_init_debug_access(struct target *target) /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &dummy); + retval = aarch64_read_prsr(target, &dummy); if (retval != ERROR_OK) return retval; @@ -281,12 +294,10 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, static int aarch64_check_state_one(struct target *target, uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr) { - struct armv8_common *armv8 = target_to_armv8(target); uint32_t prsr; int retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &prsr); + retval = aarch64_read_prsr(target, &prsr); if (retval != ERROR_OK) return retval; @@ -506,16 +517,28 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug static int aarch64_poll(struct target *target) { + struct armv8_common *armv8 = target_to_armv8(target); enum target_state prev_target_state; int retval = ERROR_OK; - int halted; + uint32_t prsr; - retval = aarch64_check_state_one(target, - PRSR_HALT, PRSR_HALT, &halted, NULL); + retval = aarch64_read_prsr(target, &prsr); if (retval != ERROR_OK) return retval; - if (halted) { + if (armv8->sticky_reset) { + armv8->sticky_reset = false; + if (target->state != TARGET_RESET) { + target->state = TARGET_RESET; + LOG_TARGET_INFO(target, "external reset detected"); + if (armv8->arm.core_cache) { + register_cache_invalidate(armv8->arm.core_cache); + register_cache_invalidate(armv8->arm.core_cache->next); + } + } + } + + if (prsr & PRSR_HALT) { prev_target_state = target->state; if (prev_target_state != TARGET_HALTED) { enum target_debug_reason debug_reason = target->debug_reason; @@ -546,8 +569,11 @@ static int aarch64_poll(struct target *target) break; } } - } else + } else if (prsr & PRSR_RESET) { + target->state = TARGET_RESET; + } else { target->state = TARGET_RUNNING; + } return retval; } @@ -663,8 +689,7 @@ static int aarch64_prepare_restart_one(struct target *target) if (retval == ERROR_OK) { /* clear sticky bits in PRSR, SDR is now 0 */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &tmp); + retval = aarch64_read_prsr(target, &tmp); } return retval; diff --git a/src/target/armv8.h b/src/target/armv8.h index f5aa211097..156b5f8bbd 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -213,6 +213,8 @@ struct armv8_common { /* True if OpenOCD provides pointer auth related info to GDB */ bool enable_pauth; + bool sticky_reset; + /* last run-control command issued to this target (resume, halt, step) */ enum run_control_op last_run_control_op; From 5159c599157cc878521ae64e836675f7939c6a09 Mon Sep 17 00:00:00 2001 From: daniellizewski Date: Thu, 21 Mar 2024 09:58:34 -0400 Subject: [PATCH 0955/1312] src/rtos/rtos_nuttx_stackings.c: Fix stack alignment for cortex-m targets Backtraces performed by GDB on any thread other than the current thread would fail if hardware 8 byte ISR stack alignment was enabled on cortex_m targets. Stack reads now adjust the stored SP to account for a potential offset introduced by hardware. Fixed incorrect register offsets for cortex_m Nuttx frames by reading the TCB info symbols to determine correct offsets. Fixed offsets can no longer be used since the offsets have changed multiple times for different Nuttx versions. Tested on nuttx-12.1.0. Tested using custom stm32h7 board and custom s32k148 board variants. Built with CONFIG_ARCH_FPU enabled and disabled to test FPU and non FPU frame logic. Change-Id: Ifcbeefb0ddcfbcb528daa9d1d95732ca9584c9ef Signed-off-by: daniellizewski Reviewed-on: https://review.openocd.org/c/openocd/+/8180 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/rtos/nuttx.c | 54 ++----------- src/rtos/rtos_nuttx_stackings.c | 134 +++++++++++++++++++++----------- src/rtos/rtos_nuttx_stackings.h | 9 +++ 3 files changed, 104 insertions(+), 93 deletions(-) diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 9100148895..821e550885 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -32,7 +32,6 @@ struct nuttx_params { const char *target_name; const struct rtos_register_stacking *stacking; - const struct rtos_register_stacking *(*select_stackinfo)(struct target *target); }; /* @@ -56,19 +55,12 @@ struct symbols { bool optional; }; -/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */ -enum nuttx_symbol_vals { - NX_SYM_READYTORUN = 0, - NX_SYM_PIDHASH, - NX_SYM_NPIDHASH, - NX_SYM_TCB_INFO, -}; - static const struct symbols nuttx_symbol_list[] = { { "g_readytorun", false }, { "g_pidhash", false }, { "g_npidhash", false }, { "g_tcbinfo", false }, + { "g_reg_offs", false}, { NULL, false } }; @@ -86,18 +78,14 @@ static char *task_state_str[] = { "STOPPED", }; -static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target); - static const struct nuttx_params nuttx_params_list[] = { { .target_name = "cortex_m", - .stacking = NULL, - .select_stackinfo = cortexm_select_stackinfo, + .stacking = &nuttx_stacking_cortex_m, }, { .target_name = "hla_target", - .stacking = NULL, - .select_stackinfo = cortexm_select_stackinfo, + .stacking = &nuttx_stacking_cortex_m, }, { .target_name = "esp32", @@ -117,28 +105,6 @@ static const struct nuttx_params nuttx_params_list[] = { }, }; -static bool cortexm_hasfpu(struct target *target) -{ - uint32_t cpacr; - struct armv7m_common *armv7m_target = target_to_armv7m(target); - - if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE) - return false; - - int retval = target_read_u32(target, FPU_CPACR, &cpacr); - if (retval != ERROR_OK) { - LOG_ERROR("Could not read CPACR register to check FPU state"); - return false; - } - - return cpacr & 0x00F00000; -} - -static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target) -{ - return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m; -} - static bool nuttx_detect_rtos(struct target *target) { if (target->rtos->symbols && @@ -371,29 +337,25 @@ static int nuttx_getreg_current_thread(struct rtos *rtos, static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs) { - uint16_t xcpreg_off; + uint16_t regs_off; uint32_t regsaddr; const struct nuttx_params *priv = rtos->rtos_specific_params; const struct rtos_register_stacking *stacking = priv->stacking; if (!stacking) { - if (priv->select_stackinfo) { - stacking = priv->select_stackinfo(rtos->target); - } else { - LOG_ERROR("Can't find a way to get stacking info"); - return ERROR_FAIL; - } + LOG_ERROR("Can't find a way to get stacking info"); + return ERROR_FAIL; } int ret = target_read_u16(rtos->target, rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off), - &xcpreg_off); + ®s_off); if (ret != ERROR_OK) { LOG_ERROR("Failed to read registers' offset: ret = %d", ret); return ERROR_FAIL; } - ret = target_read_u32(rtos->target, thread_id + xcpreg_off, ®saddr); + ret = target_read_u32(rtos->target, thread_id + regs_off, ®saddr); if (ret != ERROR_OK) { LOG_ERROR("Failed to read registers' address: ret = %d", ret); return ERROR_FAIL; diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c index b70cccb33a..6faa56a668 100644 --- a/src/rtos/rtos_nuttx_stackings.c +++ b/src/rtos/rtos_nuttx_stackings.c @@ -9,60 +9,100 @@ #include "rtos_nuttx_stackings.h" #include "rtos_standard_stackings.h" #include +#include -/* see arch/arm/include/armv7-m/irq_cmnvector.h */ +/* The cortex_m target uses nuttx_tcbinfo_stack_read which uses a symbol + * provided by Nuttx to read the registers from memory and place them directly + * in the order we need. This is because the register offsets change with + * different versions of Nuttx, FPU vs non-FPU and ARMv7 vs ARMv8. + * This allows a single function to work with many versions. + */ static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { - { ARMV7M_R0, 0x28, 32 }, /* r0 */ - { ARMV7M_R1, 0x2c, 32 }, /* r1 */ - { ARMV7M_R2, 0x30, 32 }, /* r2 */ - { ARMV7M_R3, 0x34, 32 }, /* r3 */ - { ARMV7M_R4, 0x08, 32 }, /* r4 */ - { ARMV7M_R5, 0x0c, 32 }, /* r5 */ - { ARMV7M_R6, 0x10, 32 }, /* r6 */ - { ARMV7M_R7, 0x14, 32 }, /* r7 */ - { ARMV7M_R8, 0x18, 32 }, /* r8 */ - { ARMV7M_R9, 0x1c, 32 }, /* r9 */ - { ARMV7M_R10, 0x20, 32 }, /* r10 */ - { ARMV7M_R11, 0x24, 32 }, /* r11 */ - { ARMV7M_R12, 0x38, 32 }, /* r12 */ - { ARMV7M_R13, 0, 32 }, /* sp */ - { ARMV7M_R14, 0x3c, 32 }, /* lr */ - { ARMV7M_PC, 0x40, 32 }, /* pc */ - { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */ + { ARMV7M_R0, 0, 32 }, /* r0 */ + { ARMV7M_R1, 4, 32 }, /* r1 */ + { ARMV7M_R2, 8, 32 }, /* r2 */ + { ARMV7M_R3, 12, 32 }, /* r3 */ + { ARMV7M_R4, 16, 32 }, /* r4 */ + { ARMV7M_R5, 20, 32 }, /* r5 */ + { ARMV7M_R6, 24, 32 }, /* r6 */ + { ARMV7M_R7, 28, 32 }, /* r7 */ + { ARMV7M_R8, 32, 32 }, /* r8 */ + { ARMV7M_R9, 36, 32 }, /* r9 */ + { ARMV7M_R10, 40, 32 }, /* r10 */ + { ARMV7M_R11, 44, 32 }, /* r11 */ + { ARMV7M_R12, 48, 32 }, /* r12 */ + { ARMV7M_R13, 52, 32 }, /* sp */ + { ARMV7M_R14, 56, 32 }, /* lr */ + { ARMV7M_PC, 60, 32 }, /* pc */ + { ARMV7M_XPSR, 64, 32 }, /* xPSR */ }; -const struct rtos_register_stacking nuttx_stacking_cortex_m = { - .stack_registers_size = 0x48, - .stack_growth_direction = -1, - .num_output_registers = 17, - .register_offsets = nuttx_stack_offsets_cortex_m, -}; +/* The Nuttx stack frame for most architectures has some registers placed + * by hardware and some by software. The hardware register order and number does not change + * but the software registers may change with different versions of Nuttx. + * For example with ARMv7, nuttx-12.3.0 added a new register which changed all + * the offsets. We can either create separate offset tables for each version of Nuttx + * which will break again in the future, or read the offsets from the TCB info. + * Nuttx provides a symbol (g_reg_offs) which holds all the offsets for each stored register. + * This offset table is stored in GDB org.gnu.gdb.xxx feature order. + * The same order we need. + * Please refer: + * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html + * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features.html + */ +static int nuttx_cortex_m_tcbinfo_stack_read(struct target *target, + int64_t stack_ptr, const struct rtos_register_stacking *stacking, + uint8_t *stack_data) +{ + struct rtos *rtos = target->rtos; + target_addr_t xcpreg_off = rtos->symbols[NX_SYM_REG_OFFSETS].address; -static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { - { ARMV7M_R0, 0x6c, 32 }, /* r0 */ - { ARMV7M_R1, 0x70, 32 }, /* r1 */ - { ARMV7M_R2, 0x74, 32 }, /* r2 */ - { ARMV7M_R3, 0x78, 32 }, /* r3 */ - { ARMV7M_R4, 0x08, 32 }, /* r4 */ - { ARMV7M_R5, 0x0c, 32 }, /* r5 */ - { ARMV7M_R6, 0x10, 32 }, /* r6 */ - { ARMV7M_R7, 0x14, 32 }, /* r7 */ - { ARMV7M_R8, 0x18, 32 }, /* r8 */ - { ARMV7M_R9, 0x1c, 32 }, /* r9 */ - { ARMV7M_R10, 0x20, 32 }, /* r10 */ - { ARMV7M_R11, 0x24, 32 }, /* r11 */ - { ARMV7M_R12, 0x7c, 32 }, /* r12 */ - { ARMV7M_R13, 0, 32 }, /* sp */ - { ARMV7M_R14, 0x80, 32 }, /* lr */ - { ARMV7M_PC, 0x84, 32 }, /* pc */ - { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */ -}; + for (int i = 0; i < stacking->num_output_registers; ++i) { + uint16_t stack_reg_offset; + int ret = target_read_u16(rtos->target, xcpreg_off + 2 * i, &stack_reg_offset); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read stack_reg_offset: ret = %d", ret); + return ret; + } + if (stack_reg_offset != UINT16_MAX && stacking->register_offsets[i].offset >= 0) { + ret = target_read_buffer(target, + stack_ptr + stack_reg_offset, + stacking->register_offsets[i].width_bits / 8, + &stack_data[stacking->register_offsets[i].offset]); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read register: ret = %d", ret); + return ret; + } + } + } + + /* Offset match nuttx_stack_offsets_cortex_m */ + const int XPSR_OFFSET = 64; + const int SP_OFFSET = 52; + /* Nuttx stack frames (produced in exception_common) store the SP of the ISR minus + * the hardware stack frame size. This SP may include an additional 4 byte alignment + * depending in xPSR[9]. The Nuttx stack frame stores post alignment since the + * hardware will add/remove automatically on both enter/exit. + * We need to adjust the SP to get the real SP of the stack. + * See Arm Reference manual "Stack alignment on exception entry" + */ + uint32_t xpsr = target_buffer_get_u32(target, &stack_data[XPSR_OFFSET]); + if (xpsr & BIT(9)) { + uint32_t sp = target_buffer_get_u32(target, &stack_data[SP_OFFSET]); + target_buffer_set_u32(target, &stack_data[SP_OFFSET], sp - 4 * stacking->stack_growth_direction); + } -const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = { - .stack_registers_size = 0x8c, + return ERROR_OK; +} + +const struct rtos_register_stacking nuttx_stacking_cortex_m = { + /* nuttx_tcbinfo_stack_read transforms the stack into just output registers */ + .stack_registers_size = ARRAY_SIZE(nuttx_stack_offsets_cortex_m) * 4, .stack_growth_direction = -1, - .num_output_registers = 17, - .register_offsets = nuttx_stack_offsets_cortex_m_fpu, + .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_cortex_m), + .read_stack = nuttx_cortex_m_tcbinfo_stack_read, + .calculate_process_stack = NULL, /* Stack alignment done in nuttx_cortex_m_tcbinfo_stack_read */ + .register_offsets = nuttx_stack_offsets_cortex_m, }; static const struct stack_register_offset nuttx_stack_offsets_riscv[] = { diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h index 213a060336..5d55e75458 100644 --- a/src/rtos/rtos_nuttx_stackings.h +++ b/src/rtos/rtos_nuttx_stackings.h @@ -5,6 +5,15 @@ #include "rtos.h" +/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */ +enum nuttx_symbol_vals { + NX_SYM_READYTORUN = 0, + NX_SYM_PIDHASH, + NX_SYM_NPIDHASH, + NX_SYM_TCB_INFO, + NX_SYM_REG_OFFSETS, +}; + extern const struct rtos_register_stacking nuttx_stacking_cortex_m; extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu; extern const struct rtos_register_stacking nuttx_riscv_stacking; From 1ae6b07b45198618c3f0975fd49de59cf6c04e7a Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Fri, 13 Sep 2024 18:10:48 +0100 Subject: [PATCH 0956/1312] binarybuffer: Invert buf_cmp* return value and rename to buf_eq* The current semantics are a bit confusing, as the return value looks like memcmp (0/false being equal) but the bool return type means one likely expects true to mean equal. Make this clearer by switching them out for buf_eq* functions that do that instead. Checkpatch-ignore: UNSPECIFIED_INT Change-Id: Iee0c5af794316aab5327cb9c168051fabd3bc1cb Signed-off-by: Jessica Clarke Reviewed-on: https://review.openocd.org/c/openocd/+/8490 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov Reviewed-by: Antonio Borneo --- src/helper/binarybuffer.c | 30 +++++++++++++++--------------- src/helper/binarybuffer.h | 4 ++-- src/jtag/core.c | 4 ++-- src/svf/svf.c | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index c25383dc61..a7ca5af9df 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -57,49 +57,49 @@ void *buf_cpy(const void *from, void *_to, unsigned size) return _to; } -static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m) +static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m) { - return (a & m) != (b & m); + return (a & m) == (b & m); } -static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) +static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) { uint8_t mask = (1 << trailing) - 1; - return buf_cmp_masked(a, b, mask & m); + return buf_eq_masked(a, b, mask & m); } -bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size) +bool buf_eq(const void *_buf1, const void *_buf2, unsigned size) { if (!_buf1 || !_buf2) - return _buf1 != _buf2; + return _buf1 == _buf2; unsigned last = size / 8; if (memcmp(_buf1, _buf2, last) != 0) - return true; + return false; unsigned trailing = size % 8; if (!trailing) - return false; + return true; const uint8_t *buf1 = _buf1, *buf2 = _buf2; - return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing); + return buf_eq_trailing(buf1[last], buf2[last], 0xff, trailing); } -bool buf_cmp_mask(const void *_buf1, const void *_buf2, +bool buf_eq_mask(const void *_buf1, const void *_buf2, const void *_mask, unsigned size) { if (!_buf1 || !_buf2) - return _buf1 != _buf2 || _buf1 != _mask; + return _buf1 == _buf2 && _buf1 == _mask; const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask; unsigned last = size / 8; for (unsigned i = 0; i < last; i++) { - if (buf_cmp_masked(buf1[i], buf2[i], mask[i])) - return true; + if (!buf_eq_masked(buf1[i], buf2[i], mask[i])) + return false; } unsigned trailing = size % 8; if (!trailing) - return false; - return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing); + return true; + return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing); } void *buf_set_ones(void *_buf, unsigned size) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index df4199837f..ed13b980f1 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -172,8 +172,8 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer, */ uint32_t flip_u32(uint32_t value, unsigned width); -bool buf_cmp(const void *buf1, const void *buf2, unsigned size); -bool buf_cmp_mask(const void *buf1, const void *buf2, +bool buf_eq(const void *buf1, const void *buf2, unsigned size); +bool buf_eq_mask(const void *buf1, const void *buf2, const void *mask, unsigned size); /** diff --git a/src/jtag/core.c b/src/jtag/core.c index 9eae5e74ba..a6f38a19dd 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -881,9 +881,9 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, int compare_failed; if (in_check_mask) - compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); + compare_failed = !buf_eq_mask(captured, in_check_value, in_check_mask, num_bits); else - compare_failed = buf_cmp(captured, in_check_value, num_bits); + compare_failed = !buf_eq(captured, in_check_value, num_bits); if (compare_failed) { char *captured_str, *in_check_value_str; diff --git a/src/svf/svf.c b/src/svf/svf.c index dd3d5175c3..470889948c 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -932,7 +932,7 @@ static int svf_check_tdo(void) index_var = svf_check_tdo_para[i].buffer_offset; len = svf_check_tdo_para[i].bit_len; if ((svf_check_tdo_para[i].enabled) - && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], + && !buf_eq_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len)) { LOG_ERROR("tdo check error at line %d", svf_check_tdo_para[i].line_num); From e6ade35305fa32674d615a26713487b5ad00b352 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Thu, 12 Sep 2024 15:16:45 +0300 Subject: [PATCH 0957/1312] server/gdb_server: improve error handling for `Z/z` packet * Report errors for `z` packet. * Report not supported types as required by GDB Remote Protocol's documentation: > Implementation notes: A remote target shall return an empty string for an unrecognized breakpoint or watchpoint packet type. Link: https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html#insert-breakpoint-or-watchpoint-packet Change-Id: I9130400aca5dbc54fefb413ed74f27d75fe50640 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8488 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 2db3123a04..854c4dc65d 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1781,18 +1781,9 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, case 1: if (packet[0] == 'Z') { retval = breakpoint_add(target, address, size, bp_type); - if (retval == ERROR_NOT_IMPLEMENTED) { - /* Send empty reply to report that breakpoints of this type are not supported */ - gdb_put_packet(connection, "", 0); - } else if (retval != ERROR_OK) { - retval = gdb_error(connection, retval); - if (retval != ERROR_OK) - return retval; - } else - gdb_put_packet(connection, "OK", 2); } else { - breakpoint_remove(target, address); - gdb_put_packet(connection, "OK", 2); + assert(packet[0] == 'z'); + retval = breakpoint_remove(target, address); } break; case 2: @@ -1801,26 +1792,26 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, { if (packet[0] == 'Z') { retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK); - if (retval == ERROR_NOT_IMPLEMENTED) { - /* Send empty reply to report that watchpoints of this type are not supported */ - gdb_put_packet(connection, "", 0); - } else if (retval != ERROR_OK) { - retval = gdb_error(connection, retval); - if (retval != ERROR_OK) - return retval; - } else - gdb_put_packet(connection, "OK", 2); } else { - watchpoint_remove(target, address); - gdb_put_packet(connection, "OK", 2); + assert(packet[0] == 'z'); + retval = watchpoint_remove(target, address); } break; } default: + { + retval = ERROR_NOT_IMPLEMENTED; break; + } } - return ERROR_OK; + if (retval == ERROR_NOT_IMPLEMENTED) { + /* Send empty reply to report that watchpoints of this type are not supported */ + return gdb_put_packet(connection, "", 0); + } + if (retval != ERROR_OK) + return gdb_error(connection, retval); + return gdb_put_packet(connection, "OK", 2); } /* print out a string and allocate more space as needed, From ad216136180e0cd482f414eb072c9dd25dd1c559 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 24 Jun 2024 16:26:02 +0200 Subject: [PATCH 0958/1312] server/telnet: Restructure commands Use a command group 'telnet' with subcommands instead of individual commands with 'telnet_' prefix. Even though there is only one subcommand at the moment, make this change to ensure consistency with other commands. The old command is still available to ensure backwards compatibility, but are marked as deprecated. Change-Id: I5e88632fa0d0ce5a8129e9fcf5ae743fc5b093cb Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8378 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 2 +- src/server/startup.tcl | 6 ++++++ src/server/telnet_server.c | 24 +++++++++++++++++------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index e8a1f33b5f..97396c7b70 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2227,7 +2227,7 @@ the port @var{number} defaults to 6666. When specified as "disabled", this service is not activated. @end deffn -@deffn {Config Command} {telnet_port} [number] +@deffn {Config Command} {telnet port} [number] Specify or query the port on which to listen for incoming telnet connections. This port is intended for interaction with one human through TCL commands. diff --git a/src/server/startup.tcl b/src/server/startup.tcl index ebfb0562e9..cf3eca36e6 100644 --- a/src/server/startup.tcl +++ b/src/server/startup.tcl @@ -113,3 +113,9 @@ proc "tcl_trace" {state} { echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'" eval tcl trace $state } + +lappend _telnet_autocomplete_skip "telnet_port" +proc "telnet_port" {args} { + echo "DEPRECATED! use 'telnet port', not 'telnet_port'" + eval telnet port $args +} diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 02d450fbdf..a596afef08 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -967,7 +967,6 @@ int telnet_init(char *banner) return ERROR_OK; } -/* daemon configuration command telnet_port */ COMMAND_HANDLER(handle_telnet_port_command) { return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port); @@ -978,6 +977,19 @@ COMMAND_HANDLER(handle_exit_command) return ERROR_COMMAND_CLOSE_CONNECTION; } +static const struct command_registration telnet_subcommand_handlers[] = { + { + .name = "port", + .handler = handle_telnet_port_command, + .mode = COMMAND_CONFIG, + .help = "Specify port on which to listen " + "for incoming telnet connections. " + "Read help on 'gdb port'.", + .usage = "[port_num]", + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration telnet_command_handlers[] = { { .name = "exit", @@ -987,13 +999,11 @@ static const struct command_registration telnet_command_handlers[] = { .help = "exit telnet session", }, { - .name = "telnet_port", - .handler = handle_telnet_port_command, + .name = "telnet", + .chain = telnet_subcommand_handlers, .mode = COMMAND_CONFIG, - .help = "Specify port on which to listen " - "for incoming telnet connections. " - "Read help on 'gdb port'.", - .usage = "[port_num]", + .help = "telnet commands", + .usage = "", }, COMMAND_REGISTRATION_DONE }; From 1173473f662bbdf6d1499654568256257eee6cdd Mon Sep 17 00:00:00 2001 From: Matt Trescott Date: Wed, 10 Jul 2024 14:46:28 -0400 Subject: [PATCH 0959/1312] flash/nor/atsame5: add PIC32CX-SG device IDs These devices are essentially the same as the E54 series with the exception of immutable boot (SG41, SG61) and HSM (SG60, SG61), and some bug fixes found only in E54 revision F. When the security features are not enabled, they behave identically except for the different DIDs. Signed-off-by: Matt Trescott Change-Id: Ic93313f3e20af0ed4a5768880d17b335a7b7bb04 Reviewed-on: https://review.openocd.org/c/openocd/+/8355 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/atsame5.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index c590081fcc..a6ac9060a3 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -85,6 +85,9 @@ #define SAME_SERIES_51 0x01 #define SAME_SERIES_53 0x03 #define SAME_SERIES_54 0x04 +#define PIC32CXSG_SERIES_41 0x07 +#define PIC32CXSG_SERIES_60 0x00 +#define PIC32CXSG_SERIES_61 0x02 /* Device ID macros */ #define SAMD_GET_PROCESSOR(id) (id >> 28) @@ -148,6 +151,27 @@ static const struct samd_part same54_parts[] = { { 0x03, "SAME54N19A", 512, 192 }, }; +/* See PIC32CX SG41/SG60/SG61 Family Silicon Errata and Datasheet Clarifications + * DS80000985G */ +/* Known PIC32CX-SG41 parts. */ +static const struct samd_part pic32cxsg41_parts[] = { + { 0x00, "PIC32CX1025SG41128", 1024, 256 }, + { 0x01, "PIC32CX1025SG41100", 1024, 256 }, + { 0x02, "PIC32CX1025SG41064", 1024, 256 }, +}; + +/* Known PIC32CX-SG60 parts. */ +static const struct samd_part pic32cxsg60_parts[] = { + { 0x00, "PIC32CX1025SG60128", 1024, 256 }, + { 0x01, "PIC32CX1025SG60100", 1024, 256 }, +}; + +/* Known PIC32CX-SG61 parts. */ +static const struct samd_part pic32cxsg61_parts[] = { + { 0x00, "PIC32CX1025SG61128", 1024, 256 }, + { 0x01, "PIC32CX1025SG61100", 1024, 256 }, +}; + /* Each family of parts contains a parts table in the DEVSEL field of DID. The * processor ID, family ID, and series ID are used to determine which exact * family this is and then we can use the corresponding table. */ @@ -169,6 +193,12 @@ static const struct samd_family samd_families[] = { same53_parts, ARRAY_SIZE(same53_parts) }, { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54, same54_parts, ARRAY_SIZE(same54_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_41, + pic32cxsg41_parts, ARRAY_SIZE(pic32cxsg41_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_60, + pic32cxsg60_parts, ARRAY_SIZE(pic32cxsg60_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_61, + pic32cxsg61_parts, ARRAY_SIZE(pic32cxsg61_parts) }, }; struct samd_info { From 8edfdb02ed1fd73568ef9e9522634e65791dbd69 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 1 Sep 2024 14:45:36 +0200 Subject: [PATCH 0960/1312] rtos: chibios: fix version display The field 'struct chibios_chdebug::ch_version' is 16 bits wide, so using le_to_h_u32() and be_to_h_u32() overflows in the following fields of the struct. Restrict the endianness conversion to 16 bits and use the target endianness dependent target_buffer_get_u16(). Convert the 'struct chibios_chdebug::ch_version' to an array of uint8_t. Change-Id: Iaa80e9cb1a65c27512919398b8ffbf14e5c240cd Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8473 Tested-by: jenkins --- src/rtos/chibios.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c index c1e4e84192..f4ee33a490 100644 --- a/src/rtos/chibios.c +++ b/src/rtos/chibios.c @@ -31,7 +31,7 @@ struct chibios_chdebug { char ch_identifier[4]; /**< @brief Always set to "main". */ uint8_t ch_zero; /**< @brief Must be zero. */ uint8_t ch_size; /**< @brief Size of this structure. */ - uint16_t ch_version; /**< @brief Encoded ChibiOS/RT version. */ + uint8_t ch_version[2]; /**< @brief Encoded ChibiOS/RT version. */ uint8_t ch_ptrsize; /**< @brief Size of a pointer. */ uint8_t ch_timesize; /**< @brief Size of a @p systime_t. */ uint8_t ch_threadsize; /**< @brief Size of a @p Thread struct. */ @@ -171,13 +171,7 @@ static int chibios_update_memory_signature(struct rtos *rtos) " expected. Assuming compatibility..."); } - /* Convert endianness of version field */ - const uint8_t *versiontarget = (const uint8_t *) - &signature->ch_version; - signature->ch_version = rtos->target->endianness == TARGET_LITTLE_ENDIAN ? - le_to_h_u32(versiontarget) : be_to_h_u32(versiontarget); - - const uint16_t ch_version = signature->ch_version; + const uint16_t ch_version = target_buffer_get_u16(rtos->target, signature->ch_version); LOG_INFO("Successfully loaded memory map of ChibiOS/RT target " "running version %i.%i.%i", GET_CH_KERNEL_MAJOR(ch_version), GET_CH_KERNEL_MINOR(ch_version), GET_CH_KERNEL_PATCH(ch_version)); From 017e61feb44b71ac013ae4c7f2cfa3e7ca3323ae Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 2 Apr 2023 20:47:41 +0200 Subject: [PATCH 0961/1312] HACKING: add info on ignoring check-patch checks Due to checkpatch internal state machine, the field 'Checkpatch-ignore:' must be in the commit message before the 'Signed-off-by:' line. Report it in the documentation and add that multiple 'Checkpatch-ignore:' lines are allowed. Change-Id: I770cdc4cb5b33bcf63c860c154ab3cbd4785ad20 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/7572 Tested-by: jenkins --- HACKING | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/HACKING b/HACKING index 74cbe02e74..9e8cd357ff 100644 --- a/HACKING +++ b/HACKING @@ -287,6 +287,13 @@ Only for exceptional cases, it is allowed to submit patches to Gerrit with the special field 'Checkpatch-ignore:' in the commit message. This field will cause checkpatch to ignore the error types listed in the field, only for the patch itself. +For errors in the commit message, the special field has to be put in +the commit message before the line that produces the error. +The special field must be added before the 'Signed-off-by:' +line, otherwise it is ignored. +To ignore multiple errors, either add multiple lines with the special +field or add multiple error types, separated by space or commas, in a +single line. The error type is printed by checkpatch on failure. For example the names of Windows APIs mix lower and upper case chars, in violation of OpenOCD coding style, triggering a 'CAMELCASE' error: From bd93b83f1b0625cc8c70aae46a1b0d13c41c53dc Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Tue, 10 Sep 2024 06:53:17 +0300 Subject: [PATCH 0962/1312] jtag: update constant names to follow code style guidelines Change-Id: Ib081433c67f3be0e5be0b39469680bcce079e0cc Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8485 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/cmsis_dap.c | 8 ++++---- src/jtag/drivers/jtag_vpi.c | 4 ++-- src/jtag/drivers/xds110.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index a6dcfcd3d2..4ba6b51bea 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -563,7 +563,7 @@ static int cmsis_dap_cmd_dap_delay(uint16_t delay_us) static int cmsis_dap_metacmd_targetsel(uint32_t instance_id) { uint8_t *command = cmsis_dap_handle->command; - const uint32_t SEQ_RD = 0x80, SEQ_WR = 0x00; + const uint32_t seq_rd = 0x80, seq_wr = 0x00; /* SWD multi-drop requires a transfer ala CMD_DAP_TFER, but with no expectation of an SWD ACK response. In @@ -579,14 +579,14 @@ static int cmsis_dap_metacmd_targetsel(uint32_t instance_id) command[idx++] = 3; /* sequence count */ /* sequence 0: packet request for TARGETSEL */ - command[idx++] = SEQ_WR | 8; + command[idx++] = seq_wr | 8; command[idx++] = SWD_CMD_START | swd_cmd(false, false, DP_TARGETSEL) | SWD_CMD_STOP | SWD_CMD_PARK; /* sequence 1: read Trn ACK Trn, no expectation for target to ACK */ - command[idx++] = SEQ_RD | 5; + command[idx++] = seq_rd | 5; /* sequence 2: WDATA plus parity */ - command[idx++] = SEQ_WR | (32 + 1); + command[idx++] = seq_wr | (32 + 1); h_u32_to_le(command + idx, instance_id); idx += 4; command[idx++] = parity_u32(instance_id); diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index a19060c2aa..15b2679bba 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -461,14 +461,14 @@ static int jtag_vpi_stableclocks(unsigned int num_cycles) unsigned int cycles_remain = num_cycles; int nb_bits; int retval; - const unsigned int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8; + const unsigned int cycles_one_batch = sizeof(tms_bits) * 8; /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */ memset(&tms_bits, (tap_get_state() == TAP_RESET) ? 0xff : 0x00, sizeof(tms_bits)); /* send the TMS bits */ while (cycles_remain > 0) { - nb_bits = (cycles_remain < CYCLES_ONE_BATCH) ? cycles_remain : CYCLES_ONE_BATCH; + nb_bits = (cycles_remain < cycles_one_batch) ? cycles_remain : cycles_one_batch; retval = jtag_vpi_tms_seq(tms_bits, nb_bits); if (retval != ERROR_OK) return retval; diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index f252087744..6e12b9a790 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -1887,7 +1887,7 @@ static int xds110_speed(int speed) } else { - const double XDS110_TCK_PULSE_INCREMENT = 66.0; + const double xds110_tck_pulse_increment = 66.0; freq_to_use = speed * 1000; /* Hz */ delay_count = 0; @@ -1908,7 +1908,7 @@ static int xds110_speed(int speed) double current_value = max_freq_pulse_duration; while (current_value < freq_to_pulse_width_in_ns) { - current_value += XDS110_TCK_PULSE_INCREMENT; + current_value += xds110_tck_pulse_increment; ++delay_count; } @@ -1919,9 +1919,9 @@ static int xds110_speed(int speed) if (delay_count) { double diff_freq_1 = freq_to_use - (one_giga / (max_freq_pulse_duration + - (XDS110_TCK_PULSE_INCREMENT * delay_count))); + (xds110_tck_pulse_increment * delay_count))); double diff_freq_2 = (one_giga / (max_freq_pulse_duration + - (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) - + (xds110_tck_pulse_increment * (delay_count - 1)))) - freq_to_use; /* One less count value yields a better match */ From ab3156213108138f9130defdfde7276d1e4e6afb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 21 Sep 2024 10:07:52 +0200 Subject: [PATCH 0963/1312] jep106: update to revision JEP106BK Sep 2024 Change-Id: Ica84e22b8d2da152cec39fc569c8333677c19490 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8501 Tested-by: jenkins --- src/helper/jep106.inc | 67 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index b74cda85fe..53d0355c18 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -8,7 +8,7 @@ * identification code list, please visit the JEDEC website at www.jedec.org . */ -/* This file is aligned to revision JEP106BJ.01 July 2024. */ +/* This file is aligned to revision JEP106BK September 2024. */ [0][0x01 - 1] = "AMD", [0][0x02 - 1] = "AMI", @@ -177,7 +177,7 @@ [1][0x27 - 1] = "Cabletron", [1][0x28 - 1] = "STEC (Silicon Tech)", [1][0x29 - 1] = "Vanguard", -[1][0x2a - 1] = "Hagiwara Sys-Com", +[1][0x2a - 1] = "Hagiwara Solutions Co Ltd", [1][0x2b - 1] = "Vantis", [1][0x2c - 1] = "Celestica", [1][0x2d - 1] = "Century", @@ -1373,7 +1373,7 @@ [10][0x65 - 1] = "Esperanto Technologies", [10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd", [10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology", -[10][0x68 - 1] = "Shanghai Rui Zuan Information Tech", +[10][0x68 - 1] = "Shanghai Rui Xuan Information Tech", [10][0x69 - 1] = "Fraunhofer IIS", [10][0x6a - 1] = "Kandou Bus SA", [10][0x6b - 1] = "Acer", @@ -1653,9 +1653,9 @@ [13][0x03 - 1] = "Shenzhen Feisrike Technology Co Ltd", [13][0x04 - 1] = "Shenzhen Sunhome Electronics Co Ltd", [13][0x05 - 1] = "Global Mixed-mode Technology Inc", -[13][0x06 - 1] = "Shenzhen Weien Electronics Co. Ltd.", +[13][0x06 - 1] = "Shenzhen Weien Electronics Co Ltd.", [13][0x07 - 1] = "Shenzhen Cooyes Technology Co Ltd", -[13][0x08 - 1] = "Keymos Electronics Co., Limited", +[13][0x08 - 1] = "ShenZhen ChaoYing ZhiNeng Technology", [13][0x09 - 1] = "E-Rockic Technology Company Limited", [13][0x0a - 1] = "Aerospace Science Memory Shenzhen", [13][0x0b - 1] = "Shenzhen Quanji Technology Co Ltd", @@ -1898,7 +1898,7 @@ [14][0x7a - 1] = "Cornelis Networks Inc", [14][0x7b - 1] = "WingSemi Technologies Co Ltd", [14][0x7c - 1] = "ForwardEdge ASIC", -[14][0x7d - 1] = "Beijing Future Imprint Technology Co Ltd", +[14][0x7d - 1] = "Beijing Future Signet Technology Co Ltd", [14][0x7e - 1] = "Fine Made Microelectronics Group Co Ltd", [15][0x01 - 1] = "Changxin Memory Technology (Shanghai)", [15][0x02 - 1] = "Synconv", @@ -1919,7 +1919,7 @@ [15][0x11 - 1] = "Guangzhou Beimu Technology Co., Ltd", [15][0x12 - 1] = "Rays Semiconductor Nanjing Co Ltd", [15][0x13 - 1] = "Milli-Centi Intelligence Technology Jiangsu", -[15][0x14 - 1] = "Zilia Technologioes", +[15][0x14 - 1] = "Zilia Technologies", [15][0x15 - 1] = "Incore Semiconductors", [15][0x16 - 1] = "Kinetic Technologies", [15][0x17 - 1] = "Nanjing Houmo Technology Co Ltd", @@ -1963,4 +1963,57 @@ [15][0x3d - 1] = "Shenzhen Titan Micro Electronics Co Ltd", [15][0x3e - 1] = "Shenzhen Macroflash Technology Co Ltd", [15][0x3f - 1] = "Advantech Group", +[15][0x40 - 1] = "Shenzhen Xingjiachen Electronics Co Ltd", +[15][0x41 - 1] = "CHUQI", +[15][0x42 - 1] = "Dongguan Liesun Trading Co Ltd", +[15][0x43 - 1] = "Shenzhen Miuman Technology Co Ltd", +[15][0x44 - 1] = "Shenzhen Techwinsemi Technology Twsc", +[15][0x45 - 1] = "Encharge AI Inc", +[15][0x46 - 1] = "Shenzhen Zhenchuang Electronics Co Ltd", +[15][0x47 - 1] = "Giant Chip Co. Ltd", +[15][0x48 - 1] = "Shenzhen Runner Semiconductor Co Ltd", +[15][0x49 - 1] = "Scalinx", +[15][0x4a - 1] = "Shenzhen Lanqi Electronics Co Ltd", +[15][0x4b - 1] = "CoreComm Technology Co Ltd", +[15][0x4c - 1] = "DLI Memory", +[15][0x4d - 1] = "Shenzhen Fidat Technology Co Ltd", +[15][0x4e - 1] = "Hubei Yangtze Mason Semiconductor Tech", +[15][0x4f - 1] = "Flastor", +[15][0x50 - 1] = "PIRATEMAN", +[15][0x51 - 1] = "Barrie Technologies Co Ltd", +[15][0x52 - 1] = "Dynacard Co Ltd", +[15][0x53 - 1] = "Rivian Automotive", +[15][0x54 - 1] = "Shenzhen Fidat Technology Co Ltd", +[15][0x55 - 1] = "Zhejang Weiming Semiconductor Co Ltd", +[15][0x56 - 1] = "Shenzhen Xinhua Micro Technology Co Ltd", +[15][0x57 - 1] = "Duvonn Electronic Technology Co Ltd", +[15][0x58 - 1] = "Shenzhen Xinchang Technology Co Ltd", +[15][0x59 - 1] = "Leidos", +[15][0x5a - 1] = "Keepixo", +[15][0x5b - 1] = "Applied Brain Research Inc", +[15][0x5c - 1] = "Maxio Technology (Hangzhou) Co Ltd", +[15][0x5d - 1] = "HK DCHIP Technology Limited", +[15][0x5e - 1] = "Hitachi-LG Data Storage", +[15][0x5f - 1] = "Shenzhen Huadian Communication Co Ltd", +[15][0x60 - 1] = "Achieve Memory Technology (Suzhou) Co", +[15][0x61 - 1] = "Shenzhen Think Future Semiconductor Co", +[15][0x62 - 1] = "Innosilicon", +[15][0x63 - 1] = "Shenzhen Weilida Technology Co Ltd", +[15][0x64 - 1] = "Agrade Storage (Shenzhen) Co Ltd", +[15][0x65 - 1] = "Shenzhen Worldshine Data Technology Co", +[15][0x66 - 1] = "Mindgrove Technologies", +[15][0x67 - 1] = "BYD Semiconductor Co Ltd", +[15][0x68 - 1] = "Chipsine Semiconductor (Suzhou) Co Ltd", +[15][0x69 - 1] = "Shen Zhen Shi Xun He Shi Ji Dian Zi You", +[15][0x6a - 1] = "Shenzhen Jindacheng Computer Co Ltd", +[15][0x6b - 1] = "Shenzhen Baina Haichuan Technology Co", +[15][0x6c - 1] = "Shanghai Hengshi Electronic Technology", +[15][0x6d - 1] = "Beijing Boyu Tuxian Technology Co Ltd", +[15][0x6e - 1] = "China Chips Star Semiconductor Co Ltd", +[15][0x6f - 1] = "Shenzhen Shenghuacan Technology Co", +[15][0x70 - 1] = "Kinara Inc", +[15][0x71 - 1] = "TRASNA Semiconductor", +[15][0x72 - 1] = "KEYSOM", +[15][0x73 - 1] = "Shenzhen YYF Info Tech Co Ltd", +[15][0x74 - 1] = "Sharetronics Data Technology Co Ltd", /* EOF */ From 00ee9b09d9112a09e9780ace560bd8b353661658 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Thu, 22 Feb 2024 17:06:53 +0800 Subject: [PATCH 0964/1312] target/mips32: add dsp access support for gdb Change order of dsp register name array and removed hi0 and lo0 to comply with gdb definition of dsp in mips-dsp.xml, the regs name array is now mapping corresponding dsp accumulator names onto `mips32_regs` and `core_regs` instead of mapping to instr arrays in dsp functions. feature now requires a place to store cached dsp registers. Add dsp registers to reg_list for gdb to access them. Add dsp module enable detection to avoid DSP Disabled exception while reading dsp accumulators. Add dsp register reading procedure in `mips32_pracc_read_regs` and writing procedure in `mips32_pracc_write_regs`. Change-Id: Iacc335da030ab85989922c81aac7925b3dc17459 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/8476 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- src/target/mips32.c | 102 +++++++++++++++++++++++++++----------- src/target/mips32.h | 11 +++- src/target/mips32_pracc.c | 83 +++++++++++++++++++++++++++++-- 3 files changed, 163 insertions(+), 33 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 81faab72da..af52ffca05 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -31,7 +31,7 @@ static const char *mips_isa_strings[] = { /* * GDB registers - * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu}.xml + * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu,dsp}.xml */ static const struct { unsigned id; @@ -156,6 +156,22 @@ static const struct { "org.gnu.gdb.mips.cpu", 0 }, { MIPS32_REGLIST_C0_GUESTCTL1_INDEX, "guestCtl1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 }, + + { MIPS32_REGLIST_DSP_INDEX + 0, "hi1", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 1, "lo1", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 2, "hi2", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 3, "lo2", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 4, "hi3", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 5, "lo3", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + + { MIPS32_REGLIST_DSP_DSPCTL_INDEX, "dspctl", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, }; #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) @@ -211,13 +227,11 @@ static const struct { static const struct { const char *name; } mips32_dsp_regs[MIPS32NUMDSPREGS] = { - { "hi0"}, { "hi1"}, - { "hi2"}, - { "hi3"}, - { "lo0"}, { "lo1"}, + { "hi2"}, { "lo2"}, + { "hi3"}, { "lo3"}, { "control"}, }; @@ -328,7 +342,12 @@ static int mips32_read_core_reg(struct target *target, unsigned int num) if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; - if (num >= MIPS32_REGLIST_C0_INDEX) { + if (num >= MIPS32_REGLIST_DSP_INDEX) { + /* DSP */ + cnum = num - MIPS32_REGLIST_DSP_INDEX; + reg_value = mips32->core_regs.dsp[cnum]; + buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); + } else if (num >= MIPS32_REGLIST_C0_INDEX) { /* CP0 */ cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = mips32->core_regs.cp0[cnum]; @@ -371,7 +390,12 @@ static int mips32_write_core_reg(struct target *target, unsigned int num) if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; - if (num >= MIPS32_REGLIST_C0_INDEX) { + if (num >= MIPS32_REGLIST_DSP_INDEX) { + /* DSP */ + cnum = num - MIPS32_REGLIST_DSP_INDEX; + reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); + mips32->core_regs.dsp[cnum] = (uint32_t)reg_value; + } else if (num >= MIPS32_REGLIST_C0_INDEX) { /* CP0 */ cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); @@ -1026,10 +1050,20 @@ int mips32_cpu_probe(struct target *target) /* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/ static void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { - uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); + uint32_t retval, status_value, dsp_present; + bool dsp_enabled; + + retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read cp0 status register"); + return; + } + + dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); + dsp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0; if (dsp_present) { mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1; - LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp); + LOG_USER("DSP implemented: rev %d, %s", mips32->dsp_imp, dsp_enabled ? "enabled" : "disabled"); } else { LOG_USER("DSP implemented: %s", "no"); } @@ -1747,13 +1781,11 @@ static int mips32_pracc_read_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t *va }; uint32_t dsp_read_code[] = { - MIPS32_MFHI(isa, t0), /* mfhi t0 ($ac0) - OPCODE - 0x00004010 */ MIPS32_DSP_MFHI(t0, 1), /* mfhi t0,$ac1 - OPCODE - 0x00204010 */ - MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ - MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ - MIPS32_MFLO(isa, t0), /* mflo t0 ($ac0) - OPCODE - 0x00004012 */ MIPS32_DSP_MFLO(t0, 1), /* mflo t0,$ac1 - OPCODE - 0x00204012 */ + MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ MIPS32_DSP_MFLO(t0, 2), /* mflo t0,$ac2 - OPCODE - 0x00404012 */ + MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ MIPS32_DSP_MFLO(t0, 3), /* mflo t0,$ac3 - OPCODE - 0x00604012 */ MIPS32_DSP_RDDSP(t0, 0x3F), /* rddsp t0, 0x3f (DSPCtl) - OPCODE - 0x7c3f44b8 */ }; @@ -1824,13 +1856,11 @@ static int mips32_pracc_write_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t va }; uint32_t dsp_write_code[] = { - MIPS32_MTHI(isa, t0), /* mthi t0 ($ac0) - OPCODE - 0x01000011 */ MIPS32_DSP_MTHI(t0, 1), /* mthi t0, $ac1 - OPCODE - 0x01000811 */ - MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ - MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ - MIPS32_MTLO(isa, t0), /* mtlo t0 ($ac0) - OPCODE - 0x01000013 */ MIPS32_DSP_MTLO(t0, 1), /* mtlo t0, $ac1 - OPCODE - 0x01000813 */ + MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ MIPS32_DSP_MTLO(t0, 2), /* mtlo t0, $ac2 - OPCODE - 0x01001013 */ + MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ MIPS32_DSP_MTLO(t0, 3), /* mtlo t0, $ac3 - OPCODE - 0x01001813 */ MIPS32_DSP_WRDSP(t0, 0x1F), /* wrdsp t0, 0x1f (DSPCtl) - OPCODE - 0x7d00fcf8*/ }; @@ -2107,15 +2137,18 @@ static int mips32_dsp_find_register_by_name(const char *reg_name) * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value = 0; + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; for (int i = 0; i < MIPS32NUMDSPREGS; i++) { int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i); if (retval != ERROR_OK) { command_print(CMD, "couldn't access reg %s", mips32_dsp_regs[i].name); return retval; } + mips32->core_regs.dsp[i] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + i].dirty = 1; command_print(CMD, "%*s: 0x%8.8x", 7, mips32_dsp_regs[i].name, value); } return ERROR_OK; @@ -2132,20 +2165,28 @@ static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_e * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value = 0; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, index); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { command_print(CMD, "ERROR: Could not access dsp register %s", CMD_ARGV[0]); - else - command_print(CMD, "0x%8.8x", value); + return retval; + } + + command_print(CMD, "0x%8.8x", value); + + if (mips32->core_regs.dsp[index] != value) { + mips32->core_regs.dsp[index] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + index].dirty = 1; + } return retval; } @@ -2162,9 +2203,10 @@ static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_e * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value; + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); @@ -2174,8 +2216,13 @@ static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_e COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); int retval = mips32_pracc_write_dsp_reg(ejtag_info, value, index); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { command_print(CMD, "Error: could not write to dsp register %s", CMD_ARGV[0]); + return retval; + } + + mips32->core_regs.dsp[index] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + index].dirty = 1; return retval; } @@ -2193,7 +2240,6 @@ COMMAND_HANDLER(mips32_handle_dsp_command) int retval, tmp; struct target *target = get_current_target(CMD_CTX); struct mips32_common *mips32 = target_to_mips32(target); - struct mips_ejtag *ejtag_info = &mips32->ejtag_info; retval = mips32_verify_pointer(CMD, mips32); if (retval != ERROR_OK) @@ -2217,10 +2263,10 @@ COMMAND_HANDLER(mips32_handle_dsp_command) switch (CMD_ARGC) { case 0: - retval = mips32_dsp_get_all_regs(CMD, ejtag_info); + retval = mips32_dsp_get_all_regs(CMD, mips32); break; case 1: - retval = mips32_dsp_get_register(CMD, ejtag_info); + retval = mips32_dsp_get_register(CMD, mips32); break; case 2: tmp = *CMD_ARGV[0]; @@ -2228,7 +2274,7 @@ COMMAND_HANDLER(mips32_handle_dsp_command) command_print(CMD, "Error: invalid dsp command format"); retval = ERROR_COMMAND_ARGUMENT_INVALID; } else { - retval = mips32_dsp_set_register(CMD, ejtag_info); + retval = mips32_dsp_set_register(CMD, mips32); } break; default: diff --git a/src/target/mips32.h b/src/target/mips32.h index a557f31172..3d919e7ddb 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -69,7 +69,7 @@ #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 -#define MIPS32NUMDSPREGS 9 +#define MIPS32NUMDSPREGS 7 /* Bit Mask indicating CP0 register supported by this core */ #define MIPS_CP0_MK4 0x0001 @@ -78,6 +78,7 @@ #define MIPS_CP0_IAPTIV 0x0008 /* CP0 Status register fields */ +#define MIPS32_CP0_STATUS_MX_SHIFT 24 #define MIPS32_CP0_STATUS_FR_SHIFT 26 #define MIPS32_CP0_STATUS_CU1_SHIFT 29 @@ -211,6 +212,7 @@ static const struct mips32_cp0 { enum { MIPS32_PC = 37, MIPS32_FIR = 71, + MIPS32_DSPCTL = 78, MIPS32NUMCOREREGS }; @@ -220,11 +222,13 @@ enum { #define MIPS32_REG_FP_COUNT 32 #define MIPS32_REG_FPC_COUNT 2 #define MIPS32_REG_C0_COUNT 5 +#define MIPS32_REG_DSP_COUNT 7 #define MIPS32_REGLIST_GP_INDEX 0 #define MIPS32_REGLIST_FP_INDEX (MIPS32_REGLIST_GP_INDEX + MIPS32_REG_GP_COUNT) #define MIPS32_REGLIST_FPC_INDEX (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT) #define MIPS32_REGLIST_C0_INDEX (MIPS32_REGLIST_FPC_INDEX + MIPS32_REG_FPC_COUNT) +#define MIPS32_REGLIST_DSP_INDEX (MIPS32_REGLIST_C0_INDEX + MIPS32_REG_C0_COUNT) #define MIPS32_REGLIST_C0_STATUS_INDEX (MIPS32_REGLIST_C0_INDEX + 0) #define MIPS32_REGLIST_C0_BADVADDR_INDEX (MIPS32_REGLIST_C0_INDEX + 1) @@ -238,6 +242,10 @@ enum { #define MIPS32_REG_C0_PC_INDEX 3 #define MIPS32_REG_C0_GUESTCTL1_INDEX 4 +#define MIPS32_REGLIST_DSP_DSPCTL_INDEX (MIPS32_REGLIST_DSP_INDEX + 6) + +#define MIPS32_REG_DSP_DSPCTL_INDEX 6 + enum mips32_isa_mode { MIPS32_ISA_MIPS32 = 0, MIPS32_ISA_MIPS16E = 1, @@ -377,6 +385,7 @@ struct mips32_core_regs { uint64_t fpr[MIPS32_REG_FP_COUNT]; uint32_t fpcr[MIPS32_REG_FPC_COUNT]; uint32_t cp0[MIPS32_REG_C0_COUNT]; + uint32_t dsp[MIPS32_REG_DSP_COUNT]; }; struct mips32_common { diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index aaf3875fb7..018d8424e3 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -878,6 +878,7 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) uint32_t *c0rs = mips32->core_regs.cp0; bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + bool dsp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0); uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; pracc_queue_init(&ctx); @@ -943,6 +944,34 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); } + /* Store DSP Accumulators */ + if (mips32->dsp_imp && dsp_enabled) { + /* Struct of mips32_dsp_regs: {ac{hi, lo}1-3, dspctl} */ + uint32_t *dspr = mips32->core_regs.dsp; + size_t dsp_regs = ARRAY_SIZE(mips32->core_regs.dsp); + + /* Starts from ac1, core_regs.dsp contains dspctl register, therefore - 1 */ + for (size_t index = 0; index != ((dsp_regs - 1) / 2); index++) { + /* Every accumulator have 2 registers, hi and lo, and core_regs.dsp stores ac[1~3] */ + /* reads hi[ac] from core_regs array */ + pracc_add_li32(&ctx, 2, dspr[index * 2], 0); + /* reads lo[ac] from core_regs array */ + pracc_add_li32(&ctx, 3, dspr[(index * 2) + 1], 0); + + /* Write to accumulator 1~3 and index starts from 0, therefore ac = index + 1 */ + size_t ac = index + 1; + pracc_add(&ctx, 0, MIPS32_DSP_MTHI(2, ac)); + pracc_add(&ctx, 0, MIPS32_DSP_MTLO(3, ac)); + } + + /* DSPCTL is the last element of register store */ + pracc_add_li32(&ctx, 2, dspr[6], 0); + pracc_add(&ctx, 0, MIPS32_DSP_WRDSP(2, 0x1F)); + + if (rel > MIPS32_RELEASE_1) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + } + /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, gprs[i], 1); @@ -1064,14 +1093,16 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs; unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs; unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs; - bool fp_enabled; + unsigned int offset_dsp = ((uint8_t *)&core_regs->dsp[0]) - (uint8_t *)core_regs; + bool fp_enabled, dsp_enabled; /* - * This procedure has to be in 2 distinctive steps, because we can - * only know whether FP is enabled after reading CP0. + * This procedure has to be in 3 distinctive steps, because we can + * only know whether FP and DSP are enabled after reading CP0. * - * Step 1: Read everything except CP1 stuff + * Step 1: Read everything except CP1 and DSP stuff * Step 2: Read CP1 stuff if FP is implemented + * Step 3: Read DSP registers if dsp is implemented */ pracc_queue_init(&ctx); @@ -1149,6 +1180,50 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) pracc_queue_free(&ctx); } + + dsp_enabled = (mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0; + if (mips32->dsp_imp && dsp_enabled) { + pracc_queue_init(&ctx); + + mips32_pracc_store_regs_set_base_addr(&ctx); + + /* Struct of mips32_dsp_regs[7]: {ac{hi, lo}1-3, dspctl} */ + size_t dsp_regs = ARRAY_SIZE(mips32->core_regs.dsp); + /* Starts from ac1, core_regs.dsp have dspctl register, therefore - 1 */ + for (size_t index = 0; index != ((dsp_regs - 1) / 2); index++) { + /* Every accumulator have 2 registers, hi&lo, and core_regs.dsp stores ac[1~3] */ + /* Reads offset of hi[ac] from core_regs array */ + size_t offset_hi = offset_dsp + ((index * 2) * sizeof(uint32_t)); + /* Reads offset of lo[ac] from core_regs array */ + size_t offset_lo = offset_dsp + (((index * 2) + 1) * sizeof(uint32_t)); + + /* DSP Ac registers starts from 1 and index starts from 0, therefore ac = index + 1 */ + size_t ac = index + 1; + pracc_add(&ctx, 0, MIPS32_DSP_MFHI(8, ac)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_hi, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_hi, 1)); + pracc_add(&ctx, 0, MIPS32_DSP_MFLO(8, ac)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_lo, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_lo, 1)); + } + + /* DSPCTL is the last element of register store */ + pracc_add(&ctx, 0, MIPS32_DSP_RDDSP(8, 0x3F)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_dsp + ((dsp_regs - 1) * sizeof(uint32_t)), + MIPS32_SW(ctx.isa, 8, + PRACC_OUT_OFFSET + offset_dsp + ((dsp_regs - 1) * sizeof(uint32_t)), 1)); + + mips32_pracc_store_regs_restore(&ctx); + + /* jump to start */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); + /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1); + + pracc_queue_free(&ctx); + } return ctx.retval; } From 8750beeb44fb532612ea70dfdd1e794320810a0c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 21 Sep 2024 11:11:36 +0200 Subject: [PATCH 0965/1312] tcl: update to new syntax of telnet command Commit ad216136180e ("server/telnet: Restructure commands") modifies the syntax. sed -i 's/telnet_port/telnet port/' Change-Id: If1ad34a1ec54824dbc124acd36a894862276a34f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8502 Reviewed-by: zapb Tested-by: jenkins --- tcl/interface/vdebug.cfg | 2 +- tcl/target/u8500.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/interface/vdebug.cfg b/tcl/interface/vdebug.cfg index 9097c33dac..63a5955067 100644 --- a/tcl/interface/vdebug.cfg +++ b/tcl/interface/vdebug.cfg @@ -23,7 +23,7 @@ vdebug server $_VDEBUGHOST:$_VDEBUGPORT # example config listen on all interfaces, disable tcl/telnet server bindto 0.0.0.0 #gdb port 3333 -#telnet_port disabled +#telnet port disabled tcl port disabled # transaction batching: 0 - no batching, 1 - (default) wr, 2 - rw diff --git a/tcl/target/u8500.cfg b/tcl/target/u8500.cfg index b87d2613a8..1fdc11fe34 100644 --- a/tcl/target/u8500.cfg +++ b/tcl/target/u8500.cfg @@ -143,7 +143,7 @@ proc enable_apetap {} { } tcl port 5555 -telnet_port 4444 +telnet port 4444 gdb port 3333 if { [info exists CHIPNAME] } { From bf1cf4afbb22d3c617186856c6638f4bb2d2d23b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 23:11:45 +0200 Subject: [PATCH 0966/1312] openocd: fix conversion string for stdint values Detected while converting 'unsigned' to 'unsigned int'. Use the correct conversion string for stdint values. Change-Id: I99f3dff4c64dfd7acf2bddb130b56e9ebe1e6c60 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8477 Tested-by: jenkins --- src/flash/nand/at91sam9.c | 5 ++--- src/flash/nand/lpc3180.c | 3 +-- src/flash/nand/lpc32xx.c | 3 +-- src/flash/nor/at91sam3.c | 10 +++++----- src/flash/nor/at91sam4.c | 10 +++++----- src/flash/nor/cfi.c | 3 +-- src/flash/nor/max32xxx.c | 4 ++-- src/flash/nor/stellaris.c | 4 ++-- src/flash/nor/tms470.c | 4 ++-- src/jtag/core.c | 5 ++--- src/jtag/tcl.c | 9 +++------ src/target/arm11.c | 15 ++++++--------- src/target/arm11_dbgtap.c | 25 ++++++++++--------------- src/target/arm_disassembler.c | 15 +++++++-------- src/target/arm_dpm.c | 10 ++++------ src/target/armv4_5.c | 2 +- src/target/armv8.c | 2 +- src/target/armv8_dpm.c | 5 ++--- src/target/cortex_a.c | 5 ++--- src/target/cortex_m.c | 10 ++++------ src/target/dsp563xx.c | 10 +++++----- src/target/etm.c | 7 +++---- src/target/target.c | 10 +++++----- src/target/x86_32_common.c | 4 ++-- 24 files changed, 78 insertions(+), 102 deletions(-) diff --git a/src/flash/nand/at91sam9.c b/src/flash/nand/at91sam9.c index bfbba67c4c..9c8d5e2a3d 100644 --- a/src/flash/nand/at91sam9.c +++ b/src/flash/nand/at91sam9.c @@ -389,9 +389,8 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, uint32_t bit = parity & 0x0F; data[word] ^= (0x1) << bit; - LOG_INFO("Data word %d, bit %d corrected.", - (unsigned) word, - (unsigned) bit); + LOG_INFO("Data word %" PRIu32 ", bit %" PRIu32 " corrected.", + word, bit); } } diff --git a/src/flash/nand/lpc3180.c b/src/flash/nand/lpc3180.c index c1af1d7372..8e660a0680 100644 --- a/src/flash/nand/lpc3180.c +++ b/src/flash/nand/lpc3180.c @@ -890,8 +890,7 @@ static int lpc3180_read_page(struct nand_device *nand, if (mlc_isr & 0x8) { if (mlc_isr & 0x40) { - LOG_ERROR("uncorrectable error detected: 0x%2.2x", - (unsigned)mlc_isr); + LOG_ERROR("uncorrectable error detected: 0x%2.2" PRIx32, mlc_isr); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; diff --git a/src/flash/nand/lpc32xx.c b/src/flash/nand/lpc32xx.c index 1fdae9fe53..89a00a9e30 100644 --- a/src/flash/nand/lpc32xx.c +++ b/src/flash/nand/lpc32xx.c @@ -1386,8 +1386,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page, if (mlc_isr & 0x8) { if (mlc_isr & 0x40) { - LOG_ERROR("uncorrectable error detected: " - "0x%2.2x", (unsigned)mlc_isr); + LOG_ERROR("uncorrectable error detected: 0x%2.2" PRIx32, mlc_isr); return ERROR_NAND_OPERATION_FAILED; } diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index b1cb8f110e..8e8497eb0d 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -2051,7 +2051,7 @@ static int efc_start_command(struct sam3_bank_private *private, case AT91C_EFC_FCMD_CLB: n = (private->size_bytes / private->page_size); if (argument >= n) - LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n)); + LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n); break; case AT91C_EFC_FCMD_SFB: @@ -2867,8 +2867,8 @@ static int sam3_read_this_reg(struct sam3_chip *chip, uint32_t *goes_here) r = target_read_u32(chip->target, reg->address, goes_here); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Err: %d", - reg->name, (unsigned)(reg->address), r); + LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08" PRIx32 ", Err: %d", + reg->name, reg->address, r); } return r; } @@ -2883,8 +2883,8 @@ static int sam3_read_all_regs(struct sam3_chip *chip) r = sam3_read_this_reg(chip, sam3_get_reg_ptr(&(chip->cfg), reg)); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Error: %d", - reg->name, ((unsigned)(reg->address)), r); + LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08" PRIx32 ", Error: %d", + reg->name, reg->address, r); return r; } reg++; diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 62127530f1..31ae35ccd4 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -1501,7 +1501,7 @@ static int efc_start_command(struct sam4_bank_private *private, case AT91C_EFC_FCMD_CLB: n = (private->size_bytes / private->page_size); if (argument >= n) - LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n)); + LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n); break; case AT91C_EFC_FCMD_SFB: @@ -2374,8 +2374,8 @@ static int sam4_read_this_reg(struct sam4_chip *chip, uint32_t *goes_here) r = target_read_u32(chip->target, reg->address, goes_here); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Err: %d", - reg->name, (unsigned)(reg->address), r); + LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08" PRIx32 ", Err: %d", + reg->name, reg->address, r); } return r; } @@ -2390,8 +2390,8 @@ static int sam4_read_all_regs(struct sam4_chip *chip) r = sam4_read_this_reg(chip, sam4_get_reg_ptr(&(chip->cfg), reg)); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Error: %d", - reg->name, ((unsigned)(reg->address)), r); + LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08" PRIx32 ", Error: %d", + reg->name, reg->address, r); return r; } reg++; diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 78bc91e7d0..96bd7353ff 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -2219,8 +2219,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u uint8_t current_word[CFI_MAX_BUS_WIDTH]; int retval; - LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", - (int)count, (unsigned)offset); + LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32, count, offset); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index 59a14af8b8..052a42d235 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -388,8 +388,8 @@ static int max32xxx_write_block(struct flash_bank *bank, const uint8_t *buffer, return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", - target_name(target), (unsigned) buffer_size); + LOG_DEBUG("retry target_alloc_working_area(%s, size=%" PRIu32 ")", + target_name(target), buffer_size); } target_write_buffer(target, write_algorithm->address, sizeof(write_code), diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index eab6244d43..25bc5507ad 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -1056,8 +1056,8 @@ static int stellaris_write_block(struct flash_bank *bank, target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", - target_name(target), (unsigned) buffer_size); + LOG_DEBUG("retry target_alloc_working_area(%s, size=%" PRIu32 ")", + target_name(target), buffer_size); } target_write_buffer(target, write_algorithm->address, diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index e01d2df0a5..6e0ea5b950 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -239,8 +239,8 @@ static int tms470_read_part_info(struct flash_bank *bank) break; default: - LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", - (unsigned)part_number); + LOG_WARNING("Could not identify part 0x%02" PRIx32 " as a member of the TMS470 family.", + part_number); return ERROR_FLASH_OPERATION_FAILED; } diff --git a/src/jtag/core.c b/src/jtag/core.c index a6f38a19dd..6515d71609 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1473,10 +1473,9 @@ void jtag_tap_init(struct jtag_tap *tap) jtag_tap_add(tap); LOG_DEBUG("Created Tap: %s @ abs position %u, " - "irlen %u, capture: 0x%x mask: 0x%x", tap->dotted_name, + "irlen %u, capture: 0x%" PRIx32 " mask: 0x%" PRIx32, tap->dotted_name, tap->abs_chain_position, tap->ir_length, - (unsigned) tap->ir_capture_value, - (unsigned) tap->ir_capture_mask); + tap->ir_capture_value, tap->ir_capture_mask); } void jtag_tap_free(struct jtag_tap *tap) diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 624b4e4c2a..e2b3b45a60 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -803,10 +803,8 @@ COMMAND_HANDLER(handle_scan_chain_command) while (tap) { uint32_t expected, expected_mask, ii; - snprintf(expected_id, sizeof(expected_id), "0x%08x", - (unsigned)((tap->expected_ids_cnt > 0) - ? tap->expected_ids[0] - : 0)); + snprintf(expected_id, sizeof(expected_id), "0x%08" PRIx32, + (tap->expected_ids_cnt > 0) ? tap->expected_ids[0] : 0); if (tap->ignore_version) expected_id[2] = '*'; @@ -825,8 +823,7 @@ COMMAND_HANDLER(handle_scan_chain_command) (unsigned int)(expected_mask)); for (ii = 1; ii < tap->expected_ids_cnt; ii++) { - snprintf(expected_id, sizeof(expected_id), "0x%08x", - (unsigned) tap->expected_ids[ii]); + snprintf(expected_id, sizeof(expected_id), "0x%08" PRIx32, tap->expected_ids[ii]); if (tap->ignore_version) expected_id[2] = '*'; diff --git a/src/target/arm11.c b/src/target/arm11.c index 50aaa86f12..43790c737b 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -43,7 +43,7 @@ static int arm11_check_init(struct arm11_common *arm11) CHECK_RETVAL(arm11_read_dscr(arm11)); if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) { - LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); + LOG_DEBUG("DSCR %08" PRIx32, arm11->dscr); LOG_DEBUG("Bringing target into debug mode"); arm11->dscr |= DSCR_HALT_DBG_MODE; @@ -241,8 +241,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp) registers hold data that was written by one side (CPU or JTAG) and not read out by the other side. */ - LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)", - (unsigned) arm11->dscr); + LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", arm11->dscr); return ERROR_FAIL; } } @@ -516,7 +515,7 @@ static int arm11_resume(struct target *target, int current, while (1) { CHECK_RETVAL(arm11_read_dscr(arm11)); - LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); + LOG_DEBUG("DSCR %08" PRIx32, arm11->dscr); if (arm11->dscr & DSCR_CORE_RESTARTED) break; @@ -662,7 +661,7 @@ static int arm11_step(struct target *target, int current, | DSCR_CORE_HALTED; CHECK_RETVAL(arm11_read_dscr(arm11)); - LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr); + LOG_DEBUG("DSCR %08" PRIx32 " e", arm11->dscr); if ((arm11->dscr & mask) == mask) break; @@ -1012,10 +1011,8 @@ static int arm11_write_memory_inner(struct target *target, return retval; if (address + size * count != r0) { - LOG_ERROR("Data transfer failed. Expected end " - "address 0x%08x, got 0x%08x", - (unsigned) (address + size * count), - (unsigned) r0); + LOG_ERROR("Data transfer failed. Expected end address 0x%08" PRIx32 ", got 0x%08" PRIx32, + address + size * count, r0); if (burst) LOG_ERROR( diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index b670bd7f78..b66f886183 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -242,7 +242,7 @@ int arm11_add_debug_scan_n(struct arm11_common *arm11, static void arm11_add_debug_inst(struct arm11_common *arm11, uint32_t inst, uint8_t *flag, tap_state_t state) { - JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst); + JTAG_DEBUG("INST <= 0x%08" PRIx32, inst); struct scan_field itr[2]; @@ -282,9 +282,7 @@ int arm11_read_dscr(struct arm11_common *arm11) CHECK_RETVAL(jtag_execute_queue()); if (arm11->dscr != dscr) - JTAG_DEBUG("DSCR = %08x (OLD %08x)", - (unsigned) dscr, - (unsigned) arm11->dscr); + JTAG_DEBUG("DSCR = %08" PRIx32 " (OLD %08" PRIx32 ")", dscr, arm11->dscr); arm11->dscr = dscr; @@ -317,9 +315,7 @@ int arm11_write_dscr(struct arm11_common *arm11, uint32_t dscr) CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("DSCR <= %08x (OLD %08x)", - (unsigned) dscr, - (unsigned) arm11->dscr); + JTAG_DEBUG("DSCR <= %08" PRIx32 " (OLD %08" PRIx32 ")", dscr, arm11->dscr); arm11->dscr = dscr; @@ -509,8 +505,8 @@ int arm11_run_instr_data_to_core(struct arm11_common *arm11, CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("DTR _data %08x ready %d n_retry %d", - (unsigned) _data, ready, n_retry); + JTAG_DEBUG("DTR _data %08" PRIx32 " ready %d n_retry %d", + _data, ready, n_retry); int64_t then = 0; @@ -754,8 +750,8 @@ int arm11_run_instr_data_from_core(struct arm11_common *arm11, CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("DTR _data %08x ready %d n_retry %d", - (unsigned) _data, ready, n_retry); + JTAG_DEBUG("DTR _data %08" PRIx32 " ready %d n_retry %d", + _data, ready, n_retry); int64_t then = 0; @@ -878,9 +874,8 @@ int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, /* Timeout here so we don't get stuck. */ int i_n = 0; while (1) { - JTAG_DEBUG("SC7 <= c%-3d Data %08x %s", - (unsigned) address_out, - (unsigned) data_out, + JTAG_DEBUG("SC7 <= c%-3" PRIu8 " Data %08" PRIx32 " %s", + address_out, data_out, n_rw ? "write" : "read"); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain7_fields), @@ -908,7 +903,7 @@ int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, } if (!n_rw) - JTAG_DEBUG("SC7 => Data %08x", (unsigned) data_in); + JTAG_DEBUG("SC7 => Data %08" PRIx32, data_in); if (i > 0) { if (actions[i - 1].address != address_in) diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 749274f369..5c52ad8990 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -266,18 +266,18 @@ static int evaluate_srs(uint32_t opcode, case 0x08400000: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 - "\tSRS%s\tSP%s, #%d", + "\tSRS%s\tSP%s, #%" PRIu32, address, opcode, mode, wback, - (unsigned)(opcode & 0x1f)); + opcode & 0x1f); break; case 0x08100000: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 - "\tRFE%s\tr%d%s", + "\tRFE%s\tr%" PRIu32 "%s", address, opcode, mode, - (unsigned)((opcode >> 16) & 0xf), wback); + (opcode >> 16) & 0xf, wback); break; default: return evaluate_unknown(opcode, address, instruction); @@ -842,7 +842,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, /* halfword pack */ if ((opcode & 0x01f00020) == 0x00800000) { char *type, *shift; - unsigned imm = (unsigned) (opcode >> 7) & 0x1f; + unsigned int imm = (opcode >> 7) & 0x1f; if (opcode & (1 << 6)) { type = "TB"; @@ -865,7 +865,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, /* word saturate */ if ((opcode & 0x01a00020) == 0x00a00000) { char *shift; - unsigned imm = (unsigned) (opcode >> 7) & 0x1f; + unsigned int imm = (opcode >> 7) & 0x1f; if (opcode & (1 << 6)) { shift = "ASR"; @@ -2046,8 +2046,7 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, return evaluate_cdp_mcr_mrc(opcode, address, instruction); } - LOG_ERROR("ARM: should never reach this point (opcode=%08x)", - (unsigned) opcode); + LOG_ERROR("ARM: should never reach this point (opcode=%08" PRIx32 ")", opcode); return -1; } diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 9f3a444afc..94e91ad6cd 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -198,8 +198,7 @@ static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) buf_set_u32(r->value + 4, 0, 32, value_r1); r->valid = true; r->dirty = false; - LOG_DEBUG("READ: %s, %8.8x, %8.8x", r->name, - (unsigned) value_r0, (unsigned) value_r1); + LOG_DEBUG("READ: %s, %8.8" PRIx32 ", %8.8" PRIx32, r->name, value_r0, value_r1); } return retval; @@ -266,7 +265,7 @@ int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) buf_set_u32(r->value, 0, 32, value); r->valid = true; r->dirty = false; - LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); + LOG_DEBUG("READ: %s, %8.8" PRIx32, r->name, value); } return retval; @@ -302,8 +301,7 @@ static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum if (retval == ERROR_OK) { r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8x, %8.8x", r->name, - (unsigned) value_r0, (unsigned) value_r1); + LOG_DEBUG("WRITE: %s, %8.8" PRIx32 ", %8.8" PRIx32, r->name, value_r0, value_r1); } return retval; @@ -351,7 +349,7 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) if (retval == ERROR_OK) { r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); + LOG_DEBUG("WRITE: %s, %8.8" PRIx32, r->name, value); } return retval; diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 1886d5e1f6..ae89762e11 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -482,7 +482,7 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) } arm->core_state = state; - LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, + LOG_DEBUG("set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, arm_mode_name(mode), arm_state_strings[arm->core_state]); } diff --git a/src/target/armv8.c b/src/target/armv8.c index b54ef13d37..3e0ea0b754 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -961,7 +961,7 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) arm->core_state = state; arm->core_mode = mode; - LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, + LOG_DEBUG("set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, armv8_mode_name(arm->core_mode), armv8_state_strings[arm->core_state]); } diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 271bd91c3b..bcecedc9da 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -441,8 +441,7 @@ static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, vr += 16 * index_t; cr += 16 * index_t; - LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x", - (unsigned) vr, (unsigned) cr); + LOG_DEBUG("A8: bpwp enable, vr %08" PRIx32 " cr %08" PRIx32, vr, cr); retval = mem_ap_write_atomic_u32(armv8->debug_ap, vr, addr); if (retval != ERROR_OK) @@ -469,7 +468,7 @@ static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) } cr += 16 * index_t; - LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); + LOG_DEBUG("A: bpwp disable, cr %08" PRIx32, cr); /* clear control register */ return mem_ap_write_atomic_u32(armv8->debug_ap, cr, 0); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 2de77c9602..498a9cd16a 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -595,8 +595,7 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, vr += 4 * index_t; cr += 4 * index_t; - LOG_DEBUG("A: bpwp enable, vr %08x cr %08x", - (unsigned) vr, (unsigned) cr); + LOG_DEBUG("A: bpwp enable, vr %08" PRIx32 " cr %08" PRIx32, vr, cr); retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, vr, addr); @@ -625,7 +624,7 @@ static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) } cr += 4 * index_t; - LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); + LOG_DEBUG("A: bpwp disable, cr %08" PRIx32, cr); /* clear control register */ return mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, 0); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 3b95b648ef..698a6868cb 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2081,11 +2081,9 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); - LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x", + LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%d 0x%08" PRIx32 " 0x%" PRIx32 " 0x%05" PRIx32, watchpoint->unique_id, dwt_num, - (unsigned) comparator->comp, - (unsigned) comparator->mask, - (unsigned) comparator->function); + comparator->comp, comparator->mask, comparator->function); return ERROR_OK; } @@ -2102,9 +2100,9 @@ static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *w unsigned int dwt_num = watchpoint->number; - LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%u address: 0x%08x clear", + LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%u address: " TARGET_ADDR_FMT " clear", watchpoint->unique_id, dwt_num, - (unsigned) watchpoint->address); + watchpoint->address); if (dwt_num >= cortex_m->dwt_num_comp) { LOG_TARGET_DEBUG(target, "Invalid DWT Comparator number in watchpoint"); diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 80cca1ed50..687821c5d7 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -1135,7 +1135,7 @@ static int dsp563xx_resume(struct target *target, current = 0; } - LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address); + LOG_DEBUG("%s %08X %08" TARGET_PRIXADDR, __func__, current, address); err = dsp563xx_restore_context(target); if (err != ERROR_OK) @@ -1199,7 +1199,7 @@ static int dsp563xx_step_ex(struct target *target, current = 0; } - LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address); + LOG_DEBUG("%s %08X %08" PRIX32, __func__, current, address); err = dsp563xx_jtag_debug_request(target); if (err != ERROR_OK) @@ -1260,15 +1260,15 @@ static int dsp563xx_step_ex(struct target *target, err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABFR, &dr_in); if (err != ERROR_OK) return err; - LOG_DEBUG("fetch: %08X", (unsigned) dr_in&0x00ffffff); + LOG_DEBUG("fetch: %08" PRIX32, dr_in & 0x00ffffff); err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABDR, &dr_in); if (err != ERROR_OK) return err; - LOG_DEBUG("decode: %08X", (unsigned) dr_in&0x00ffffff); + LOG_DEBUG("decode: %08" PRIX32, dr_in & 0x00ffffff); err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABEX, &dr_in); if (err != ERROR_OK) return err; - LOG_DEBUG("execute: %08X", (unsigned) dr_in&0x00ffffff); + LOG_DEBUG("execute: %08" PRIX32, dr_in & 0x00ffffff); /* reset trace mode */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000); diff --git a/src/target/etm.c b/src/target/etm.c index d083017f71..d8f2a2faa2 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -320,9 +320,8 @@ struct reg_cache *etm_build_reg_cache(struct target *target, etm_reg_add(0x20, jtag_info, reg_cache, arch_info, etm_core + 1, 1); etm_get_reg(reg_list + 1); - etm_ctx->id = buf_get_u32( - arch_info[1].value, 0, 32); - LOG_DEBUG("ETM ID: %08x", (unsigned) etm_ctx->id); + etm_ctx->id = buf_get_u32(arch_info[1].value, 0, 32); + LOG_DEBUG("ETM ID: %08" PRIx32, etm_ctx->id); bcd_vers = 0x10 + (((etm_ctx->id) >> 4) & 0xff); } else { @@ -1495,7 +1494,7 @@ COMMAND_HANDLER(handle_etm_info_command) etm_get_reg(etm_sys_config_reg); config = buf_get_u32(etm_sys_config_reg->value, 0, 32); - LOG_DEBUG("ETM SYS CONFIG %08x", (unsigned) config); + LOG_DEBUG("ETM SYS CONFIG %08" PRIx32, config); max_port_size = config & 0x7; if (etm->bcd_vers >= 0x30) diff --git a/src/target/target.c b/src/target/target.c index 9d1d2f5507..c3a4ed6d27 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3851,11 +3851,11 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver for (t = 0; t < buf_cnt; t++) { if (data[t] != buffer[t]) { command_print(CMD, - "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", - diffs, - (unsigned)(t + image.sections[i].base_address), - data[t], - buffer[t]); + "diff %d address " TARGET_ADDR_FMT ". Was 0x%02" PRIx8 " instead of 0x%02" PRIx8, + diffs, + t + image.sections[i].base_address, + data[t], + buffer[t]); if (diffs++ >= 127) { command_print(CMD, "More than 128 errors, the rest are not printed."); free(data); diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index ecaf52b3ab..666bb07bf9 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -1360,8 +1360,8 @@ static void handle_iod_output(struct command_invocation *cmd, if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, - "0x%8.8x: ", - (unsigned)(address + (i*size))); + "0x%8.8" PRIx32 ": ", + address + (i * size)); } uint32_t value = 0; From 50586c9a063de2475ec12c4858dccfa8d5545221 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:44:32 +0200 Subject: [PATCH 0967/1312] target: use 'unsigned int' for smp group Change the type to 'struct target::smp' and to the initialization variable 'smp_group'. Change-Id: I5f5a30a796aaf4e0014a38e81abdf4fb4afbdf48 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8478 Reviewed-by: zapb Tested-by: jenkins --- src/target/target.c | 2 +- src/target/target.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index c3a4ed6d27..281bbbd408 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -6007,7 +6007,7 @@ static int get_target_with_common_rtos_type(struct command_invocation *cmd, COMMAND_HANDLER(handle_target_smp) { - static int smp_group = 1; + static unsigned int smp_group = 1; if (CMD_ARGC == 0) { LOG_DEBUG("Empty SMP target"); diff --git a/src/target/target.h b/src/target/target.h index d3077f5716..ecc8a90321 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -184,7 +184,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; /* Unique non-zero number for each SMP group */ + unsigned 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 */ From 2ad48b78d4a19921f57a8cb7a4994b534c047b95 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:15:53 +0200 Subject: [PATCH 0968/1312] flash: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Ignore the cast as they could be better addressed. Fix only minor additional checkpatch issue (spacing and line length). Change-Id: Id808747855a02052f3738e2d232bff4dd99b27f1 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8479 Tested-by: jenkins Reviewed-by: zapb --- src/flash/common.c | 6 ++-- src/flash/common.h | 2 +- src/flash/nand/arm_io.c | 6 ++-- src/flash/nand/arm_io.h | 2 +- src/flash/nand/at91sam9.c | 8 ++--- src/flash/nand/core.c | 8 ++--- src/flash/nand/core.h | 2 +- src/flash/nand/davinci.c | 2 +- src/flash/nand/driver.c | 4 +-- src/flash/nand/fileio.c | 4 +-- src/flash/nand/lpc3180.c | 2 +- src/flash/nand/lpc32xx.c | 2 +- src/flash/nor/aducm360.c | 2 +- src/flash/nor/at91sam3.c | 68 +++++++++++++++++++------------------- src/flash/nor/at91sam4.c | 68 +++++++++++++++++++------------------- src/flash/nor/at91samd.c | 4 +-- src/flash/nor/ath79.c | 2 +- src/flash/nor/atsame5.c | 4 +-- src/flash/nor/atsamv.c | 28 ++++++++-------- src/flash/nor/cfi.c | 2 +- src/flash/nor/cfi.h | 8 ++--- src/flash/nor/core.c | 6 ++-- src/flash/nor/core.h | 2 +- src/flash/nor/drivers.c | 2 +- src/flash/nor/fespi.c | 2 +- src/flash/nor/fm4.c | 4 +-- src/flash/nor/kinetis.c | 36 ++++++++++---------- src/flash/nor/kinetis_ke.c | 6 ++-- src/flash/nor/max32xxx.c | 8 ++--- src/flash/nor/psoc5lp.c | 24 +++++++------- src/flash/nor/sim3x.c | 6 ++-- src/flash/nor/stellaris.c | 6 ++-- src/flash/nor/tcl.c | 8 ++--- src/flash/nor/tms470.c | 6 ++-- src/flash/nor/xmc1xxx.c | 6 ++-- 35 files changed, 178 insertions(+), 178 deletions(-) diff --git a/src/flash/common.c b/src/flash/common.c index ebd9396eb0..9f40a3a6f8 100644 --- a/src/flash/common.c +++ b/src/flash/common.c @@ -11,14 +11,14 @@ #include "common.h" #include -unsigned get_flash_name_index(const char *name) +unsigned int get_flash_name_index(const char *name) { const char *name_index = strrchr(name, '.'); if (!name_index) return 0; if (name_index[1] < '0' || name_index[1] > '9') return ~0U; - unsigned requested; + unsigned int requested; int retval = parse_uint(name_index + 1, &requested); /* detect parsing error by forcing past end of bank list */ return (retval == ERROR_OK) ? requested : ~0U; @@ -26,7 +26,7 @@ unsigned get_flash_name_index(const char *name) bool flash_driver_name_matches(const char *name, const char *expected) { - unsigned blen = strlen(name); + unsigned int blen = strlen(name); /* only match up to the length of the driver name... */ if (strncmp(name, expected, blen) != 0) return false; diff --git a/src/flash/common.h b/src/flash/common.h index 15aea5b810..6ceaa8d3c7 100644 --- a/src/flash/common.h +++ b/src/flash/common.h @@ -17,7 +17,7 @@ * name provides a suffix but it does not parse as an unsigned integer, * the routine returns ~0U. This will prevent further matching. */ -unsigned get_flash_name_index(const char *name); +unsigned int get_flash_name_index(const char *name); /** * Attempt to match the @c expected name with the @c name of a driver. * @param name The name of the driver (from the bank's device structure). diff --git a/src/flash/nand/arm_io.c b/src/flash/nand/arm_io.c index 80bd0cf25b..dd012e161a 100644 --- a/src/flash/nand/arm_io.c +++ b/src/flash/nand/arm_io.c @@ -31,12 +31,12 @@ * @return Success or failure of the operation */ static int arm_code_to_working_area(struct target *target, - const uint32_t *code, unsigned code_size, - unsigned additional, struct working_area **area) + const uint32_t *code, unsigned int code_size, + unsigned int additional, struct working_area **area) { uint8_t code_buf[code_size]; int retval; - unsigned size = code_size + additional; + unsigned int size = code_size + additional; /* REVISIT this assumes size doesn't ever change. * That's usually correct; but there are boards with diff --git a/src/flash/nand/arm_io.h b/src/flash/nand/arm_io.h index 10f0e661c1..760dc7e6f3 100644 --- a/src/flash/nand/arm_io.h +++ b/src/flash/nand/arm_io.h @@ -27,7 +27,7 @@ struct arm_nand_data { struct working_area *copy_area; /** The chunk size is the page size or ECC chunk. */ - unsigned chunk_size; + unsigned int chunk_size; /** Where data is read from or written to. */ uint32_t data; diff --git a/src/flash/nand/at91sam9.c b/src/flash/nand/at91sam9.c index 9c8d5e2a3d..41cb07bc90 100644 --- a/src/flash/nand/at91sam9.c +++ b/src/flash/nand/at91sam9.c @@ -532,7 +532,7 @@ COMMAND_HANDLER(handle_at91sam9_cle_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, address_line; + unsigned int num, address_line; if (CMD_ARGC != 2) { command_print(CMD, "incorrect number of arguments for 'at91sam9 cle' command"); @@ -562,7 +562,7 @@ COMMAND_HANDLER(handle_at91sam9_ale_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, address_line; + unsigned int num, address_line; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -590,7 +590,7 @@ COMMAND_HANDLER(handle_at91sam9_rdy_busy_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, base_pioc, pin_num; + unsigned int num, base_pioc, pin_num; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; @@ -621,7 +621,7 @@ COMMAND_HANDLER(handle_at91sam9_ce_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, base_pioc, pin_num; + unsigned int num, base_pioc, pin_num; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c index 37e1d12e03..c5430aeb05 100644 --- a/src/flash/nand/core.c +++ b/src/flash/nand/core.c @@ -165,8 +165,8 @@ static struct nand_ecclayout nand_oob_8 = { */ static struct nand_device *get_nand_device_by_name(const char *name) { - unsigned requested = get_flash_name_index(name); - unsigned found = 0; + unsigned int requested = get_flash_name_index(name); + unsigned int found = 0; struct nand_device *nand; for (nand = nand_devices; nand; nand = nand->next) { @@ -194,7 +194,7 @@ struct nand_device *get_nand_device_by_num(int num) return NULL; } -COMMAND_HELPER(nand_command_get_device, unsigned name_index, +COMMAND_HELPER(nand_command_get_device, unsigned int name_index, struct nand_device **nand) { const char *str = CMD_ARGV[name_index]; @@ -202,7 +202,7 @@ COMMAND_HELPER(nand_command_get_device, unsigned name_index, if (*nand) return ERROR_OK; - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, str, num); *nand = get_nand_device_by_num(num); if (!*nand) { diff --git a/src/flash/nand/core.h b/src/flash/nand/core.h index 137298cbc8..4286e11832 100644 --- a/src/flash/nand/core.h +++ b/src/flash/nand/core.h @@ -209,7 +209,7 @@ int nand_correct_data(struct nand_device *nand, u_char *dat, int nand_register_commands(struct command_context *cmd_ctx); /** helper for parsing a nand device command argument string */ -COMMAND_HELPER(nand_command_get_device, unsigned name_index, +COMMAND_HELPER(nand_command_get_device, unsigned int name_index, struct nand_device **nand); diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c index b7169feeba..17040fe172 100644 --- a/src/flash/nand/davinci.c +++ b/src/flash/nand/davinci.c @@ -379,7 +379,7 @@ static int davinci_writepage_tail(struct nand_device *nand, static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { - unsigned oob_offset; + unsigned int oob_offset; struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c index ce79e1382b..5d99102c85 100644 --- a/src/flash/nand/driver.c +++ b/src/flash/nand/driver.c @@ -33,7 +33,7 @@ static struct nand_flash_controller *nand_flash_controllers[] = { struct nand_flash_controller *nand_driver_find_by_name(const char *name) { - for (unsigned i = 0; nand_flash_controllers[i]; i++) { + for (unsigned int i = 0; nand_flash_controllers[i]; i++) { struct nand_flash_controller *controller = nand_flash_controllers[i]; if (strcmp(name, controller->name) == 0) return controller; @@ -42,7 +42,7 @@ struct nand_flash_controller *nand_driver_find_by_name(const char *name) } int nand_driver_walk(nand_driver_walker_t f, void *x) { - for (unsigned i = 0; nand_flash_controllers[i]; i++) { + for (unsigned int i = 0; nand_flash_controllers[i]; i++) { int retval = (*f)(nand_flash_controllers[i], x); if (retval != ERROR_OK) return retval; diff --git a/src/flash/nand/fileio.c b/src/flash/nand/fileio.c index ca618b3756..613ae3cb32 100644 --- a/src/flash/nand/fileio.c +++ b/src/flash/nand/fileio.c @@ -107,7 +107,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, { nand_fileio_init(state); - unsigned minargs = need_size ? 4 : 3; + unsigned int minargs = need_size ? 4 : 3; if (minargs > CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; @@ -131,7 +131,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, } if (minargs < CMD_ARGC) { - for (unsigned i = minargs; i < CMD_ARGC; i++) { + for (unsigned int i = minargs; i < CMD_ARGC; i++) { if (!strcmp(CMD_ARGV[i], "oob_raw")) state->oob_format |= NAND_OOB_RAW; else if (!strcmp(CMD_ARGV[i], "oob_only")) diff --git a/src/flash/nand/lpc3180.c b/src/flash/nand/lpc3180.c index 8e660a0680..d221c34d9e 100644 --- a/src/flash/nand/lpc3180.c +++ b/src/flash/nand/lpc3180.c @@ -1274,7 +1274,7 @@ COMMAND_HANDLER(handle_lpc3180_select_command) if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct nand_device *nand = get_nand_device_by_num(num); if (!nand) { diff --git a/src/flash/nand/lpc32xx.c b/src/flash/nand/lpc32xx.c index 89a00a9e30..c67f2aa303 100644 --- a/src/flash/nand/lpc32xx.c +++ b/src/flash/nand/lpc32xx.c @@ -1742,7 +1742,7 @@ COMMAND_HANDLER(handle_lpc32xx_select_command) if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct nand_device *nand = get_nand_device_by_num(num); if (!nand) { diff --git a/src/flash/nor/aducm360.c b/src/flash/nor/aducm360.c index ce9bf24453..aa573acded 100644 --- a/src/flash/nor/aducm360.c +++ b/src/flash/nor/aducm360.c @@ -79,7 +79,7 @@ static int aducm360_build_sector_list(struct flash_bank *bank) /* sector size is 512 */ bank->num_sectors = bank->size / FLASH_SECTOR_SIZE; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); - for (unsigned i = 0; i < bank->num_sectors; ++i) { + for (unsigned int i = 0; i < bank->num_sectors; ++i) { bank->sectors[i].offset = offset; bank->sectors[i].size = FLASH_SECTOR_SIZE; offset += bank->sectors[i].size; diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index 8e8497eb0d..b86a18da75 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -154,15 +154,15 @@ struct sam3_bank_private { struct sam3_chip *chip; /* so we can find the original bank pointer */ struct flash_bank *bank; - unsigned bank_number; + unsigned int bank_number; uint32_t controller_address; uint32_t base_address; uint32_t flash_wait_states; bool present; - unsigned size_bytes; - unsigned nsectors; - unsigned sector_size; - unsigned page_size; + unsigned int size_bytes; + unsigned int nsectors; + unsigned int sector_size; + unsigned int page_size; }; struct sam3_chip_details { @@ -176,12 +176,12 @@ struct sam3_chip_details { uint32_t chipid_cidr; const char *name; - unsigned n_gpnvms; + unsigned int n_gpnvms; #define SAM3_N_NVM_BITS 3 - unsigned gpnvm[SAM3_N_NVM_BITS]; - unsigned total_flash_size; - unsigned total_sram_size; - unsigned n_banks; + unsigned int gpnvm[SAM3_N_NVM_BITS]; + unsigned int total_flash_size; + unsigned int total_sram_size; + unsigned int n_banks; #define SAM3_MAX_FLASH_BANKS 2 /* these are "initialized" from the global const data */ struct sam3_bank_private bank[SAM3_MAX_FLASH_BANKS]; @@ -2029,7 +2029,7 @@ static int efc_get_result(struct sam3_bank_private *private, uint32_t *v) } static int efc_start_command(struct sam3_bank_private *private, - unsigned command, unsigned argument) + unsigned int command, unsigned int argument) { uint32_t n, v; int r; @@ -2124,8 +2124,8 @@ static int efc_start_command(struct sam3_bank_private *private, * @param status - put command status bits here */ static int efc_perform_command(struct sam3_bank_private *private, - unsigned command, - unsigned argument, + unsigned int command, + unsigned int argument, uint32_t *status) { @@ -2220,7 +2220,7 @@ static int flashd_erase_entire_bank(struct sam3_bank_private *private) * @param puthere - result stored here. */ /* ------------------------------------------------------------------------------ */ -static int flashd_get_gpnvm(struct sam3_bank_private *private, unsigned gpnvm, unsigned *puthere) +static int flashd_get_gpnvm(struct sam3_bank_private *private, unsigned int gpnvm, unsigned int *puthere) { uint32_t v; int r; @@ -2261,10 +2261,10 @@ static int flashd_get_gpnvm(struct sam3_bank_private *private, unsigned gpnvm, u * @param gpnvm GPNVM index. * @returns 0 if successful; otherwise returns an error code. */ -static int flashd_clr_gpnvm(struct sam3_bank_private *private, unsigned gpnvm) +static int flashd_clr_gpnvm(struct sam3_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; LOG_DEBUG("Here"); if (private->bank_number != 0) { @@ -2293,10 +2293,10 @@ static int flashd_clr_gpnvm(struct sam3_bank_private *private, unsigned gpnvm) * @param private info about the bank * @param gpnvm GPNVM index. */ -static int flashd_set_gpnvm(struct sam3_bank_private *private, unsigned gpnvm) +static int flashd_set_gpnvm(struct sam3_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (private->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); @@ -2346,8 +2346,8 @@ static int flashd_get_lock_bits(struct sam3_bank_private *private, uint32_t *v) */ static int flashd_unlock(struct sam3_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { int r; uint32_t status; @@ -2376,8 +2376,8 @@ static int flashd_unlock(struct sam3_bank_private *private, * @param end_sector - last sector (inclusive) to lock */ static int flashd_lock(struct sam3_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { uint32_t status; uint32_t pg; @@ -2405,8 +2405,8 @@ static int flashd_lock(struct sam3_bank_private *private, static uint32_t sam3_reg_fieldname(struct sam3_chip *chip, const char *regname, uint32_t value, - unsigned shift, - unsigned width) + unsigned int shift, + unsigned int width) { uint32_t v; int hwidth, dwidth; @@ -2491,7 +2491,7 @@ static const char *const sramsize[] = { }; -static const struct archnames { unsigned value; const char *name; } archnames[] = { +static const struct archnames { unsigned int value; const char *name; } archnames[] = { { 0x19, "AT91SAM9xx Series" }, { 0x29, "AT91SAM9XExx Series" }, { 0x34, "AT91x34 Series" }, @@ -2951,7 +2951,7 @@ static int sam3_protect_check(struct flash_bank *bank) { int r; uint32_t v = 0; - unsigned x; + unsigned int x; struct sam3_bank_private *private; LOG_DEBUG("Begin"); @@ -3071,7 +3071,7 @@ static int sam3_get_details(struct sam3_bank_private *private) const struct sam3_chip_details *details; struct sam3_chip *chip; struct flash_bank *saved_banks[SAM3_MAX_FLASH_BANKS]; - unsigned x; + unsigned int x; LOG_DEBUG("Begin"); details = all_sam3_details; @@ -3264,7 +3264,7 @@ static int sam3_protect(struct flash_bank *bank, int set, unsigned int first, } -static int sam3_page_read(struct sam3_bank_private *private, unsigned pagenum, uint8_t *buf) +static int sam3_page_read(struct sam3_bank_private *private, unsigned int pagenum, uint8_t *buf) { uint32_t adr; int r; @@ -3283,7 +3283,7 @@ static int sam3_page_read(struct sam3_bank_private *private, unsigned pagenum, u return r; } -static int sam3_page_write(struct sam3_bank_private *private, unsigned pagenum, const uint8_t *buf) +static int sam3_page_write(struct sam3_bank_private *private, unsigned int pagenum, const uint8_t *buf) { uint32_t adr; uint32_t status; @@ -3347,10 +3347,10 @@ static int sam3_write(struct flash_bank *bank, uint32_t count) { int n; - unsigned page_cur; - unsigned page_end; + unsigned int page_cur; + unsigned int page_end; int r; - unsigned page_offset; + unsigned int page_offset; struct sam3_bank_private *private; uint8_t *pagebuffer; @@ -3497,7 +3497,7 @@ COMMAND_HANDLER(sam3_handle_info_command) if (!chip) return ERROR_OK; - unsigned x; + unsigned int x; int r; /* bank0 must exist before we can do anything */ @@ -3549,7 +3549,7 @@ COMMAND_HANDLER(sam3_handle_info_command) COMMAND_HANDLER(sam3_handle_gpnvm_command) { - unsigned x, v; + unsigned int x, v; int r, who; struct sam3_chip *chip; diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 31ae35ccd4..26a803784d 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -134,15 +134,15 @@ struct sam4_bank_private { struct sam4_chip *chip; /* so we can find the original bank pointer */ struct flash_bank *bank; - unsigned bank_number; + unsigned int bank_number; uint32_t controller_address; uint32_t base_address; uint32_t flash_wait_states; bool present; - unsigned size_bytes; - unsigned nsectors; - unsigned sector_size; - unsigned page_size; + unsigned int size_bytes; + unsigned int nsectors; + unsigned int sector_size; + unsigned int page_size; }; struct sam4_chip_details { @@ -156,12 +156,12 @@ struct sam4_chip_details { uint32_t chipid_cidr; const char *name; - unsigned n_gpnvms; + unsigned int n_gpnvms; #define SAM4_N_NVM_BITS 3 - unsigned gpnvm[SAM4_N_NVM_BITS]; - unsigned total_flash_size; - unsigned total_sram_size; - unsigned n_banks; + unsigned int gpnvm[SAM4_N_NVM_BITS]; + unsigned int total_flash_size; + unsigned int total_sram_size; + unsigned int n_banks; #define SAM4_MAX_FLASH_BANKS 2 /* these are "initialized" from the global const data */ struct sam4_bank_private bank[SAM4_MAX_FLASH_BANKS]; @@ -1479,7 +1479,7 @@ static int efc_get_result(struct sam4_bank_private *private, uint32_t *v) } static int efc_start_command(struct sam4_bank_private *private, - unsigned command, unsigned argument) + unsigned int command, unsigned int argument) { uint32_t n, v; int r; @@ -1574,8 +1574,8 @@ static int efc_start_command(struct sam4_bank_private *private, * @param status - put command status bits here */ static int efc_perform_command(struct sam4_bank_private *private, - unsigned command, - unsigned argument, + unsigned int command, + unsigned int argument, uint32_t *status) { @@ -1716,7 +1716,7 @@ static int flashd_erase_pages(struct sam4_bank_private *private, * @param puthere - result stored here. */ /* ------------------------------------------------------------------------------ */ -static int flashd_get_gpnvm(struct sam4_bank_private *private, unsigned gpnvm, unsigned *puthere) +static int flashd_get_gpnvm(struct sam4_bank_private *private, unsigned int gpnvm, unsigned int *puthere) { uint32_t v; int r; @@ -1757,10 +1757,10 @@ static int flashd_get_gpnvm(struct sam4_bank_private *private, unsigned gpnvm, u * @param gpnvm GPNVM index. * @returns 0 if successful; otherwise returns an error code. */ -static int flashd_clr_gpnvm(struct sam4_bank_private *private, unsigned gpnvm) +static int flashd_clr_gpnvm(struct sam4_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; LOG_DEBUG("Here"); if (private->bank_number != 0) { @@ -1789,10 +1789,10 @@ static int flashd_clr_gpnvm(struct sam4_bank_private *private, unsigned gpnvm) * @param private info about the bank * @param gpnvm GPNVM index. */ -static int flashd_set_gpnvm(struct sam4_bank_private *private, unsigned gpnvm) +static int flashd_set_gpnvm(struct sam4_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (private->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); @@ -1846,8 +1846,8 @@ static int flashd_get_lock_bits(struct sam4_bank_private *private, uint32_t *v) */ static int flashd_unlock(struct sam4_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { int r; uint32_t status; @@ -1876,8 +1876,8 @@ static int flashd_unlock(struct sam4_bank_private *private, * @param end_sector - last sector (inclusive) to lock */ static int flashd_lock(struct sam4_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { uint32_t status; uint32_t pg; @@ -1905,8 +1905,8 @@ static int flashd_lock(struct sam4_bank_private *private, static uint32_t sam4_reg_fieldname(struct sam4_chip *chip, const char *regname, uint32_t value, - unsigned shift, - unsigned width) + unsigned int shift, + unsigned int width) { uint32_t v; int hwidth, dwidth; @@ -1991,7 +1991,7 @@ static const char *const sramsize[] = { }; -static const struct archnames { unsigned value; const char *name; } archnames[] = { +static const struct archnames { unsigned int value; const char *name; } archnames[] = { { 0x19, "AT91SAM9xx Series" }, { 0x29, "AT91SAM9XExx Series" }, { 0x34, "AT91x34 Series" }, @@ -2444,7 +2444,7 @@ static int sam4_protect_check(struct flash_bank *bank) { int r; uint32_t v[4] = {0}; - unsigned x; + unsigned int x; struct sam4_bank_private *private; LOG_DEBUG("Begin"); @@ -2557,7 +2557,7 @@ static int sam4_get_details(struct sam4_bank_private *private) const struct sam4_chip_details *details; struct sam4_chip *chip; struct flash_bank *saved_banks[SAM4_MAX_FLASH_BANKS]; - unsigned x; + unsigned int x; LOG_DEBUG("Begin"); details = all_sam4_details; @@ -2796,7 +2796,7 @@ static int sam4_protect(struct flash_bank *bank, int set, unsigned int first, } -static int sam4_page_read(struct sam4_bank_private *private, unsigned pagenum, uint8_t *buf) +static int sam4_page_read(struct sam4_bank_private *private, unsigned int pagenum, uint8_t *buf) { uint32_t adr; int r; @@ -2841,7 +2841,7 @@ static int sam4_set_wait(struct sam4_bank_private *private) return r; } -static int sam4_page_write(struct sam4_bank_private *private, unsigned pagenum, const uint8_t *buf) +static int sam4_page_write(struct sam4_bank_private *private, unsigned int pagenum, const uint8_t *buf) { uint32_t adr; uint32_t status; @@ -2891,10 +2891,10 @@ static int sam4_write(struct flash_bank *bank, uint32_t count) { int n; - unsigned page_cur; - unsigned page_end; + unsigned int page_cur; + unsigned int page_end; int r; - unsigned page_offset; + unsigned int page_offset; struct sam4_bank_private *private; uint8_t *pagebuffer; @@ -3045,7 +3045,7 @@ COMMAND_HANDLER(sam4_handle_info_command) if (!chip) return ERROR_OK; - unsigned x; + unsigned int x; int r; /* bank0 must exist before we can do anything */ @@ -3097,7 +3097,7 @@ COMMAND_HANDLER(sam4_handle_info_command) COMMAND_HANDLER(sam4_handle_gpnvm_command) { - unsigned x, v; + unsigned int x, v; int r, who; struct sam4_chip *chip; diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 36298f19d0..0f7b0bb300 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -365,7 +365,7 @@ static const struct samd_family *samd_find_family(uint32_t id) uint8_t family = SAMD_GET_FAMILY(id); uint8_t series = SAMD_GET_SERIES(id); - for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(samd_families); i++) { if (samd_families[i].processor == processor && samd_families[i].series == series && samd_families[i].family == family) @@ -387,7 +387,7 @@ static const struct samd_part *samd_find_part(uint32_t id) if (!family) return NULL; - for (unsigned i = 0; i < family->num_parts; i++) { + for (unsigned int i = 0; i < family->num_parts; i++) { if (family->parts[i].id == devsel) return &family->parts[i]; } diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c index 1d1ec02b33..7ce42b2da7 100644 --- a/src/flash/nor/ath79.c +++ b/src/flash/nor/ath79.c @@ -513,7 +513,7 @@ static int ath79_erase(struct flash_bank *bank, unsigned int first, if (ath79_info->dev->erase_cmd == 0x00) return ERROR_FLASH_OPER_UNSUPPORTED; - for (unsigned sector = first; sector <= last; sector++) { + for (unsigned int sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %u protected", sector); return ERROR_FAIL; diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index a6ac9060a3..f34958fdb9 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -224,7 +224,7 @@ static const struct samd_family *samd_find_family(uint32_t id) uint8_t family = SAMD_GET_FAMILY(id); uint8_t series = SAMD_GET_SERIES(id); - for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(samd_families); i++) { if (samd_families[i].processor == processor && samd_families[i].series == series && samd_families[i].family == family) @@ -246,7 +246,7 @@ static const struct samd_part *samd_find_part(uint32_t id) if (!family) return NULL; - for (unsigned i = 0; i < family->num_parts; i++) { + for (unsigned int i = 0; i < family->num_parts; i++) { if (family->parts[i].id == devsel) return &family->parts[i]; } diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c index 24c432cba3..d6d8938b67 100644 --- a/src/flash/nor/atsamv.c +++ b/src/flash/nor/atsamv.c @@ -55,8 +55,8 @@ struct samv_flash_bank { bool probed; - unsigned size_bytes; - unsigned gpnvm[SAMV_NUM_GPNVM_BITS]; + unsigned int size_bytes; + unsigned int gpnvm[SAMV_NUM_GPNVM_BITS]; }; /* The actual sector size of the SAMV7 flash memory is 128K bytes. @@ -82,7 +82,7 @@ static int samv_efc_get_result(struct target *target, uint32_t *v) } static int samv_efc_start_command(struct target *target, - unsigned command, unsigned argument) + unsigned int command, unsigned int argument) { uint32_t v; samv_efc_get_status(target, &v); @@ -100,7 +100,7 @@ static int samv_efc_start_command(struct target *target, } static int samv_efc_perform_command(struct target *target, - unsigned command, unsigned argument, uint32_t *status) + unsigned int command, unsigned int argument, uint32_t *status) { int r; uint32_t v; @@ -166,7 +166,7 @@ static int samv_erase_pages(struct target *target, first_page | erase_pages, status); } -static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out) +static int samv_get_gpnvm(struct target *target, unsigned int gpnvm, unsigned int *out) { uint32_t v; int r; @@ -190,10 +190,10 @@ static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out) return r; } -static int samv_clear_gpnvm(struct target *target, unsigned gpnvm) +static int samv_clear_gpnvm(struct target *target, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (gpnvm >= SAMV_NUM_GPNVM_BITS) { LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS); @@ -209,10 +209,10 @@ static int samv_clear_gpnvm(struct target *target, unsigned gpnvm) return r; } -static int samv_set_gpnvm(struct target *target, unsigned gpnvm) +static int samv_set_gpnvm(struct target *target, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (gpnvm >= SAMV_NUM_GPNVM_BITS) { LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS); return ERROR_FAIL; @@ -231,7 +231,7 @@ static int samv_set_gpnvm(struct target *target, unsigned gpnvm) } static int samv_flash_unlock(struct target *target, - unsigned start_sector, unsigned end_sector) + unsigned int start_sector, unsigned int end_sector) { int r; uint32_t status; @@ -251,7 +251,7 @@ static int samv_flash_unlock(struct target *target, } static int samv_flash_lock(struct target *target, - unsigned start_sector, unsigned end_sector) + unsigned int start_sector, unsigned int end_sector) { uint32_t status; uint32_t pg; @@ -419,7 +419,7 @@ static int samv_protect(struct flash_bank *bank, int set, unsigned int first, } static int samv_page_read(struct target *target, - unsigned page_num, uint8_t *buf) + unsigned int page_num, uint8_t *buf) { uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE; int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf); @@ -430,7 +430,7 @@ static int samv_page_read(struct target *target, } static int samv_page_write(struct target *target, - unsigned pagenum, const uint8_t *buf) + unsigned int pagenum, const uint8_t *buf) { uint32_t status; const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE; @@ -618,7 +618,7 @@ COMMAND_HANDLER(samv_handle_gpnvm_command) return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned v = 0; + unsigned int v = 0; if (!strcmp("show", CMD_ARGV[0])) { if (who == -1) { showall: diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 96bd7353ff..2a15e49132 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -806,7 +806,7 @@ int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char ** } bank->driver_priv = cfi_info; - for (unsigned i = 6; i < argc; i++) { + for (unsigned int i = 6; i < argc; i++) { if (strcmp(argv[i], "x16_as_x8") == 0) cfi_info->x16_as_x8 = true; else if (strcmp(argv[i], "data_swap") == 0) diff --git a/src/flash/nor/cfi.h b/src/flash/nor/cfi.h index ec7f47403a..3a76d98ef2 100644 --- a/src/flash/nor/cfi.h +++ b/src/flash/nor/cfi.h @@ -58,10 +58,10 @@ struct cfi_flash_bank { void *alt_ext; /* calculated timeouts */ - unsigned word_write_timeout; - unsigned buf_write_timeout; - unsigned block_erase_timeout; - unsigned chip_erase_timeout; + unsigned int word_write_timeout; + unsigned int buf_write_timeout; + unsigned int block_erase_timeout; + unsigned int chip_erase_timeout; /* memory accessors */ int (*write_mem)(struct flash_bank *bank, target_addr_t addr, diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 5e6c971527..5c4f2accaf 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -164,7 +164,7 @@ int default_flash_verify(struct flash_bank *bank, void flash_bank_add(struct flash_bank *bank) { /* put flash bank in linked list */ - unsigned bank_num = 0; + unsigned int bank_num = 0; if (flash_banks) { /* find last flash bank */ struct flash_bank *p = flash_banks; @@ -242,8 +242,8 @@ void flash_free_all_banks(void) struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) { - unsigned requested = get_flash_name_index(name); - unsigned found = 0; + unsigned int requested = get_flash_name_index(name); + unsigned int found = 0; struct flash_bank *bank; for (bank = flash_banks; bank; bank = bank->next) { diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index ff175a1329..f8cf5e2698 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -250,7 +250,7 @@ int get_flash_bank_by_num(unsigned int num, struct flash_bank **bank); * @param bank On output, contains a pointer to the bank or NULL. * @returns ERROR_OK on success, or an error indicating the problem. */ -COMMAND_HELPER(flash_command_get_bank, unsigned name_index, +COMMAND_HELPER(flash_command_get_bank, unsigned int name_index, struct flash_bank **bank); /** * Retrieves @a bank from a command argument, reporting errors parsing diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 34359889a6..dd9995ecba 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -91,7 +91,7 @@ static const struct flash_driver * const flash_drivers[] = { const struct flash_driver *flash_driver_find_by_name(const char *name) { - for (unsigned i = 0; flash_drivers[i]; i++) { + for (unsigned int i = 0; flash_drivers[i]; i++) { if (strcmp(name, flash_drivers[i]->name) == 0) return flash_drivers[i]; } diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index 9191764a96..6c4e8a928f 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -531,7 +531,7 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer, bin_size = sizeof(riscv64_bin); } - unsigned data_wa_size = 0; + unsigned int data_wa_size = 0; if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) { retval = target_write_buffer(target, algorithm_wa->address, bin_size, bin); diff --git a/src/flash/nor/fm4.c b/src/flash/nor/fm4.c index 979ae84d01..2db79ef502 100644 --- a/src/flash/nor/fm4.c +++ b/src/flash/nor/fm4.c @@ -107,7 +107,7 @@ static int fm4_flash_erase(struct flash_bank *bank, unsigned int first, struct working_area *workarea; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_algo; - unsigned i; + unsigned int i; int retval; const uint8_t erase_sector_code[] = { #include "../../../contrib/loaders/flash/fm4/erase.inc" @@ -207,7 +207,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer, struct armv7m_algorithm armv7m_algo; uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2); uint32_t result; - unsigned i; + unsigned int i; int retval, retval2 = ERROR_OK; const uint8_t write_block_code[] = { #include "../../../contrib/loaders/flash/fm4/write.inc" diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 2d0a75334d..2f88b9c1fe 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -256,7 +256,7 @@ struct kinetis_flash_bank { struct kinetis_chip *k_chip; bool probed; - unsigned bank_number; /* bank number in particular chip */ + unsigned int bank_number; /* bank number in particular chip */ struct flash_bank *bank; uint32_t sector_size; @@ -285,9 +285,9 @@ struct kinetis_chip { uint32_t fcfg2_maxaddr0_shifted; uint32_t fcfg2_maxaddr1_shifted; - unsigned num_pflash_blocks, num_nvm_blocks; - unsigned pflash_sector_size, nvm_sector_size; - unsigned max_flash_prog_size; + unsigned int num_pflash_blocks, num_nvm_blocks; + unsigned int pflash_sector_size, nvm_sector_size; + unsigned int max_flash_prog_size; uint32_t pflash_base; uint32_t pflash_size; @@ -337,7 +337,7 @@ struct kinetis_chip { char name[40]; - unsigned num_banks; + unsigned int num_banks; struct kinetis_flash_bank banks[KINETIS_MAX_BANKS]; }; @@ -425,7 +425,7 @@ static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip); static int kinetis_auto_probe(struct flash_bank *bank); -static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) +static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned int reg, uint32_t value) { LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); @@ -453,7 +453,7 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3 return ERROR_OK; } -static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) +static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned int reg, uint32_t *result) { struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); if (!ap) { @@ -479,7 +479,7 @@ static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32 return ERROR_OK; } -static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, +static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value, uint32_t timeout_ms) { uint32_t val; @@ -977,7 +977,7 @@ static void kinetis_free_driver_priv(struct flash_bank *bank) static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) { - unsigned num_blocks; + unsigned int num_blocks; struct kinetis_flash_bank *k_bank; struct flash_bank *bank; char base_name[69], name[87], num[11]; @@ -1463,7 +1463,7 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) uint32_t fprot = 0xffffffff; uint8_t fsec = 0xfe; /* set MCU unsecure */ uint8_t fdprot = 0xff; - unsigned num_blocks; + unsigned int num_blocks; uint32_t pflash_bit; uint8_t dflash_bit; struct flash_bank *bank_iter; @@ -2269,12 +2269,12 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) uint32_t ee_size = 0; uint32_t pflash_size_k, nvm_size_k, dflash_size_k; uint32_t pflash_size_m; - unsigned num_blocks = 0; - unsigned maxaddr_shift = 13; + unsigned int num_blocks = 0; + unsigned int maxaddr_shift = 13; struct target *target = k_chip->target; - unsigned familyid = 0, subfamid = 0; - unsigned cpu_mhz = 120; + unsigned int familyid = 0, subfamid = 0; + unsigned int cpu_mhz = 120; bool use_nvm_marking = false; char flash_marking[12], nvm_marking[2]; char name[40]; @@ -2895,7 +2895,7 @@ static int kinetis_probe(struct flash_bank *bank) { int result; uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1; - unsigned num_blocks, first_nvm_bank; + unsigned int num_blocks, first_nvm_bank; uint32_t size_k; struct kinetis_flash_bank *k_bank = bank->driver_priv; struct kinetis_chip *k_chip; @@ -2940,7 +2940,7 @@ static int kinetis_probe(struct flash_bank *bank) } else if (k_bank->bank_number < num_blocks) { /* nvm, banks start at address 0x10000000 */ - unsigned nvm_ord = k_bank->bank_number - first_nvm_bank; + unsigned int nvm_ord = k_bank->bank_number - first_nvm_bank; uint32_t limit; k_bank->flash_class = FC_FLEX_NVM; @@ -3139,8 +3139,8 @@ static int kinetis_blank_check(struct flash_bank *bank) COMMAND_HANDLER(kinetis_nvm_partition) { int result; - unsigned bank_idx; - unsigned num_blocks, first_nvm_bank; + unsigned int bank_idx; + unsigned int num_blocks, first_nvm_bank; unsigned long par, log2 = 0, ee1 = 0, ee2 = 0; enum { SHOW_INFO, DF_SIZE, EEBKP_SIZE } sz_type = SHOW_INFO; bool enable; diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index c069f3ac89..e4dffa6d5c 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -134,7 +134,7 @@ struct kinetis_ke_flash_bank { #define MDM_ACCESS_TIMEOUT 3000 /* iterations */ -static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) +static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned int reg, uint32_t value) { LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); @@ -161,7 +161,7 @@ static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, ui return ERROR_OK; } -static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) +static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned int reg, uint32_t *result) { struct adiv5_ap *ap = dap_get_ap(dap, 1); if (!ap) { @@ -187,7 +187,7 @@ static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uin return ERROR_OK; } -static int kinetis_ke_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value) +static int kinetis_ke_mdm_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value) { uint32_t val; int retval; diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index 052a42d235..267fd43120 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -202,14 +202,14 @@ static int max32xxx_protect_check(struct flash_bank *bank) return ERROR_FLASH_BANK_NOT_PROBED; if (!info->max326xx) { - for (unsigned i = 0; i < bank->num_sectors; i++) + for (unsigned int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = -1; return ERROR_FLASH_OPER_UNSUPPORTED; } /* Check the protection */ - for (unsigned i = 0; i < bank->num_sectors; i++) { + for (unsigned int i = 0; i < bank->num_sectors; i++) { if (i%32 == 0) target_read_u32(target, info->flc_base + FLSH_PROT + ((i/32)*4), &temp_reg); @@ -360,7 +360,7 @@ static int max32xxx_write_block(struct flash_bank *bank, const uint8_t *buffer, struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* power of two, and multiple of word size */ - static const unsigned buf_min = 128; + static const unsigned int buf_min = 128; /* for small buffers it's faster not to download an algorithm */ if (wcount * 4 < buf_min) @@ -903,7 +903,7 @@ COMMAND_HANDLER(max32xxx_handle_protection_check_command) } LOG_WARNING("s: a:
p:"); - for (unsigned i = 0; i < bank->num_sectors; i += 4) { + for (unsigned int i = 0; i < bank->num_sectors; i += 4) { LOG_WARNING("s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d", (i+0), (i+0)*info->sector_size, bank->sectors[(i+0)].is_protected, (i+1), (i+1)*info->sector_size, bank->sectors[(i+1)].is_protected, diff --git a/src/flash/nor/psoc5lp.c b/src/flash/nor/psoc5lp.c index 407efbcab3..e8c9019505 100644 --- a/src/flash/nor/psoc5lp.c +++ b/src/flash/nor/psoc5lp.c @@ -102,10 +102,10 @@ struct psoc5lp_device { uint32_t id; - unsigned fam; - unsigned speed_mhz; - unsigned flash_kb; - unsigned eeprom_kb; + unsigned int fam; + unsigned int speed_mhz; + unsigned int flash_kb; + unsigned int eeprom_kb; }; /* @@ -245,7 +245,7 @@ static int psoc5lp_find_device(struct target *target, const struct psoc5lp_device **device) { uint32_t device_id; - unsigned i; + unsigned int i; int retval; *device = NULL; @@ -381,9 +381,9 @@ static int psoc5lp_spc_load_byte(struct target *target, } static int psoc5lp_spc_load_row(struct target *target, - uint8_t array_id, const uint8_t *data, unsigned row_size) + uint8_t array_id, const uint8_t *data, unsigned int row_size) { - unsigned i; + unsigned int i; int retval; retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW); @@ -853,7 +853,7 @@ static int psoc5lp_eeprom_write(struct flash_bank *bank, { struct target *target = bank->target; uint8_t temp[2]; - unsigned row; + unsigned int row; int retval; if (offset % EEPROM_ROW_SIZE != 0) { @@ -1124,7 +1124,7 @@ static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer, struct working_area *code_area, *even_row_area, *odd_row_area; uint32_t row_size; uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE]; - unsigned array_id, row; + unsigned int array_id, row; int i, retval; if (offset + byte_count > bank->size) { @@ -1183,7 +1183,7 @@ static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer, row < ROWS_PER_BLOCK && byte_count > 0; row++) { bool even_row = (row % 2 == 0); struct working_area *data_area = even_row ? even_row_area : odd_row_area; - unsigned len = MIN(ROW_SIZE, byte_count); + unsigned int len = MIN(ROW_SIZE, byte_count); LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT, array_id, row, data_area->address); @@ -1307,8 +1307,8 @@ static int psoc5lp_protect_check(struct flash_bank *bank) { struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; uint8_t row_data[ROW_SIZE]; - const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8; - unsigned i, k, num_sectors; + const unsigned int protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8; + unsigned int i, k, num_sectors; int retval; if (bank->target->state != TARGET_HALTED) { diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index 42550d06bc..58d7913c26 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -859,7 +859,7 @@ static int sim3x_flash_info(struct flash_bank *bank, struct command_invocation * * reg 3:2 - register * reg 1:0 - no effect */ -static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) +static int ap_write_register(struct adiv5_dap *dap, unsigned int reg, uint32_t value) { LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value); @@ -886,7 +886,7 @@ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value return ERROR_OK; } -static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) +static int ap_read_register(struct adiv5_dap *dap, unsigned int reg, uint32_t *result) { struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP); if (!ap) { @@ -912,7 +912,7 @@ static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *resul return ERROR_OK; } -static int ap_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value, int timeout) +static int ap_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value, int timeout) { uint32_t val; int retval; diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 25bc5507ad..1f53b2f35e 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -530,7 +530,7 @@ static void stellaris_set_flash_timing(struct flash_bank *bank) target_write_u32(target, SCB_BASE | USECRL, usecrl); } -static const unsigned rcc_xtal[32] = { +static const unsigned int rcc_xtal[32] = { [0x00] = 1000000, /* no pll */ [0x01] = 1843200, /* no pll */ [0x02] = 2000000, /* no pll */ @@ -569,7 +569,7 @@ static void stellaris_read_clock_info(struct flash_bank *bank) struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc; - unsigned xtal; + unsigned int xtal; unsigned long mainfreq; target_read_u32(target, SCB_BASE | RCC, &rcc); @@ -1029,7 +1029,7 @@ static int stellaris_write_block(struct flash_bank *bank, int retval = ERROR_OK; /* power of two, and multiple of word size */ - static const unsigned buf_min = 128; + static const unsigned int buf_min = 128; /* for small buffers it's faster not to download an algorithm */ if (wcount * 4 < buf_min) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 6ac932be7f..e21620934a 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -36,7 +36,7 @@ COMMAND_HELPER(flash_command_get_bank_probe_optional, unsigned int name_index, if (*bank) return ERROR_OK; - unsigned bank_num; + unsigned int bank_num; COMMAND_PARSE_NUMBER(uint, name, bank_num); if (do_probe) { @@ -48,7 +48,7 @@ COMMAND_HELPER(flash_command_get_bank_probe_optional, unsigned int name_index, } } -COMMAND_HELPER(flash_command_get_bank, unsigned name_index, +COMMAND_HELPER(flash_command_get_bank, unsigned int name_index, struct flash_bank **bank) { return CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional, @@ -518,7 +518,7 @@ COMMAND_HANDLER(handle_flash_fill_command) uint64_t pattern; uint32_t count; struct target *target = get_current_target(CMD_CTX); - unsigned i; + unsigned int i; uint32_t wordsize; int retval; @@ -1316,7 +1316,7 @@ COMMAND_HANDLER(handle_flash_banks_command) if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned n = 0; + unsigned int n = 0; for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) { command_print(CMD, "#%d : %s (%s) at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32 ", " "buswidth %u, chipwidth %u", p->bank_number, diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index 6e0ea5b950..00ee77bb80 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -16,7 +16,7 @@ * ---------------------------------------------------------------------- */ struct tms470_flash_bank { - unsigned ordinal; + unsigned int ordinal; /* device identification register */ uint32_t device_ident_reg; @@ -391,7 +391,7 @@ static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set) /* only perform the key match when 3VSTAT is clear */ target_read_u32(target, 0xFFE8BC0C, &fmmstat); if (!(fmmstat & 0x08)) { - unsigned i; + unsigned int i; uint32_t fmbptr, fmbac2, orig_fmregopt; target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07); @@ -455,7 +455,7 @@ static int tms470_unlock_flash(struct flash_bank *bank) { struct target *target = bank->target; const uint32_t *p_key_sets[5]; - unsigned i, key_set_count; + unsigned int i, key_set_count; if (keys_set) { key_set_count = 5; diff --git a/src/flash/nor/xmc1xxx.c b/src/flash/nor/xmc1xxx.c index 6e30fc125c..4aa97a912f 100644 --- a/src/flash/nor/xmc1xxx.c +++ b/src/flash/nor/xmc1xxx.c @@ -84,7 +84,7 @@ static int xmc1xxx_erase(struct flash_bank *bank, unsigned int first, struct working_area *workarea; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_algo; - unsigned i; + unsigned int i; int retval; const uint8_t erase_code[] = { #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc" @@ -159,7 +159,7 @@ static int xmc1xxx_erase_check(struct flash_bank *bank) struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_algo; uint16_t val; - unsigned i; + unsigned int i; int retval; const uint8_t erase_check_code[] = { #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc" @@ -245,7 +245,7 @@ static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer, struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_algo; uint32_t block_count = DIV_ROUND_UP(byte_count, NVM_BLOCK_SIZE); - unsigned i; + unsigned int i; int retval; const uint8_t write_code[] = { #include "../../../contrib/loaders/flash/xmc1xxx/write.inc" From e72733d59025b5d595bf955b227e95e5db7305c7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:20:48 +0200 Subject: [PATCH 0969/1312] target: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Ignore the cast as they could be better addressed. Fix only minor additional checkpatch issue (spacing and line length). Use Checkpatch-ignore below for the function pointers in the file 'armv7a_cache_l2x.h' that do not assign the identifier names to the function arguments. Most of these struct are unused and should be fixed or dropped. Checkpatch-ignore: FUNCTION_ARGUMENTS Change-Id: I8f27e68eb3502e431c1ba801b362358105f9f2dc Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8480 Tested-by: jenkins Reviewed-by: zapb --- src/target/adi_v5_jtag.c | 10 +++--- src/target/adi_v5_swd.c | 10 +++--- src/target/arc.c | 4 +-- src/target/arm.h | 8 ++--- src/target/arm11.c | 2 +- src/target/arm11.h | 2 +- src/target/arm11_dbgtap.c | 10 +++--- src/target/arm9tdmi.c | 6 ++-- src/target/arm_adi_v5.h | 20 +++++------ src/target/arm_disassembler.c | 20 +++++------ src/target/arm_disassembler.h | 2 +- src/target/arm_dpm.c | 38 ++++++++++----------- src/target/arm_dpm.h | 14 ++++---- src/target/armv4_5.c | 22 ++++++------ src/target/armv7a_cache_l2x.h | 8 ++--- src/target/armv7m.c | 6 ++-- src/target/armv8.c | 22 ++++++------ src/target/armv8.h | 2 +- src/target/armv8_dpm.c | 28 +++++++-------- src/target/cortex_a.c | 4 +-- src/target/cortex_m.c | 14 ++++---- src/target/dsp563xx.c | 4 +-- src/target/dsp5680xx.c | 2 +- src/target/esirisc.c | 4 +-- src/target/esirisc_trace.c | 10 +++--- src/target/etb.h | 2 +- src/target/etm.c | 12 +++---- src/target/hla_target.c | 2 +- src/target/image.c | 4 +-- src/target/lakemont.c | 6 ++-- src/target/mips32.c | 4 +-- src/target/mips32_pracc.c | 6 ++-- src/target/mips32_pracc.h | 2 +- src/target/mips64.c | 10 +++--- src/target/mips64_pracc.c | 64 +++++++++++++++++------------------ src/target/mips64_pracc.h | 14 ++++---- src/target/mips_ejtag.c | 2 +- src/target/mips_ejtag.h | 2 +- src/target/register.h | 2 +- src/target/stm8.c | 2 +- src/target/target.c | 46 ++++++++++++------------- src/target/target.h | 6 ++-- src/target/target_type.h | 2 +- src/target/x86_32_common.c | 20 +++++------ src/target/xscale.c | 14 ++++---- 45 files changed, 248 insertions(+), 246 deletions(-) diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 8d54a50fb0..fee1a24858 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -736,7 +736,7 @@ static int jtag_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) return retval; } -static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, +static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) { int retval = jtag_limit_queue_size(dap); @@ -749,7 +749,7 @@ static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, return retval; } -static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, +static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { int retval = jtag_limit_queue_size(dap); @@ -763,7 +763,7 @@ static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, } /** Select the AP register bank */ -static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) +static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned int reg) { int retval; struct adiv5_dap *dap = ap->dap; @@ -818,7 +818,7 @@ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) return ERROR_OK; } -static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg, +static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { int retval = jtag_limit_queue_size(ap->dap); @@ -840,7 +840,7 @@ static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg, return retval; } -static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg, +static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { int retval = jtag_limit_queue_size(ap->dap); diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 1231005884..dda1b0674a 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -485,7 +485,7 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) return check_sync(dap); } -static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, +static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) { int retval = swd_check_reconnect(dap); @@ -499,7 +499,7 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, return swd_queue_dp_read_inner(dap, reg, data); } -static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, +static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { const struct swd_driver *swd = adiv5_dap_swd_driver(dap); @@ -517,7 +517,7 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, } /** Select the AP register bank */ -static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) +static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned int reg) { int retval; struct adiv5_dap *dap = ap->dap; @@ -567,7 +567,7 @@ static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) return ERROR_OK; } -static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, +static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { struct adiv5_dap *dap = ap->dap; @@ -592,7 +592,7 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, return check_sync(dap); } -static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, +static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { struct adiv5_dap *dap = ap->dap; diff --git a/src/target/arc.c b/src/target/arc.c index 72e4d918de..28ce939473 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -516,7 +516,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], unsigned long i = 0; struct reg_cache *reg_cache = target->reg_cache; while (reg_cache) { - for (unsigned j = 0; j < reg_cache->num_regs; j++, i++) + for (unsigned int j = 0; j < reg_cache->num_regs; j++, i++) (*reg_list)[i] = ®_cache->reg_list[j]; reg_cache = reg_cache->next; } @@ -527,7 +527,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], unsigned long gdb_reg_number = 0; struct reg_cache *reg_cache = target->reg_cache; while (reg_cache) { - for (unsigned j = 0; + for (unsigned int j = 0; j < reg_cache->num_regs && gdb_reg_number <= arc->last_general_reg; j++) { if (reg_cache->reg_list[j].exist) { diff --git a/src/target/arm.h b/src/target/arm.h index 0de322a5a1..79ec99d117 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -143,8 +143,8 @@ enum { ARM_VFP_V3_FPSCR, }; -const char *arm_mode_name(unsigned psr_mode); -bool is_arm_mode(unsigned psr_mode); +const char *arm_mode_name(unsigned int psr_mode); +bool is_arm_mode(unsigned int psr_mode); /** The PSR "T" and "J" bits define the mode of "classic ARM" cores. */ enum arm_state { @@ -325,7 +325,7 @@ int arm_blank_check_memory(struct target *target, struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value); void arm_set_cpsr(struct arm *arm, uint32_t cpsr); -struct reg *arm_reg_current(struct arm *arm, unsigned regnum); -struct reg *armv8_reg_current(struct arm *arm, unsigned regnum); +struct reg *arm_reg_current(struct arm *arm, unsigned int regnum); +struct reg *armv8_reg_current(struct arm *arm, unsigned int regnum); #endif /* OPENOCD_TARGET_ARM_H */ diff --git a/src/target/arm11.c b/src/target/arm11.c index 43790c737b..c583a2ebd7 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -478,7 +478,7 @@ static int arm11_resume(struct target *target, int current, /* activate all breakpoints */ if (true) { struct breakpoint *bp; - unsigned brp_num = 0; + unsigned int brp_num = 0; for (bp = target->breakpoints; bp; bp = bp->next) { struct arm11_sc7_action brp[2]; diff --git a/src/target/arm11.h b/src/target/arm11.h index 1f56f7bba4..40a3f9024d 100644 --- a/src/target/arm11.h +++ b/src/target/arm11.h @@ -39,7 +39,7 @@ struct arm11_common { /** Debug module state. */ struct arm_dpm dpm; struct arm11_sc7_action *bpwp_actions; - unsigned bpwp_n; + unsigned int bpwp_n; size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */ size_t free_brps; /**< Number of breakpoints allocated */ diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index b66f886183..36325911ad 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -567,8 +567,8 @@ static int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, chain5_fields[2].in_value = NULL; uint8_t *readies; - unsigned readies_num = count; - unsigned bytes = sizeof(*readies)*readies_num; + unsigned int readies_num = count; + unsigned int bytes = sizeof(*readies) * readies_num; readies = malloc(bytes); if (!readies) { @@ -592,7 +592,7 @@ static int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, int retval = jtag_execute_queue(); if (retval == ERROR_OK) { - unsigned error_count = 0; + unsigned int error_count = 0; for (size_t i = 0; i < readies_num; i++) { if (readies[i] != 1) @@ -1042,7 +1042,7 @@ static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm, * and watchpoint operations instead of running them right away. Since we * pre-allocated our vector, we don't need to worry about space. */ -static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, +static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t, uint32_t addr, uint32_t control) { struct arm11_common *arm11 = dpm_to_arm11(dpm); @@ -1079,7 +1079,7 @@ static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, return ERROR_OK; } -static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t) { struct arm11_common *arm11 = dpm_to_arm11(dpm); struct arm11_sc7_action *action; diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index 3bacfaefdf..7e31306b6c 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -821,9 +821,9 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command) else if (strcmp(CMD_ARGV[0], "none") == 0) { /* do nothing */ } else { - for (unsigned i = 0; i < CMD_ARGC; i++) { + for (unsigned int i = 0; i < CMD_ARGC; i++) { /* go through list of vectors */ - unsigned j; + unsigned int j; for (j = 0; arm9tdmi_vectors[j].name; j++) { if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0) { vector_catch_value |= arm9tdmi_vectors[j].value; @@ -850,7 +850,7 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command) } /* output current settings */ - for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) { + for (unsigned int i = 0; arm9tdmi_vectors[i].name; i++) { command_print(CMD, "%s: %s", arm9tdmi_vectors[i].name, (vector_catch_value & arm9tdmi_vectors[i].value) ? "catch" : "don't catch"); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 92c3dbc3a6..ebd2752bd8 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -454,17 +454,17 @@ struct dap_ops { int (*send_sequence)(struct adiv5_dap *dap, enum swd_special_seq seq); /** DP register read. */ - int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg, + int (*queue_dp_read)(struct adiv5_dap *dap, unsigned int reg, uint32_t *data); /** DP register write. */ - int (*queue_dp_write)(struct adiv5_dap *dap, unsigned reg, + int (*queue_dp_write)(struct adiv5_dap *dap, unsigned int reg, uint32_t data); /** AP register read. */ - int (*queue_ap_read)(struct adiv5_ap *ap, unsigned reg, + int (*queue_ap_read)(struct adiv5_ap *ap, unsigned int reg, uint32_t *data); /** AP register write. */ - int (*queue_ap_write)(struct adiv5_ap *ap, unsigned reg, + int (*queue_ap_write)(struct adiv5_ap *ap, unsigned int reg, uint32_t data); /** AP operation abort. */ @@ -553,7 +553,7 @@ static inline int dap_send_sequence(struct adiv5_dap *dap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_dp_read(struct adiv5_dap *dap, - unsigned reg, uint32_t *data) + unsigned int reg, uint32_t *data) { assert(dap->ops); return dap->ops->queue_dp_read(dap, reg, data); @@ -571,7 +571,7 @@ static inline int dap_queue_dp_read(struct adiv5_dap *dap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_dp_write(struct adiv5_dap *dap, - unsigned reg, uint32_t data) + unsigned int reg, uint32_t data) { assert(dap->ops); return dap->ops->queue_dp_write(dap, reg, data); @@ -588,7 +588,7 @@ static inline int dap_queue_dp_write(struct adiv5_dap *dap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_read(struct adiv5_ap *ap, - unsigned reg, uint32_t *data) + unsigned int reg, uint32_t *data) { assert(ap->dap->ops); if (ap->refcount == 0) { @@ -608,7 +608,7 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_write(struct adiv5_ap *ap, - unsigned reg, uint32_t data) + unsigned int reg, uint32_t data) { assert(ap->dap->ops); if (ap->refcount == 0) { @@ -659,7 +659,7 @@ static inline int dap_sync(struct adiv5_dap *dap) return ERROR_OK; } -static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg, +static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned int reg, uint32_t *value) { int retval; @@ -671,7 +671,7 @@ static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg, return dap_run(dap); } -static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg, +static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value, int timeout) { assert(timeout > 0); diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 5c52ad8990..8619f8f82e 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -114,7 +114,7 @@ static int evaluate_pld(uint32_t opcode, if ((opcode & 0x0d30f000) == 0x0510f000) { uint8_t rn; uint8_t u; - unsigned offset; + unsigned int offset; instruction->type = ARM_PLD; rn = (opcode & 0xf0000) >> 16; @@ -701,9 +701,9 @@ static int evaluate_load_store(uint32_t opcode, static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp) { - unsigned rm = (opcode >> 0) & 0xf; - unsigned rd = (opcode >> 12) & 0xf; - unsigned rn = (opcode >> 16) & 0xf; + unsigned int rm = (opcode >> 0) & 0xf; + unsigned int rd = (opcode >> 12) & 0xf; + unsigned int rn = (opcode >> 16) & 0xf; char *type, *rot; switch ((opcode >> 24) & 0x3) { @@ -892,7 +892,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, /* multiplies */ if ((opcode & 0x01f00080) == 0x01000000) { - unsigned rn = (opcode >> 12) & 0xf; + unsigned int rn = (opcode >> 12) & 0xf; if (rn != 0xf) sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d", @@ -925,7 +925,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, return ERROR_OK; } if ((opcode & 0x01f00000) == 0x01500000) { - unsigned rn = (opcode >> 12) & 0xf; + unsigned int rn = (opcode >> 12) & 0xf; switch (opcode & 0xc0) { case 3: @@ -1001,8 +1001,8 @@ static int evaluate_media(uint32_t opcode, uint32_t address, return ERROR_OK; } if (mnemonic) { - unsigned rm = (opcode >> 0) & 0xf; - unsigned rd = (opcode >> 12) & 0xf; + unsigned int rm = (opcode >> 0) & 0xf; + unsigned int rd = (opcode >> 12) & 0xf; sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd); return ERROR_OK; @@ -2747,7 +2747,7 @@ static int evaluate_cond_branch_thumb(uint16_t opcode, static int evaluate_cb_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { - unsigned offset; + unsigned int offset; /* added in Thumb2 */ offset = (opcode >> 3) & 0x1f; @@ -2858,7 +2858,7 @@ static int evaluate_hint_thumb(uint16_t opcode, uint32_t address, static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { - unsigned cond = (opcode >> 4) & 0x0f; + unsigned int cond = (opcode >> 4) & 0x0f; char *x = "", *y = "", *z = ""; if (opcode & 0x01) diff --git a/src/target/arm_disassembler.h b/src/target/arm_disassembler.h index 1be567475c..8317da997b 100644 --- a/src/target/arm_disassembler.h +++ b/src/target/arm_disassembler.h @@ -171,7 +171,7 @@ struct arm_instruction { uint32_t opcode; /* return value ... Thumb-2 sizes vary */ - unsigned instruction_size; + unsigned int instruction_size; union { struct arm_b_bl_bx_blx_instr b_bl_bx_blx; diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 94e91ad6cd..318d5afec9 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -167,7 +167,7 @@ int arm_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) } /* Read 64bit VFP registers */ -static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { int retval = ERROR_FAIL; uint32_t value_r0, value_r1; @@ -205,7 +205,7 @@ static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) } /* just read the register -- rely on the core mode being right */ -int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { uint32_t value; int retval; @@ -272,7 +272,7 @@ int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) } /* Write 64bit VFP registers */ -static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { int retval = ERROR_FAIL; uint32_t value_r0 = buf_get_u32(r->value, 0, 32); @@ -308,7 +308,7 @@ static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum } /* just write the register -- rely on the core mode being right */ -static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { int retval; uint32_t value = buf_get_u32(r->value, 0, 32); @@ -386,7 +386,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) return retval; /* read R0 and R1 first (it's used for scratch), then CPSR */ - for (unsigned i = 0; i < 2; i++) { + for (unsigned int i = 0; i < 2; i++) { r = arm->core_cache->reg_list + i; if (!r->valid) { retval = arm_dpm_read_reg(dpm, r, i); @@ -404,7 +404,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) arm_set_cpsr(arm, cpsr); /* REVISIT we can probably avoid reading R1..R14, saving time... */ - for (unsigned i = 2; i < 16; i++) { + for (unsigned int i = 2; i < 16; i++) { r = arm_reg_current(arm, i); if (r->valid) continue; @@ -501,7 +501,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) * cope with the hand-crafted breakpoint code. */ if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { struct dpm_bp *dbp = dpm->dbp + i; struct breakpoint *bp = dbp->bp; @@ -513,7 +513,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) } /* enable/disable watchpoints */ - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { struct dpm_wp *dwp = dpm->dwp + i; struct watchpoint *wp = dwp->wp; @@ -538,9 +538,9 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) did_write = false; /* check everything except our scratch registers R0 and R1 */ - for (unsigned i = 2; i < cache->num_regs; i++) { + for (unsigned int i = 2; i < cache->num_regs; i++) { struct arm_reg *r; - unsigned regnum; + unsigned int regnum; /* also skip PC, CPSR, and non-dirty */ if (i == 15) @@ -625,7 +625,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) arm->pc->dirty = false; /* flush R0 and R1 (our scratch registers) */ - for (unsigned i = 0; i < 2; i++) { + for (unsigned int i = 0; i < 2; i++) { retval = dpm_write_reg(dpm, &cache->reg_list[i], i); if (retval != ERROR_OK) goto done; @@ -643,7 +643,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) * or MODE_ANY. */ static enum arm_mode dpm_mapmode(struct arm *arm, - unsigned num, enum arm_mode mode) + unsigned int num, enum arm_mode mode) { enum arm_mode amode = arm->core_mode; @@ -793,7 +793,7 @@ static int arm_dpm_full_context(struct target *target) * Pick some mode with unread registers and read them all. * Repeat until done. */ - for (unsigned i = 0; i < cache->num_regs; i++) { + for (unsigned int i = 0; i < cache->num_regs; i++) { struct arm_reg *r; if (!cache->reg_list[i].exist || cache->reg_list[i].valid) @@ -921,7 +921,7 @@ static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp) if (bp->type == BKPT_SOFT) LOG_DEBUG("using HW bkpt, not SW..."); - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (!dpm->dbp[i].bp) { retval = dpm_bpwp_setup(dpm, &dpm->dbp[i].bpwp, bp->address, bp->length); @@ -940,7 +940,7 @@ static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (dpm->dbp[i].bp == bp) { dpm->dbp[i].bp = NULL; dpm->dbp[i].bpwp.dirty = true; @@ -954,7 +954,7 @@ static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp) return retval; } -static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t, +static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned int index_t, struct watchpoint *wp) { int retval; @@ -997,7 +997,7 @@ static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp) int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (dpm->bpwp_enable) { - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (!dpm->dwp[i].wp) { retval = dpm_watchpoint_setup(dpm, i, wp); break; @@ -1014,7 +1014,7 @@ static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (dpm->dwp[i].wp == wp) { dpm->dwp[i].wp = NULL; dpm->dwp[i].bpwp.dirty = true; @@ -1161,7 +1161,7 @@ int arm_dpm_initialize(struct arm_dpm *dpm) { /* Disable all breakpoints and watchpoints at startup. */ if (dpm->bpwp_disable) { - unsigned i; + unsigned int i; for (i = 0; i < dpm->nbp; i++) { dpm->dbp[i].bpwp.number = i; diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 2da4631112..16c801ea53 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -19,7 +19,7 @@ */ struct dpm_bpwp { - unsigned number; + unsigned int number; uint32_t address; uint32_t control; /* true if hardware state needs flushing */ @@ -109,7 +109,7 @@ struct arm_dpm { uint32_t opcode, uint64_t *data); struct reg *(*arm_reg_current)(struct arm *arm, - unsigned regnum); + unsigned int regnum); /* BREAKPOINT/WATCHPOINT SUPPORT */ @@ -119,7 +119,7 @@ struct arm_dpm { * must currently be disabled. Indices 0..15 are used for * breakpoints; indices 16..31 are for watchpoints. */ - int (*bpwp_enable)(struct arm_dpm *dpm, unsigned index_value, + int (*bpwp_enable)(struct arm_dpm *dpm, unsigned int index_value, uint32_t addr, uint32_t control); /** @@ -127,15 +127,15 @@ struct arm_dpm { * hardware control registers. Indices are the same ones * accepted by bpwp_enable(). */ - int (*bpwp_disable)(struct arm_dpm *dpm, unsigned index_value); + int (*bpwp_disable)(struct arm_dpm *dpm, unsigned int index_value); /* The breakpoint and watchpoint arrays are private to the * DPM infrastructure. There are nbp indices in the dbp * array. There are nwp indices in the dwp array. */ - unsigned nbp; - unsigned nwp; + unsigned int nbp; + unsigned int nwp; struct dpm_bp *dbp; struct dpm_wp *dwp; @@ -158,7 +158,7 @@ struct arm_dpm { int arm_dpm_setup(struct arm_dpm *dpm); int arm_dpm_initialize(struct arm_dpm *dpm); -int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum); +int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum); int arm_dpm_read_current_registers(struct arm_dpm *dpm); int arm_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index ae89762e11..c1836bc7ae 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -168,9 +168,9 @@ static const struct { }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ -const char *arm_mode_name(unsigned psr_mode) +const char *arm_mode_name(unsigned int psr_mode) { - for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { if (arm_mode_data[i].psr == psr_mode) return arm_mode_data[i].name; } @@ -179,9 +179,9 @@ const char *arm_mode_name(unsigned psr_mode) } /** Return true iff the parameter denotes a valid ARM processor mode. */ -bool is_arm_mode(unsigned psr_mode) +bool is_arm_mode(unsigned int psr_mode) { - for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { if (arm_mode_data[i].psr == psr_mode) return true; } @@ -272,8 +272,8 @@ static const struct { * CPSR -or- SPSR depending on whether 'mode' is MODE_ANY. * (Exception modes have both CPSR and SPSR registers ...) */ - unsigned cookie; - unsigned gdb_index; + unsigned int cookie; + unsigned int gdb_index; enum arm_mode mode; } arm_core_regs[] = { /* IMPORTANT: we guarantee that the first eight cached registers @@ -499,7 +499,7 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) * However, R8..R14, and SPSR (arm->spsr) *must* be mapped. * CPSR (arm->cpsr) is also not mapped. */ -struct reg *arm_reg_current(struct arm *arm, unsigned regnum) +struct reg *arm_reg_current(struct arm *arm, unsigned int regnum) { struct reg *r; @@ -840,7 +840,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) regs = arm->core_cache->reg_list; - for (unsigned mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) { + for (unsigned int mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) { const char *name; char *sep = "\n"; char *shadow = ""; @@ -875,11 +875,11 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) sep, name, shadow); /* display N rows of up to 4 registers each */ - for (unsigned i = 0; i < arm_mode_data[mode].n_indices; ) { + for (unsigned int i = 0; i < arm_mode_data[mode].n_indices; ) { char output[80]; int output_len = 0; - for (unsigned j = 0; j < 4; j++, i++) { + for (unsigned int j = 0; j < 4; j++, i++) { uint32_t value; struct reg *reg = regs; @@ -1750,7 +1750,7 @@ int arm_blank_check_memory(struct target *target, static int arm_full_context(struct target *target) { struct arm *arm = target_to_arm(target); - unsigned num_regs = arm->core_cache->num_regs; + unsigned int num_regs = arm->core_cache->num_regs; struct reg *reg = arm->core_cache->reg_list; int retval = ERROR_OK; diff --git a/src/target/armv7a_cache_l2x.h b/src/target/armv7a_cache_l2x.h index d5f1a6f0e5..ea726ec58e 100644 --- a/src/target/armv7a_cache_l2x.h +++ b/src/target/armv7a_cache_l2x.h @@ -122,16 +122,16 @@ struct outer_cache_fns { void (*resume)(void); /* This is an ARM L2C thing */ - void (*write_sec)(unsigned long, unsigned); + void (*write_sec)(unsigned long, unsigned int); void (*configure)(const struct l2x0_regs *); }; struct l2c_init_data { const char *type; - unsigned way_size_0; - unsigned num_lock; + unsigned int way_size_0; + unsigned int num_lock; - void (*enable)(uint32_t, uint32_t, unsigned); + void (*enable)(uint32_t, uint32_t, unsigned int); void (*fixup)(uint32_t, uint32_t, struct outer_cache_fns *); void (*save)(uint32_t); void (*configure)(uint32_t); diff --git a/src/target/armv7m.c b/src/target/armv7m.c index d508af7bf0..a403b25a91 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -74,9 +74,9 @@ const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = { * doesn't include basepri or faultmask registers. */ static const struct { - unsigned id; + unsigned int id; const char *name; - unsigned bits; + unsigned int bits; enum reg_type type; const char *group; const char *feature; @@ -530,7 +530,7 @@ int armv7m_start_algorithm(struct target *target, } /* Store all non-debug execution registers to armv7m_algorithm_info context */ - for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) { + for (unsigned int i = 0; i < armv7m->arm.core_cache->num_regs; i++) { struct reg *reg = &armv7m->arm.core_cache->reg_list[i]; if (!reg->exist) continue; diff --git a/src/target/armv8.c b/src/target/armv8.c index 3e0ea0b754..3bf0942759 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -36,7 +36,7 @@ static const char * const armv8_state_strings[] = { static const struct { const char *name; - unsigned psr; + unsigned int psr; } armv8_mode_data[] = { { .name = "USR", @@ -105,9 +105,9 @@ static const struct { }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ -const char *armv8_mode_name(unsigned psr_mode) +const char *armv8_mode_name(unsigned int psr_mode) { - for (unsigned i = 0; i < ARRAY_SIZE(armv8_mode_data); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(armv8_mode_data); i++) { if (armv8_mode_data[i].psr == psr_mode) return armv8_mode_data[i].name; } @@ -683,7 +683,7 @@ static int armv8_read_reg_simdfp_aarch32(struct armv8_common *armv8, int regnum, struct arm_dpm *dpm = &armv8->dpm; struct reg *reg_r1 = dpm->arm->core_cache->reg_list + ARMV8_R1; uint32_t value_r0 = 0, value_r1 = 0; - unsigned num = (regnum - ARMV8_V0) << 1; + unsigned int num = (regnum - ARMV8_V0) << 1; switch (regnum) { case ARMV8_V0 ... ARMV8_V15: @@ -817,7 +817,7 @@ static int armv8_write_reg_simdfp_aarch32(struct armv8_common *armv8, int regnum struct arm_dpm *dpm = &armv8->dpm; struct reg *reg_r1 = dpm->arm->core_cache->reg_list + ARMV8_R1; uint32_t value_r0 = 0, value_r1 = 0; - unsigned num = (regnum - ARMV8_V0) << 1; + unsigned int num = (regnum - ARMV8_V0) << 1; switch (regnum) { case ARMV8_V0 ... ARMV8_V15: @@ -1506,9 +1506,9 @@ static struct reg_data_type aarch64_flags_cpsr[] = { }; static const struct { - unsigned id; + unsigned int id; const char *name; - unsigned bits; + unsigned int bits; enum arm_mode mode; enum reg_type type; const char *group; @@ -1611,10 +1611,10 @@ static const struct { }; static const struct { - unsigned id; - unsigned mapping; + unsigned int id; + unsigned int mapping; const char *name; - unsigned bits; + unsigned int bits; enum arm_mode mode; enum reg_type type; const char *group; @@ -1881,7 +1881,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) return cache; } -struct reg *armv8_reg_current(struct arm *arm, unsigned regnum) +struct reg *armv8_reg_current(struct arm *arm, unsigned int regnum) { struct reg *r; diff --git a/src/target/armv8.h b/src/target/armv8.h index 156b5f8bbd..349c8f002c 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -329,7 +329,7 @@ static inline unsigned int armv8_curel_from_core_mode(enum arm_mode core_mode) } } -const char *armv8_mode_name(unsigned psr_mode); +const char *armv8_mode_name(unsigned int psr_mode); void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64); int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value); diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index bcecedc9da..22617fd0ec 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -417,7 +417,7 @@ static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm, } #if 0 -static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, +static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t, target_addr_t addr, uint32_t control) { struct armv8_common *armv8 = dpm->arm->arch_info; @@ -450,7 +450,7 @@ static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, } #endif -static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t) { struct armv8_common *armv8 = dpm->arm->arch_info; uint32_t cr; @@ -641,7 +641,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) /* * Common register read, relies on armv8_select_reg_access() having been called. */ -static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { struct armv8_common *armv8 = dpm->arm->arch_info; int retval = ERROR_FAIL; @@ -684,7 +684,7 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) /* * Common register write, relies on armv8_select_reg_access() having been called. */ -static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { struct armv8_common *armv8 = dpm->arm->arch_info; int retval = ERROR_FAIL; @@ -887,7 +887,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) * cope with the hand-crafted breakpoint code. */ if (arm->target->type->add_breakpoint == dpmv8_add_breakpoint) { - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { struct dpm_bp *dbp = dpm->dbp + i; struct breakpoint *bp = dbp->bp; @@ -899,7 +899,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) } /* enable/disable watchpoints */ - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { struct dpm_wp *dwp = dpm->dwp + i; struct watchpoint *wp = dwp->wp; @@ -919,7 +919,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) goto done; /* check everything except our scratch register R0 */ - for (unsigned i = 1; i < cache->num_regs; i++) { + for (unsigned int i = 1; i < cache->num_regs; i++) { struct arm_reg *r; /* skip non-existent */ @@ -1047,7 +1047,7 @@ static int armv8_dpm_full_context(struct target *target) * Pick some mode with unread registers and read them all. * Repeat until done. */ - for (unsigned i = 0; i < cache->num_regs; i++) { + for (unsigned int i = 0; i < cache->num_regs; i++) { struct arm_reg *r; if (!cache->reg_list[i].exist || cache->reg_list[i].valid) @@ -1175,7 +1175,7 @@ static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp) if (bp->type == BKPT_SOFT) LOG_DEBUG("using HW bkpt, not SW..."); - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (!dpm->dbp[i].bp) { retval = dpmv8_bpwp_setup(dpm, &dpm->dbp[i].bpwp, bp->address, bp->length); @@ -1194,7 +1194,7 @@ static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (dpm->dbp[i].bp == bp) { dpm->dbp[i].bp = NULL; dpm->dbp[i].bpwp.dirty = true; @@ -1208,7 +1208,7 @@ static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp) return retval; } -static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t, +static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned int index_t, struct watchpoint *wp) { int retval; @@ -1251,7 +1251,7 @@ static int dpmv8_add_watchpoint(struct target *target, struct watchpoint *wp) int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (dpm->bpwp_enable) { - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (!dpm->dwp[i].wp) { retval = dpmv8_watchpoint_setup(dpm, i, wp); break; @@ -1268,7 +1268,7 @@ static int dpmv8_remove_watchpoint(struct target *target, struct watchpoint *wp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (dpm->dwp[i].wp == wp) { dpm->dwp[i].wp = NULL; dpm->dwp[i].bpwp.dirty = true; @@ -1484,7 +1484,7 @@ int armv8_dpm_initialize(struct arm_dpm *dpm) { /* Disable all breakpoints and watchpoints at startup. */ if (dpm->bpwp_disable) { - unsigned i; + unsigned int i; for (i = 0; i < dpm->nbp; i++) { dpm->dbp[i].bpwp.number = i; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 498a9cd16a..086aafe199 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -571,7 +571,7 @@ static int cortex_a_instr_read_data_r0_r1(struct arm_dpm *dpm, return retval; } -static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, +static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t, uint32_t addr, uint32_t control) { struct cortex_a_common *a = dpm_to_a(dpm); @@ -606,7 +606,7 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, return retval; } -static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t) { struct cortex_a_common *a = dpm_to_a(dpm); uint32_t cr; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 698a6868cb..880a83a18c 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -898,7 +898,7 @@ static int cortex_m_debug_entry(struct target *target) arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { - unsigned control = buf_get_u32(arm->core_cache + unsigned int control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 3); /* is this thread privileged? */ @@ -2142,7 +2142,7 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint } /* hardware allows address masks of up to 32K */ - unsigned mask; + unsigned int mask; for (mask = 0; mask < 16; mask++) { if ((1u << mask) == watchpoint->length) @@ -2378,7 +2378,7 @@ static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf) struct dwt_reg { uint32_t addr; const char *name; - unsigned size; + unsigned int size; }; static const struct dwt_reg dwt_base_regs[] = { @@ -2946,7 +2946,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) static const struct { char name[10]; - unsigned mask; + unsigned int mask; } vec_ids[] = { { "hard_err", VC_HARDERR, }, { "int_err", VC_INTERR, }, @@ -2972,7 +2972,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) return retval; if (CMD_ARGC > 0) { - unsigned catch = 0; + unsigned int catch = 0; if (CMD_ARGC == 1) { if (strcmp(CMD_ARGV[0], "all") == 0) { @@ -2984,7 +2984,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) goto write; } while (CMD_ARGC-- > 0) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(vec_ids); i++) { if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name) != 0) continue; @@ -3017,7 +3017,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) */ } - for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(vec_ids); i++) { command_print(CMD, "%9s: %s", vec_ids[i].name, (demcr & vec_ids[i].mask) ? "catch" : "ignore"); } diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 687821c5d7..953888de3d 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -220,9 +220,9 @@ enum dsp563xx_reg_idx { }; static const struct { - unsigned id; + unsigned int id; const char *name; - unsigned bits; + unsigned int bits; /* effective addressing mode encoding */ uint8_t eame; uint32_t instr_mask; diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index c90bca3c1f..8b3b1c49b6 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -1172,7 +1172,7 @@ static int dsp5680xx_read(struct target *t, target_addr_t a, uint32_t size, dsp5680xx_context.flush = 0; int counter = FLUSH_COUNT_READ_WRITE; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_READ_WRITE; diff --git a/src/target/esirisc.c b/src/target/esirisc.c index 14d34ff04b..6111414398 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -283,7 +283,7 @@ static int esirisc_save_context(struct target *target) LOG_DEBUG("-"); - for (unsigned i = 0; i < esirisc->reg_cache->num_regs; ++i) { + for (unsigned int i = 0; i < esirisc->reg_cache->num_regs; ++i) { struct reg *reg = esirisc->reg_cache->reg_list + i; struct esirisc_reg *reg_info = reg->arch_info; @@ -300,7 +300,7 @@ static int esirisc_restore_context(struct target *target) LOG_DEBUG("-"); - for (unsigned i = 0; i < esirisc->reg_cache->num_regs; ++i) { + for (unsigned int i = 0; i < esirisc->reg_cache->num_regs; ++i) { struct reg *reg = esirisc->reg_cache->reg_list + i; struct esirisc_reg *reg_info = reg->arch_info; diff --git a/src/target/esirisc_trace.c b/src/target/esirisc_trace.c index 376ea1db74..a70d9d74bf 100644 --- a/src/target/esirisc_trace.c +++ b/src/target/esirisc_trace.c @@ -287,9 +287,9 @@ static int esirisc_trace_init(struct target *target) } static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size, - unsigned *pos, unsigned count, uint32_t *value) + unsigned int *pos, unsigned int count, uint32_t *value) { - const unsigned num_bits = size * 8; + const unsigned int num_bits = size * 8; if (*pos+count > num_bits) return ERROR_FAIL; @@ -301,7 +301,7 @@ static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size, } static int esirisc_trace_buf_get_pc(struct target *target, uint8_t *buffer, uint32_t size, - unsigned *pos, uint32_t *value) + unsigned int *pos, uint32_t *value) { struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_trace *trace_info = &esirisc->trace_info; @@ -380,7 +380,7 @@ static int esirisc_trace_analyze_full(struct command_invocation *cmd, uint8_t *b const uint32_t num_bits = size * 8; int retval; - unsigned pos = 0; + unsigned int pos = 0; while (pos < num_bits) { uint32_t id; @@ -484,7 +484,7 @@ static int esirisc_trace_analyze_simple(struct command_invocation *cmd, uint8_t const uint32_t num_bits = size * 8; int retval; - unsigned pos = 0; + unsigned int pos = 0; while (pos < num_bits) { uint32_t pc; diff --git a/src/target/etb.h b/src/target/etb.h index fa75600ad6..1d0c08b2c2 100644 --- a/src/target/etb.h +++ b/src/target/etb.h @@ -32,7 +32,7 @@ struct etb { uint32_t ram_width; /** how much trace buffer to fill after trigger */ - unsigned trigger_percent; + unsigned int trigger_percent; }; struct etb_reg { diff --git a/src/target/etm.c b/src/target/etm.c index d8f2a2faa2..53d5cb68ca 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -220,10 +220,10 @@ static const struct reg_arch_type etm_scan6_type = { /* Look up register by ID ... most ETM instances only * support a subset of the possible registers. */ -static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id) +static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned int id) { struct reg_cache *cache = etm_ctx->reg_cache; - unsigned i; + unsigned int i; for (i = 0; i < cache->num_regs; i++) { struct etm_reg *reg = cache->reg_list[i].arch_info; @@ -238,9 +238,9 @@ static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id) return NULL; } -static void etm_reg_add(unsigned bcd_vers, struct arm_jtag *jtag_info, +static void etm_reg_add(unsigned int bcd_vers, struct arm_jtag *jtag_info, struct reg_cache *cache, struct etm_reg *ereg, - const struct etm_reg_info *r, unsigned nreg) + const struct etm_reg_info *r, unsigned int nreg) { struct reg *reg = cache->reg_list; @@ -281,7 +281,7 @@ struct reg_cache *etm_build_reg_cache(struct target *target, struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = NULL; struct etm_reg *arch_info = NULL; - unsigned bcd_vers, config; + unsigned int bcd_vers, config; /* the actual registers are kept in two arrays */ reg_list = calloc(128, sizeof(struct reg)); @@ -1590,7 +1590,7 @@ COMMAND_HANDLER(handle_etm_status_command) if (!reg) return ERROR_FAIL; if (etm_get_reg(reg) == ERROR_OK) { - unsigned s = buf_get_u32(reg->value, 0, reg->size); + unsigned int s = buf_get_u32(reg->value, 0, reg->size); command_print(CMD, "etm: %s%s%s%s", /* bit(1) == progbit */ diff --git a/src/target/hla_target.c b/src/target/hla_target.c index d6f2afb4e8..6b0d2e95e8 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -258,7 +258,7 @@ static int adapter_debug_entry(struct target *target) arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { - unsigned control = buf_get_u32(arm->core_cache + unsigned int control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 3); /* is this thread privileged? */ diff --git a/src/target/image.c b/src/target/image.c index 440fe17d18..e8ac066fdd 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -195,7 +195,7 @@ static int image_ihex_buffer_complete_inner(struct image *image, } while (count-- > 0) { - unsigned value; + unsigned int value; sscanf(&lpsz_line[bytes_read], "%2x", &value); ihex->buffer[cooked_bytes] = (uint8_t)value; cal_checksum += (uint8_t)ihex->buffer[cooked_bytes]; @@ -864,7 +864,7 @@ static int image_mot_buffer_complete_inner(struct image *image, } while (count-- > 0) { - unsigned value; + unsigned int value; sscanf(&lpsz_line[bytes_read], "%2x", &value); mot->buffer[cooked_bytes] = (uint8_t)value; cal_checksum += (uint8_t)mot->buffer[cooked_bytes]; diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 1fcd6426ae..0340d0d0b1 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -67,7 +67,7 @@ static const struct { const char *name; uint64_t op; uint8_t pm_idx; - unsigned bits; + unsigned int bits; enum reg_type type; const char *group; const char *feature; @@ -597,7 +597,7 @@ static int read_all_core_hw_regs(struct target *t) { int err; uint32_t regval; - unsigned i; + unsigned int i; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < (x86_32->cache->num_regs); i++) { if (regs[i].pm_idx == NOT_AVAIL_REG) @@ -616,7 +616,7 @@ static int read_all_core_hw_regs(struct target *t) static int write_all_core_hw_regs(struct target *t) { int err; - unsigned i; + unsigned int i; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < (x86_32->cache->num_regs); i++) { if (regs[i].pm_idx == NOT_AVAIL_REG) diff --git a/src/target/mips32.c b/src/target/mips32.c index af52ffca05..dd40558a18 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -34,7 +34,7 @@ static const char *mips_isa_strings[] = { * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu,dsp}.xml */ static const struct { - unsigned id; + unsigned int id; const char *name; enum reg_type type; const char *group; @@ -1187,7 +1187,7 @@ int mips32_read_config_regs(struct target *target) mips32->isa_imp = MIPS32_MIPS16; LOG_USER("ISA implemented: %s%s", "MIPS32, MIPS16", buf); } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */ - unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT; + unsigned int isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT; if (isa_imp == 1) { mips32->isa_imp = MMIPS32_ONLY; LOG_USER("ISA implemented: %s%s", "microMIPS32", buf); diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 018d8424e3..2d0bd641b2 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -370,7 +370,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in return ERROR_FAIL; } - unsigned num_clocks = + unsigned int num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; @@ -1362,7 +1362,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code)); /* execute jump code, with no address check */ - for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(jmp_code); i++) { int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1397,7 +1397,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); - unsigned num_clocks = 0; /* like in legacy code */ + unsigned int num_clocks = 0; /* like in legacy code */ if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index f78f89153f..a0244a695d 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -45,7 +45,7 @@ struct pa_list { struct pracc_queue_info { struct mips_ejtag *ejtag_info; - unsigned isa; + unsigned int isa; int retval; int code_count; int store_count; diff --git a/src/target/mips64.c b/src/target/mips64.c index 48f4563dc6..3d193a3009 100644 --- a/src/target/mips64.c +++ b/src/target/mips64.c @@ -21,7 +21,7 @@ #include "mips64.h" static const struct { - unsigned id; + unsigned int id; const char *name; enum reg_type type; const char *group; @@ -332,8 +332,8 @@ int mips64_save_context(struct target *target) if (retval != ERROR_OK) return retval; - for (unsigned i = 0; i < MIPS64_NUM_REGS; i++) - retval = mips64->read_core_reg(target, i); + for (unsigned int i = 0; i < MIPS64_NUM_REGS; i++) + retval = mips64->read_core_reg(target, i); return retval; } @@ -343,7 +343,7 @@ int mips64_restore_context(struct target *target) struct mips64_common *mips64 = target->arch_info; struct mips_ejtag *ejtag_info = &mips64->ejtag_info; - for (unsigned i = 0; i < MIPS64_NUM_REGS; i++) { + for (unsigned int i = 0; i < MIPS64_NUM_REGS; i++) { if (mips64->core_cache->reg_list[i].dirty) mips64->write_core_reg(target, i); } @@ -379,7 +379,7 @@ int mips64_build_reg_cache(struct target *target) struct reg_cache **cache_p, *cache; struct mips64_core_reg *arch_info = NULL; struct reg *reg_list = NULL; - unsigned i; + unsigned int i; cache = calloc(1, sizeof(*cache)); if (!cache) { diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index b083f5ce8b..8cfce32e3f 100644 --- a/src/target/mips64_pracc.c +++ b/src/target/mips64_pracc.c @@ -27,13 +27,13 @@ struct mips64_pracc_context { uint64_t *local_iparam; - unsigned num_iparam; + unsigned int num_iparam; uint64_t *local_oparam; - unsigned num_oparam; + unsigned int num_oparam; const uint32_t *code; - unsigned code_len; + unsigned int code_len; uint64_t stack[STACK_DEPTH]; - unsigned stack_offset; + unsigned int stack_offset; struct mips_ejtag *ejtag_info; }; @@ -65,7 +65,7 @@ static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) static int mips64_pracc_exec_read(struct mips64_pracc_context *ctx, uint64_t address) { struct mips_ejtag *ejtag_info = ctx->ejtag_info; - unsigned offset; + unsigned int offset; uint32_t ejtag_ctrl; uint64_t data; int rc; @@ -154,7 +154,7 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad { uint32_t ejtag_ctrl; uint64_t data; - unsigned offset; + unsigned int offset; struct mips_ejtag *ejtag_info = ctx->ejtag_info; int rc; @@ -209,9 +209,9 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad } int mips64_pracc_exec(struct mips_ejtag *ejtag_info, - unsigned code_len, const uint32_t *code, - unsigned num_param_in, uint64_t *param_in, - unsigned num_param_out, uint64_t *param_out) + unsigned int code_len, const uint32_t *code, + unsigned int num_param_in, uint64_t *param_in, + unsigned int num_param_out, uint64_t *param_out) { uint32_t ejtag_ctrl; uint64_t address = 0, address_prev = 0; @@ -219,7 +219,7 @@ int mips64_pracc_exec(struct mips_ejtag *ejtag_info, int retval; int pass = 0; bool first_time_call = true; - unsigned i; + unsigned int i; for (i = 0; i < code_len; i++) LOG_DEBUG("%08" PRIx32, code[i]); @@ -354,11 +354,11 @@ static int mips64_pracc_read_u64(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem64(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint64_t *buf) + unsigned int count, uint64_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u64(ejtag_info, addr + 8*i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -414,11 +414,11 @@ static int mips64_pracc_read_u32(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint32_t *buf) + unsigned int count, uint32_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u32(ejtag_info, addr + 4 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -474,11 +474,11 @@ static int mips64_pracc_read_u16(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint16_t *buf) + unsigned int count, uint16_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u16(ejtag_info, addr + 2*i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -534,11 +534,11 @@ static int mips64_pracc_read_u8(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint8_t *buf) + unsigned int count, uint8_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u8(ejtag_info, addr + i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -547,7 +547,7 @@ static int mips64_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint64_t addr, } int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned size, unsigned count, void *buf) + unsigned int size, unsigned int count, void *buf) { switch (size) { case 1: @@ -612,11 +612,11 @@ static int mips64_pracc_write_u64(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem64(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned count, uint64_t *buf) + uint64_t addr, unsigned int count, uint64_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u64(ejtag_info, addr + 8 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -674,11 +674,11 @@ static int mips64_pracc_write_u32(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint32_t *buf) + unsigned int count, uint32_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u32(ejtag_info, addr + 4 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -734,11 +734,11 @@ static int mips64_pracc_write_u16(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem16(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned count, uint16_t *buf) + uint64_t addr, unsigned int count, uint16_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u16(ejtag_info, addr + 2 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -795,11 +795,11 @@ static int mips64_pracc_write_u8(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem8(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned count, uint8_t *buf) + uint64_t addr, unsigned int count, uint8_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u8(ejtag_info, addr + i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -808,8 +808,8 @@ static int mips64_pracc_write_mem8(struct mips_ejtag *ejtag_info, } int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned size, - unsigned count, void *buf) + uint64_t addr, unsigned int size, + unsigned int count, void *buf) { switch (size) { case 1: @@ -1270,7 +1270,7 @@ int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs) int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, bool write_t, uint64_t addr, - unsigned count, uint64_t *buf) + unsigned int count, uint64_t *buf) { uint32_t handler_code[] = { /* caution when editing, table is modified below */ @@ -1321,7 +1321,7 @@ int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, }; int retval; - unsigned i; + unsigned int i; uint32_t ejtag_ctrl, address32; uint64_t address, val; @@ -1385,7 +1385,7 @@ int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, mips64_ejtag_fastdata_scan(ejtag_info, 1, &val); /* like in legacy code */ - unsigned num_clocks = 0; + unsigned int num_clocks = 0; if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; LOG_DEBUG("num_clocks=%d", num_clocks); diff --git a/src/target/mips64_pracc.h b/src/target/mips64_pracc.h index 19d1519466..2bdc856b91 100644 --- a/src/target/mips64_pracc.h +++ b/src/target/mips64_pracc.h @@ -40,20 +40,22 @@ #define MIPS64_PRACC_ADDR_STEP 4 #define MIPS64_PRACC_DATA_STEP 8 -int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned size, unsigned count, void *buf); -int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned size, unsigned count, void *buf); +int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned int size, + unsigned int count, void *buf); +int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned int size, + unsigned int count, void *buf); int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs); int mips64_pracc_write_regs(struct mips_ejtag *ejtag_info, uint64_t *regs); int mips64_pracc_exec(struct mips_ejtag *ejtag_info, - unsigned code_len, const uint32_t *code, - unsigned num_param_in, uint64_t *param_in, - unsigned num_param_out, uint64_t *param_out); + unsigned int code_len, const uint32_t *code, + unsigned int num_param_in, uint64_t *param_in, + unsigned int num_param_out, uint64_t *param_out); int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, bool write_t, uint64_t addr, - unsigned count, uint64_t *buf); + unsigned int count, uint64_t *buf); #endif /* OPENOCD_TARGET_MIPS64_PRACC_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 389461cae6..2ff4aa926f 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -493,7 +493,7 @@ int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, bool enable_step) MIPS64_NOP, }; const uint32_t *code = enable_step ? code_enable : code_disable; - unsigned code_len = enable_step ? ARRAY_SIZE(code_enable) : + unsigned int code_len = enable_step ? ARRAY_SIZE(code_enable) : ARRAY_SIZE(code_disable); return mips64_pracc_exec(ejtag_info, diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 7376e5141d..30a46903f5 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -214,7 +214,7 @@ struct mips_ejtag { uint32_t reg8; uint32_t reg9; - unsigned scan_delay; + unsigned int scan_delay; int mode; uint32_t pa_ctrl; uint32_t pa_addr; diff --git a/src/target/register.h b/src/target/register.h index 1e4f2e0889..b9af401b4c 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -145,7 +145,7 @@ struct reg_cache { const char *name; struct reg_cache *next; struct reg *reg_list; - unsigned num_regs; + unsigned int num_regs; }; struct reg_arch_type { diff --git a/src/target/stm8.c b/src/target/stm8.c index 227101b6f0..2b3466dacb 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -38,7 +38,7 @@ static int (*adapter_speed)(int speed); extern struct adapter_driver *adapter_driver; static const struct { - unsigned id; + unsigned int id; const char *name; const uint8_t bits; enum reg_type type; diff --git a/src/target/target.c b/src/target/target.c index 281bbbd408..56aa8b1e70 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1443,14 +1443,14 @@ int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, target_addr_t target_address_max(struct target *target) { - unsigned bits = target_address_bits(target); + unsigned int bits = target_address_bits(target); if (sizeof(target_addr_t) * 8 == bits) return (target_addr_t) -1; else return (((target_addr_t) 1) << bits) - 1; } -unsigned target_address_bits(struct target *target) +unsigned int target_address_bits(struct target *target) { if (target->type->address_bits) return target->type->address_bits(target); @@ -3035,7 +3035,7 @@ COMMAND_HANDLER(handle_reg_command) unsigned int count = 0; while (cache) { - unsigned i; + unsigned int i; command_print(CMD, "===== %s", cache->name); @@ -3070,13 +3070,13 @@ COMMAND_HANDLER(handle_reg_command) /* access a single register by its ordinal number */ if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct reg_cache *cache = target->reg_cache; unsigned int count = 0; while (cache) { - unsigned i; + unsigned int i; for (i = 0; i < cache->num_regs; i++) { if (count++ == num) { reg = &cache->reg_list[i]; @@ -3194,7 +3194,7 @@ COMMAND_HANDLER(handle_wait_halt_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned ms = DEFAULT_HALT_TIMEOUT; + unsigned int ms = DEFAULT_HALT_TIMEOUT; if (1 == CMD_ARGC) { int retval = parse_uint(CMD_ARGV[0], &ms); if (retval != ERROR_OK) @@ -3260,7 +3260,7 @@ COMMAND_HANDLER(handle_halt_command) return retval; if (CMD_ARGC == 1) { - unsigned wait_local; + unsigned int wait_local; retval = parse_uint(CMD_ARGV[0], &wait_local); if (retval != ERROR_OK) return ERROR_COMMAND_SYNTAX_ERROR; @@ -3344,14 +3344,14 @@ COMMAND_HANDLER(handle_step_command) } void target_handle_md_output(struct command_invocation *cmd, - struct target *target, target_addr_t address, unsigned size, - unsigned count, const uint8_t *buffer) + struct target *target, target_addr_t address, unsigned int size, + unsigned int count, const uint8_t *buffer) { - const unsigned line_bytecnt = 32; - unsigned line_modulo = line_bytecnt / size; + const unsigned int line_bytecnt = 32; + unsigned int line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; - unsigned output_len = 0; + unsigned int output_len = 0; const char *value_fmt; switch (size) { @@ -3373,7 +3373,7 @@ void target_handle_md_output(struct command_invocation *cmd, return; } - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, @@ -3412,7 +3412,7 @@ COMMAND_HANDLER(handle_md_command) if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned size = 0; + unsigned int size = 0; switch (CMD_NAME[2]) { case 'd': size = 8; @@ -3445,7 +3445,7 @@ COMMAND_HANDLER(handle_md_command) target_addr_t address; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); - unsigned count = 1; + unsigned int count = 1; if (CMD_ARGC == 2) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); @@ -3471,22 +3471,22 @@ typedef int (*target_write_fn)(struct target *target, static int target_fill_mem(struct target *target, target_addr_t address, target_write_fn fn, - unsigned data_size, + unsigned int data_size, /* value */ uint64_t b, /* count */ - unsigned c) + unsigned int c) { /* We have to write in reasonably large chunks to be able * to fill large memory areas with any sane speed */ - const unsigned chunk_size = 16384; + const unsigned int chunk_size = 16384; uint8_t *target_buf = malloc(chunk_size * data_size); if (!target_buf) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } - for (unsigned i = 0; i < chunk_size; i++) { + for (unsigned int i = 0; i < chunk_size; i++) { switch (data_size) { case 8: target_buffer_set_u64(target, target_buf + i * data_size, b); @@ -3507,8 +3507,8 @@ static int target_fill_mem(struct target *target, int retval = ERROR_OK; - for (unsigned x = 0; x < c; x += chunk_size) { - unsigned current; + for (unsigned int x = 0; x < c; x += chunk_size) { + unsigned int current; current = c - x; if (current > chunk_size) current = chunk_size; @@ -3550,12 +3550,12 @@ COMMAND_HANDLER(handle_mw_command) uint64_t value; COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], value); - unsigned count = 1; + unsigned int count = 1; if (CMD_ARGC == 3) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); struct target *target = get_current_target(CMD_CTX); - unsigned wordsize; + unsigned int wordsize; switch (CMD_NAME[2]) { case 'd': wordsize = 8; diff --git a/src/target/target.h b/src/target/target.h index ecc8a90321..abd0b58255 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -685,7 +685,7 @@ target_addr_t target_address_max(struct target *target); * * This routine is a wrapper for target->type->address_bits. */ -unsigned target_address_bits(struct target *target); +unsigned int target_address_bits(struct target *target); /** * Return the number of data bits this target supports. @@ -778,8 +778,8 @@ int target_arch_state(struct target *target); void target_handle_event(struct target *t, enum target_event e); void target_handle_md_output(struct command_invocation *cmd, - struct target *target, target_addr_t address, unsigned size, - unsigned count, const uint8_t *buffer); + struct target *target, target_addr_t address, unsigned int size, + unsigned int count, const uint8_t *buffer); int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); diff --git a/src/target/target_type.h b/src/target/target_type.h index bc42c2d16e..f35a59c5fe 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -303,7 +303,7 @@ struct target_type { /* Return the number of address bits this target supports. This will * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not * implemented, it's assumed to be 32. */ - unsigned (*address_bits)(struct target *target); + unsigned int (*address_bits)(struct target *target); /* Return the number of system bus data bits this target supports. This * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index 666bb07bf9..2c60b9f7e0 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -1330,14 +1330,14 @@ static int write_hw_reg_from_cache(struct target *t, int num) /* x86 32 commands */ static void handle_iod_output(struct command_invocation *cmd, - struct target *target, uint32_t address, unsigned size, - unsigned count, const uint8_t *buffer) + struct target *target, uint32_t address, unsigned int size, + unsigned int count, const uint8_t *buffer) { - const unsigned line_bytecnt = 32; - unsigned line_modulo = line_bytecnt / size; + const unsigned int line_bytecnt = 32; + unsigned int line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; - unsigned output_len = 0; + unsigned int output_len = 0; const char *value_fmt; switch (size) { @@ -1356,7 +1356,7 @@ static void handle_iod_output(struct command_invocation *cmd, return; } - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, @@ -1399,7 +1399,7 @@ COMMAND_HANDLER(handle_iod_command) return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned size = 0; + unsigned int size = 0; switch (CMD_NAME[2]) { case 'w': size = 4; @@ -1413,7 +1413,7 @@ COMMAND_HANDLER(handle_iod_command) default: return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned count = 1; + unsigned int count = 1; uint8_t *buffer = calloc(count, size); struct target *target = get_current_target(CMD_CTX); int retval = x86_32_common_read_io(target, address, size, buffer); @@ -1425,7 +1425,7 @@ COMMAND_HANDLER(handle_iod_command) static int target_fill_io(struct target *target, uint32_t address, - unsigned data_size, + unsigned int data_size, /* value */ uint32_t b) { @@ -1458,7 +1458,7 @@ COMMAND_HANDLER(handle_iow_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); struct target *target = get_current_target(CMD_CTX); - unsigned wordsize; + unsigned int wordsize; switch (CMD_NAME[2]) { case 'w': wordsize = 4; diff --git a/src/target/xscale.c b/src/target/xscale.c index fbf43516d0..155abaef1a 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -840,7 +840,7 @@ static int xscale_debug_entry(struct target *target) struct arm *arm = &xscale->arm; uint32_t pc; uint32_t buffer[10]; - unsigned i; + unsigned int i; int retval; uint32_t moe; @@ -1515,7 +1515,7 @@ static int xscale_deassert_reset(struct target *target) */ { uint32_t address; - unsigned buf_cnt; + unsigned int buf_cnt; const uint8_t *buffer = xscale_debug_handler; int retval; @@ -1539,11 +1539,11 @@ static int xscale_deassert_reset(struct target *target) * coprocessors, trace data, etc. */ address = xscale->handler_address; - for (unsigned binary_size = sizeof(xscale_debug_handler); + for (unsigned int binary_size = sizeof(xscale_debug_handler); binary_size > 0; binary_size -= buf_cnt, buffer += buf_cnt) { uint32_t cache_line[8]; - unsigned i; + unsigned int i; buf_cnt = binary_size; if (buf_cnt > 32) @@ -3215,7 +3215,7 @@ COMMAND_HANDLER(xscale_handle_idcache_command) static const struct { char name[15]; - unsigned mask; + unsigned int mask; } vec_ids[] = { { "fiq", DCSR_TF, }, { "irq", DCSR_TI, }, @@ -3250,7 +3250,7 @@ COMMAND_HANDLER(xscale_handle_vector_catch_command) } } while (CMD_ARGC-- > 0) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(vec_ids); i++) { if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name)) continue; @@ -3268,7 +3268,7 @@ COMMAND_HANDLER(xscale_handle_vector_catch_command) } dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32); - for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(vec_ids); i++) { command_print(CMD, "%15s: %s", vec_ids[i].name, (dcsr_value & vec_ids[i].mask) ? "catch" : "ignore"); } From a64dc23bf19fb4a7626fbda3c02693523ab5a75b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:21:35 +0200 Subject: [PATCH 0970/1312] jtag: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Ignore the cast as they could be better addressed. Fix only minor additional checkpatch issue (spacing and line length). Change-Id: I2c1ef03bbc828112cc5bea89463cff9fc0c1e94f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8481 Reviewed-by: zapb Tested-by: jenkins --- src/jtag/adapter.c | 12 ++-- src/jtag/core.c | 4 +- src/jtag/drivers/bitbang.c | 10 ++-- src/jtag/drivers/cmsis_dap.c | 4 +- src/jtag/drivers/driver.c | 2 +- src/jtag/drivers/ft232r.c | 10 ++-- src/jtag/drivers/ftdi.c | 12 ++-- src/jtag/drivers/jlink.c | 30 +++++----- src/jtag/drivers/jtag_vpi.c | 2 +- src/jtag/drivers/libusb_helper.c | 2 +- src/jtag/drivers/minidriver_imp.h | 2 +- src/jtag/drivers/mpsse.c | 58 +++++++++---------- src/jtag/drivers/mpsse.h | 18 +++--- src/jtag/drivers/stlink_usb.c | 2 +- .../usb_blaster/ublast2_access_libusb.c | 2 +- src/jtag/drivers/usb_blaster/ublast_access.h | 2 +- .../drivers/usb_blaster/ublast_access_ftdi.c | 2 +- src/jtag/drivers/usb_blaster/usb_blaster.c | 2 +- src/jtag/drivers/xlnx-pcie-xvc.c | 2 +- src/jtag/interface.c | 14 ++--- src/jtag/interface.h | 4 +- src/jtag/minidriver.h | 2 +- src/jtag/swd.h | 14 ++--- src/jtag/tcl.c | 8 +-- 24 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index bbf1cb3d2e..996a23f1ff 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -401,7 +401,7 @@ COMMAND_HANDLER(adapter_transports_command) retval = allow_transports(CMD_CTX, (const char **)transports); if (retval != ERROR_OK) { - for (unsigned i = 0; transports[i]; i++) + for (unsigned int i = 0; transports[i]; i++) free(transports[i]); free(transports); } @@ -414,7 +414,7 @@ COMMAND_HANDLER(handle_adapter_list_command) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD, "The following debug adapters are available:"); - for (unsigned i = 0; adapter_drivers[i]; i++) { + for (unsigned int i = 0; adapter_drivers[i]; i++) { const char *name = adapter_drivers[i]->name; command_print(CMD, "%u: %s", i + 1, name); } @@ -436,7 +436,7 @@ COMMAND_HANDLER(handle_adapter_driver_command) if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0') return ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; adapter_drivers[i]; i++) { + for (unsigned int i = 0; adapter_drivers[i]; i++) { if (strcmp(CMD_ARGV[0], adapter_drivers[i]->name) != 0) continue; @@ -684,7 +684,7 @@ COMMAND_HANDLER(handle_adapter_srst_delay_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned delay; + unsigned int delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_nsrst_delay(delay); @@ -698,7 +698,7 @@ COMMAND_HANDLER(handle_adapter_srst_pulse_width_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned width; + unsigned int width; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], width); jtag_set_nsrst_assert_width(width); @@ -714,7 +714,7 @@ COMMAND_HANDLER(handle_adapter_speed_command) int retval = ERROR_OK; if (CMD_ARGC == 1) { - unsigned khz = 0; + unsigned int khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); retval = adapter_config_khz(khz); diff --git a/src/jtag/core.c b/src/jtag/core.c index 6515d71609..907883f099 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -224,7 +224,7 @@ static void jtag_tap_add(struct jtag_tap *t) } /* returns a pointer to the n-th device in the scan chain */ -struct jtag_tap *jtag_tap_by_position(unsigned n) +struct jtag_tap *jtag_tap_by_position(unsigned int n) { struct jtag_tap *t = jtag_all_taps(); @@ -246,7 +246,7 @@ struct jtag_tap *jtag_tap_by_string(const char *s) } /* no tap found by name, so try to parse the name as a number */ - unsigned n; + unsigned int n; if (parse_uint(s, &n) != ERROR_OK) return NULL; diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index e41659263c..17e01a2330 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -92,13 +92,13 @@ static int bitbang_state_move(int skip) */ static int bitbang_execute_tms(struct jtag_command *cmd) { - unsigned num_bits = cmd->cmd.tms->num_bits; + unsigned int num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; LOG_DEBUG_IO("TMS: %u bits", num_bits); int tms = 0; - for (unsigned i = 0; i < num_bits; i++) { + for (unsigned int i = 0; i < num_bits; i++) { tms = ((bits[i/8] >> (i % 8)) & 1); if (bitbang_interface->write(0, tms, 0) != ERROR_OK) return ERROR_FAIL; @@ -193,10 +193,10 @@ static int bitbang_stableclocks(unsigned int num_cycles) } static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, - unsigned scan_size) + unsigned int scan_size) { tap_state_t saved_end_state = tap_get_end_state(); - unsigned bit_cnt; + unsigned int bit_cnt; if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || @@ -254,7 +254,7 @@ static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, if (type != SCAN_OUT && bitbang_interface->buf_size && (buffered == bitbang_interface->buf_size || bit_cnt == scan_size - 1)) { - for (unsigned i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) { + for (unsigned int i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) { switch (bitbang_interface->read_sample()) { case BB_LOW: buffer[i/8] &= ~(1 << (i % 8)); diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 4ba6b51bea..2f776cb387 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -2153,7 +2153,7 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command) { uint8_t *command = cmsis_dap_handle->command; - for (unsigned i = 0; i < CMD_ARGC; i++) + for (unsigned int i = 0; i < CMD_ARGC; i++) COMMAND_PARSE_NUMBER(u8, CMD_ARGV[i], command[i]); int retval = cmsis_dap_xfer(cmsis_dap_handle, CMD_ARGC); @@ -2185,7 +2185,7 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) CMD_ARGC -= 1; } - unsigned i; + unsigned int i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], cmsis_dap_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], cmsis_dap_pid[i >> 1]); diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index 2aad4a0c13..d52a345a0a 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -234,7 +234,7 @@ int interface_jtag_add_tlr(void) return ERROR_OK; } -int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state) +int interface_add_tms_seq(unsigned int num_bits, const uint8_t *seq, enum tap_state state) { struct jtag_command *cmd; diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index a4d072cd77..6dc1304930 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -177,7 +177,7 @@ static void ft232r_increase_buf_size(size_t new_buf_size) */ static void ft232r_write(int tck, int tms, int tdi) { - unsigned out_value = (1<cmd.tms->num_bits; + unsigned int num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; LOG_DEBUG_IO("TMS: %u bits", num_bits); int tms = 0; - for (unsigned i = 0; i < num_bits; i++) { + for (unsigned int i = 0; i < num_bits; i++) { tms = ((bits[i/8] >> (i % 8)) & 1); ft232r_write(0, tms, 0); ft232r_write(1, tms, 0); diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 82117f12c1..42ecda117b 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -324,7 +324,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd) unsigned int i = cmd->cmd.runtest->num_cycles; while (i > 0) { /* there are no state transitions in this code, so omit state tracking */ - unsigned this_len = i > 7 ? 7 : i; + unsigned int this_len = i > 7 ? 7 : i; mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, ftdi_jtag_mode); i -= this_len; } @@ -378,7 +378,7 @@ static void ftdi_execute_pathmove(struct jtag_command *cmd) tap_state_name(path[num_states-1])); int state_count = 0; - unsigned bit_count = 0; + unsigned int bit_count = 0; uint8_t tms_byte = 0; LOG_DEBUG_IO("-"); @@ -447,7 +447,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd) ftdi_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; - unsigned scan_size = 0; + unsigned int scan_size = 0; for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; @@ -584,7 +584,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd) * the correct level and remain there during the scan */ while (num_cycles > 0) { /* there are no state transitions in this code, so omit state tracking */ - unsigned this_len = num_cycles > 7 ? 7 : num_cycles; + unsigned int this_len = num_cycles > 7 ? 7 : num_cycles; mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, ftdi_jtag_mode); num_cycles -= this_len; } @@ -750,7 +750,7 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command) uint16_t input_mask = 0; bool invert_oe = false; uint16_t oe_mask = 0; - for (unsigned i = 1; i < CMD_ARGC; i += 2) { + for (unsigned int i = 1; i < CMD_ARGC; i += 2) { if (strcmp("-data", CMD_ARGV[i]) == 0) { invert_data = false; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask); @@ -879,7 +879,7 @@ COMMAND_HANDLER(ftdi_handle_vid_pid_command) CMD_ARGC -= 1; } - unsigned i; + unsigned int i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ftdi_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ftdi_pid[i >> 1]); diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 1b2fb4e304..74660744a7 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -104,10 +104,10 @@ static int jlink_flush(void); * @param in_offset A bit offset for TDO data. * @param length Amount of bits to transfer out and in. */ -static void jlink_clock_data(const uint8_t *out, unsigned out_offset, - const uint8_t *tms_out, unsigned tms_offset, - uint8_t *in, unsigned in_offset, - unsigned length); +static void jlink_clock_data(const uint8_t *out, unsigned int out_offset, + const uint8_t *tms_out, unsigned int tms_offset, + uint8_t *in, unsigned int in_offset, + unsigned int length); static enum tap_state jlink_last_state = TAP_RESET; static int queued_retval; @@ -179,7 +179,7 @@ static void jlink_execute_scan(struct jtag_command *cmd) jlink_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; - unsigned scan_size = 0; + unsigned int scan_size = 0; for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; @@ -1962,7 +1962,7 @@ static void jlink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_c /***************************************************************************/ /* J-Link tap functions */ -static unsigned tap_length; +static unsigned int tap_length; /* In SWD mode use tms buffer for direction control */ static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE]; static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE]; @@ -1970,13 +1970,13 @@ static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE]; struct pending_scan_result { /** First bit position in tdo_buffer to read. */ - unsigned first; + unsigned int first; /** Number of bits to read. */ - unsigned length; + unsigned int length; /** Location to store the result */ void *buffer; /** Offset in the destination buffer */ - unsigned buffer_offset; + unsigned int buffer_offset; /** SWD command */ uint8_t swd_cmd; }; @@ -1994,13 +1994,13 @@ static void jlink_tap_init(void) memset(tdi_buffer, 0, sizeof(tdi_buffer)); } -static void jlink_clock_data(const uint8_t *out, unsigned out_offset, - const uint8_t *tms_out, unsigned tms_offset, - uint8_t *in, unsigned in_offset, - unsigned length) +static void jlink_clock_data(const uint8_t *out, unsigned int out_offset, + const uint8_t *tms_out, unsigned int tms_offset, + uint8_t *in, unsigned int in_offset, + unsigned int length) { do { - unsigned available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8; + unsigned int available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8; if (!available_length || (in && pending_scan_results_length == MAX_PENDING_SCAN_RESULTS)) { @@ -2012,7 +2012,7 @@ static void jlink_clock_data(const uint8_t *out, unsigned out_offset, struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length]; - unsigned scan_length = length > available_length ? + unsigned int scan_length = length > available_length ? available_length : length; if (out) diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 15b2679bba..079bb1d0a1 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -158,7 +158,7 @@ static int jtag_vpi_send_cmd(struct vpi_cmd *vpi) static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi) { - unsigned bytes_buffered = 0; + unsigned int bytes_buffered = 0; while (bytes_buffered < sizeof(struct vpi_cmd)) { int bytes_to_receive = sizeof(struct vpi_cmd) - bytes_buffered; int retval = read_socket(sockfd, ((char *)vpi) + bytes_buffered, bytes_to_receive); diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 57ea8cd3fa..ee90e78b37 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -53,7 +53,7 @@ static int jtag_libusb_error(int err) bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc, const uint16_t vids[], const uint16_t pids[]) { - for (unsigned i = 0; vids[i]; i++) { + for (unsigned int i = 0; vids[i]; i++) { if (dev_desc->idVendor == vids[i] && dev_desc->idProduct == pids[i]) { return true; diff --git a/src/jtag/drivers/minidriver_imp.h b/src/jtag/drivers/minidriver_imp.h index 7afb46345f..b29b3c9cca 100644 --- a/src/jtag/drivers/minidriver_imp.h +++ b/src/jtag/drivers/minidriver_imp.h @@ -13,7 +13,7 @@ static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field) { - unsigned num_bytes = DIV_ROUND_UP(field->num_bits, 8); + unsigned int num_bytes = DIV_ROUND_UP(field->num_bits, 8); field->in_value = cmd_queue_alloc(num_bytes); } diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 3decddb0e8..1ef9550a08 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -64,13 +64,13 @@ struct mpsse_ctx { uint8_t interface; enum ftdi_chip_type type; uint8_t *write_buffer; - unsigned write_size; - unsigned write_count; + unsigned int write_size; + unsigned int write_count; uint8_t *read_buffer; - unsigned read_size; - unsigned read_count; + unsigned int read_size; + unsigned int read_count; uint8_t *read_chunk; - unsigned read_chunk_size; + unsigned int read_chunk_size; struct bit_copy_queue read_queue; int retval; }; @@ -444,13 +444,13 @@ void mpsse_purge(struct mpsse_ctx *ctx) } } -static unsigned buffer_write_space(struct mpsse_ctx *ctx) +static unsigned int buffer_write_space(struct mpsse_ctx *ctx) { /* Reserve one byte for SEND_IMMEDIATE */ return ctx->write_size - ctx->write_count - 1; } -static unsigned buffer_read_space(struct mpsse_ctx *ctx) +static unsigned int buffer_read_space(struct mpsse_ctx *ctx) { return ctx->read_size - ctx->read_count; } @@ -462,8 +462,8 @@ static void buffer_write_byte(struct mpsse_ctx *ctx, uint8_t data) ctx->write_buffer[ctx->write_count++] = data; } -static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned bit_count) +static unsigned int buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int bit_count) { LOG_DEBUG_IO("%d bits", bit_count); assert(ctx->write_count + DIV_ROUND_UP(bit_count, 8) <= ctx->write_size); @@ -472,8 +472,8 @@ static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned return bit_count; } -static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, - unsigned bit_count, unsigned offset) +static unsigned int buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned int in_offset, + unsigned int bit_count, unsigned int offset) { LOG_DEBUG_IO("%d bits, offset %d", bit_count, offset); assert(ctx->read_count + DIV_ROUND_UP(bit_count, 8) <= ctx->read_size); @@ -483,20 +483,20 @@ static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_ return bit_count; } -void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, uint8_t mode) +void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, uint8_t mode) { mpsse_clock_data(ctx, out, out_offset, NULL, 0, length, mode); } -void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length, +void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned int in_offset, unsigned int length, uint8_t mode) { mpsse_clock_data(ctx, NULL, 0, in, in_offset, length, mode); } -void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, uint8_t mode) +void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, uint8_t mode) { /* TODO: Fix MSB first modes */ LOG_DEBUG_IO("%s%s %d bits", in ? "in" : "", out ? "out" : "", length); @@ -531,7 +531,7 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of length = 0; } else { /* Byte transfer */ - unsigned this_bytes = length / 8; + unsigned int this_bytes = length / 8; /* MPSSE command limit */ if (this_bytes > 65536) this_bytes = 65536; @@ -558,7 +558,7 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of this_bytes * 8, 0); if (!out && !in) - for (unsigned n = 0; n < this_bytes; n++) + for (unsigned int n = 0; n < this_bytes; n++) buffer_write_byte(ctx, 0x00); length -= this_bytes * 8; } @@ -566,14 +566,14 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of } } -void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, bool tdi, uint8_t mode) +void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, bool tdi, uint8_t mode) { mpsse_clock_tms_cs(ctx, out, out_offset, NULL, 0, length, tdi, mode); } -void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, bool tdi, uint8_t mode) +void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, bool tdi, uint8_t mode) { LOG_DEBUG_IO("%sout %d bits, tdi=%d", in ? "in" : "", length, tdi); assert(out); @@ -593,7 +593,7 @@ void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_ ctx->retval = mpsse_flush(ctx); /* Byte transfer */ - unsigned this_bits = length; + unsigned int this_bits = length; /* MPSSE command limit */ /* NOTE: there's a report of an FT2232 bug in this area, where shifting * exactly 7 bits can make problems with TMS signaling for the last @@ -783,7 +783,7 @@ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency) struct transfer_result { struct mpsse_ctx *ctx; bool done; - unsigned transferred; + unsigned int transferred; }; static LIBUSB_CALL void read_cb(struct libusb_transfer *transfer) @@ -791,16 +791,16 @@ static LIBUSB_CALL void read_cb(struct libusb_transfer *transfer) struct transfer_result *res = transfer->user_data; struct mpsse_ctx *ctx = res->ctx; - unsigned packet_size = ctx->max_packet_size; + unsigned int packet_size = ctx->max_packet_size; DEBUG_PRINT_BUF(transfer->buffer, transfer->actual_length); /* Strip the two status bytes sent at the beginning of each USB packet * while copying the chunk buffer to the read buffer */ - unsigned num_packets = DIV_ROUND_UP(transfer->actual_length, packet_size); - unsigned chunk_remains = transfer->actual_length; - for (unsigned i = 0; i < num_packets && chunk_remains > 2; i++) { - unsigned this_size = packet_size - 2; + unsigned int num_packets = DIV_ROUND_UP(transfer->actual_length, packet_size); + unsigned int chunk_remains = transfer->actual_length; + for (unsigned int i = 0; i < num_packets && chunk_remains > 2; i++) { + unsigned int this_size = packet_size - 2; if (this_size > chunk_remains - 2) this_size = chunk_remains - 2; if (this_size > ctx->read_count - res->transferred) diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index 737560d956..4a625d890b 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -44,16 +44,16 @@ bool mpsse_is_high_speed(struct mpsse_ctx *ctx); /* Command queuing. These correspond to the MPSSE commands with the same names, but no need to care * about bit/byte transfer or data length limitation. Read data is guaranteed to be available only * after the following mpsse_flush(). */ -void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, uint8_t mode); -void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length, +void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, uint8_t mode); +void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned int in_offset, unsigned int length, uint8_t mode); -void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, uint8_t mode); -void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, bool tdi, uint8_t mode); -void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, bool tdi, uint8_t mode); +void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, uint8_t mode); +void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, bool tdi, uint8_t mode); +void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, bool tdi, uint8_t mode); void mpsse_set_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir); void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir); void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data); diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 8cf3b0c73a..812a192c22 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -3740,7 +3740,7 @@ static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode, h->st_mode = mode; - for (unsigned i = 0; param->vid[i]; i++) { + for (unsigned int i = 0; param->vid[i]; i++) { LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", h->st_mode, param->vid[i], param->pid[i], adapter_get_required_serial() ? adapter_get_required_serial() : ""); diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index de0d2d8472..e790f3ae53 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -30,7 +30,7 @@ #define SECTION_BUFFERSIZE 16384 static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf, - unsigned size, uint32_t *bytes_read) + unsigned int size, uint32_t *bytes_read) { int ret, tmp = 0; diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h index 3e138bd23b..e9c9268131 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access.h +++ b/src/jtag/drivers/usb_blaster/ublast_access.h @@ -30,7 +30,7 @@ struct ublast_lowlevel { int (*write)(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written); - int (*read)(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, + int (*read)(struct ublast_lowlevel *low, uint8_t *buf, unsigned int size, uint32_t *bytes_read); int (*open)(struct ublast_lowlevel *low); int (*close)(struct ublast_lowlevel *low); diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c index eb312ef4ee..9647f2b82c 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c +++ b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c @@ -28,7 +28,7 @@ static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low) } static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf, - unsigned size, uint32_t *bytes_read) + unsigned int size, uint32_t *bytes_read) { int retval; int timeout = 100; diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 53dd158f66..496466ca3d 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -158,7 +158,7 @@ static char *hexdump(uint8_t *buf, unsigned int size) return str; } -static int ublast_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) +static int ublast_buf_read(uint8_t *buf, unsigned int size, uint32_t *bytes_read) { int ret = info.drv->read(info.drv, buf, size, bytes_read); char *str = hexdump(buf, *bytes_read); diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index b5c7e2fd69..d90a022cda 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -43,7 +43,7 @@ struct xlnx_pcie_xvc { int fd; - unsigned offset; + unsigned int offset; char *device; }; diff --git a/src/jtag/interface.c b/src/jtag/interface.c index 1230bb1b3d..87d704db97 100644 --- a/src/jtag/interface.c +++ b/src/jtag/interface.c @@ -343,7 +343,7 @@ static const struct name_mapping { const char *tap_state_name(tap_state_t state) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) { if (tap_name_mapping[i].symbol == state) @@ -354,7 +354,7 @@ const char *tap_state_name(tap_state_t state) tap_state_t tap_state_by_name(const char *name) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) { /* be nice to the human */ @@ -376,11 +376,11 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, { const uint8_t *tms_buffer; const uint8_t *tdi_buffer; - unsigned tap_bytes; - unsigned cur_byte; - unsigned cur_bit; + unsigned int tap_bytes; + unsigned int cur_byte; + unsigned int cur_bit; - unsigned tap_out_bits; + unsigned int tap_out_bits; char tms_str[33]; char tdi_str[33]; @@ -400,7 +400,7 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, for (cur_byte = 0; cur_byte < tap_bytes; cur_byte++) { for (cur_bit = 0; cur_bit < 8; cur_bit++) { /* make sure we do not run off the end of the buffers */ - unsigned tap_bit = cur_byte * 8 + cur_bit; + unsigned int tap_bit = cur_byte * 8 + cur_bit; if (tap_bit == tap_bits) break; diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 28c1458cb0..b448851dc4 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -159,7 +159,7 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, * @returns the final TAP state; pass as @a start_tap_state in following call. */ static inline tap_state_t jtag_debug_state_machine(const void *tms_buf, - const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state) + const void *tdi_buf, unsigned int tap_len, tap_state_t start_tap_state) { if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) return jtag_debug_state_machine_(tms_buf, tdi_buf, tap_len, start_tap_state); @@ -183,7 +183,7 @@ struct jtag_interface { /** * Bit vector listing capabilities exposed by this driver. */ - unsigned supported; + unsigned int supported; #define DEBUG_CAP_TMS_SEQ (1 << 0) /** diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h index 45b0bf619d..1b1094dd5b 100644 --- a/src/jtag/minidriver.h +++ b/src/jtag/minidriver.h @@ -54,7 +54,7 @@ int interface_jtag_add_tlr(void); int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path); int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate); -int interface_add_tms_seq(unsigned num_bits, +int interface_add_tms_seq(unsigned int num_bits, const uint8_t *bits, enum tap_state state); /** diff --git a/src/jtag/swd.h b/src/jtag/swd.h index 5f626c1bf8..3fe1365b58 100644 --- a/src/jtag/swd.h +++ b/src/jtag/swd.h @@ -101,7 +101,7 @@ static const uint8_t swd_seq_line_reset[] = { /* At least 2 idle (low) cycles */ 0x00, }; -static const unsigned swd_seq_line_reset_len = 64; +static const unsigned int swd_seq_line_reset_len = 64; /** * JTAG-to-SWD sequence. @@ -122,7 +122,7 @@ static const uint8_t swd_seq_jtag_to_swd[] = { /* At least 2 idle (low) cycles */ 0x00, }; -static const unsigned swd_seq_jtag_to_swd_len = 136; +static const unsigned int swd_seq_jtag_to_swd_len = 136; /** * SWD-to-JTAG sequence. @@ -141,7 +141,7 @@ static const uint8_t swd_seq_swd_to_jtag[] = { /* At least 5 TCK/SWCLK cycles with TMS/SWDIO high */ 0xff, }; -static const unsigned swd_seq_swd_to_jtag_len = 80; +static const unsigned int swd_seq_swd_to_jtag_len = 80; /** * SWD-to-dormant sequence. @@ -156,7 +156,7 @@ static const uint8_t swd_seq_swd_to_dormant[] = { /* Switching sequence from SWD to dormant */ 0xbc, 0xe3, }; -static const unsigned swd_seq_swd_to_dormant_len = 72; +static const unsigned int swd_seq_swd_to_dormant_len = 72; /** * Dormant-to-SWD sequence. @@ -187,7 +187,7 @@ static const uint8_t swd_seq_dormant_to_swd[] = { /* At least 2 idle (low) cycles */ 0x00, }; -static const unsigned swd_seq_dormant_to_swd_len = 224; +static const unsigned int swd_seq_dormant_to_swd_len = 224; /** * JTAG-to-dormant sequence. @@ -208,7 +208,7 @@ static const uint8_t swd_seq_jtag_to_dormant[] = { 0x77, /* ((0xbb >> 7) & GENMASK(0, 0)) | ((0xbb << 1) & GENMASK(7, 1)) */ 0x67, /* ((0xbb >> 7) & GENMASK(0, 0)) | ((0x33 << 1) & GENMASK(7, 1)) */ }; -static const unsigned swd_seq_jtag_to_dormant_len = 40; +static const unsigned int swd_seq_jtag_to_dormant_len = 40; /** * Dormant-to-JTAG sequence. @@ -241,7 +241,7 @@ static const uint8_t swd_seq_dormant_to_jtag[] = { /* put the TAP in Run/Test Idle */ 0x00, }; -static const unsigned swd_seq_dormant_to_jtag_len = 160; +static const unsigned int swd_seq_dormant_to_jtag_len = 160; struct swd_driver { /** diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index e2b3b45a60..790aedfc46 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -843,7 +843,7 @@ COMMAND_HANDLER(handle_jtag_ntrst_delay_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned delay; + unsigned int delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_ntrst_delay(delay); @@ -857,7 +857,7 @@ COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned delay; + unsigned int delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_ntrst_assert_width(delay); @@ -873,7 +873,7 @@ COMMAND_HANDLER(handle_jtag_rclk_command) int retval = ERROR_OK; if (CMD_ARGC == 1) { - unsigned khz = 0; + unsigned int khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); retval = adapter_config_rclk(khz); @@ -899,7 +899,7 @@ COMMAND_HANDLER(handle_runtest_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned num_clocks; + unsigned int num_clocks; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num_clocks); jtag_add_runtest(num_clocks, TAP_IDLE); From 436e6f1770e4da6ec5b52724cfb637e8916b535a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:22:40 +0200 Subject: [PATCH 0971/1312] openocd: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Ignore the cast as they could be better addressed. Fix only minor additional checkpatch issue (spacing and line length). Change-Id: I4f936ffc4cedb153afa331cd293b08f4c913dc93 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8482 Tested-by: jenkins --- src/helper/binarybuffer.c | 48 +++++++++++++++++++-------------------- src/helper/binarybuffer.h | 48 +++++++++++++++++++-------------------- src/helper/command.c | 16 ++++++------- src/helper/command.h | 4 ++-- src/helper/log.c | 10 ++++---- src/helper/log.h | 10 ++++---- src/helper/replacements.h | 2 +- src/openocd.c | 2 +- src/rtos/hwthread.c | 2 +- src/svf/svf.c | 4 ++-- src/transport/transport.c | 8 +++---- src/xsvf/xsvf.c | 2 +- 12 files changed, 78 insertions(+), 78 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index a7ca5af9df..6fba86a660 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -40,7 +40,7 @@ static const char hex_digits[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; -void *buf_cpy(const void *from, void *_to, unsigned size) +void *buf_cpy(const void *from, void *_to, unsigned int size) { if (!from || !_to) return NULL; @@ -49,7 +49,7 @@ void *buf_cpy(const void *from, void *_to, unsigned size) memcpy(_to, from, DIV_ROUND_UP(size, 8)); /* mask out bits that don't belong to the buffer */ - unsigned trailing_bits = size % 8; + unsigned int trailing_bits = size % 8; if (trailing_bits) { uint8_t *to = _to; to[size / 8] &= (1 << trailing_bits) - 1; @@ -61,22 +61,22 @@ static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m) { return (a & m) == (b & m); } -static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) +static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned int trailing) { uint8_t mask = (1 << trailing) - 1; return buf_eq_masked(a, b, mask & m); } -bool buf_eq(const void *_buf1, const void *_buf2, unsigned size) +bool buf_eq(const void *_buf1, const void *_buf2, unsigned int size) { if (!_buf1 || !_buf2) return _buf1 == _buf2; - unsigned last = size / 8; + unsigned int last = size / 8; if (memcmp(_buf1, _buf2, last) != 0) return false; - unsigned trailing = size % 8; + unsigned int trailing = size % 8; if (!trailing) return true; @@ -85,24 +85,24 @@ bool buf_eq(const void *_buf1, const void *_buf2, unsigned size) } bool buf_eq_mask(const void *_buf1, const void *_buf2, - const void *_mask, unsigned size) + const void *_mask, unsigned int size) { if (!_buf1 || !_buf2) return _buf1 == _buf2 && _buf1 == _mask; const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask; - unsigned last = size / 8; - for (unsigned i = 0; i < last; i++) { + unsigned int last = size / 8; + for (unsigned int i = 0; i < last; i++) { if (!buf_eq_masked(buf1[i], buf2[i], mask[i])) return false; } - unsigned trailing = size % 8; + unsigned int trailing = size % 8; if (!trailing) return true; return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing); } -void *buf_set_ones(void *_buf, unsigned size) +void *buf_set_ones(void *_buf, unsigned int size) { uint8_t *buf = _buf; if (!buf) @@ -110,19 +110,19 @@ void *buf_set_ones(void *_buf, unsigned size) memset(buf, 0xff, size / 8); - unsigned trailing_bits = size % 8; + unsigned int trailing_bits = size % 8; if (trailing_bits) buf[size / 8] = (1 << trailing_bits) - 1; return buf; } -void *buf_set_buf(const void *_src, unsigned src_start, - void *_dst, unsigned dst_start, unsigned len) +void *buf_set_buf(const void *_src, unsigned int src_start, + void *_dst, unsigned int dst_start, unsigned int len) { const uint8_t *src = _src; uint8_t *dst = _dst; - unsigned i, sb, db, sq, dq, lb, lq; + unsigned int i, sb, db, sq, dq, lb, lq; sb = src_start / 8; db = dst_start / 8; @@ -175,13 +175,13 @@ uint32_t flip_u32(uint32_t value, unsigned int num) return c; } -char *buf_to_hex_str(const void *_buf, unsigned buf_len) +char *buf_to_hex_str(const void *_buf, unsigned int buf_len) { - unsigned len_bytes = DIV_ROUND_UP(buf_len, 8); + unsigned int len_bytes = DIV_ROUND_UP(buf_len, 8); char *str = calloc(len_bytes * 2 + 1, 1); const uint8_t *buf = _buf; - for (unsigned i = 0; i < len_bytes; i++) { + for (unsigned int i = 0; i < len_bytes; i++) { uint8_t tmp = buf[len_bytes - i - 1]; if ((i == 0) && (buf_len % 8)) tmp &= (0xff >> (8 - (buf_len % 8))); @@ -289,8 +289,8 @@ void bit_copy_queue_init(struct bit_copy_queue *q) INIT_LIST_HEAD(&q->list); } -int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src, - unsigned src_offset, unsigned bit_count) +int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned int dst_offset, const uint8_t *src, + unsigned int src_offset, unsigned int bit_count) { struct bit_copy_queue_entry *qe = malloc(sizeof(*qe)); if (!qe) @@ -395,12 +395,12 @@ size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length) return i; } -void buffer_shr(void *_buf, unsigned buf_len, unsigned count) +void buffer_shr(void *_buf, unsigned int buf_len, unsigned int count) { - unsigned i; + unsigned int i; unsigned char *buf = _buf; - unsigned bytes_to_remove; - unsigned shift; + unsigned int bytes_to_remove; + unsigned int shift; bytes_to_remove = count / 8; shift = count - (bytes_to_remove * 8); diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index ed13b980f1..99132798b6 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -32,7 +32,7 @@ * @param value Up to 32 bits that will be copied to _buffer. */ static inline void buf_set_u32(uint8_t *_buffer, - unsigned first, unsigned num, uint32_t value) + unsigned int first, unsigned int num, uint32_t value) { assert(num >= 1 && num <= 32); uint8_t *buffer = _buffer; @@ -43,7 +43,7 @@ static inline void buf_set_u32(uint8_t *_buffer, buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else { - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((value >> (i - first)) & 1) == 1) buffer[i / 8] |= 1 << (i % 8); else @@ -63,7 +63,7 @@ static inline void buf_set_u32(uint8_t *_buffer, * @param value Up to 64 bits that will be copied to _buffer. */ static inline void buf_set_u64(uint8_t *_buffer, - unsigned first, unsigned num, uint64_t value) + unsigned int first, unsigned int num, uint64_t value) { assert(num >= 1 && num <= 64); uint8_t *buffer = _buffer; @@ -83,7 +83,7 @@ static inline void buf_set_u64(uint8_t *_buffer, buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else { - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((value >> (i - first)) & 1) == 1) buffer[i / 8] |= 1 << (i % 8); else @@ -102,7 +102,7 @@ static inline void buf_set_u64(uint8_t *_buffer, * @returns Up to 32-bits that were read from @c _buffer. */ static inline uint32_t buf_get_u32(const uint8_t *_buffer, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { assert(num >= 1 && num <= 32); const uint8_t *buffer = _buffer; @@ -114,7 +114,7 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer, (((uint32_t)buffer[0]) << 0); } else { uint32_t result = 0; - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((buffer[i / 8] >> (i % 8)) & 1) == 1) result |= 1U << (i - first); } @@ -132,7 +132,7 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer, * @returns Up to 64-bits that were read from @c _buffer. */ static inline uint64_t buf_get_u64(const uint8_t *_buffer, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { assert(num >= 1 && num <= 64); const uint8_t *buffer = _buffer; @@ -153,7 +153,7 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer, (((uint64_t)buffer[0]) << 0)); } else { uint64_t result = 0; - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((buffer[i / 8] >> (i % 8)) & 1) == 1) result = result | ((uint64_t)1 << (uint64_t)(i - first)); } @@ -170,11 +170,11 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer, * @param width The number of bits in value (2-32). * @returns A 32-bit word with @c value in reversed bit-order. */ -uint32_t flip_u32(uint32_t value, unsigned width); +uint32_t flip_u32(uint32_t value, unsigned int width); -bool buf_eq(const void *buf1, const void *buf2, unsigned size); +bool buf_eq(const void *buf1, const void *buf2, unsigned int size); bool buf_eq_mask(const void *buf1, const void *buf2, - const void *mask, unsigned size); + const void *mask, unsigned int size); /** * Copies @c size bits out of @c from and into @c to. Any extra @@ -183,7 +183,7 @@ bool buf_eq_mask(const void *buf1, const void *buf2, * @param to The buffer that will receive the copy of @c from. * @param size The number of bits to copy. */ -void *buf_cpy(const void *from, void *to, unsigned size); +void *buf_cpy(const void *from, void *to, unsigned int size); /** * Set the contents of @c buf with @c count bits, all set to 1. @@ -191,10 +191,10 @@ void *buf_cpy(const void *from, void *to, unsigned size); * @param size The number of bits. * @returns The original buffer (@c buf). */ -void *buf_set_ones(void *buf, unsigned size); +void *buf_set_ones(void *buf, unsigned int size); -void *buf_set_buf(const void *src, unsigned src_start, - void *dst, unsigned dst_start, unsigned len); +void *buf_set_buf(const void *src, unsigned int src_start, + void *dst, unsigned int dst_start, unsigned int len); /** * Parse an unsigned number (provided as a zero-terminated string) @@ -207,7 +207,7 @@ void *buf_set_buf(const void *src, unsigned src_start, */ int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize); -char *buf_to_hex_str(const void *buf, unsigned size); +char *buf_to_hex_str(const void *buf, unsigned int size); /* read a uint32_t from a buffer in target memory endianness */ static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le) @@ -215,8 +215,8 @@ static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le) return le ? le_to_h_u32(p) : be_to_h_u32(p); } -static inline void bit_copy(uint8_t *dst, unsigned dst_offset, const uint8_t *src, - unsigned src_offset, unsigned bit_count) +static inline void bit_copy(uint8_t *dst, unsigned int dst_offset, const uint8_t *src, + unsigned int src_offset, unsigned int bit_count) { buf_set_buf(src, src_offset, dst, dst_offset, bit_count); } @@ -227,16 +227,16 @@ struct bit_copy_queue { struct bit_copy_queue_entry { uint8_t *dst; - unsigned dst_offset; + unsigned int dst_offset; const uint8_t *src; - unsigned src_offset; - unsigned bit_count; + unsigned int src_offset; + unsigned int bit_count; struct list_head list; }; void bit_copy_queue_init(struct bit_copy_queue *q); -int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src, - unsigned src_offset, unsigned bit_count); +int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned int dst_offset, const uint8_t *src, + unsigned int src_offset, unsigned int bit_count); void bit_copy_execute(struct bit_copy_queue *q); void bit_copy_discard(struct bit_copy_queue *q); @@ -244,6 +244,6 @@ void bit_copy_discard(struct bit_copy_queue *q); * used in ti-icdi driver and gdb server */ size_t unhexify(uint8_t *bin, const char *hex, size_t count); size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen); -void buffer_shr(void *_buf, unsigned buf_len, unsigned count); +void buffer_shr(void *_buf, unsigned int buf_len, unsigned int count); #endif /* OPENOCD_HELPER_BINARYBUFFER_H */ diff --git a/src/helper/command.c b/src/helper/command.c index 907869325d..d90d34141b 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -58,7 +58,7 @@ void *jimcmd_privdata(Jim_Cmd *cmd) return cmd->isproc ? NULL : cmd->u.native.privData; } -static void tcl_output(void *privData, const char *file, unsigned line, +static void tcl_output(void *privData, const char *file, unsigned int line, const char *function, const char *string) { struct log_capture_state *state = privData; @@ -144,7 +144,7 @@ static void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const return; char *dbg = alloc_printf("command -"); - for (unsigned i = 0; i < argc; i++) { + for (unsigned int i = 0; i < argc; i++) { const char *w = Jim_GetString(argv[i], NULL); char *t = alloc_printf("%s %s", dbg, w); free(dbg); @@ -288,7 +288,7 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, struct target *override_target) { int retval = ERROR_OK; - unsigned i; + unsigned int i; for (i = 0; cmds[i].name || cmds[i].chain; i++) { const struct command_registration *cr = cmds + i; @@ -323,7 +323,7 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, } } if (retval != ERROR_OK) { - for (unsigned j = 0; j < i; j++) + for (unsigned int j = 0; j < i; j++) unregister_command(cmd_ctx, cmd_prefix, cmds[j].name); } return retval; @@ -728,12 +728,12 @@ static COMMAND_HELPER(command_help_show_list, bool show_help, const char *cmd_ma #define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n)) -static void command_help_show_indent(unsigned n) +static void command_help_show_indent(unsigned int n) { - for (unsigned i = 0; i < n; i++) + for (unsigned int i = 0; i < n; i++) LOG_USER_N(" "); } -static void command_help_show_wrap(const char *str, unsigned n, unsigned n2) +static void command_help_show_wrap(const char *str, unsigned int n, unsigned int n2) { const char *cp = str, *last = str; while (*cp) { @@ -1317,7 +1317,7 @@ DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX) #define DEFINE_PARSE_ULONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long long, _ullong) -DEFINE_PARSE_ULONGLONG(_uint, unsigned, 0, UINT_MAX) +DEFINE_PARSE_ULONGLONG(_uint, unsigned int, 0, UINT_MAX) DEFINE_PARSE_ULONGLONG(_u64, uint64_t, 0, UINT64_MAX) DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) diff --git a/src/helper/command.h b/src/helper/command.h index b224bd0221..18fe561782 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -77,7 +77,7 @@ struct command_invocation { struct command_context *ctx; struct command *current; const char *name; - unsigned argc; + unsigned int argc; const char **argv; Jim_Obj * const *jimtcl_argv; Jim_Obj *output; @@ -414,7 +414,7 @@ int parse_llong(const char *str, long long *ul); #define DECLARE_PARSE_WRAPPER(name, type) \ int parse ## name(const char *str, type * ul) -DECLARE_PARSE_WRAPPER(_uint, unsigned); +DECLARE_PARSE_WRAPPER(_uint, unsigned int); DECLARE_PARSE_WRAPPER(_u64, uint64_t); DECLARE_PARSE_WRAPPER(_u32, uint32_t); DECLARE_PARSE_WRAPPER(_u16, uint16_t); diff --git a/src/helper/log.c b/src/helper/log.c index 471069adee..62ba4da4cd 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -53,7 +53,7 @@ static const char * const log_strings[6] = { static int count; /* forward the log to the listeners */ -static void log_forward(const char *file, unsigned line, const char *function, const char *string) +static void log_forward(const char *file, unsigned int line, const char *function, const char *string) { struct log_callback *cb, *next; cb = log_callbacks; @@ -133,7 +133,7 @@ static void log_puts(enum log_levels level, void log_printf(enum log_levels level, const char *file, - unsigned line, + unsigned int line, const char *function, const char *format, ...) @@ -156,7 +156,7 @@ void log_printf(enum log_levels level, va_end(ap); } -void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, +void log_vprintf_lf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, va_list args) { char *tmp; @@ -182,7 +182,7 @@ void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, void log_printf_lf(enum log_levels level, const char *file, - unsigned line, + unsigned int line, const char *function, const char *format, ...) @@ -505,7 +505,7 @@ void log_socket_error(const char *socket_desc) * Find the first non-printable character in the char buffer, return a pointer to it. * If no such character exists, return NULL. */ -char *find_nonprint_char(char *buf, unsigned buf_len) +char *find_nonprint_char(char *buf, unsigned int buf_len) { for (unsigned int i = 0; i < buf_len; i++) { if (!isprint(buf[i])) diff --git a/src/helper/log.h b/src/helper/log.h index d52c05f99d..0f11cfa9a4 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -48,12 +48,12 @@ enum log_levels { LOG_LVL_DEBUG_IO = 4, }; -void log_printf(enum log_levels level, const char *file, unsigned line, +void log_printf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); -void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, +void log_vprintf_lf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, va_list args); -void log_printf_lf(enum log_levels level, const char *file, unsigned line, +void log_printf_lf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); @@ -73,7 +73,7 @@ void busy_sleep(uint64_t ms); void log_socket_error(const char *socket_desc); -typedef void (*log_callback_fn)(void *priv, const char *file, unsigned line, +typedef void (*log_callback_fn)(void *priv, const char *file, unsigned int line, const char *function, const char *string); struct log_callback { @@ -89,7 +89,7 @@ char *alloc_vprintf(const char *fmt, va_list ap); char *alloc_printf(const char *fmt, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2))); -char *find_nonprint_char(char *buf, unsigned buf_len); +char *find_nonprint_char(char *buf, unsigned int buf_len); extern int debug_level; diff --git a/src/helper/replacements.h b/src/helper/replacements.h index 6e30b628b0..ecc0e5e955 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -111,7 +111,7 @@ size_t strnlen(const char *s, size_t maxlen); #ifndef HAVE_USLEEP #ifdef _WIN32 -static inline unsigned usleep(unsigned int usecs) +static inline unsigned int usleep(unsigned int usecs) { Sleep((usecs/1000)); return 0; diff --git a/src/openocd.c b/src/openocd.c index 54c5eb34f7..7a51470502 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -258,7 +258,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp) &arm_tpiu_swo_register_commands, NULL }; - for (unsigned i = 0; command_registrants[i]; i++) { + for (unsigned int i = 0; command_registrants[i]; i++) { int retval = (*command_registrants[i])(cmd_ctx); if (retval != ERROR_OK) { command_done(cmd_ctx); diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 4fe8419025..65b89eb223 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -320,7 +320,7 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, rtos_reg->number = reg->number; rtos_reg->size = reg->size; - unsigned bytes = (reg->size + 7) / 8; + unsigned int bytes = (reg->size + 7) / 8; assert(bytes <= sizeof(rtos_reg->value)); memcpy(rtos_reg->value, reg->value, bytes); diff --git a/src/svf/svf.c b/src/svf/svf.c index 470889948c..9dd2463c0a 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -245,7 +245,7 @@ static int svf_last_printed_percentage = -1; #define SVF_BUF_LOG(_lvl, _buf, _nbits, _desc) \ svf_hexbuf_print(LOG_LVL_##_lvl, __FILE__, __LINE__, __func__, _buf, _nbits, _desc) -static void svf_hexbuf_print(int dbg_lvl, const char *file, unsigned line, +static void svf_hexbuf_print(int dbg_lvl, const char *file, unsigned int line, const char *function, const uint8_t *buf, int bit_len, const char *desc) { @@ -316,7 +316,7 @@ static void svf_free_xxd_para(struct svf_xxr_para *para) int svf_add_statemove(tap_state_t state_to) { tap_state_t state_from = cmd_queue_cur_state; - unsigned index_var; + unsigned int index_var; /* when resetting, be paranoid and ignore current state */ if (state_to == TAP_RESET) { diff --git a/src/transport/transport.c b/src/transport/transport.c index bf306e7314..c7293e7fda 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -176,8 +176,8 @@ struct transport *get_current_transport(void) COMMAND_HELPER(transport_list_parse, char ***vector) { char **argv; - unsigned n = CMD_ARGC; - unsigned j = 0; + unsigned int n = CMD_ARGC; + unsigned int j = 0; *vector = NULL; @@ -189,7 +189,7 @@ COMMAND_HELPER(transport_list_parse, char ***vector) if (!argv) return ERROR_FAIL; - for (unsigned i = 0; i < n; i++) { + for (unsigned int i = 0; i < n; i++) { struct transport *t; for (t = transport_list; t; t = t->next) { @@ -208,7 +208,7 @@ COMMAND_HELPER(transport_list_parse, char ***vector) return ERROR_OK; fail: - for (unsigned i = 0; i < n; i++) + for (unsigned int i = 0; i < n; i++) free(argv[i]); free(argv); return ERROR_FAIL; diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index 0266c2120c..74a4dcfde1 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -217,7 +217,7 @@ COMMAND_HANDLER(handle_xsvf_command) bool collecting_path = false; tap_state_t path[XSTATE_MAX_PATH]; - unsigned pathlen = 0; + unsigned int pathlen = 0; /* a flag telling whether to clock TCK during waits, * or simply sleep, controlled by virt2 From 39f024900e7e69d2695071267fb079afb5ad6635 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 10:42:47 +0200 Subject: [PATCH 0972/1312] flash: stm32l4x: fix open brace style Checkpatch triggers the error ERROR:OPEN_BRACE: open brace '{' following function definitions go on the next line Fix it! Change-Id: I0ce4585a6507eca094b82cdabdecf6fdbe7923b1 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8491 Tested-by: jenkins Reviewed-by: zapb --- src/flash/nor/stm32l4x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 9235dd7877..d66a83dd34 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -717,7 +717,8 @@ struct range { }; static void bitmap_to_ranges(unsigned long *bitmap, unsigned int nbits, - struct range *ranges, unsigned int *ranges_count) { + struct range *ranges, unsigned int *ranges_count) +{ *ranges_count = 0; bool last_bit = 0, cur_bit; for (unsigned int i = 0; i < nbits; i++) { From 537793bb245750f4af992a04547f856d1a99cbfc Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 10:45:17 +0200 Subject: [PATCH 0973/1312] target: mem_ap: drop return from void function Checkpatch triggers the error ERROR:RETURN_VOID: void function return statements are not generally useful Fix it! Change-Id: I72d9fb8242d6a91c0aa481d5d023f0359c76a5ec Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8492 Tested-by: jenkins Reviewed-by: zapb --- src/target/mem_ap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 61a9475e64..4114020776 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -75,7 +75,6 @@ static void mem_ap_deinit_target(struct target *target) free(target->private_config); free(target->arch_info); - return; } static int mem_ap_arch_state(struct target *target) From 4214fca4478404fff21110fd8ce5b4dc9ccfa72a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 11:31:37 +0200 Subject: [PATCH 0974/1312] OpenOCD: fix code alignment Fix checkpatch errors: ERROR:TABSTOP: Statements should start on a tabstop Change-Id: Ia771e7b7fa2cc4ef0be7f52b670525175555c8e4 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8493 Reviewed-by: zapb Tested-by: jenkins --- src/flash/nor/ocl.c | 2 +- src/jtag/drivers/buspirate.c | 16 ++++++++-------- src/jtag/hla/hla_interface.c | 2 +- src/target/mips32_pracc.c | 6 +++--- src/target/openrisc/or1k_du_adv.c | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/flash/nor/ocl.c b/src/flash/nor/ocl.c index e00c365edd..61af908f58 100644 --- a/src/flash/nor/ocl.c +++ b/src/flash/nor/ocl.c @@ -160,7 +160,7 @@ static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer); if (retval != ERROR_OK) { free(dcc_buffer); - return retval; + return retval; } /* wait for response, fixed timeout of 1 s */ diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index b01a796442..6f8df5adad 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -1442,7 +1442,7 @@ static void buspirate_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_del data); switch (ack) { - case SWD_ACK_OK: + case SWD_ACK_OK: if (parity != parity_u32(data)) { LOG_DEBUG("Read data parity mismatch %x %x", parity, parity_u32(data)); queued_retval = ERROR_FAIL; @@ -1453,15 +1453,15 @@ static void buspirate_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_del if (cmd & SWD_CMD_APNDP) buspirate_swd_idle_clocks(ap_delay_clk); return; - case SWD_ACK_WAIT: + case SWD_ACK_WAIT: LOG_DEBUG("SWD_ACK_WAIT"); buspirate_swd_clear_sticky_errors(); return; - case SWD_ACK_FAULT: + case SWD_ACK_FAULT: LOG_DEBUG("SWD_ACK_FAULT"); queued_retval = ack; return; - default: + default: LOG_DEBUG("No valid acknowledge: ack=%d", ack); queued_retval = ack; return; @@ -1500,19 +1500,19 @@ static void buspirate_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_del value); switch (ack) { - case SWD_ACK_OK: + case SWD_ACK_OK: if (cmd & SWD_CMD_APNDP) buspirate_swd_idle_clocks(ap_delay_clk); return; - case SWD_ACK_WAIT: + case SWD_ACK_WAIT: LOG_DEBUG("SWD_ACK_WAIT"); buspirate_swd_clear_sticky_errors(); return; - case SWD_ACK_FAULT: + case SWD_ACK_FAULT: LOG_DEBUG("SWD_ACK_FAULT"); queued_retval = ack; return; - default: + default: LOG_DEBUG("No valid acknowledge: ack=%d", ack); queued_retval = ack; return; diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index c73f6c8d39..f284278ddc 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -348,7 +348,7 @@ static const struct command_registration hl_interface_subcommand_handlers[] = { .help = "select which ST-Link backend to use", .usage = "usb | tcp [port]", }, - { + { .name = "command", .handler = &interface_handle_hla_command, .mode = COMMAND_EXEC, diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 2d0bd641b2..587e20d2be 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -212,7 +212,7 @@ static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_i store_pending--; } else { /* read/fetch access */ - if (!final_check) { /* executing function code */ + if (!final_check) { /* executing function code */ /* check address */ if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) { LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x", @@ -243,7 +243,7 @@ static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_i if (code_count == ctx->code_count) /* last instruction, start final check */ final_check = 1; - } else { /* final check after function code shifted out */ + } else { /* final check after function code shifted out */ /* check address */ if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) { if (!pass) { /* first pass through pracc text */ @@ -275,7 +275,7 @@ static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_i } instr = MIPS32_NOP; /* shift out NOPs instructions */ code_count++; - } + } /* Send instruction out */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); diff --git a/src/target/openrisc/or1k_du_adv.c b/src/target/openrisc/or1k_du_adv.c index e4003a213d..f401ea9fb5 100644 --- a/src/target/openrisc/or1k_du_adv.c +++ b/src/target/openrisc/or1k_du_adv.c @@ -362,7 +362,7 @@ static int adbg_ctrl_read(struct or1k_jtag *jtag_info, uint32_t regidx, default: LOG_ERROR("Illegal debug chain selected (%i) while doing control read", jtag_info->or1k_jtag_module_selected); - return ERROR_FAIL; + return ERROR_FAIL; } /* Zero MSB = op for module, not top-level debug unit */ From 39197cdb4ee8f7ed605308a07bac67b33fb4973f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 11:36:03 +0200 Subject: [PATCH 0975/1312] jtag: stlink_usb: drop comparison to NULL Fix checkpatch error: ERROR:COMPARISON_TO_NULL: Comparison to NULL could be written "handle" Change-Id: I0ac12ccfc5fce4dd41266f83eb4b973a4e6a314d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8494 Reviewed-by: zapb Tested-by: jenkins --- src/jtag/drivers/stlink_usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 812a192c22..0385e4d857 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -2754,7 +2754,7 @@ static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_ { struct stlink_usb_handle *h = handle; - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_MEM_RD_NO_INC)) return ERROR_COMMAND_NOTFOUND; @@ -2796,7 +2796,7 @@ static int stlink_usb_write_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32 { struct stlink_usb_handle *h = handle; - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_MEM_WR_NO_INC)) return ERROR_COMMAND_NOTFOUND; @@ -3947,7 +3947,7 @@ static int stlink_usb_rw_misc_out(void *handle, uint32_t items, const uint8_t *b LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) return ERROR_COMMAND_NOTFOUND; @@ -3968,7 +3968,7 @@ static int stlink_usb_rw_misc_in(void *handle, uint32_t items, uint8_t *buffer) LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) return ERROR_COMMAND_NOTFOUND; From 66006d83b99843ab7c6ec19125e2fc20855a4c7c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 11:37:05 +0200 Subject: [PATCH 0976/1312] target: drop comparison to NULL Fix checkpatch error: ERROR:COMPARISON_TO_NULL: Comparison to NULL could be written "cmd_ctx" Change-Id: I3615fc427f8b160d44b6edbf7a066a086cab99bb Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8495 Tested-by: jenkins Reviewed-by: zapb --- src/target/target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 56aa8b1e70..2be8b24b92 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4596,7 +4596,7 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, } struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx != NULL); + assert(cmd_ctx); struct target *target = get_current_target(cmd_ctx); const size_t buffersize = 4096; @@ -4739,7 +4739,7 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc, return JIM_ERR; struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx != NULL); + assert(cmd_ctx); const struct target *target = get_current_target(cmd_ctx); for (int i = 0; i < length; i++) { From 3ccf68cd0a8aa740565456317bae9d43618ef662 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 11:55:20 +0200 Subject: [PATCH 0977/1312] OpenOCD: drop comparison with true/false Fix checkpatch errors: ERROR:BOOL_COMPARISON: Using comparison to true/false is error prone While there, - drop useless parenthesis, - drop unnecessary else after a return. Change-Id: I1234737b3e65bd10df5e938d1c36f9abaf02d348 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8496 Reviewed-by: zapb Tested-by: jenkins --- src/flash/nor/psoc6.c | 2 +- src/flash/nor/xcf.c | 68 +++++++++---------- src/jtag/drivers/ulink.c | 6 +- .../usb_blaster/ublast2_access_libusb.c | 2 +- src/rtos/hwthread.c | 4 +- src/rtos/rtos.c | 2 +- src/server/gdb_server.c | 8 +-- src/target/cortex_m.c | 2 +- src/target/target.c | 2 +- 9 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 47f3ac6980..662910aa04 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -487,7 +487,7 @@ static int psoc6_get_info(struct flash_bank *bank, struct command_invocation *cm { struct psoc6_target_info *psoc6_info = bank->driver_priv; - if (psoc6_info->is_probed == false) + if (!psoc6_info->is_probed) return ERROR_FAIL; int hr = get_silicon_id(bank->target, &psoc6_info->silicon_id, &psoc6_info->protection); diff --git a/src/flash/nor/xcf.c b/src/flash/nor/xcf.c index 1d67b09430..4011fa42be 100644 --- a/src/flash/nor/xcf.c +++ b/src/flash/nor/xcf.c @@ -143,28 +143,27 @@ static int isc_enter(struct flash_bank *bank) struct xcf_status status = read_status(bank); - if (true == status.isc_mode) + if (status.isc_mode) return ERROR_OK; - else { - struct scan_field scan; - scan.check_mask = NULL; - scan.check_value = NULL; - scan.num_bits = 16; - scan.out_value = cmd_isc_enable; - scan.in_value = NULL; + struct scan_field scan; - jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); - jtag_execute_queue(); + scan.check_mask = NULL; + scan.check_value = NULL; + scan.num_bits = 16; + scan.out_value = cmd_isc_enable; + scan.in_value = NULL; - status = read_status(bank); - if (!status.isc_mode) { - LOG_ERROR("*** XCF: FAILED to enter ISC mode"); - return ERROR_FLASH_OPERATION_FAILED; - } + jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); + jtag_execute_queue(); - return ERROR_OK; + status = read_status(bank); + if (!status.isc_mode) { + LOG_ERROR("*** XCF: FAILED to enter ISC mode"); + return ERROR_FLASH_OPERATION_FAILED; } + + return ERROR_OK; } static int isc_leave(struct flash_bank *bank) @@ -174,27 +173,26 @@ static int isc_leave(struct flash_bank *bank) if (!status.isc_mode) return ERROR_OK; - else { - struct scan_field scan; - - scan.check_mask = NULL; - scan.check_value = NULL; - scan.num_bits = 16; - scan.out_value = cmd_isc_disable; - scan.in_value = NULL; - - jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); - jtag_execute_queue(); - alive_sleep(1); /* device needs 50 uS to leave ISC mode */ - - status = read_status(bank); - if (status.isc_mode) { - LOG_ERROR("*** XCF: FAILED to leave ISC mode"); - return ERROR_FLASH_OPERATION_FAILED; - } - return ERROR_OK; + struct scan_field scan; + + scan.check_mask = NULL; + scan.check_value = NULL; + scan.num_bits = 16; + scan.out_value = cmd_isc_disable; + scan.in_value = NULL; + + jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); + jtag_execute_queue(); + alive_sleep(1); /* device needs 50 uS to leave ISC mode */ + + status = read_status(bank); + if (status.isc_mode) { + LOG_ERROR("*** XCF: FAILED to leave ISC mode"); + return ERROR_FLASH_OPERATION_FAILED; } + + return ERROR_OK; } static int sector_state(uint8_t wrpt, int sector) diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index ad3bc6e37e..3a248e388f 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -606,7 +606,7 @@ static void ulink_clear_queue(struct ulink *device) /* IN payload MUST be freed ONLY if no other commands use the * payload_in_start buffer */ - if (current->free_payload_in_start == true) { + if (current->free_payload_in_start) { free(current->payload_in_start); current->payload_in_start = NULL; current->payload_in = NULL; @@ -1861,7 +1861,7 @@ static int ulink_post_process_queue(struct ulink *device) /* Check if a corresponding OpenOCD command is stored for this * OpenULINK command */ - if ((current->needs_postprocessing == true) && (openocd_cmd)) { + if (current->needs_postprocessing && openocd_cmd) { switch (openocd_cmd->type) { case JTAG_SCAN: ret = ulink_post_process_scan(current); @@ -2131,7 +2131,7 @@ static int ulink_init(void) download_firmware = true; } - if (download_firmware == true) { + if (download_firmware) { LOG_INFO("Loading OpenULINK firmware. This is reversible by power-cycling" " ULINK device."); ret = ulink_load_firmware_and_renumerate(&ulink_handle, diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index e790f3ae53..8f0ed96f34 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -215,7 +215,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low) const uint16_t vids_renum[] = { low->ublast_vid, 0 }; const uint16_t pids_renum[] = { low->ublast_pid, 0 }; - if (renumeration == false) { + if (!renumeration) { if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK) { LOG_ERROR("Altera USB-Blaster II not found"); return ERROR_FAIL; diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 65b89eb223..1890a3d87a 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -254,7 +254,7 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, int j = 0; for (int i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; j++; } @@ -267,7 +267,7 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, j = 0; for (int i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; if (!reg_list[i]->valid) { retval = reg_list[i]->type->get(reg_list[i]); diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 0df1182c0a..54e31e4268 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -389,7 +389,7 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa return ERROR_OK; } else if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { - if (target->rtos_auto_detect == true) { + if (target->rtos_auto_detect) { target->rtos_auto_detect = false; target->rtos->type->create(target); } diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 854c4dc65d..c1e5e268fb 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1262,7 +1262,7 @@ static int gdb_get_registers_packet(struct connection *connection, return gdb_error(connection, retval); for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1276,7 +1276,7 @@ static int gdb_get_registers_packet(struct connection *connection, reg_packet_p = reg_packet; for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; retval = gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]); if (retval != ERROR_OK && gdb_report_register_access_error) { @@ -2254,7 +2254,7 @@ static int get_reg_features_list(struct target *target, char const **feature_lis *feature_list = calloc(1, sizeof(char *)); for (int i = 0; i < reg_list_size; i++) { - if (reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i]->exist || reg_list[i]->hidden) continue; if (reg_list[i]->feature @@ -2464,7 +2464,7 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o int i; for (i = 0; i < reg_list_size; i++) { - if (reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i]->exist || reg_list[i]->hidden) continue; if (strcmp(reg_list[i]->feature->name, features[current_feature])) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 880a83a18c..bd0e8d8867 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1521,7 +1521,7 @@ static int cortex_m_step(struct target *target, int current, /* if no bkpt instruction is found at pc then we can perform * a normal step, otherwise we have to manually step over the bkpt * instruction - as such simulate a step */ - if (bkpt_inst_found == false) { + if (!bkpt_inst_found) { if (cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO) { /* Automatic ISR masking mode off: Just step over the next * instruction, with interrupts on or off as appropriate. */ diff --git a/src/target/target.c b/src/target/target.c index 2be8b24b92..49611dfb45 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3042,7 +3042,7 @@ COMMAND_HANDLER(handle_reg_command) for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { - if (reg->exist == false || reg->hidden) + if (!reg->exist || reg->hidden) continue; /* only print cached values if they are valid */ if (reg->valid) { From 8c23e6c1759be497c1328837fb49992d489b0719 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 13:49:04 +0200 Subject: [PATCH 0978/1312] target: arm: drop casts commented-out The function dpm->finish() returns a value that is almost always ignored. Drop the commented-out cast /* (void) */ Change-Id: I7ff210a2693dd1877b7c7591705cdcd96a2c6125 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8498 Tested-by: jenkins Reviewed-by: zapb --- src/target/arm_dpm.c | 22 +++++++++++----------- src/target/armv7a.c | 2 +- src/target/armv8.c | 2 +- src/target/armv8_dpm.c | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 318d5afec9..0b2db77c5c 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -59,7 +59,7 @@ static int dpm_mrc(struct target *target, int cpnum, ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -82,7 +82,7 @@ static int dpm_mrrc(struct target *target, int cpnum, ARMV5_T_MRRC(cpnum, op, 0, 1, crm), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -107,7 +107,7 @@ static int dpm_mcr(struct target *target, int cpnum, ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -129,7 +129,7 @@ static int dpm_mcrr(struct target *target, int cpnum, retval = dpm->instr_write_data_r0_r1(dpm, ARMV5_T_MCRR(cpnum, op, 0, 1, crm), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -422,7 +422,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) */ fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -632,7 +632,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) cache->reg_list[i].dirty = false; } - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); done: return retval; } @@ -719,10 +719,10 @@ static int arm_dpm_read_core_reg(struct target *target, struct reg *r, /* always clean up, regardless of error */ if (mode != ARM_MODE_ANY) - /* (void) */ arm_dpm_modeswitch(dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(dpm, ARM_MODE_ANY); fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -761,10 +761,10 @@ static int arm_dpm_write_core_reg(struct target *target, struct reg *r, /* always clean up, regardless of error */ if (mode != ARM_MODE_ANY) - /* (void) */ arm_dpm_modeswitch(dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(dpm, ARM_MODE_ANY); fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -831,7 +831,7 @@ static int arm_dpm_full_context(struct target *target) } while (did_read); retval = arm_dpm_modeswitch(dpm, ARM_MODE_ANY); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); done: return retval; } diff --git a/src/target/armv7a.c b/src/target/armv7a.c index dc3752e0b0..e22d309a07 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -74,7 +74,7 @@ static void armv7a_show_fault_registers(struct target *target) ", IFAR: %8.8" PRIx32, ifsr, ifar); done: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); } diff --git a/src/target/armv8.c b/src/target/armv8.c index 3bf0942759..61d72741a9 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1010,7 +1010,7 @@ static void armv8_show_fault_registers32(struct armv8_common *armv8) ", IFAR: %8.8" PRIx32, ifsr, ifar); done: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); } static __attribute__((unused)) void armv8_show_fault_registers(struct target *target) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 22617fd0ec..d1cee8a10c 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -500,7 +500,7 @@ static int dpmv8_mrc(struct target *target, int cpnum, ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -525,7 +525,7 @@ static int dpmv8_mcr(struct target *target, int cpnum, ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -991,7 +991,7 @@ static int armv8_dpm_read_core_reg(struct target *target, struct reg *r, goto fail; fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -1085,7 +1085,7 @@ static int armv8_dpm_full_context(struct target *target) } while (did_read); retval = armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); done: return retval; } From 595bb965b745371e07091c96ced478c8cd0b0d82 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 10:58:37 +0200 Subject: [PATCH 0979/1312] jtag: bcm2835gpio: fix macro definition The macros trigger few errors with checkpatch: ERROR:MACRO_ARG_REUSE: Macro argument reuse 'g' - possible side-effects? ERROR:TRAILING_STATEMENTS: trailing statements should be on next line ERROR:SPACING: spaces preferred around (several cases) ERROR:SINGLE_STATEMENT_DO_WHILE_MACRO: Single statement macros should not use a do {} while (0) loop plus an empty line triggers ERROR:BRACES: Blank lines aren't necessary before a close brace '}' Fix them! Change-Id: I0690b68b511ed7f45a7e0909a0addd2822ba9fe8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8499 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/bcm2835gpio.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index ff10b0a78c..b8d91bf382 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -31,16 +31,28 @@ static off_t bcm2835_peri_base = 0x20000000; #define BCM2835_GPIO_MODE_OUTPUT 1 /* GPIO setup macros */ -#define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7) -#define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0) -#define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \ - INP_GPIO(g); \ - *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0) +#define MODE_GPIO(_g) ({ \ + typeof(_g) g = (_g); \ + *(pio_base + (g / 10)) >> ((g % 10) * 3) & 7; \ +}) + +#define INP_GPIO(_g) do { \ + typeof(_g) g1 = (_g); \ + *(pio_base + (g1 / 10)) &= ~(7 << ((g1 % 10) * 3)); \ +} while (0) + +#define SET_MODE_GPIO(_g, m) do { \ + typeof(_g) g = (_g); \ + /* clear the mode bits first, then set as necessary */ \ + INP_GPIO(g); \ + *(pio_base + (g / 10)) |= ((m) << ((g % 10) * 3)); \ +} while (0) + #define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT) -#define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */ -#define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */ -#define GPIO_LEV (*(pio_base+13)) /* current level of the pin */ +#define GPIO_SET (*(pio_base + 7)) /* sets bits which are 1, ignores bits which are 0 */ +#define GPIO_CLR (*(pio_base + 10)) /* clears bits which are 1, ignores bits which are 0 */ +#define GPIO_LEV (*(pio_base + 13)) /* current level of the pin */ static int dev_mem_fd; static volatile uint32_t *pio_base = MAP_FAILED; @@ -175,7 +187,6 @@ static bb_value_t bcm2835gpio_read(void) unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num; uint32_t value = (GPIO_LEV >> shift) & 1; return value ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].active_low ? BB_HIGH : BB_LOW); - } static int bcm2835gpio_write(int tck, int tms, int tdi) From 116e9553d12193faa08e668b3d9504ef995bd21f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 22 Sep 2024 18:32:21 +0200 Subject: [PATCH 0980/1312] openocd: build: allow more socket connections on Windows Cross compiling OpenOCD for Windows forces the maximum number of open files (including sockets) to 64. See in include file psdk_inc/_fd_types.h: #ifndef FD_SETSIZE #define FD_SETSIZE 64 #endif This limit is far lower than the default value 1024 used by Linux. In pull request #644 [1] in risc-v fork it's reported that: - each socket server of OpenOCD (GDB, telnet, ...) uses one FD; - each active connection to a socket server uses another FD; - multi-core devices with 32 or more cores, each having a GDB connection, already saturates the 64 available FD at the 26th GDB connection. The patch [2] proposed and merged in risc-v fork adds the compile flag -DFD_SETSIZE=128 to all the host types. While this looks fine for Windows, it reduces the default value for Linux and other OS. Add the compile flag FD_SETSIZE only to cross compile for Windows. Link: [1] https://github.com/riscv-collab/riscv-openocd/pull/644 Link: [2] https://github.com/riscv-collab/riscv-openocd/pull/644/commits/1bab4cfbc4f4 Change-Id: Ie43a792ac11a5e63e0407b68e3f270efea0c87be Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8503 Tested-by: jenkins --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b7aed245e6..07e06551f8 100644 --- a/configure.ac +++ b/configure.ac @@ -435,7 +435,7 @@ AS_CASE([$host], # In case enable_buspirate=auto, make sure it will not be built. enable_buspirate=no - AC_SUBST([HOST_CPPFLAGS], [-D__USE_MINGW_ANSI_STDIO]) + AC_SUBST([HOST_CPPFLAGS], ["-D__USE_MINGW_ANSI_STDIO -DFD_SETSIZE=128"]) ], [*darwin*], [ is_darwin=yes From 73390332d203f02aa5b9798a7550191d55650d97 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 27 Sep 2024 22:36:52 +0200 Subject: [PATCH 0981/1312] openocd: fix build with jimtcl 0.83 In jimtcl 0.82, the include file jim.h included in turn stdio.h This made redundant to include the former in openocd source files. Since jimtcl 0.83, jim.h drops the include of stdio.h, causing openocd build to fail. Include stdio.h in the files that need it. Change-Id: Ic81c9b273d7520f4d2d8c32bc3e0a6bcfffb67ed Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8512 Reviewed-by: Jonathan McDowell Tested-by: jenkins --- src/helper/configuration.h | 1 + src/helper/jim-nvp.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/helper/configuration.h b/src/helper/configuration.h index 295ea591d6..d646670eb3 100644 --- a/src/helper/configuration.h +++ b/src/helper/configuration.h @@ -11,6 +11,7 @@ #ifndef OPENOCD_HELPER_CONFIGURATION_H #define OPENOCD_HELPER_CONFIGURATION_H +#include #include int parse_cmdline_args(struct command_context *cmd_ctx, diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index e1ab64ae5b..cdd4d34291 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -21,6 +21,7 @@ #endif #include "jim-nvp.h" +#include #include int jim_get_nvp(Jim_Interp *interp, From 30c3d077f281876286a7aa37afbd411d4bd1667e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 27 Sep 2024 22:40:06 +0200 Subject: [PATCH 0982/1312] jimtcl: update to version 0.83 New version tagged on 2024-08-28. Change-Id: Id0cf82a692469ccf794c9680c5d5ac09ea26e6da Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8513 Tested-by: jenkins --- jimtcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jimtcl b/jimtcl index 1933e5457b..f160866171 160000 --- a/jimtcl +++ b/jimtcl @@ -1 +1 @@ -Subproject commit 1933e5457b9512d39ebbe11ed32578aada149f49 +Subproject commit f160866171457474f7c4d6ccda70f9b77524407e From edf2c82cf615af4926cc3536bbbafce2c55fe4e0 Mon Sep 17 00:00:00 2001 From: Jan Matyas Date: Fri, 27 Sep 2024 09:49:52 +0200 Subject: [PATCH 0983/1312] helper/align.h: Fix macro IS_PWR_OF_2 Zero is not a power of two. All functions that use IS_PWR_OF_2 were checked and the edge case of IS_PWR_OF_2(0) does not occur anywhere at the moment. Therefore the fix is safe. Change-Id: I84d9f9c64c9a7df452ca6e99c2ee4169ccb2b0be Signed-off-by: Jan Matyas Fixes: 9544cd653df1 ("helper: add align.h") Reviewed-on: https://review.openocd.org/c/openocd/+/8511 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/helper/align.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/align.h b/src/helper/align.h index 935a6a3b26..d7170065ed 100644 --- a/src/helper/align.h +++ b/src/helper/align.h @@ -24,7 +24,7 @@ #define IS_PWR_OF_2(x) \ ({ \ typeof(x) _x = (x); \ - _x == 0 || (_x & (_x - 1)) == 0; \ + _x != 0 && (_x & (_x - 1)) == 0; \ }) #endif /* OPENOCD_HELPER_ALIGN_H */ From bcf63ac56242b4060586761eb39b436e7fe2c1f7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 8 Oct 2024 00:37:48 +0200 Subject: [PATCH 0984/1312] checkpatch: check SPDX in Makefile The firmware in contrib folder use Makefile for the build. Force checkpatch to check these Makefile for the SPDX. Change-Id: I815bf6df636c96a15f82c3d8a9de0c4f219303d2 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8520 Tested-by: jenkins --- tools/scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl index 59a3eed121..01bd547ff5 100755 --- a/tools/scripts/checkpatch.pl +++ b/tools/scripts/checkpatch.pl @@ -3728,7 +3728,7 @@ sub process { } elsif ($realfile =~ /\.rst$/) { $comment = '..'; # OpenOCD specific: Begin - } elsif ($realfile =~ /\.(am|cfg|tcl)$/) { + } elsif (($realfile =~ /\.(am|cfg|tcl)$/) || ($realfile =~ /\/Makefile$/)) { $comment = '#'; } elsif ($realfile =~ /\.(ld)$/) { $comment = '/*'; From 957eb741a0980408fe4d0682fccb99a183f90998 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:23:28 +0200 Subject: [PATCH 0985/1312] target: riscv: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Ignore the cast as they could be better addressed. Fix only minor additional checkpatch issue (spacing and line length). Change-Id: I11f10eddadc21e051c96eb3d4d4c0554a2cddd15 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8483 Tested-by: jenkins --- src/target/riscv/batch.c | 6 +- src/target/riscv/batch.h | 6 +- src/target/riscv/opcodes.h | 16 ++--- src/target/riscv/program.c | 2 +- src/target/riscv/riscv-011.c | 24 +++---- src/target/riscv/riscv-013.c | 128 +++++++++++++++++------------------ src/target/riscv/riscv.c | 32 ++++----- src/target/riscv/riscv.h | 28 ++++---- 8 files changed, 121 insertions(+), 121 deletions(-) diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index d4bdadf170..859e2275e5 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -127,7 +127,7 @@ int riscv_batch_run(struct riscv_batch *batch) return ERROR_OK; } -void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data) +void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address, uint64_t data) { assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; @@ -140,7 +140,7 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint batch->used_scans++; } -size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address) +size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int address) { assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; @@ -156,7 +156,7 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address) return batch->read_keys_used++; } -unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key) +unsigned int riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key) { assert(key < batch->read_keys_used); size_t index = batch->read_keys[key]; diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index 9c42ba81ea..e5b94cc219 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -59,13 +59,13 @@ bool riscv_batch_full(struct riscv_batch *batch); int riscv_batch_run(struct riscv_batch *batch); /* Adds a DMI write to this batch. */ -void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data); +void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address, uint64_t data); /* DMI reads must be handled in two parts: the first one schedules a read and * provides a key, the second one actually obtains the result of the read - * status (op) and the actual data. */ -size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address); -unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key); +size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int address); +unsigned int riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key); uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key); /* Scans in a NOP. */ diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h index 8faa154bae..7d17e6eea0 100644 --- a/src/target/riscv/opcodes.h +++ b/src/target/riscv/opcodes.h @@ -191,26 +191,26 @@ static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) return imm_i(offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLD; } -static uint32_t fmv_x_w(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_x_w(unsigned dest, unsigned src) +static uint32_t fmv_x_w(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_x_w(unsigned int dest, unsigned int src) { return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_W; } -static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_x_d(unsigned dest, unsigned src) +static uint32_t fmv_x_d(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_x_d(unsigned int dest, unsigned int src) { return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_D; } -static uint32_t fmv_w_x(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_w_x(unsigned dest, unsigned src) +static uint32_t fmv_w_x(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_w_x(unsigned int dest, unsigned int src) { return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_W_X; } -static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_d_x(unsigned dest, unsigned src) +static uint32_t fmv_d_x(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_d_x(unsigned int dest, unsigned int src) { return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_D_X; } diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index 0976539b3c..1014137f4f 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -31,7 +31,7 @@ int riscv_program_init(struct riscv_program *p, struct target *target) int riscv_program_write(struct riscv_program *program) { - for (unsigned i = 0; i < program->instruction_count; ++i) { + for (unsigned int i = 0; i < program->instruction_count; ++i) { LOG_DEBUG("debug_buffer[%02x] = DASM(0x%08x)", i, program->debug_buffer[i]); if (riscv_write_debug_buffer(program->target, i, program->debug_buffer[i]) != ERROR_OK) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 565721c28b..302ace8698 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -474,7 +474,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address) * While somewhat nonintuitive, this is an efficient way to get the data. */ - unsigned i = 0; + unsigned int i = 0; do { status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0); if (status == DBUS_STATUS_BUSY) @@ -495,7 +495,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address) static void dbus_write(struct target *target, uint16_t address, uint64_t value) { dbus_status_t status = DBUS_STATUS_BUSY; - unsigned i = 0; + unsigned int i = 0; while (status == DBUS_STATUS_BUSY && i++ < 256) { status = dbus_scan(target, NULL, NULL, DBUS_OP_WRITE, address, value); if (status == DBUS_STATUS_BUSY) @@ -656,13 +656,13 @@ static void scans_add_read(scans_t *scans, slot_t slot, bool set_interrupt) } static uint32_t scans_get_u32(scans_t *scans, unsigned int index, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { return buf_get_u32(scans->in + scans->scan_size * index, first, num); } static uint64_t scans_get_u64(scans_t *scans, unsigned int index, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { return buf_get_u64(scans->in + scans->scan_size * index, first, num); } @@ -699,7 +699,7 @@ static bits_t read_bits(struct target *target) }; do { - unsigned i = 0; + unsigned int i = 0; do { status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, 0, 0); if (status == DBUS_STATUS_BUSY) { @@ -1296,7 +1296,7 @@ static int register_write(struct target *target, unsigned int number, int result = update_mstatus_actual(target); if (result != ERROR_OK) return result; - unsigned i = 0; + unsigned int i = 0; if ((info->mstatus_actual & MSTATUS_FS) == 0) { info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1); cache_set_load(target, i++, S0, SLOT1); @@ -1352,7 +1352,7 @@ static int get_register(struct target *target, riscv_reg_t *value, int regid) int result = update_mstatus_actual(target); if (result != ERROR_OK) return result; - unsigned i = 0; + unsigned int i = 0; if ((info->mstatus_actual & MSTATUS_FS) == 0) { info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1); cache_set_load(target, i++, S0, SLOT1); @@ -1538,7 +1538,7 @@ static int examine(struct target *target) /* 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff */ cache_set32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4)); cache_set_jump(target, 5); - for (unsigned i = 6; i < info->dramsize; i++) + for (unsigned int i = 6; i < info->dramsize; i++) cache_set32(target, i, i * 0x01020304); cache_write(target, 0, false); @@ -1569,7 +1569,7 @@ static int examine(struct target *target) LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target)); if (read_remote_csr(target, &r->misa, CSR_MISA) != ERROR_OK) { - const unsigned old_csr_misa = 0xf10; + const unsigned int old_csr_misa = 0xf10; LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA, old_csr_misa); if (read_remote_csr(target, &r->misa, old_csr_misa) != ERROR_OK) { @@ -1651,7 +1651,7 @@ static riscv_error_t handle_halt_routine(struct target *target) unsigned int dbus_busy = 0; unsigned int interrupt_set = 0; - unsigned result = 0; + unsigned int result = 0; uint64_t value = 0; reg_cache_set(target, 0, 0); /* The first scan result is the result from something old we don't care @@ -2016,7 +2016,7 @@ static int read_memory(struct target *target, target_addr_t address, cache_write(target, CACHE_NO_READ, false); riscv011_info_t *info = get_info(target); - const unsigned max_batch_size = 256; + const unsigned int max_batch_size = 256; scans_t *scans = scans_new(target, max_batch_size); if (!scans) return ERROR_FAIL; @@ -2174,7 +2174,7 @@ static int write_memory(struct target *target, target_addr_t address, if (setup_write_memory(target, size) != ERROR_OK) return ERROR_FAIL; - const unsigned max_batch_size = 256; + const unsigned int max_batch_size = 256; scans_t *scans = scans_new(target, max_batch_size); if (!scans) return ERROR_FAIL; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index dbf9aad1d9..16eced2d89 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -48,7 +48,7 @@ static int riscv013_on_step(struct target *target); static int riscv013_resume_prep(struct target *target); static bool riscv013_is_halted(struct target *target); static enum riscv_halt_reason riscv013_halt_reason(struct target *target); -static int riscv013_write_debug_buffer(struct target *target, unsigned index, +static int riscv013_write_debug_buffer(struct target *target, unsigned int index, riscv_insn_t d); static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned index); @@ -59,7 +59,7 @@ static int riscv013_dmi_write_u64_bits(struct target *target); static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf); static int register_read(struct target *target, uint64_t *value, uint32_t number); static int register_read_direct(struct target *target, uint64_t *value, uint32_t number); -static int register_write_direct(struct target *target, unsigned number, +static int register_write_direct(struct target *target, unsigned int number, uint64_t value); static int read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment); @@ -156,13 +156,13 @@ typedef struct { typedef struct { /* The indexed used to address this hart in its DM. */ - unsigned index; + unsigned int index; /* Number of address bits in the dbus register. */ - unsigned abits; + unsigned int abits; /* Number of abstract command data registers. */ - unsigned datacount; + unsigned int datacount; /* Number of words in the Program Buffer. */ - unsigned progbufsize; + unsigned int progbufsize; /* We cache the read-only bits of sbcs here. */ uint32_t sbcs; @@ -209,7 +209,7 @@ typedef struct { int16_t dataaddr; /* The width of the hartsel field. */ - unsigned hartsellen; + unsigned int hartsellen; /* DM that provides access to this target. */ dm013_info_t *dm; @@ -290,10 +290,10 @@ static uint32_t set_hartsel(uint32_t initial, uint32_t index) return initial; } -static void decode_dmi(char *text, unsigned address, unsigned data) +static void decode_dmi(char *text, unsigned int address, unsigned int data) { static const struct { - unsigned address; + unsigned int address; uint64_t mask; const char *name; } description[] = { @@ -350,10 +350,10 @@ static void decode_dmi(char *text, unsigned address, unsigned data) }; text[0] = 0; - for (unsigned i = 0; i < ARRAY_SIZE(description); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(description); i++) { if (description[i].address == address) { uint64_t mask = description[i].mask; - unsigned value = get_field(data, mask); + unsigned int value = get_field(data, mask); if (value) { if (i > 0) *(text++) = ' '; @@ -468,7 +468,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, { riscv013_info_t *info = get_info(target); RISCV_INFO(r); - unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH; + unsigned int num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH; size_t num_bytes = (num_bits + 7) / 8; uint8_t in[num_bytes]; uint8_t out[num_bytes]; @@ -680,7 +680,7 @@ static int dmi_write_exec(struct target *target, uint32_t address, } static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus, - bool authenticated, unsigned timeout_sec) + bool authenticated, unsigned int timeout_sec) { int result = dmi_op_timeout(target, dmstatus, NULL, DMI_OP_READ, DM_DMSTATUS, 0, timeout_sec, false, true); @@ -717,7 +717,7 @@ static void increase_ac_busy_delay(struct target *target) info->ac_busy_delay); } -static uint32_t __attribute__((unused)) abstract_register_size(unsigned width) +static uint32_t __attribute__((unused)) abstract_register_size(unsigned int width) { switch (width) { case 32: @@ -807,12 +807,12 @@ static int execute_abstract_command(struct target *target, uint32_t command) return ERROR_OK; } -static riscv_reg_t read_abstract_arg(struct target *target, unsigned index, - unsigned size_bits) +static riscv_reg_t read_abstract_arg(struct target *target, unsigned int index, + unsigned int size_bits) { riscv_reg_t value = 0; uint32_t v; - unsigned offset = index * size_bits / 32; + unsigned int offset = index * size_bits / 32; switch (size_bits) { default: LOG_ERROR("Unsupported size: %d bits", size_bits); @@ -828,10 +828,10 @@ static riscv_reg_t read_abstract_arg(struct target *target, unsigned index, return value; } -static int write_abstract_arg(struct target *target, unsigned index, - riscv_reg_t value, unsigned size_bits) +static int write_abstract_arg(struct target *target, unsigned int index, + riscv_reg_t value, unsigned int size_bits) { - unsigned offset = index * size_bits / 32; + unsigned int offset = index * size_bits / 32; switch (size_bits) { default: LOG_ERROR("Unsupported size: %d bits", size_bits); @@ -849,7 +849,7 @@ static int write_abstract_arg(struct target *target, unsigned index, * @par size in bits */ static uint32_t access_register_command(struct target *target, uint32_t number, - unsigned size, uint32_t flags) + unsigned int size, uint32_t flags) { uint32_t command = set_field(0, DM_COMMAND_CMDTYPE, 0); switch (size) { @@ -891,7 +891,7 @@ static uint32_t access_register_command(struct target *target, uint32_t number, } static int register_read_abstract(struct target *target, uint64_t *value, - uint32_t number, unsigned size) + uint32_t number, unsigned int size) { RISCV013_INFO(info); @@ -929,7 +929,7 @@ static int register_read_abstract(struct target *target, uint64_t *value, } static int register_write_abstract(struct target *target, uint32_t number, - uint64_t value, unsigned size) + uint64_t value, unsigned int size) { RISCV013_INFO(info); @@ -968,7 +968,7 @@ static int register_write_abstract(struct target *target, uint32_t number, * Sets the AAMSIZE field of a memory access abstract command based on * the width (bits). */ -static uint32_t abstract_memory_size(unsigned width) +static uint32_t abstract_memory_size(unsigned int width) { switch (width) { case 8: @@ -991,7 +991,7 @@ static uint32_t abstract_memory_size(unsigned width) * Creates a memory access abstract command. */ static uint32_t access_memory_command(struct target *target, bool virtual, - unsigned width, bool postincrement, bool write) + unsigned int width, bool postincrement, bool write) { uint32_t command = set_field(0, AC_ACCESS_MEMORY_CMDTYPE, 2); command = set_field(command, AC_ACCESS_MEMORY_AAMVIRTUAL, virtual); @@ -1134,7 +1134,7 @@ typedef struct { static int scratch_reserve(struct target *target, scratch_mem_t *scratch, struct riscv_program *program, - unsigned size_bytes) + unsigned int size_bytes) { riscv_addr_t alignment = 1; while (alignment < size_bytes) @@ -1166,7 +1166,7 @@ static int scratch_reserve(struct target *target, return ERROR_FAIL; /* Allow for ebreak at the end of the program. */ - unsigned program_size = (program->instruction_count + 1) * 4; + unsigned int program_size = (program->instruction_count + 1) * 4; scratch->hart_address = (info->progbuf_address + program_size + alignment - 1) & ~(alignment - 1); if ((info->progbuf_writable == YNM_YES) && @@ -1271,7 +1271,7 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch, } /** Return register size in bits. */ -static unsigned register_size(struct target *target, unsigned number) +static unsigned int register_size(struct target *target, unsigned int number) { /* If reg_cache hasn't been initialized yet, make a guess. We need this for * when this function is called during examine(). */ @@ -1281,7 +1281,7 @@ static unsigned register_size(struct target *target, unsigned number) return riscv_xlen(target); } -static bool has_sufficient_progbuf(struct target *target, unsigned size) +static bool has_sufficient_progbuf(struct target *target, unsigned int size) { RISCV013_INFO(info); RISCV_INFO(r); @@ -1293,7 +1293,7 @@ static bool has_sufficient_progbuf(struct target *target, unsigned size) * Immediately write the new value to the requested register. This mechanism * bypasses any caches. */ -static int register_write_direct(struct target *target, unsigned number, +static int register_write_direct(struct target *target, unsigned int number, uint64_t value) { LOG_DEBUG("{%d} %s <- 0x%" PRIx64, riscv_current_hartid(target), @@ -1834,7 +1834,7 @@ static int riscv013_hart_count(struct target *target) } /* Try to find out the widest memory access size depending on the selected memory access methods. */ -static unsigned riscv013_data_bits(struct target *target) +static unsigned int riscv013_data_bits(struct target *target) { RISCV013_INFO(info); RISCV_INFO(r); @@ -1904,12 +1904,12 @@ static COMMAND_HELPER(riscv013_print_info, struct target *target) } static int prep_for_vector_access(struct target *target, uint64_t *vtype, - uint64_t *vl, unsigned *debug_vl) + uint64_t *vl, unsigned int *debug_vl) { RISCV_INFO(r); /* TODO: this continuous save/restore is terrible for performance. */ /* Write vtype and vl. */ - unsigned encoded_vsew; + unsigned int encoded_vsew; switch (riscv_xlen(target)) { case 32: encoded_vsew = 2; @@ -1965,12 +1965,12 @@ static int riscv013_get_register_buf(struct target *target, return ERROR_FAIL; uint64_t vtype, vl; - unsigned debug_vl; + unsigned int debug_vl; if (prep_for_vector_access(target, &vtype, &vl, &debug_vl) != ERROR_OK) return ERROR_FAIL; - unsigned vnum = regno - GDB_REGNO_V0; - unsigned xlen = riscv_xlen(target); + unsigned int vnum = regno - GDB_REGNO_V0; + unsigned int xlen = riscv_xlen(target); struct riscv_program program; riscv_program_init(&program, target); @@ -1978,7 +1978,7 @@ static int riscv013_get_register_buf(struct target *target, riscv_program_insert(&program, vslide1down_vx(vnum, vnum, S0, true)); int result = ERROR_OK; - for (unsigned i = 0; i < debug_vl; i++) { + for (unsigned int i = 0; i < debug_vl; i++) { /* Executing the program might result in an exception if there is some * issue with the vector implementation/instructions we're using. If that * happens, attempt to restore as usual. We may have clobbered the @@ -2024,18 +2024,18 @@ static int riscv013_set_register_buf(struct target *target, return ERROR_FAIL; uint64_t vtype, vl; - unsigned debug_vl; + unsigned int debug_vl; if (prep_for_vector_access(target, &vtype, &vl, &debug_vl) != ERROR_OK) return ERROR_FAIL; - unsigned vnum = regno - GDB_REGNO_V0; - unsigned xlen = riscv_xlen(target); + unsigned int vnum = regno - GDB_REGNO_V0; + unsigned int xlen = riscv_xlen(target); struct riscv_program program; riscv_program_init(&program, target); riscv_program_insert(&program, vslide1down_vx(vnum, vnum, S0, true)); int result = ERROR_OK; - for (unsigned i = 0; i < debug_vl; i++) { + for (unsigned int i = 0; i < debug_vl; i++) { if (register_write_direct(target, GDB_REGNO_S0, buf_get_u64(value, xlen * i, xlen)) != ERROR_OK) return ERROR_FAIL; @@ -2476,7 +2476,7 @@ static int execute_fence(struct target *target) } static void log_memory_access(target_addr_t address, uint64_t value, - unsigned size_bytes, bool read) + unsigned int size_bytes, bool read) { if (debug_level < LOG_LVL_DEBUG) return; @@ -2524,7 +2524,7 @@ static int read_memory_bus_word(struct target *target, target_addr_t address, static target_addr_t sb_read_address(struct target *target) { RISCV013_INFO(info); - unsigned sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); + unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); target_addr_t address = 0; uint32_t v; if (sbasize > 32) { @@ -2717,7 +2717,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, for (uint32_t i = (next_address - address) / size; i < count - 1; i++) { for (int j = (size - 1) / 4; j >= 0; j--) { uint32_t value; - unsigned attempt = 0; + unsigned int attempt = 0; while (1) { if (attempt++ > 100) { LOG_ERROR("DMI keeps being busy in while reading memory just past " TARGET_ADDR_FMT, @@ -2745,7 +2745,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, uint32_t sbcs_read = 0; if (count > 1) { uint32_t value; - unsigned attempt = 0; + unsigned int attempt = 0; while (1) { if (attempt++ > 100) { LOG_ERROR("DMI keeps being busy in while reading memory just past " TARGET_ADDR_FMT, @@ -2793,7 +2793,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, continue; } - unsigned error = get_field(sbcs_read, DM_SBCS_SBERROR); + unsigned int error = get_field(sbcs_read, DM_SBCS_SBERROR); if (error == 0) { next_address = end_address; } else { @@ -2959,7 +2959,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address, memset(buffer, 0, count * size); /* Convert the size (bytes) to width (bits) */ - unsigned width = size << 3; + unsigned int width = size << 3; /* Create the command (physical address, postincrement, read) */ uint32_t command = access_memory_command(target, false, width, use_aampostincrement, false); @@ -3035,7 +3035,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address, size, address); /* Convert the size (bytes) to width (bits) */ - unsigned width = size << 3; + unsigned int width = size << 3; /* Create the command (physical address, postincrement, write) */ uint32_t command = access_memory_command(target, false, width, use_aampostincrement, true); @@ -3145,7 +3145,7 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres /* read_addr is the next address that the hart will read from, which is the * value in s0. */ - unsigned index = 2; + unsigned int index = 2; while (index < count) { riscv_addr_t read_addr = address + index * increment; LOG_DEBUG("i=%d, count=%d, read_addr=0x%" PRIx64, index, count, read_addr); @@ -3162,8 +3162,8 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres if (!batch) return ERROR_FAIL; - unsigned reads = 0; - for (unsigned j = index; j < count; j++) { + unsigned int reads = 0; + for (unsigned int j = index; j < count; j++) { if (size > 4) riscv_batch_add_dmi_read(batch, DM_DATA1); riscv_batch_add_dmi_read(batch, DM_DATA0); @@ -3186,8 +3186,8 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres return ERROR_FAIL; info->cmderr = get_field(abstractcs, DM_ABSTRACTCS_CMDERR); - unsigned next_index; - unsigned ignore_last = 0; + unsigned int next_index; + unsigned int ignore_last = 0; switch (info->cmderr) { case CMDERR_NONE: LOG_DEBUG("successful (partial?) memory read"); @@ -3256,9 +3256,9 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres /* Now read whatever we got out of the batch. */ dmi_status_t status = DMI_STATUS_SUCCESS; - unsigned read = 0; + unsigned int read = 0; assert(index >= 2); - for (unsigned j = index - 2; j < index + reads; j++) { + for (unsigned int j = index - 2; j < index + reads; j++) { assert(j < count); LOG_DEBUG("index=%d, reads=%d, next_index=%d, ignore_last=%d, j=%d", index, reads, next_index, ignore_last, j); @@ -3867,9 +3867,9 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, goto error; /* To write another word, we put it in S1 and execute the program. */ - unsigned start = (cur_addr - address) / size; - for (unsigned i = start; i < count; ++i) { - unsigned offset = size*i; + unsigned int start = (cur_addr - address) / size; + for (unsigned int i = start; i < count; ++i) { + unsigned int offset = size * i; const uint8_t *t_buffer = buffer + offset; uint64_t value = buf_get_u64(t_buffer, 0, 8 * size); @@ -4160,18 +4160,18 @@ static int select_prepped_harts(struct target *target, bool *use_hasel) } assert(dm->hart_count); - unsigned hawindow_count = (dm->hart_count + 31) / 32; + unsigned int hawindow_count = (dm->hart_count + 31) / 32; uint32_t hawindow[hawindow_count]; memset(hawindow, 0, sizeof(uint32_t) * hawindow_count); target_list_t *entry; - unsigned total_selected = 0; + unsigned int total_selected = 0; list_for_each_entry(entry, &dm->target_list, list) { struct target *t = entry->target; struct riscv_info *r = riscv_info(t); riscv013_info_t *info = get_info(t); - unsigned index = info->index; + unsigned int index = info->index; LOG_DEBUG("index=%d, coreid=%d, prepped=%d", index, t->coreid, r->prepped); r->selected = r->prepped; if (r->prepped) { @@ -4188,7 +4188,7 @@ static int select_prepped_harts(struct target *target, bool *use_hasel) return ERROR_OK; } - for (unsigned i = 0; i < hawindow_count; i++) { + for (unsigned int i = 0; i < hawindow_count; i++) { if (dmi_write(target, DM_HAWINDOWSEL, i) != ERROR_OK) return ERROR_FAIL; if (dmi_write(target, DM_HAWINDOW, hawindow[i]) != ERROR_OK) @@ -4346,7 +4346,7 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target) return RISCV_HALT_UNKNOWN; } -int riscv013_write_debug_buffer(struct target *target, unsigned index, riscv_insn_t data) +int riscv013_write_debug_buffer(struct target *target, unsigned int index, riscv_insn_t data) { dm013_info_t *dm = get_dm(target); if (!dm) @@ -4361,7 +4361,7 @@ int riscv013_write_debug_buffer(struct target *target, unsigned index, riscv_ins return ERROR_OK; } -riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned index) +riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned int index) { uint32_t value; dmi_read(target, &value, DM_PROGBUF0 + index); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 511a3c6c32..99f40a7393 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -476,7 +476,7 @@ static void riscv_free_registers(struct target *target) if (target->reg_cache->reg_list) { free(target->reg_cache->reg_list[0].arch_info); /* Free the ones we allocated separately. */ - for (unsigned i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++) + for (unsigned int i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++) free(target->reg_cache->reg_list[i].arch_info); for (unsigned int i = 0; i < target->reg_cache->num_regs; i++) free(target->reg_cache->reg_list[i].value); @@ -1583,7 +1583,7 @@ static int riscv_address_translate(struct target *target, if (result != ERROR_OK) return result; - unsigned xlen = riscv_xlen(target); + unsigned int xlen = riscv_xlen(target); mode = get_field(satp_value, RISCV_SATP_MODE(xlen)); switch (mode) { case SATP_MODE_SV32: @@ -1927,7 +1927,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, GDB_REGNO_PC, GDB_REGNO_MSTATUS, GDB_REGNO_MEPC, GDB_REGNO_MCAUSE, }; - for (unsigned i = 0; i < ARRAY_SIZE(regnums); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(regnums); i++) { enum gdb_regno regno = regnums[i]; riscv_reg_t reg_value; if (riscv_get_register(target, ®_value, regno) != ERROR_OK) @@ -2007,8 +2007,8 @@ static int riscv_checksum_memory(struct target *target, static const uint8_t *crc_code; - unsigned xlen = riscv_xlen(target); - unsigned crc_code_size; + unsigned int xlen = riscv_xlen(target); + unsigned int crc_code_size; if (xlen == 32) { crc_code = riscv32_crc_code; crc_code_size = sizeof(riscv32_crc_code); @@ -2187,8 +2187,8 @@ int riscv_openocd_poll(struct target *target) int halted_hart = -1; if (target->smp) { - unsigned should_remain_halted = 0; - unsigned should_resume = 0; + unsigned int should_remain_halted = 0; + unsigned int should_resume = 0; struct target_list *list; foreach_smp_target(list, target->smp_targets) { struct target *t = list->target; @@ -2436,8 +2436,8 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha /* For backward compatibility, allow multiple parameters within one TCL argument, separated by ',' */ char *arg = strtok(args, ","); while (arg) { - unsigned low = 0; - unsigned high = 0; + unsigned int low = 0; + unsigned int high = 0; char *name = NULL; char *dash = strchr(arg, '-'); @@ -3055,7 +3055,7 @@ static const struct command_registration riscv_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static unsigned riscv_xlen_nonconst(struct target *target) +static unsigned int riscv_xlen_nonconst(struct target *target) { return riscv_xlen(target); } @@ -3194,7 +3194,7 @@ static int riscv_step_rtos_hart(struct target *target) bool riscv_supports_extension(struct target *target, char letter) { RISCV_INFO(r); - unsigned num; + unsigned int num; if (letter >= 'a' && letter <= 'z') num = letter - 'a'; else if (letter >= 'A' && letter <= 'Z') @@ -3204,7 +3204,7 @@ bool riscv_supports_extension(struct target *target, char letter) return r->misa & BIT(num); } -unsigned riscv_xlen(const struct target *target) +unsigned int riscv_xlen(const struct target *target) { RISCV_INFO(r); return r->xlen; @@ -3778,7 +3778,7 @@ static struct reg_arch_type riscv_reg_arch_type = { }; struct csr_info { - unsigned number; + unsigned int number; const char *name; }; @@ -3958,7 +3958,7 @@ int riscv_init_registers(struct target *target) }; /* encoding.h does not contain the registers in sorted order. */ qsort(csr_info, ARRAY_SIZE(csr_info), sizeof(*csr_info), cmp_csr_info); - unsigned csr_info_index = 0; + unsigned int csr_info_index = 0; int custom_within_range = 0; @@ -4213,7 +4213,7 @@ int riscv_init_registers(struct target *target) } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { r->group = "csr"; r->feature = &feature_csr; - unsigned csr_number = number - GDB_REGNO_CSR0; + unsigned int csr_number = number - GDB_REGNO_CSR0; while (csr_info[csr_info_index].number < csr_number && csr_info_index < ARRAY_SIZE(csr_info) - 1) { @@ -4376,7 +4376,7 @@ int riscv_init_registers(struct target *target) range_list_t *range = list_first_entry(&info->expose_custom, range_list_t, list); - unsigned custom_number = range->low + custom_within_range; + unsigned int custom_number = range->low + custom_within_range; r->group = "custom"; r->feature = &feature_custom; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index aba0864e6d..6cb2709de8 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -61,7 +61,7 @@ enum riscv_halt_reason { typedef struct { struct target *target; - unsigned custom_number; + unsigned int custom_number; } riscv_reg_info_t; #define RISCV_SAMPLE_BUF_TIMESTAMP_BEFORE 0x80 @@ -90,7 +90,7 @@ typedef struct { struct riscv_info { unsigned int common_magic; - unsigned dtm_version; + unsigned int dtm_version; struct command_context *cmd_ctx; void *version_specific; @@ -159,9 +159,9 @@ struct riscv_info { int (*halt_go)(struct target *target); int (*on_step)(struct target *target); enum riscv_halt_reason (*halt_reason)(struct target *target); - int (*write_debug_buffer)(struct target *target, unsigned index, + int (*write_debug_buffer)(struct target *target, unsigned int index, riscv_insn_t d); - riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned index); + riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned int index); int (*execute_debug_buffer)(struct target *target); int (*dmi_write_u64_bits)(struct target *target); void (*fill_dmi_write_u64)(struct target *target, char *buf, int a, uint64_t d); @@ -184,7 +184,7 @@ struct riscv_info { /* How many harts are attached to the DM that this target is attached to? */ int (*hart_count)(struct target *target); - unsigned (*data_bits)(struct target *target); + unsigned int (*data_bits)(struct target *target); COMMAND_HELPER((*print_info), struct target *target); @@ -239,14 +239,14 @@ typedef struct { typedef struct { const char *name; int level; - unsigned va_bits; - unsigned pte_shift; - unsigned vpn_shift[PG_MAX_LEVEL]; - unsigned vpn_mask[PG_MAX_LEVEL]; - unsigned pte_ppn_shift[PG_MAX_LEVEL]; - unsigned pte_ppn_mask[PG_MAX_LEVEL]; - unsigned pa_ppn_shift[PG_MAX_LEVEL]; - unsigned pa_ppn_mask[PG_MAX_LEVEL]; + unsigned int va_bits; + unsigned int pte_shift; + unsigned int vpn_shift[PG_MAX_LEVEL]; + unsigned int vpn_mask[PG_MAX_LEVEL]; + unsigned int pte_ppn_shift[PG_MAX_LEVEL]; + unsigned int pte_ppn_mask[PG_MAX_LEVEL]; + unsigned int pa_ppn_shift[PG_MAX_LEVEL]; + unsigned int pa_ppn_mask[PG_MAX_LEVEL]; } virt2phys_info_t; /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ @@ -307,7 +307,7 @@ int riscv_openocd_deassert_reset(struct target *target); bool riscv_supports_extension(struct target *target, char letter); /* Returns XLEN for the given (or current) hart. */ -unsigned riscv_xlen(const struct target *target); +unsigned int riscv_xlen(const struct target *target); int riscv_xlen_of_hart(const struct target *target); /* Sets the current hart, which is the hart that will actually be used when From fec3b224214e3784b0c00970d2421212402da880 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 8 Sep 2024 21:47:31 +0200 Subject: [PATCH 0986/1312] target: riscv: remove non-trivial 'unsigned' cast Change the prototype of riscv_batch_get_dmi_read_op(). Now that 'target->smp' is unsigned, drop the cast. Change-Id: I2a54268ed1e4bf0ea884b62cceb73f5c7451da78 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8484 Tested-by: jenkins --- src/target/riscv/batch.c | 4 ++-- src/target/riscv/batch.h | 2 +- src/target/riscv/riscv-013.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index 859e2275e5..e3f8ff3d4b 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -156,14 +156,14 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int address) return batch->read_keys_used++; } -unsigned int riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key) +uint32_t riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key) { assert(key < batch->read_keys_used); size_t index = batch->read_keys[key]; assert(index <= batch->used_scans); uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index; /* extract "op" field from the DMI read result */ - return (unsigned)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); + return buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); } uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key) diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index e5b94cc219..537fa59233 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -65,7 +65,7 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address, * provides a key, the second one actually obtains the result of the read - * status (op) and the actual data. */ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int address); -unsigned int riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key); +uint32_t riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key); uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key); /* Scans in a NOP. */ diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 16eced2d89..6c9ed317b0 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1537,7 +1537,7 @@ static int set_haltgroup(struct target *target, bool *supported) uint32_t read; if (dmi_read(target, &read, DM_DMCS2) != ERROR_OK) return ERROR_FAIL; - *supported = get_field(read, DM_DMCS2_GROUP) == (unsigned)target->smp; + *supported = get_field(read, DM_DMCS2_GROUP) == target->smp; return ERROR_OK; } From 21a211d547406d2639ed02256f491ead93a22a20 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 6 Aug 2024 15:28:15 -0700 Subject: [PATCH 0987/1312] arm_adi_v5: Added Cortex-A55 debug unit identifier Add identifier of the Cortex-A55 debug unit. Change-Id: I67336094a5153a3187cccc32c0e38d78ae4af542 Signed-off-by: Florian Fainelli Reviewed-on: https://review.openocd.org/c/openocd/+/8430 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_adi_v5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 3a5afc605a..eaaa209b9a 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1532,6 +1532,7 @@ static const struct dap_part_nums { { ARM_ID, 0xc17, "Cortex-R7 Debug", "(Debug Unit)", }, { ARM_ID, 0xd03, "Cortex-A53 Debug", "(Debug Unit)", }, { ARM_ID, 0xd04, "Cortex-A35 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd05, "Cortex-A55 Debug", "(Debug Unit)", }, { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", }, { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", }, From 114ca19f64d8af5365ecf171cc2adc45a763a406 Mon Sep 17 00:00:00 2001 From: Jan Matyas Date: Thu, 3 Oct 2024 09:59:24 +0200 Subject: [PATCH 0988/1312] gitignore: Start ignoring ".vscode" To help the developers who use Visual Studio Code IDE, ignore the ".vscode" folder in Git. This folder contains local configuration of the VSCode workspace. Change-Id: I1d54d8ce2bd0680f2fa1fb773bb33c786bdcc608 Signed-off-by: Jan Matyas Reviewed-on: https://review.openocd.org/c/openocd/+/8518 Reviewed-by: Antonio Borneo Tested-by: jenkins --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 103dad2c75..5de33077e3 100644 --- a/.gitignore +++ b/.gitignore @@ -84,6 +84,9 @@ patches .cproject .settings +# VSCode stuff +.vscode + # Emacs temp files *~ From d09ff476446a5403e556476b41a5a3c9bdf0a706 Mon Sep 17 00:00:00 2001 From: Jan Matyas Date: Mon, 30 Sep 2024 14:55:58 +0200 Subject: [PATCH 0989/1312] gdb_server: Improve const correctness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On several packet-handling functions, add "const" to arguments that represent read-only packet buffers. For instance on GCC 13.2.0, this code: const char *some_packet = "..."; gdb_put_packet(conn, some_packet, strlen(some_packet)); would prior to the fix produce warning: passing argument 2 of ‘gdb_put_packet’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] Change-Id: Idb62f57d37ed323c39de38982e57afdd3882e280 Signed-off-by: Jan Matyas Reviewed-on: https://review.openocd.org/c/openocd/+/8517 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/helper/log.c | 2 +- src/helper/log.h | 2 +- src/server/gdb_server.c | 10 +++++----- src/server/gdb_server.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/helper/log.c b/src/helper/log.c index 62ba4da4cd..9ad00ce628 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -505,7 +505,7 @@ void log_socket_error(const char *socket_desc) * Find the first non-printable character in the char buffer, return a pointer to it. * If no such character exists, return NULL. */ -char *find_nonprint_char(char *buf, unsigned int buf_len) +const char *find_nonprint_char(const char *buf, unsigned int buf_len) { for (unsigned int i = 0; i < buf_len; i++) { if (!isprint(buf[i])) diff --git a/src/helper/log.h b/src/helper/log.h index 0f11cfa9a4..dc8df6fbb6 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -89,7 +89,7 @@ char *alloc_vprintf(const char *fmt, va_list ap); char *alloc_printf(const char *fmt, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2))); -char *find_nonprint_char(char *buf, unsigned int buf_len); +const char *find_nonprint_char(const char *buf, unsigned int buf_len); extern int debug_level; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index c1e5e268fb..579a388d25 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -335,7 +335,7 @@ static int gdb_putback_char(struct connection *connection, int last_char) /* The only way we can detect that the socket is closed is the first time * we write to it, we will fail. Subsequent write operations will * succeed. Shudder! */ -static int gdb_write(struct connection *connection, void *data, int len) +static int gdb_write(struct connection *connection, const void *data, int len) { struct gdb_connection *gdb_con = connection->priv; if (gdb_con->closed) { @@ -351,7 +351,7 @@ static int gdb_write(struct connection *connection, void *data, int len) return ERROR_SERVER_REMOTE_CLOSED; } -static void gdb_log_incoming_packet(struct connection *connection, char *packet) +static void gdb_log_incoming_packet(struct connection *connection, const char *packet) { if (!LOG_LEVEL_IS(LOG_LVL_DEBUG)) return; @@ -384,7 +384,7 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet) } } -static void gdb_log_outgoing_packet(struct connection *connection, char *packet_buf, +static void gdb_log_outgoing_packet(struct connection *connection, const char *packet_buf, unsigned int packet_len, unsigned char checksum) { if (!LOG_LEVEL_IS(LOG_LVL_DEBUG)) @@ -402,7 +402,7 @@ static void gdb_log_outgoing_packet(struct connection *connection, char *packet_ } static int gdb_put_packet_inner(struct connection *connection, - char *buffer, int len) + const char *buffer, int len) { int i; unsigned char my_checksum = 0; @@ -522,7 +522,7 @@ static int gdb_put_packet_inner(struct connection *connection, return ERROR_OK; } -int gdb_put_packet(struct connection *connection, char *buffer, int len) +int gdb_put_packet(struct connection *connection, const char *buffer, int len) { struct gdb_connection *gdb_con = connection->priv; gdb_con->busy = true; diff --git a/src/server/gdb_server.h b/src/server/gdb_server.h index 4288ceb878..1a626ebd94 100644 --- a/src/server/gdb_server.h +++ b/src/server/gdb_server.h @@ -28,7 +28,7 @@ int gdb_target_add_all(struct target *target); int gdb_register_commands(struct command_context *command_context); void gdb_service_free(void); -int gdb_put_packet(struct connection *connection, char *buffer, int len); +int gdb_put_packet(struct connection *connection, const char *buffer, int len); int gdb_get_actual_connections(void); From 7214c8be46f749f210e00d334c30883bd73cca03 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 1 Jun 2024 21:20:31 +0200 Subject: [PATCH 0990/1312] configure: show adapter Xilinx XVC/PCIe in the configuration summary Adapter Xilinx XVC/PCIe was not appearing in the configuration summary because of the wrong variable name: build_xlnx_pcie_xvc instead of enable_xlnx_pcie_xvc. Also build this adapter automatically on Linux. Change-Id: I69ea92f550052b9ce55ce32597ac446a15a87388 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8312 Tested-by: jenkins Reviewed-by: R. Diez Reviewed-by: Antonio Borneo --- configure.ac | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index 07e06551f8..9355ffb932 100644 --- a/configure.ac +++ b/configure.ac @@ -104,12 +104,18 @@ AS_IF([test -x "$srcdir/guess-rev.sh"], [ AC_MSG_RESULT([$build_release]) # Adapter drivers -# 1st column -- configure option -# 2nd column -- description -# 3rd column -- symbol used for both config.h and automake +# 1st column -- Basename for the configure option generated with AC_ARG_ENABLE. +# For example, "buspirate" generates options "--enable-buspirate[=yes/no]" +# and "--disable-buspirate". +# 2nd column -- Description for the configure option. For example, "Bus Pirate" +# generates "Enable building support for the Bus Pirate (default is auto)". +# 3rd column -- Basename for the config.h and Automake symbols. +# For example, basename "BUS_PIRATE" generates "BUILD_BUS_PIRATE" with AC_DEFINE +# for config.h and "BUS_PIRATE" with AM_CONDITIONAL for Automake. m4_define([ADAPTER_ARG], [m4_argn([1], $1)]) m4_define([ADAPTER_DESC], [m4_argn([2], $1)]) m4_define([ADAPTER_SYM], [m4_argn([3], $1)]) +# AC_ARG_ENABLE uses prefix "enable_" to name the corresponding option variable. m4_define([ADAPTER_VAR], [enable_[]ADAPTER_ARG($1)]) m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])]) @@ -264,6 +270,7 @@ AC_ARG_ADAPTERS([ LIBFTDI_USB1_ADAPTERS LIBGPIOD_ADAPTERS, SERIAL_PORT_ADAPTERS, + PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) @@ -340,12 +347,10 @@ AC_ARG_ENABLE([sysfsgpio], AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) -AC_ARG_ENABLE([xlnx_pcie_xvc], - AS_HELP_STRING([--enable-xlnx-pcie-xvc], [Enable building support for Xilinx XVC/PCIe.]), - [build_xlnx_pcie_xvc=$enableval], [build_xlnx_pcie_xvc=no]) - AS_CASE([$host_os], - [linux*], [], + [linux*], [ + is_linux=yes + ], [ AS_IF([test "x$build_sysfsgpio" = "xyes"], [ AC_MSG_ERROR([sysfsgpio is only available on linux]) @@ -355,10 +360,6 @@ AS_CASE([$host_os], AC_MSG_ERROR([linuxgpiod is only available on linux]) ]) - AS_IF([test "x$build_xlnx_pcie_xvc" = "xyes"], [ - AC_MSG_ERROR([xlnx_pcie_xvc is only available on linux]) - ]) - AS_CASE([$host_os], [freebsd*], [], [ AS_IF([test "x$build_rshim" = "xyes"], [ @@ -619,13 +620,6 @@ AS_IF([test "x$build_sysfsgpio" = "xyes"], [ AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) ]) -AS_IF([test "x$build_xlnx_pcie_xvc" = "xyes"], [ - build_xlnx_pcie_xvc=yes - AC_DEFINE([BUILD_XLNX_PCIE_XVC], [1], [1 if you want the Xilinx XVC/PCIe driver.]) -], [ - AC_DEFINE([BUILD_XLNX_PCIE_XVC], [0], [0 if you don't want Xilinx XVC/PCIe driver.]) -]) - PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [ use_libusb1=yes AC_DEFINE([HAVE_LIBUSB1], [1], [Define if you have libusb-1.x]) @@ -687,11 +681,11 @@ PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [ PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], [use_libjaylink=yes], [use_libjaylink=no]) -# Arg $1: The adapter name, used to derive option and variable names for the adapter. -# Arg $2: Whether the adapter can be enabled, for example, because -# its prerequisites are installed in the system. +# Arg $1: An array of adapter triplets, used to derive option and variable names for each adapter. +# Arg $2: Whether the adapters can be enabled, for example, because +# their prerequisites are installed in the system. # Arg $3: What prerequisites are missing, to be shown in an error message -# if the adapter was requested but cannot be enabled. +# if an adapter was requested but cannot be enabled. m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ AS_IF([test $2], [ @@ -702,7 +696,7 @@ m4_define([PROCESS_ADAPTERS], [ ]) ], [ AS_IF([test "x$ADAPTER_VAR([adapter])" = "xyes"], [ - AC_MSG_ERROR([$3 is required for the ADAPTER_DESC([adapter])]) + AC_MSG_ERROR([$3 is required for [adapter] ADAPTER_DESC([adapter]).]) ]) ADAPTER_VAR([adapter])=no AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).) @@ -718,6 +712,7 @@ PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x]) PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [libgpiod]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) +PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -774,7 +769,6 @@ AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"]) AM_CONDITIONAL([BUSPIRATE], [test "x$enable_buspirate" != "xno"]) AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) -AM_CONDITIONAL([XLNX_PCIE_XVC], [test "x$build_xlnx_pcie_xvc" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) AM_CONDITIONAL([IS_MINGW], [test "x$is_mingw" = "xyes"]) From 3ce0962f2c525595bcbd0bd5da73673e236fc42d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 15 Jul 2024 11:56:36 +0200 Subject: [PATCH 0991/1312] target: cortex_m: fix polling for target kept under reset In multi-target SoC not all the targets are running simultaneously and some target could be powered off or kept under reset. Commit 4892e32294c6 ("target/cortex_m: allow poll quickly get out of TARGET_RESET state") does not considers the case of a target that is kept in reset and expects the target to change state from TARGET_RESET immediately. This causes OpenOCD to log continuously: Info : [stm32mp15x.cm4] external reset detected Info : [stm32mp15x.cm4] external reset detected Info : [stm32mp15x.cm4] external reset detected Read again dhcsr to detect the 'stable' reset status and quit, waiting for next poll to re-check the target's status. Change-Id: Ic66029b988404a1599bb99bc66d4a8845b8b02c6 Signed-off-by: Antonio Borneo Fixes: 4892e32294c6 ("target/cortex_m: allow poll quickly get out of TARGET_RESET state") Reviewed-on: https://review.openocd.org/c/openocd/+/8399 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/target/cortex_m.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index bd0e8d8867..e78d2e29ba 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -989,6 +989,18 @@ static int cortex_m_poll_one(struct target *target) * and keep it until the next poll to allow its detection */ return ERROR_OK; } + + /* refresh status bits */ + retval = cortex_m_read_dhcsr_atomic_sticky(target); + if (retval != ERROR_OK) + return retval; + + /* If still under reset, quit and re-check at next poll */ + if (cortex_m->dcb_dhcsr_cumulated_sticky & S_RESET_ST) { + cortex_m->dcb_dhcsr_cumulated_sticky &= ~S_RESET_ST; + return ERROR_OK; + } + /* S_RESET_ST was expected (in a reset command). Continue processing * to quickly get out of TARGET_RESET state */ } From 34ec5536c0ba3315bc5a841244bbf70141ccfbb4 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 12 Oct 2024 11:48:05 +0200 Subject: [PATCH 0992/1312] stlink: deprecate HLA support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The STLink API that supports dap-direct is available from STLink firmware v2j24, published in early 2015. We can reasonably expect that any old STLink still in use today has got at least one firmware update during the last 10 years. Most of the board files in upstream OpenOCD still use the STLink in HLA mode. This limits the test coverage of the dap-direct code, which was introduced in OpenOCD v0.11.0. - Rename interface/stlink.cfg as interface/stlink-hla.cfg to still provide support for HLA, adding a deprecated message. - Rename interface/stlink-dap.cfg as interface/stlink.cfg to make dap-direct the default trasport. - Add a redirect file interface/stlink-dap.cfg for users that have out-of-tree custom board files. - Update all the board files to the new setup. - Remove STLink HLA mentions from the documentation, while adding a reference to interface/stlink-hla.cfg Checkpatch-ignore: LONG_LINE Change-Id: I99366bb03cd3b83f8f408514e657f30e59813063 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8523 Tested-by: jenkins Reviewed-by: Andrzej Sierżęga --- doc/openocd.texi | 20 +++++++------------- tcl/board/st_b-l475e-iot01a.cfg | 2 +- tcl/board/st_nucleo_8l152r8.cfg | 2 +- tcl/board/st_nucleo_8s208rb.cfg | 2 +- tcl/board/st_nucleo_f0.cfg | 2 +- tcl/board/st_nucleo_f103rb.cfg | 2 +- tcl/board/st_nucleo_f3.cfg | 2 +- tcl/board/st_nucleo_f4.cfg | 2 +- tcl/board/st_nucleo_f7.cfg | 2 +- tcl/board/st_nucleo_g0.cfg | 2 +- tcl/board/st_nucleo_g4.cfg | 2 +- tcl/board/st_nucleo_h743zi.cfg | 2 +- tcl/board/st_nucleo_h745zi.cfg | 2 +- tcl/board/st_nucleo_l073rz.cfg | 2 +- tcl/board/st_nucleo_l1.cfg | 2 +- tcl/board/st_nucleo_l4.cfg | 2 +- tcl/board/st_nucleo_l5.cfg | 2 +- tcl/board/st_nucleo_wb55.cfg | 2 +- tcl/board/stm320518_eval_stlink.cfg | 2 +- tcl/board/stm3220g_eval_stlink.cfg | 2 +- tcl/board/stm3241g_eval_stlink.cfg | 2 +- tcl/board/stm32429i_eval_stlink.cfg | 2 +- tcl/board/stm32439i_eval_stlink.cfg | 2 +- tcl/board/stm32f0discovery.cfg | 2 +- tcl/board/stm32f3discovery.cfg | 2 +- tcl/board/stm32f412g-disco.cfg | 2 +- tcl/board/stm32f413h-disco.cfg | 2 +- tcl/board/stm32f429disc1.cfg | 2 +- tcl/board/stm32f429discovery.cfg | 2 +- tcl/board/stm32f469discovery.cfg | 2 +- tcl/board/stm32f469i-disco.cfg | 2 +- tcl/board/stm32f4discovery.cfg | 2 +- tcl/board/stm32f723e-disco.cfg | 2 +- tcl/board/stm32f746g-disco.cfg | 2 +- tcl/board/stm32f769i-disco.cfg | 2 +- tcl/board/stm32f7discovery.cfg | 2 +- tcl/board/stm32h735g-disco.cfg | 2 +- tcl/board/stm32h745i-disco.cfg | 2 +- tcl/board/stm32h747i-disco.cfg | 2 +- tcl/board/stm32h750b-disco.cfg | 2 +- tcl/board/stm32h7b3i-disco.cfg | 2 +- tcl/board/stm32h7x3i_eval.cfg | 2 +- tcl/board/stm32l0discovery.cfg | 2 +- tcl/board/stm32l476g-disco.cfg | 2 +- tcl/board/stm32l496g-disco.cfg | 2 +- tcl/board/stm32l4discovery.cfg | 2 +- tcl/board/stm32l4p5g-disco.cfg | 2 +- tcl/board/stm32l4r9i-disco.cfg | 2 +- tcl/board/stm32ldiscovery.cfg | 2 +- tcl/board/stm32mp13x_dk.cfg | 2 +- tcl/board/stm32mp15x_dk2.cfg | 2 +- tcl/board/stm32vldiscovery.cfg | 2 +- tcl/interface/stlink-dap.cfg | 21 ++------------------- tcl/interface/stlink-hla.cfg | 21 +++++++++++++++++++++ tcl/interface/stlink.cfg | 22 +++++++++++++--------- 55 files changed, 94 insertions(+), 92 deletions(-) create mode 100644 tcl/interface/stlink-hla.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 97396c7b70..9b5cfbb83e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2489,7 +2489,7 @@ This command is only available if your libusb1 is at least version 1.0.16. Specifies the @var{serial_string} of the adapter to use. If this command is not specified, serial strings are not checked. Only the following adapter drivers use the serial string from this command: -arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus, +arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (ti-icdi), jlink, kitprog, opendus, openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110. @end deffn @@ -3206,7 +3206,7 @@ version reported is V2.J21.S4. Currently Not Supported. @end deffn -@deffn {Config Command} {hla layout} (@option{stlink}|@option{icdi}|@option{nulink}) +@deffn {Config Command} {hla layout} (@option{icdi}|@option{nulink}) Specifies the adapter layout to use. @end deffn @@ -3214,15 +3214,6 @@ Specifies the adapter layout to use. Pairs of vendor IDs and product IDs of the device. @end deffn -@deffn {Config Command} {hla stlink_backend} (usb | tcp [port]) -@emph{ST-Link only:} Choose between 'exclusive' USB communication (the default backend) or -'shared' mode using ST-Link TCP server (the default port is 7184). - -@emph{Note:} ST-Link TCP server is a binary application provided by ST -available from @url{https://www.st.com/en/development-tools/st-link-server.html, -ST-LINK server software module}. -@end deffn - @deffn {Command} {hla command} command Execute a custom adapter-specific command. The @var{command} string is passed as is to the underlying adapter layout handler. @@ -3232,9 +3223,12 @@ passed as is to the underlying adapter layout handler. @anchor{st_link_dap_interface} @deffn {Interface Driver} {st-link} This is a driver that supports STMicroelectronics adapters ST-LINK/V2 -(from firmware V2J24), STLINK-V3 and STLINK-V3PWR, thanks to a new API that provides +(from 2015 firmware V2J24), STLINK-V3 and STLINK-V3PWR, thanks to a new API that provides directly access the arm ADIv5 DAP. +The older API that requires HLA transport is deprecated and will be dropped +from OpenOCD. In mean time it's still available by using @file{interface/stlink-hla.cfg}. + The new API provide access to multiple AP on the same DAP, but the maximum number of the AP port is limited by the specific firmware version (e.g. firmware V2J29 has 3 as maximum AP number, while V2J32 has 8). @@ -10677,7 +10671,7 @@ baud with our custom divisor to get 12MHz) @item OpenOCD invocation line: @example openocd -f interface/stlink.cfg \ --c "transport select hla_swd" \ +-c "transport select dapdirect_swd" \ -f target/stm32l1.cfg \ -c "stm32l1.tpiu configure -protocol uart" \ -c "stm32l1.tpiu configure -traceclk 24000000 -pin-freq 12000000" \ diff --git a/tcl/board/st_b-l475e-iot01a.cfg b/tcl/board/st_b-l475e-iot01a.cfg index e75c99d7a5..3f3db125c8 100644 --- a/tcl/board/st_b-l475e-iot01a.cfg +++ b/tcl/board/st_b-l475e-iot01a.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/st_nucleo_8l152r8.cfg b/tcl/board/st_nucleo_8l152r8.cfg index 7cb8bcecd8..681b5a2433 100644 --- a/tcl/board/st_nucleo_8l152r8.cfg +++ b/tcl/board/st_nucleo_8l152r8.cfg @@ -3,7 +3,7 @@ # This is a ST NUCLEO 8L152R8 board with a single STM8L152R8T6 chip. # http://www.st.com/en/evaluation-tools/nucleo-8l152r8.html -source [find interface/stlink-dap.cfg] +source [find interface/stlink.cfg] transport select swim diff --git a/tcl/board/st_nucleo_8s208rb.cfg b/tcl/board/st_nucleo_8s208rb.cfg index 0d3c0c9125..0f6bde215c 100644 --- a/tcl/board/st_nucleo_8s208rb.cfg +++ b/tcl/board/st_nucleo_8s208rb.cfg @@ -3,7 +3,7 @@ # This is a ST NUCLEO 8S208RB board with a single STM8S208RBT6 chip. # https://www.st.com/en/evaluation-tools/nucleo-8s208rb.html -source [find interface/stlink-dap.cfg] +source [find interface/stlink.cfg] transport select swim diff --git a/tcl/board/st_nucleo_f0.cfg b/tcl/board/st_nucleo_f0.cfg index 31a95f59d2..00c131fd64 100644 --- a/tcl/board/st_nucleo_f0.cfg +++ b/tcl/board/st_nucleo_f0.cfg @@ -10,7 +10,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f0x.cfg] diff --git a/tcl/board/st_nucleo_f103rb.cfg b/tcl/board/st_nucleo_f103rb.cfg index 9815d4546e..892bdda99d 100644 --- a/tcl/board/st_nucleo_f103rb.cfg +++ b/tcl/board/st_nucleo_f103rb.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f1x.cfg] diff --git a/tcl/board/st_nucleo_f3.cfg b/tcl/board/st_nucleo_f3.cfg index 8833724945..38f49e3d5f 100644 --- a/tcl/board/st_nucleo_f3.cfg +++ b/tcl/board/st_nucleo_f3.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f3x.cfg] diff --git a/tcl/board/st_nucleo_f4.cfg b/tcl/board/st_nucleo_f4.cfg index a1908e4031..7617a17580 100644 --- a/tcl/board/st_nucleo_f4.cfg +++ b/tcl/board/st_nucleo_f4.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f4x.cfg] diff --git a/tcl/board/st_nucleo_f7.cfg b/tcl/board/st_nucleo_f7.cfg index 9c5b36ea46..41f8b21291 100644 --- a/tcl/board/st_nucleo_f7.cfg +++ b/tcl/board/st_nucleo_f7.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f7x.cfg] diff --git a/tcl/board/st_nucleo_g0.cfg b/tcl/board/st_nucleo_g0.cfg index f8e67a0432..f22a7e397e 100644 --- a/tcl/board/st_nucleo_g0.cfg +++ b/tcl/board/st_nucleo_g0.cfg @@ -12,7 +12,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32g0x.cfg] diff --git a/tcl/board/st_nucleo_g4.cfg b/tcl/board/st_nucleo_g4.cfg index 8e583e77d5..309f7a4c84 100644 --- a/tcl/board/st_nucleo_g4.cfg +++ b/tcl/board/st_nucleo_g4.cfg @@ -12,7 +12,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32g4x.cfg] diff --git a/tcl/board/st_nucleo_h743zi.cfg b/tcl/board/st_nucleo_h743zi.cfg index b857b00e05..be2d42fb8a 100644 --- a/tcl/board/st_nucleo_h743zi.cfg +++ b/tcl/board/st_nucleo_h743zi.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32h7x_dual_bank.cfg] diff --git a/tcl/board/st_nucleo_h745zi.cfg b/tcl/board/st_nucleo_h745zi.cfg index ad563b7d31..84865f422d 100644 --- a/tcl/board/st_nucleo_h745zi.cfg +++ b/tcl/board/st_nucleo_h745zi.cfg @@ -2,7 +2,7 @@ # This is an ST NUCLEO-H745ZI-Q board with single STM32H745ZITx chip. -source [find interface/stlink-dap.cfg] +source [find interface/stlink.cfg] transport select dapdirect_swd # STM32H745xx devices are dual core (Cortex-M7 and Cortex-M4) diff --git a/tcl/board/st_nucleo_l073rz.cfg b/tcl/board/st_nucleo_l073rz.cfg index 10fac5ef84..317c86e21d 100644 --- a/tcl/board/st_nucleo_l073rz.cfg +++ b/tcl/board/st_nucleo_l073rz.cfg @@ -4,7 +4,7 @@ # http://www.st.com/en/evaluation-tools/nucleo-l073rz.html source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set WORKAREASIZE 0x2000 diff --git a/tcl/board/st_nucleo_l1.cfg b/tcl/board/st_nucleo_l1.cfg index 50688d2b67..d7474d0fe2 100644 --- a/tcl/board/st_nucleo_l1.cfg +++ b/tcl/board/st_nucleo_l1.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32l1x_dual_bank.cfg] diff --git a/tcl/board/st_nucleo_l4.cfg b/tcl/board/st_nucleo_l4.cfg index 8c63d8cbf8..b0a75afe02 100644 --- a/tcl/board/st_nucleo_l4.cfg +++ b/tcl/board/st_nucleo_l4.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32l4x.cfg] diff --git a/tcl/board/st_nucleo_l5.cfg b/tcl/board/st_nucleo_l5.cfg index 6450f08b8d..626914aa75 100644 --- a/tcl/board/st_nucleo_l5.cfg +++ b/tcl/board/st_nucleo_l5.cfg @@ -3,7 +3,7 @@ # This is for STM32L5 Nucleo Dev Boards. # http://www.st.com/en/evaluation-tools/stm32-mcu-nucleo.html -source [find interface/stlink-dap.cfg] +source [find interface/stlink.cfg] transport select dapdirect_swd diff --git a/tcl/board/st_nucleo_wb55.cfg b/tcl/board/st_nucleo_wb55.cfg index 29b7ec98d6..ab7307c683 100644 --- a/tcl/board/st_nucleo_wb55.cfg +++ b/tcl/board/st_nucleo_wb55.cfg @@ -6,7 +6,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32wbx.cfg] diff --git a/tcl/board/stm320518_eval_stlink.cfg b/tcl/board/stm320518_eval_stlink.cfg index 153f7e5cbc..997bb4af95 100644 --- a/tcl/board/stm320518_eval_stlink.cfg +++ b/tcl/board/stm320518_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 8KB set WORKAREASIZE 0x2000 diff --git a/tcl/board/stm3220g_eval_stlink.cfg b/tcl/board/stm3220g_eval_stlink.cfg index d5296720c2..4233d04f15 100644 --- a/tcl/board/stm3220g_eval_stlink.cfg +++ b/tcl/board/stm3220g_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm3241g_eval_stlink.cfg b/tcl/board/stm3241g_eval_stlink.cfg index d2d5790776..3bccd28661 100644 --- a/tcl/board/stm3241g_eval_stlink.cfg +++ b/tcl/board/stm3241g_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32429i_eval_stlink.cfg b/tcl/board/stm32429i_eval_stlink.cfg index be3c482263..7d04aa7f3a 100644 --- a/tcl/board/stm32429i_eval_stlink.cfg +++ b/tcl/board/stm32429i_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32439i_eval_stlink.cfg b/tcl/board/stm32439i_eval_stlink.cfg index 7a1a396fcb..b9ea084dfd 100644 --- a/tcl/board/stm32439i_eval_stlink.cfg +++ b/tcl/board/stm32439i_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f0discovery.cfg b/tcl/board/stm32f0discovery.cfg index 60fb4a65e4..398ecc1037 100644 --- a/tcl/board/stm32f0discovery.cfg +++ b/tcl/board/stm32f0discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set WORKAREASIZE 0x2000 source [find target/stm32f0x.cfg] diff --git a/tcl/board/stm32f3discovery.cfg b/tcl/board/stm32f3discovery.cfg index f28e11f6a6..73c349a6ef 100644 --- a/tcl/board/stm32f3discovery.cfg +++ b/tcl/board/stm32f3discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f3x.cfg] diff --git a/tcl/board/stm32f412g-disco.cfg b/tcl/board/stm32f412g-disco.cfg index 757b25d75c..30a9537f0b 100644 --- a/tcl/board/stm32f412g-disco.cfg +++ b/tcl/board/stm32f412g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f413h-disco.cfg b/tcl/board/stm32f413h-disco.cfg index 6abf495514..c82d0d4349 100644 --- a/tcl/board/stm32f413h-disco.cfg +++ b/tcl/board/stm32f413h-disco.cfg @@ -10,7 +10,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f429disc1.cfg b/tcl/board/stm32f429disc1.cfg index 657aa1986f..0a8e7ef4e6 100644 --- a/tcl/board/stm32f429disc1.cfg +++ b/tcl/board/stm32f429disc1.cfg @@ -7,7 +7,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32f4x.cfg] diff --git a/tcl/board/stm32f429discovery.cfg b/tcl/board/stm32f429discovery.cfg index d1b5f5a118..865602ab69 100644 --- a/tcl/board/stm32f429discovery.cfg +++ b/tcl/board/stm32f429discovery.cfg @@ -7,7 +7,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f469discovery.cfg b/tcl/board/stm32f469discovery.cfg index cca25b7f04..c9acbbbd0c 100644 --- a/tcl/board/stm32f469discovery.cfg +++ b/tcl/board/stm32f469discovery.cfg @@ -7,7 +7,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f469i-disco.cfg b/tcl/board/stm32f469i-disco.cfg index 7ce57f6e75..63c42c64e9 100644 --- a/tcl/board/stm32f469i-disco.cfg +++ b/tcl/board/stm32f469i-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f4discovery.cfg b/tcl/board/stm32f4discovery.cfg index 714f1e9032..d96e2dbd34 100644 --- a/tcl/board/stm32f4discovery.cfg +++ b/tcl/board/stm32f4discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 64KB set WORKAREASIZE 0x10000 diff --git a/tcl/board/stm32f723e-disco.cfg b/tcl/board/stm32f723e-disco.cfg index 2dee2f9023..0207956206 100644 --- a/tcl/board/stm32f723e-disco.cfg +++ b/tcl/board/stm32f723e-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f746g-disco.cfg b/tcl/board/stm32f746g-disco.cfg index fed1d8ec9b..75ff4ec1e2 100644 --- a/tcl/board/stm32f746g-disco.cfg +++ b/tcl/board/stm32f746g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 256KB set WORKAREASIZE 0x40000 diff --git a/tcl/board/stm32f769i-disco.cfg b/tcl/board/stm32f769i-disco.cfg index 2969bb9272..cd6383a700 100644 --- a/tcl/board/stm32f769i-disco.cfg +++ b/tcl/board/stm32f769i-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 256KB set WORKAREASIZE 0x40000 diff --git a/tcl/board/stm32f7discovery.cfg b/tcl/board/stm32f7discovery.cfg index 4cc22ea625..6fd6c64b3d 100644 --- a/tcl/board/stm32f7discovery.cfg +++ b/tcl/board/stm32f7discovery.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK/V2-1 source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 256KB set WORKAREASIZE 0x40000 diff --git a/tcl/board/stm32h735g-disco.cfg b/tcl/board/stm32h735g-disco.cfg index 4097ae28b2..327a36418c 100644 --- a/tcl/board/stm32h735g-disco.cfg +++ b/tcl/board/stm32h735g-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set CHIPNAME stm32h735igk6 diff --git a/tcl/board/stm32h745i-disco.cfg b/tcl/board/stm32h745i-disco.cfg index 1c0bc6748c..9da1daefc6 100644 --- a/tcl/board/stm32h745i-disco.cfg +++ b/tcl/board/stm32h745i-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set CHIPNAME stm32h745xih6 diff --git a/tcl/board/stm32h747i-disco.cfg b/tcl/board/stm32h747i-disco.cfg index e0a348ef08..7f8eda8c45 100644 --- a/tcl/board/stm32h747i-disco.cfg +++ b/tcl/board/stm32h747i-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set CHIPNAME stm32h747xih6 diff --git a/tcl/board/stm32h750b-disco.cfg b/tcl/board/stm32h750b-disco.cfg index efb32b1dfb..8b254f21fd 100644 --- a/tcl/board/stm32h750b-disco.cfg +++ b/tcl/board/stm32h750b-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set CHIPNAME stm32h750xbh6 diff --git a/tcl/board/stm32h7b3i-disco.cfg b/tcl/board/stm32h7b3i-disco.cfg index 58ad9f7814..df0d0a6f27 100644 --- a/tcl/board/stm32h7b3i-disco.cfg +++ b/tcl/board/stm32h7b3i-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set CHIPNAME stm32h7b3lih6q diff --git a/tcl/board/stm32h7x3i_eval.cfg b/tcl/board/stm32h7x3i_eval.cfg index b9c4c74c26..508f10d5d1 100644 --- a/tcl/board/stm32h7x3i_eval.cfg +++ b/tcl/board/stm32h7x3i_eval.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32h7x_dual_bank.cfg] diff --git a/tcl/board/stm32l0discovery.cfg b/tcl/board/stm32l0discovery.cfg index c711d9c8a8..59aed3405d 100644 --- a/tcl/board/stm32l0discovery.cfg +++ b/tcl/board/stm32l0discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set WORKAREASIZE 0x2000 source [find target/stm32l0.cfg] diff --git a/tcl/board/stm32l476g-disco.cfg b/tcl/board/stm32l476g-disco.cfg index a32d20fb3f..fe33ffefb9 100644 --- a/tcl/board/stm32l476g-disco.cfg +++ b/tcl/board/stm32l476g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32l496g-disco.cfg b/tcl/board/stm32l496g-disco.cfg index 1ba2299ca9..823fa6e380 100644 --- a/tcl/board/stm32l496g-disco.cfg +++ b/tcl/board/stm32l496g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32l4discovery.cfg b/tcl/board/stm32l4discovery.cfg index f089550780..64a456b612 100644 --- a/tcl/board/stm32l4discovery.cfg +++ b/tcl/board/stm32l4discovery.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd source [find target/stm32l4x.cfg] diff --git a/tcl/board/stm32l4p5g-disco.cfg b/tcl/board/stm32l4p5g-disco.cfg index 20d781a1a4..33bb9a7662 100644 --- a/tcl/board/stm32l4p5g-disco.cfg +++ b/tcl/board/stm32l4p5g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32l4r9i-disco.cfg b/tcl/board/stm32l4r9i-disco.cfg index f364ad3d58..cbb86669f0 100644 --- a/tcl/board/stm32l4r9i-disco.cfg +++ b/tcl/board/stm32l4r9i-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32ldiscovery.cfg b/tcl/board/stm32ldiscovery.cfg index d760edaba7..e39b52295a 100644 --- a/tcl/board/stm32ldiscovery.cfg +++ b/tcl/board/stm32ldiscovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set WORKAREASIZE 0x4000 source [find target/stm32l1.cfg] diff --git a/tcl/board/stm32mp13x_dk.cfg b/tcl/board/stm32mp13x_dk.cfg index 6328ddb4c0..08377ca76a 100644 --- a/tcl/board/stm32mp13x_dk.cfg +++ b/tcl/board/stm32mp13x_dk.cfg @@ -3,7 +3,7 @@ # board MB1635x # http://www.st.com/en/evaluation-tools/stm32mp135f-dk.html -source [find interface/stlink-dap.cfg] +source [find interface/stlink.cfg] transport select dapdirect_swd diff --git a/tcl/board/stm32mp15x_dk2.cfg b/tcl/board/stm32mp15x_dk2.cfg index 9503428d1a..0e71e05ee0 100644 --- a/tcl/board/stm32mp15x_dk2.cfg +++ b/tcl/board/stm32mp15x_dk2.cfg @@ -4,7 +4,7 @@ # http://www.st.com/en/evaluation-tools/stm32mp157a-dk1.html # http://www.st.com/en/evaluation-tools/stm32mp157c-dk2.html -source [find interface/stlink-dap.cfg] +source [find interface/stlink.cfg] transport select dapdirect_swd diff --git a/tcl/board/stm32vldiscovery.cfg b/tcl/board/stm32vldiscovery.cfg index 30e35b9817..57852bfd4f 100644 --- a/tcl/board/stm32vldiscovery.cfg +++ b/tcl/board/stm32vldiscovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select hla_swd +transport select dapdirect_swd set WORKAREASIZE 0x2000 source [find target/stm32f1x.cfg] diff --git a/tcl/interface/stlink-dap.cfg b/tcl/interface/stlink-dap.cfg index 99c81c180c..009fdb7e0f 100644 --- a/tcl/interface/stlink-dap.cfg +++ b/tcl/interface/stlink-dap.cfg @@ -1,22 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-or-later -# -# STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit -# debugger/programmer -# -# This new interface driver creates a ST-Link wrapper for ARM-DAP named "dapdirect" -# Old ST-LINK/V1 and ST-LINK/V2 pre version V2J24 don't support "dapdirect" -# -# SWIM transport is natively supported -# +echo "WARNING: interface/stlink-dap.cfg is deprecated, please switch to interface/stlink.cfg" +source [find interface/stlink.cfg] -adapter driver st-link -st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 - -# transport select dapdirect_jtag -# transport select dapdirect_swd -# transport select swim - -# Optionally specify the serial number of usb device -# e.g. -# adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" diff --git a/tcl/interface/stlink-hla.cfg b/tcl/interface/stlink-hla.cfg new file mode 100644 index 0000000000..5c4adb8973 --- /dev/null +++ b/tcl/interface/stlink-hla.cfg @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit +# debugger/programmer +# + +echo "DEPRECATED: OpenOCD support for ST-Link HLA transport will be dropped soon!" +echo "Consider updating your ST-Link firmware to a version >= V2J24 (2015)" + +adapter driver hla +hla layout stlink +hla device_desc "ST-LINK" +hla vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 + +# Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2 +# devices seem to have serial numbers with unreadable characters. ST-LINK/V2 +# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial +# number reset issues. +# eg. +# adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" diff --git a/tcl/interface/stlink.cfg b/tcl/interface/stlink.cfg index 9b7f1f9ebf..99c81c180c 100644 --- a/tcl/interface/stlink.cfg +++ b/tcl/interface/stlink.cfg @@ -4,15 +4,19 @@ # STMicroelectronics ST-LINK/V1, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 in-circuit # debugger/programmer # +# This new interface driver creates a ST-Link wrapper for ARM-DAP named "dapdirect" +# Old ST-LINK/V1 and ST-LINK/V2 pre version V2J24 don't support "dapdirect" +# +# SWIM transport is natively supported +# + +adapter driver st-link +st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 -adapter driver hla -hla layout stlink -hla device_desc "ST-LINK" -hla vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 +# transport select dapdirect_jtag +# transport select dapdirect_swd +# transport select swim -# Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2 -# devices seem to have serial numbers with unreadable characters. ST-LINK/V2 -# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial -# number reset issues. -# eg. +# Optionally specify the serial number of usb device +# e.g. # adapter serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f" From 134e56338d365319380092a7bc5becf82c6d47f2 Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Fri, 25 Oct 2024 22:15:29 +0800 Subject: [PATCH 0993/1312] target: riscv: convert 'unsigned' to 'unsigned int' Change-Id: I10b9abf9e42389eb91b210b8c2f01219ca9068cd Signed-off-by: Mark Zhuang Reviewed-on: https://review.openocd.org/c/openocd/+/8366 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/riscv/riscv-013.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 6c9ed317b0..658c1fd9db 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -50,8 +50,7 @@ static bool riscv013_is_halted(struct target *target); static enum riscv_halt_reason riscv013_halt_reason(struct target *target); static int riscv013_write_debug_buffer(struct target *target, unsigned int index, riscv_insn_t d); -static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned - index); +static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned int index); static int riscv013_execute_debug_buffer(struct target *target); static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d); static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a); From 114ad468ca6be45e25cfc1a521f04f959cc76159 Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Sat, 26 Oct 2024 10:42:03 +0800 Subject: [PATCH 0994/1312] server: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Ignore the cast as they could be better addressed. Change-Id: Ib0cbd9388d61659f8d47c8f57c09baa6df123487 Signed-off-by: Mark Zhuang Reviewed-on: https://review.openocd.org/c/openocd/+/8369 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 12 ++++++------ src/server/telnet_server.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 579a388d25..c572f392a9 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -116,7 +116,7 @@ static int gdb_error(struct connection *connection, int retval); static char *gdb_port; static char *gdb_port_next; -static void gdb_log_callback(void *priv, const char *file, unsigned line, +static void gdb_log_callback(void *priv, const char *file, unsigned int line, const char *function, const char *string); static void gdb_sig_halted(struct connection *connection); @@ -360,7 +360,7 @@ static void gdb_log_incoming_packet(struct connection *connection, const char *p struct gdb_connection *gdb_connection = connection->priv; /* Avoid dumping non-printable characters to the terminal */ - const unsigned packet_len = strlen(packet); + const unsigned int packet_len = strlen(packet); const char *nonprint = find_nonprint_char(packet, packet_len); if (nonprint) { /* Does packet at least have a prefix that is printable? @@ -1203,7 +1203,7 @@ static void gdb_target_to_reg(struct target *target, int i; for (i = 0; i < str_len; i += 2) { - unsigned t; + unsigned int t; if (sscanf(tstr + i, "%02x", &t) != 1) { LOG_ERROR("BUG: unable to convert register value"); exit(-1); @@ -1948,8 +1948,8 @@ static int gdb_memory_map(struct connection *connection, compare_bank); for (unsigned int i = 0; i < target_flash_banks; i++) { - unsigned sector_size = 0; - unsigned group_len = 0; + unsigned int sector_size = 0; + unsigned int group_len = 0; p = banks[i]; @@ -3469,7 +3469,7 @@ static int gdb_fileio_response_packet(struct connection *connection, return ERROR_OK; } -static void gdb_log_callback(void *priv, const char *file, unsigned line, +static void gdb_log_callback(void *priv, const char *file, unsigned int line, const char *function, const char *string) { struct connection *connection = priv; diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index a596afef08..7818af2dbb 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -93,7 +93,7 @@ static int telnet_output(struct command_context *cmd_ctx, const char *line) return telnet_outputline(connection, line); } -static void telnet_log_callback(void *priv, const char *file, unsigned line, +static void telnet_log_callback(void *priv, const char *file, unsigned int line, const char *function, const char *string) { struct connection *connection = priv; From b95633b30c35058005f7d69578773944e32e98e5 Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Sat, 26 Oct 2024 11:09:16 +0800 Subject: [PATCH 0995/1312] flash: convert 'unsigned' to 'unsigned int' Change-Id: I8e8da78385eed714524891b580e19a79cfb459d3 Signed-off-by: Mark Zhuang Reviewed-on: https://review.openocd.org/c/openocd/+/8370 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nand/mx3.h | 8 ++++---- src/flash/nand/mxc.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/flash/nand/mx3.h b/src/flash/nand/mx3.h index b272962b4c..648cd86ccc 100644 --- a/src/flash/nand/mx3.h +++ b/src/flash/nand/mx3.h @@ -86,10 +86,10 @@ enum mx_nf_finalize_action { }; struct mx3_nf_flags { - unsigned target_little_endian:1; - unsigned nand_readonly:1; - unsigned one_kb_sram:1; - unsigned hw_ecc_enabled:1; + unsigned int target_little_endian:1; + unsigned int nand_readonly:1; + unsigned int one_kb_sram:1; + unsigned int hw_ecc_enabled:1; }; struct mx3_nf_controller { diff --git a/src/flash/nand/mxc.h b/src/flash/nand/mxc.h index ae2c03a758..e9dc0a2f3d 100644 --- a/src/flash/nand/mxc.h +++ b/src/flash/nand/mxc.h @@ -138,11 +138,11 @@ enum mxc_nf_finalize_action { }; struct mxc_nf_flags { - unsigned target_little_endian:1; - unsigned nand_readonly:1; - unsigned one_kb_sram:1; - unsigned hw_ecc_enabled:1; - unsigned biswap_enabled:1; + unsigned int target_little_endian:1; + unsigned int nand_readonly:1; + unsigned int one_kb_sram:1; + unsigned int hw_ecc_enabled:1; + unsigned int biswap_enabled:1; }; struct mxc_nf_controller { From 99f60d5e594278b876142a957090d8649d5e6c44 Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Sat, 26 Oct 2024 10:15:00 +0800 Subject: [PATCH 0996/1312] jtag: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Change-Id: I2c2d56aa98e89bcc6088a1bd51d70066d67d6dad Signed-off-by: Mark Zhuang Reviewed-on: https://review.openocd.org/c/openocd/+/8367 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/hla/hla_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index f284278ddc..e826f79103 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -76,7 +76,7 @@ int hl_interface_init_target(struct target *t) if (res != ERROR_OK) return res; - unsigned ii, limit = t->tap->expected_ids_cnt; + unsigned int ii, limit = t->tap->expected_ids_cnt; int found = 0; for (ii = 0; ii < limit; ii++) { @@ -264,7 +264,7 @@ COMMAND_HANDLER(hl_interface_handle_vid_pid_command) return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned i; + unsigned int i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], hl_if.param.vid[i / 2]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], hl_if.param.pid[i / 2]); From f4d81cd4d49336f695b8d4b00aa0afdbc6ea22cd Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 30 Aug 2024 10:47:55 +0200 Subject: [PATCH 0997/1312] tcl/interface: Restructure parport config files Provide cable specific configuration files like for the FTDI interface. Depcrecate the old configuration files but keep them until the next release for compatibility reasons. Change-Id: I436bd60779a107120c9e1b1f0b8a69a39a240ad4 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8514 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/interface/parport.cfg | 15 ++------------- tcl/interface/parport/dlc5.cfg | 17 +++++++++++++++++ tcl/interface/parport/wiggler.cfg | 21 +++++++++++++++++++++ tcl/interface/parport_dlc5.cfg | 11 ++--------- 4 files changed, 42 insertions(+), 22 deletions(-) create mode 100644 tcl/interface/parport/dlc5.cfg create mode 100644 tcl/interface/parport/wiggler.cfg diff --git a/tcl/interface/parport.cfg b/tcl/interface/parport.cfg index b9fceeb852..8fb1c148b2 100644 --- a/tcl/interface/parport.cfg +++ b/tcl/interface/parport.cfg @@ -5,17 +5,6 @@ # # Addresses: 0x378/LPT1 or 0x278/LPT2 ... # +echo "DEPRECATED: use interface/parport/wiggler.cfg instead of deprecated interface/parport.cfg" -if { [info exists PARPORTADDR] } { - set _PARPORTADDR $PARPORTADDR -} else { - if {$tcl_platform(platform) eq "windows"} { - set _PARPORTADDR 0x378 - } { - set _PARPORTADDR 0 - } -} - -adapter driver parport -parport port $_PARPORTADDR -parport cable wiggler +source [find interface/parport/wiggler.cfg] diff --git a/tcl/interface/parport/dlc5.cfg b/tcl/interface/parport/dlc5.cfg new file mode 100644 index 0000000000..24acea7a95 --- /dev/null +++ b/tcl/interface/parport/dlc5.cfg @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Xilinx Parallel Cable III 'DLC 5' (and various clones) +# +# http://www.xilinx.com/itp/xilinx4/data/docs/pac/appendixb.html +# + +if { [info exists PARPORTADDR] } { + set _PARPORTADDR $PARPORTADDR +} else { + set _PARPORTADDR 0 +} + +adapter driver parport +parport port $_PARPORTADDR +parport cable dlc5 diff --git a/tcl/interface/parport/wiggler.cfg b/tcl/interface/parport/wiggler.cfg new file mode 100644 index 0000000000..b9fceeb852 --- /dev/null +++ b/tcl/interface/parport/wiggler.cfg @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Parallel port wiggler (many clones available) on port 0x378 +# +# Addresses: 0x378/LPT1 or 0x278/LPT2 ... +# + +if { [info exists PARPORTADDR] } { + set _PARPORTADDR $PARPORTADDR +} else { + if {$tcl_platform(platform) eq "windows"} { + set _PARPORTADDR 0x378 + } { + set _PARPORTADDR 0 + } +} + +adapter driver parport +parport port $_PARPORTADDR +parport cable wiggler diff --git a/tcl/interface/parport_dlc5.cfg b/tcl/interface/parport_dlc5.cfg index 24acea7a95..83f3b56c48 100644 --- a/tcl/interface/parport_dlc5.cfg +++ b/tcl/interface/parport_dlc5.cfg @@ -5,13 +5,6 @@ # # http://www.xilinx.com/itp/xilinx4/data/docs/pac/appendixb.html # +echo "DEPRECATED: use interface/parport/dlc5.cfg instead of deprecated interface/parport_dlc5.cfg" -if { [info exists PARPORTADDR] } { - set _PARPORTADDR $PARPORTADDR -} else { - set _PARPORTADDR 0 -} - -adapter driver parport -parport port $_PARPORTADDR -parport cable dlc5 +source [find interface/parport/dlc5.cfg] From 337db329c9c30a58ffa08c01691f12dd95890cbb Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 30 Aug 2024 11:06:13 +0200 Subject: [PATCH 0998/1312] adapter/bitbang: Use 'bool' data type for blink() Change-Id: I187f8944ad5fd92f28cbd32e447f9ec1a97e16d6 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8515 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/am335xgpio.c | 4 ++-- src/jtag/drivers/bcm2835gpio.c | 4 ++-- src/jtag/drivers/bitbang.c | 8 ++++---- src/jtag/drivers/bitbang.h | 2 +- src/jtag/drivers/dummy.c | 2 +- src/jtag/drivers/linuxgpiod.c | 4 ++-- src/jtag/drivers/parport.c | 8 ++++---- src/jtag/drivers/remote_bitbang.c | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index cfe41c3be5..9bb7ea7d13 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -275,10 +275,10 @@ static int am335xgpio_swdio_read(void) return get_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO]); } -static int am335xgpio_blink(int on) +static int am335xgpio_blink(bool on) { if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED])) - set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on ? 1 : 0); return ERROR_OK; } diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index b8d91bf382..2c2061daec 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -419,10 +419,10 @@ static void bcm2835gpio_munmap(void) } } -static int bcm2835gpio_blink(int on) +static int bcm2835gpio_blink(bool on) { if (is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) - set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on ? 1 : 0); return ERROR_OK; } diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 17e01a2330..42234a6f72 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -309,7 +309,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) retval = ERROR_OK; if (bitbang_interface->blink) { - if (bitbang_interface->blink(1) != ERROR_OK) + if (bitbang_interface->blink(true) != ERROR_OK) return ERROR_FAIL; } @@ -377,7 +377,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) cmd = cmd->next; } if (bitbang_interface->blink) { - if (bitbang_interface->blink(0) != ERROR_OK) + if (bitbang_interface->blink(false) != ERROR_OK) return ERROR_FAIL; } @@ -396,7 +396,7 @@ static void bitbang_swd_exchange(bool rnw, uint8_t buf[], unsigned int offset, u { if (bitbang_interface->blink) { /* FIXME: we should manage errors */ - bitbang_interface->blink(1); + bitbang_interface->blink(true); } for (unsigned int i = offset; i < bit_cnt + offset; i++) { @@ -418,7 +418,7 @@ static void bitbang_swd_exchange(bool rnw, uint8_t buf[], unsigned int offset, u if (bitbang_interface->blink) { /* FIXME: we should manage errors */ - bitbang_interface->blink(0); + bitbang_interface->blink(false); } } diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index dc941796e2..82405eb8ab 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -45,7 +45,7 @@ struct bitbang_interface { int (*write)(int tck, int tms, int tdi); /** Blink led (optional). */ - int (*blink)(int on); + int (*blink)(bool on); /** Sample SWDIO and return the value. */ int (*swdio_read)(void); diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index 1b1e57392f..4fe598fe32 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -72,7 +72,7 @@ static int dummy_reset(int trst, int srst) return ERROR_OK; } -static int dummy_led(int on) +static int dummy_led(bool on) { return ERROR_OK; } diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 1926ed9ae6..fa14e42d6e 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -178,14 +178,14 @@ static int linuxgpiod_swd_write(int swclk, int swdio) return ERROR_OK; } -static int linuxgpiod_blink(int on) +static int linuxgpiod_blink(bool on) { int retval; if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) return ERROR_OK; - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on ? 1 : 0); if (retval < 0) LOG_WARNING("Fail set led"); return retval; diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index d26a51048f..d03d3b89c8 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -183,8 +183,8 @@ static int parport_reset(int trst, int srst) return ERROR_OK; } -/* turn LED on parport adapter on (1) or off (0) */ -static int parport_led(int on) +/* turn LED on parport adapter on (true) or off (true) */ +static int parport_led(bool on) { if (on) dataport_value |= cable->LED_MASK; @@ -364,7 +364,7 @@ static int parport_init(void) return ERROR_FAIL; if (parport_write(0, 0, 0) != ERROR_OK) return ERROR_FAIL; - if (parport_led(1) != ERROR_OK) + if (parport_led(true) != ERROR_OK) return ERROR_FAIL; bitbang_interface = &parport_bitbang; @@ -374,7 +374,7 @@ static int parport_init(void) static int parport_quit(void) { - if (parport_led(0) != ERROR_OK) + if (parport_led(false) != ERROR_OK) return ERROR_FAIL; if (parport_exit) { diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index edd36f2e67..91a8532b79 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -251,7 +251,7 @@ static int remote_bitbang_sleep(unsigned int microseconds) return remote_bitbang_flush(); } -static int remote_bitbang_blink(int on) +static int remote_bitbang_blink(bool on) { char c = on ? 'B' : 'b'; return remote_bitbang_queue(c, FLUSH_SEND_BUF); From 3b261fb155dd9165c39fc848bd66aae2e5dea370 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 30 Aug 2024 11:22:17 +0200 Subject: [PATCH 0999/1312] adapter/parport: Coding style changes Apply some coding style changes according to the C style guide. The patch is tested for regression with the 'wiggler' parallel port cable. Change-Id: I43774f596831d8c46f90f18893418178041a930b Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8516 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/parport.c | 130 ++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index d03d3b89c8..bdd3388955 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -45,21 +45,31 @@ #include #endif -/* parallel port cable description - */ +// Parallel port cable description. struct cable { const char *name; - uint8_t TDO_MASK; /* status port bit containing current TDO value */ - uint8_t TRST_MASK; /* data port bit for TRST */ - uint8_t TMS_MASK; /* data port bit for TMS */ - uint8_t TCK_MASK; /* data port bit for TCK */ - uint8_t TDI_MASK; /* data port bit for TDI */ - uint8_t SRST_MASK; /* data port bit for SRST */ - uint8_t OUTPUT_INVERT; /* data port bits that should be inverted */ - uint8_t INPUT_INVERT; /* status port that should be inverted */ - uint8_t PORT_INIT; /* initialize data port with this value */ - uint8_t PORT_EXIT; /* de-initialize data port with this value */ - uint8_t LED_MASK; /* data port bit for LED */ + // Status port bit containing current TDO value. + uint8_t tdo_mask; + // Data port bit for TRST. + uint8_t trst_mask; + // Data port bit for TMD. + uint8_t tms_mask; + // Data port bit for TCK. + uint8_t tck_mask; + // Data port bit for TDI. + uint8_t tdi_mask; + // Data port bit for SRST. + uint8_t srst_mask; + // Data port bits that should be inverted. + uint8_t output_invert; + // Status port that should be inverted. + uint8_t input_invert; + // Initialize data port with this value. + uint8_t port_init; + // De-initialize data port with this value. + uint8_t port_exit; + // Data port bit for LED. + uint8_t led_mask; }; static const struct cable cables[] = { @@ -87,15 +97,14 @@ static const struct cable cables[] = { { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; -/* configuration */ +// Configuration variables. static char *parport_cable; static uint16_t parport_port; static bool parport_exit; static uint32_t parport_toggling_time_ns = 1000; static int wait_states; -/* interface variables - */ +// Interface variables. static const struct cable *cable; static uint8_t dataport_value; @@ -116,7 +125,7 @@ static bb_value_t parport_read(void) data = inb(statusport); #endif - if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK) + if ((data ^ cable->input_invert) & cable->tdo_mask) return BB_HIGH; else return BB_LOW; @@ -125,7 +134,7 @@ static bb_value_t parport_read(void) static inline void parport_write_data(void) { uint8_t output; - output = dataport_value ^ cable->OUTPUT_INVERT; + output = dataport_value ^ cable->output_invert; #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &output); @@ -143,19 +152,19 @@ static int parport_write(int tck, int tms, int tdi) int i = wait_states + 1; if (tck) - dataport_value |= cable->TCK_MASK; + dataport_value |= cable->tck_mask; else - dataport_value &= ~cable->TCK_MASK; + dataport_value &= ~cable->tck_mask; if (tms) - dataport_value |= cable->TMS_MASK; + dataport_value |= cable->tms_mask; else - dataport_value &= ~cable->TMS_MASK; + dataport_value &= ~cable->tms_mask; if (tdi) - dataport_value |= cable->TDI_MASK; + dataport_value |= cable->tdi_mask; else - dataport_value &= ~cable->TDI_MASK; + dataport_value &= ~cable->tdi_mask; while (i-- > 0) parport_write_data(); @@ -163,33 +172,32 @@ static int parport_write(int tck, int tms, int tdi) return ERROR_OK; } -/* (1) assert or (0) deassert reset lines */ +// (1) assert or (0) deassert reset lines. static int parport_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (trst == 0) - dataport_value |= cable->TRST_MASK; + dataport_value |= cable->trst_mask; else if (trst == 1) - dataport_value &= ~cable->TRST_MASK; + dataport_value &= ~cable->trst_mask; if (srst == 0) - dataport_value |= cable->SRST_MASK; + dataport_value |= cable->srst_mask; else if (srst == 1) - dataport_value &= ~cable->SRST_MASK; + dataport_value &= ~cable->srst_mask; parport_write_data(); return ERROR_OK; } -/* turn LED on parport adapter on (true) or off (true) */ static int parport_led(bool on) { if (on) - dataport_value |= cable->LED_MASK; + dataport_value |= cable->led_mask; else - dataport_value &= ~cable->LED_MASK; + dataport_value &= ~cable->led_mask; parport_write_data(); @@ -204,7 +212,7 @@ static int parport_speed(int speed) static int parport_khz(int khz, int *jtag_speed) { - if (khz == 0) { + if (!khz) { LOG_DEBUG("RCLK not supported"); return ERROR_FAIL; } @@ -248,10 +256,10 @@ static int parport_get_giveio_access(void) #endif static struct bitbang_interface parport_bitbang = { - .read = &parport_read, - .write = &parport_write, - .blink = &parport_led, - }; + .read = &parport_read, + .write = &parport_write, + .blink = &parport_led, +}; static int parport_init(void) { @@ -268,7 +276,7 @@ static int parport_init(void) } while (cur_cable->name) { - if (strcmp(cur_cable->name, parport_cable) == 0) { + if (!strcmp(cur_cable->name, parport_cable)) { cable = cur_cable; break; } @@ -280,7 +288,7 @@ static int parport_init(void) return ERROR_JTAG_INIT_FAILED; } - dataport_value = cable->PORT_INIT; + dataport_value = cable->port_init; #if PARPORT_USE_PPDEV == 1 if (device_handle > 0) { @@ -332,7 +340,7 @@ static int parport_init(void) #endif /* not __FreeBSD__, __FreeBSD_kernel__ */ #else /* not PARPORT_USE_PPDEV */ - if (parport_port == 0) { + if (!parport_port) { parport_port = 0x378; LOG_WARNING("No parport port specified, using default '0x378' (LPT1)"); } @@ -351,7 +359,7 @@ static int parport_init(void) } LOG_DEBUG("...privileges granted"); - /* make sure parallel port is in right mode (clear tristate and interrupt */ + // Make sure parallel port is in right mode (clear tristate and interrupt. #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(parport_port + 2, 0x0); #else @@ -378,7 +386,7 @@ static int parport_quit(void) return ERROR_FAIL; if (parport_exit) { - dataport_value = cable->PORT_EXIT; + dataport_value = cable->port_exit; parport_write_data(); } @@ -388,13 +396,13 @@ static int parport_quit(void) return ERROR_OK; } -COMMAND_HANDLER(parport_handle_parport_port_command) +COMMAND_HANDLER(parport_handle_port_command) { if (CMD_ARGC == 1) { - /* only if the port wasn't overwritten by cmdline */ - if (parport_port == 0) + // Only if the port wasn't overwritten by cmdline. + if (!parport_port) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port); - else { + } else { LOG_ERROR("The parport port was already configured!"); return ERROR_FAIL; } @@ -405,14 +413,14 @@ COMMAND_HANDLER(parport_handle_parport_port_command) return ERROR_OK; } -COMMAND_HANDLER(parport_handle_parport_cable_command) +COMMAND_HANDLER(parport_handle_cable_command) { - if (CMD_ARGC == 0) + if (!CMD_ARGC) return ERROR_OK; - /* only if the cable name wasn't overwritten by cmdline */ + // Only if the cable name wasn't overwritten by cmdline. if (!parport_cable) { - /* REVISIT first verify that it's listed in cables[] ... */ + // TODO: REVISIT first verify that it's listed in cables[]. parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char)); if (!parport_cable) { LOG_ERROR("Out of memory"); @@ -421,7 +429,7 @@ COMMAND_HANDLER(parport_handle_parport_cable_command) strcpy(parport_cable, CMD_ARGV[0]); } - /* REVISIT it's probably worth returning the current value ... */ + // TODO: REVISIT it's probably worth returning the current value. return ERROR_OK; } @@ -436,7 +444,7 @@ COMMAND_HANDLER(parport_handle_write_on_exit_command) return ERROR_OK; } -COMMAND_HANDLER(parport_handle_parport_toggling_time_command) +COMMAND_HANDLER(parport_handle_toggling_time_command) { if (CMD_ARGC == 1) { uint32_t ns; @@ -445,7 +453,7 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) if (retval != ERROR_OK) return retval; - if (ns == 0) { + if (!ns) { LOG_ERROR("0 ns is not a valid parport toggling time"); return ERROR_FAIL; } @@ -453,9 +461,11 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) parport_toggling_time_ns = ns; retval = adapter_get_speed(&wait_states); if (retval != ERROR_OK) { - /* if adapter_get_speed fails then the clock_mode - * has not been configured, this happens if parport_toggling_time is - * called before the adapter speed is set */ + /* + * If adapter_get_speed fails then the clock_mode has + * not been configured, this happens if toggling_time is + * called before the adapter speed is set. + */ LOG_INFO("no parport speed set - defaulting to zero wait states"); wait_states = 0; } @@ -470,7 +480,7 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) static const struct command_registration parport_subcommand_handlers[] = { { .name = "port", - .handler = parport_handle_parport_port_command, + .handler = parport_handle_port_command, .mode = COMMAND_CONFIG, .help = "Display the address of the I/O port (e.g. 0x378) " "or the number of the '/dev/parport' device used. " @@ -479,11 +489,11 @@ static const struct command_registration parport_subcommand_handlers[] = { }, { .name = "cable", - .handler = parport_handle_parport_cable_command, + .handler = parport_handle_cable_command, .mode = COMMAND_CONFIG, .help = "Set the layout of the parallel port cable " "used to connect to the target.", - /* REVISIT there's no way to list layouts we know ... */ + // TODO: REVISIT there's no way to list layouts we know. .usage = "[layout]", }, { @@ -496,7 +506,7 @@ static const struct command_registration parport_subcommand_handlers[] = { }, { .name = "toggling_time", - .handler = parport_handle_parport_toggling_time_command, + .handler = parport_handle_toggling_time_command, .mode = COMMAND_CONFIG, .help = "Displays or assigns how many nanoseconds it " "takes for the hardware to toggle TCK.", From 40d58ce5290a51c58615c4f95912b69fa7975aea Mon Sep 17 00:00:00 2001 From: MicBiso Date: Wed, 10 Apr 2024 12:38:09 +0200 Subject: [PATCH 1000/1312] tcl/target/renesas_rz_g2: Rename to renesas_rz and add RZ/V2L-G3S Rename file to get it more generic and add more targets belonging to the same family. Add support for two new devices: RZ/V2L and RZ/G3S Change-Id: Idb7f4d81d2f95ad15ef686e940f43ed29f49f343 Signed-off-by: MicBiso Reviewed-on: https://review.openocd.org/c/openocd/+/8211 Reviewed-by: Antonio Borneo Tested-by: jenkins --- .../{renesas_rz_g2.cfg => renesas_rz.cfg} | 78 ++++++++++++++----- 1 file changed, 58 insertions(+), 20 deletions(-) rename tcl/target/{renesas_rz_g2.cfg => renesas_rz.cfg} (70%) diff --git a/tcl/target/renesas_rz_g2.cfg b/tcl/target/renesas_rz.cfg similarity index 70% rename from tcl/target/renesas_rz_g2.cfg rename to tcl/target/renesas_rz.cfg index a3d5f48fbc..a0489de3dd 100644 --- a/tcl/target/renesas_rz_g2.cfg +++ b/tcl/target/renesas_rz.cfg @@ -1,23 +1,25 @@ # SPDX-License-Identifier: GPL-2.0-or-later -# Renesas RZ/G2 SOCs +# Renesas RZ SOCs # - There are a combination of Cortex-A57s, Cortex-A53s, Cortex-A55, Cortex-R7 # and Cortex-M33 for each SOC -# - Each SOC can boot through the Cortex-A5x cores +# - Each SOC can boot through the Cortex-A5x cores or the Cortex-M33 -# Supported RZ/G2 SOCs and their cores: +# Supported RZ SOCs and their cores: # RZ/G2H: Cortex-A57 x4, Cortex-A53 x4, Cortex-R7 # RZ/G2M: Cortex-A57 x2, Cortex-A53 x4, Cortex-R7 # RZ/G2N: Cortex-A57 x2, Cortex-R7 # RZ/G2E: Cortex-A53 x2, Cortex-R7 # RZ/G2L: Cortex-A55 x2, Cortex-M33 +# RZ/V2L: Cortex-A55 x2, Cortex-M33 # RZ/G2LC: Cortex-A55 x2, Cortex-M33 # RZ/G2UL: Cortex-A55 x1, Cortex-M33 +# RZ/G3S: Cortex-A55 x1, Cortex-M33 x2 # Usage: # There are 2 configuration options: # SOC: Selects the supported SOC. (Default 'G2L') -# BOOT_CORE: Selects the booting core. 'CA57', 'CA53' or 'CA55' +# BOOT_CORE: Selects the booting core. 'CA57', 'CA53', 'CA55' or CM33 transport select jtag reset_config trst_and_srst srst_gates_jtag @@ -77,6 +79,13 @@ switch $_soc { set _boot_core CA55 set _ap_num 0 } + V2L { + set _CHIPNAME r9a07g054l + set _num_ca55 2 + set _num_cm33 1 + set _boot_core CA55 + set _ap_num 0 + } G2LC { set _CHIPNAME r9a07g044c set _num_ca55 2 @@ -91,6 +100,13 @@ switch $_soc { set _boot_core CA55 set _ap_num 0 } + G3S { + set _CHIPNAME r9a08g045s + set _num_ca55 1 + set _num_cm33 2 + set _boot_core CA55 + set _ap_num 0 + } default { error "'$_soc' is invalid!" } @@ -112,16 +128,16 @@ if { [info exists DAP_TAPID] } { set _DAP_TAPID 0x6ba00477 } -echo "\t$_soc - $_num_ca57 CA57(s), $_num_ca55 CA55(s), $_num_ca53 CA53(s), $_num_cr7 CR7(s), \ - $_num_cm33 CM33(s)" +echo "\t$_soc - $_num_ca57 CA57(s), $_num_ca55 CA55(s), $_num_ca53 CA53(s), \ + $_num_cr7 CR7(s), $_num_cm33 CM33(s)" echo "\tBoot Core - $_boot_core\n" set _DAPNAME $_CHIPNAME.dap # TAP and DAP -jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID \ - -ignore-version +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf \ + -expected-id $_DAP_TAPID -ignore-version dap create $_DAPNAME -chain-position $_CHIPNAME.cpu echo "$_CHIPNAME.cpu" @@ -133,8 +149,8 @@ set CA53_DBGBASE {0x80C10000 0x80D10000 0x80E10000 0x80F10000} set CA53_CTIBASE {0x80C20000 0x80D20000 0x80E20000 0x80F20000} set CR7_DBGBASE 0x80910000 set CR7_CTIBASE 0x80918000 -set CM33_DBGBASE 0xE000E000 -set CM33_CTIBASE 0xE0042000 +set CM33_DBGBASE {0xE000E000 0xE010E000} +set CM33_CTIBASE {0xE0042000 0xE0142000} set smp_targets "" @@ -145,7 +161,8 @@ proc setup_a5x {core_name dbgbase ctibase num boot} { cti create $_CTINAME -dap $::_DAPNAME -ap-num $::_ap_num \ -baseaddr [lindex $ctibase $_core] target create $_TARGETNAME aarch64 -dap $::_DAPNAME \ - -ap-num $::_ap_num -dbgbase [lindex $dbgbase $_core] -cti $_CTINAME + -ap-num $::_ap_num -dbgbase [lindex $dbgbase $_core] \ + -cti $_CTINAME if { $_core > 0 || $boot == 0 } { $_TARGETNAME configure -defer-examine } @@ -160,13 +177,29 @@ proc setup_cr7 {dbgbase ctibase} { target create $_TARGETNAME cortex_r4 -dap $::_DAPNAME \ -ap-num 1 -dbgbase $dbgbase -defer-examine } - -proc setup_cm33 {dbgbase ctibase} { - set _TARGETNAME $::_CHIPNAME.m33 - set _CTINAME $_TARGETNAME.cti - cti create $_CTINAME -dap $::_DAPNAME -ap-num 2 -baseaddr $ctibase - target create $_TARGETNAME cortex_m -dap $::_DAPNAME \ - -ap-num 2 -dbgbase $dbgbase -defer-examine +proc setup_cm33 {dbgbase ctibase num boot} { + if { $::_soc == "G2L" || $::_soc == "V2L" \ + || $::_soc == "G2LC" || $::_soc == "G2UL" } { + set _ap_num 2 + } elseif { $::_soc == "G3S" } { + set _ap_num 3 + } + for { set _core 0 } { $_core < $num } { incr _core } { + if { $num <= 1 } { + set _TARGETNAME $::_CHIPNAME.m33 + } else { + set _TARGETNAME $::_CHIPNAME.m33.$_core + } + set _CTINAME $_TARGETNAME.cti + cti create $_CTINAME -dap $::_DAPNAME -ap-num $_ap_num \ + -baseaddr [lindex $ctibase $_core] + target create $_TARGETNAME cortex_m -dap $::_DAPNAME \ + -ap-num $_ap_num -dbgbase [lindex $dbgbase $_core] + if { $boot == 0 } { + $_TARGETNAME configure -defer-examine + } + incr $_ap_num + } } # Organize target list based on the boot core @@ -180,12 +213,17 @@ if { $_boot_core == "CA57" } { setup_cr7 $CR7_DBGBASE $CR7_CTIBASE } elseif { $_boot_core == "CA55" } { setup_a5x a55 $CA55_DBGBASE $CA55_CTIBASE $_num_ca55 1 - setup_cm33 $CM33_DBGBASE $CM33_CTIBASE + setup_cm33 $CM33_DBGBASE $CM33_CTIBASE $_num_cm33 0 +} elseif { $_boot_core == "CM33" } { + setup_a5x a55 $CA55_DBGBASE $CA55_CTIBASE $_num_ca55 0 + setup_cm33 $CM33_DBGBASE $CM33_CTIBASE $_num_cm33 1 } + echo "SMP targets:$smp_targets" eval "target smp $smp_targets" -if { $_soc == "G2L" || $_soc == "G2LC" || $_soc == "G2UL" } { +if { $_soc == "G2L" || $_soc == "V2L" || $_soc == "G2LC" \ +|| $_soc == "G2UL" || $_soc == "G3S"} { target create $_CHIPNAME.axi_ap mem_ap -dap $_DAPNAME -ap-num 1 } From bcebc84882116c5c08c9243297a925262b1c3f0f Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Sat, 26 Oct 2024 10:30:18 +0800 Subject: [PATCH 1001/1312] contrib: convert 'unsigned' to 'unsigned int' Conversion done with checkpatch --fix-inplace -types UNSPECIFIED_INT Change-Id: I0e31f87d437fcf3503736474f10a63f9c6be242b Signed-off-by: Mark Zhuang Reviewed-on: https://review.openocd.org/c/openocd/+/8368 Reviewed-by: Antonio Borneo Tested-by: jenkins --- contrib/itmdump.c | 24 +++++++++++------------ contrib/loaders/flash/fespi/riscv_fespi.c | 20 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/contrib/itmdump.c b/contrib/itmdump.c index e7523d9bc2..7c93a3963f 100644 --- a/contrib/itmdump.c +++ b/contrib/itmdump.c @@ -43,9 +43,9 @@ unsigned int dump_swit; * NOTE that this specific encoding could be space-optimized; and that * trace data streams could also be history-sensitive. */ -static void show_task(int port, unsigned data) +static void show_task(int port, unsigned int data) { - unsigned code = data >> 16; + unsigned int code = data >> 16; char buf[16]; if (dump_swit) @@ -77,7 +77,7 @@ static void show_task(int port, unsigned data) static void show_reserved(FILE *f, char *label, int c) { - unsigned i; + unsigned int i; if (dump_swit) return; @@ -96,9 +96,9 @@ static void show_reserved(FILE *f, char *label, int c) printf("\n"); } -static bool read_varlen(FILE *f, int c, unsigned *value) +static bool read_varlen(FILE *f, int c, unsigned int *value) { - unsigned size; + unsigned int size; unsigned char buf[4]; *value = 0; @@ -135,8 +135,8 @@ static bool read_varlen(FILE *f, int c, unsigned *value) static void show_hard(FILE *f, int c) { - unsigned type = c >> 3; - unsigned value; + unsigned int type = c >> 3; + unsigned int value; char *label; if (dump_swit) @@ -230,16 +230,16 @@ static void show_hard(FILE *f, int c) */ struct { int port; - void (*show)(int port, unsigned data); + void (*show)(int port, unsigned int data); } format[] = { { .port = 31, .show = show_task, }, }; static void show_swit(FILE *f, int c) { - unsigned port = c >> 3; - unsigned value = 0; - unsigned i; + unsigned int port = c >> 3; + unsigned int value = 0; + unsigned int i; if (port + 1 == dump_swit) { if (!read_varlen(f, c, &value)) @@ -272,7 +272,7 @@ static void show_swit(FILE *f, int c) static void show_timestamp(FILE *f, int c) { - unsigned counter = 0; + unsigned int counter = 0; char *label = ""; bool delayed = false; diff --git a/contrib/loaders/flash/fespi/riscv_fespi.c b/contrib/loaders/flash/fespi/riscv_fespi.c index 17ae2fd22e..08fb09477f 100644 --- a/contrib/loaders/flash/fespi/riscv_fespi.c +++ b/contrib/loaders/flash/fespi/riscv_fespi.c @@ -103,7 +103,7 @@ static void fespi_disable_hw_mode(volatile uint32_t *ctrl_base); static void fespi_enable_hw_mode(volatile uint32_t *ctrl_base); static int fespi_wip(volatile uint32_t *ctrl_base); static int fespi_write_buffer(volatile uint32_t *ctrl_base, - const uint8_t *buffer, unsigned offset, unsigned len, + const uint8_t *buffer, unsigned int offset, unsigned int len, uint32_t flash_info); /* Can set bits 3:0 in result. */ @@ -113,7 +113,7 @@ static int fespi_write_buffer(volatile uint32_t *ctrl_base, * after pprog_cmd */ int flash_fespi(volatile uint32_t *ctrl_base, uint32_t page_size, - const uint8_t *buffer, unsigned offset, uint32_t count, + const uint8_t *buffer, unsigned int offset, uint32_t count, uint32_t flash_info) { int result; @@ -163,12 +163,12 @@ int flash_fespi(volatile uint32_t *ctrl_base, uint32_t page_size, return result; } -static uint32_t fespi_read_reg(volatile uint32_t *ctrl_base, unsigned address) +static uint32_t fespi_read_reg(volatile uint32_t *ctrl_base, unsigned int address) { return ctrl_base[address / 4]; } -static void fespi_write_reg(volatile uint32_t *ctrl_base, unsigned address, uint32_t value) +static void fespi_write_reg(volatile uint32_t *ctrl_base, unsigned int address, uint32_t value) { ctrl_base[address / 4] = value; } @@ -188,7 +188,7 @@ static void fespi_enable_hw_mode(volatile uint32_t *ctrl_base) /* Can set bits 7:4 in result. */ static int fespi_txwm_wait(volatile uint32_t *ctrl_base) { - unsigned timeout = TIMEOUT; + unsigned int timeout = TIMEOUT; while (timeout--) { uint32_t ip = fespi_read_reg(ctrl_base, FESPI_REG_IP); @@ -209,7 +209,7 @@ static void fespi_set_dir(volatile uint32_t *ctrl_base, bool dir) /* Can set bits 11:8 in result. */ static int fespi_tx(volatile uint32_t *ctrl_base, uint8_t in) { - unsigned timeout = TIMEOUT; + unsigned int timeout = TIMEOUT; while (timeout--) { uint32_t txfifo = fespi_read_reg(ctrl_base, FESPI_REG_TXFIFO); @@ -224,7 +224,7 @@ static int fespi_tx(volatile uint32_t *ctrl_base, uint8_t in) /* Can set bits 15:12 in result. */ static int fespi_rx(volatile uint32_t *ctrl_base, uint8_t *out) { - unsigned timeout = TIMEOUT; + unsigned int timeout = TIMEOUT; while (timeout--) { uint32_t value = fespi_read_reg(ctrl_base, FESPI_REG_RXFIFO); @@ -252,7 +252,7 @@ static int fespi_wip(volatile uint32_t *ctrl_base) if (result != ERROR_OK) return result | ERROR_STACK(0x20000); - unsigned timeout = TIMEOUT; + unsigned int timeout = TIMEOUT; while (timeout--) { result = fespi_tx(ctrl_base, 0); if (result != ERROR_OK) @@ -273,7 +273,7 @@ static int fespi_wip(volatile uint32_t *ctrl_base) /* Can set bits 23:20 in result. */ static int fespi_write_buffer(volatile uint32_t *ctrl_base, - const uint8_t *buffer, unsigned offset, unsigned len, + const uint8_t *buffer, unsigned int offset, unsigned int len, uint32_t flash_info) { int result = fespi_tx(ctrl_base, SPIFLASH_WRITE_ENABLE); @@ -304,7 +304,7 @@ static int fespi_write_buffer(volatile uint32_t *ctrl_base, if (result != ERROR_OK) return result | ERROR_STACK(0x600000); - for (unsigned i = 0; i < len; i++) { + for (unsigned int i = 0; i < len; i++) { result = fespi_tx(ctrl_base, buffer[i]); if (result != ERROR_OK) return result | ERROR_STACK(0x700000); From b68d23da3c3bc67cffc750fddd64a6be9c615fdb Mon Sep 17 00:00:00 2001 From: Marek Kraus Date: Wed, 23 Oct 2024 16:27:33 +0200 Subject: [PATCH 1002/1312] tcl/target/bl702: implement full software reset In previous implementation, it was known that it does not perform full reset, and that some peripherals, such as GLB core, which handles among other stuff GPIOs, was not reset. It was presumed, that full reset by software is not possible, although, by accident, even when comment says that CTRL_PWRON_RESET is set to 1, it is not (value written into 0x40000018 supposed to be 0x7, not 0x6). CTRL_PWRON_RESET indeed triggers full "power-on like" reset, so this method is implemented in this commit. There are some workarounds to make reset seamless, without any error messages, which are described in comments of TCL script. Only down-side of this reset is, that chip is halted after reset bit later in BootROM than previous implementation, but it's still good. Change-Id: Ife2cdcc6a2d96a2e24039bfec149705baf046318 Signed-off-by: Marek Kraus Reviewed-on: https://review.openocd.org/c/openocd/+/8529 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/bl702.cfg | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tcl/target/bl702.cfg b/tcl/target/bl702.cfg index 6d4a048d90..5046cd189a 100644 --- a/tcl/target/bl702.cfg +++ b/tcl/target/bl702.cfg @@ -34,6 +34,10 @@ $_TARGETNAME configure -work-area-phys 0x22020000 -work-area-size 0x10000 -work- # Internal RC ticks on 32 MHz, so this speed should be safe to use. adapter speed 4000 +# Debug Module's ndmreset resets only Trust Zone Controller, so we need to do SW reset instead. +# CTRL_PWRON_RESET triggers full "power-on like" reset. +# This means that pinmux configuration to access JTAG is reset as well, and configured back early +# in BootROM. $_TARGETNAME configure -event reset-assert-pre { halt @@ -55,6 +59,15 @@ $_TARGETNAME configure -event reset-assert-pre { # Do reset # In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET mmw 0x40000018 0x0 0x00000007 + + # Since this full software reset resets GPIO pinmux as well, we will lose access + # to JTAG right away after writing to register. This chip doesn't support abstract + # memory access, so when this is done by progbuf or sysbus, OpenOCD will fail to read + # if write was successful or not, and will print error about that. Since receiving of + # this error is expected, we will turn off log printing for a moment, + set lvl [lindex [debug_level] 1] + debug_level -1 # In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1 - mmw 0x40000018 0x6 0x0 + catch {mmw 0x40000018 0x7 0x0} + debug_level $lvl } From fd62626dff25cf503a25040d3040b0a2bb9b2a76 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Mon, 16 Sep 2024 18:01:17 +0300 Subject: [PATCH 1003/1312] target/breakpoints: fix types in `watchpoint_add_internal()` There was a conflict: 1. commit 2cd8ebf44d1a ("breakpoints: use 64-bit type for watchpoint mask and value") 2. commit 0bf3373e808a ("target/breakpoints: Use 'unsigned int' for length") The second commit was created erlier, but merged later so the types of `mask` and `value` became `uint32_t` in `watchpoint_add_internal()`. This created a bug: `WATCHPOINT_IGNORE_DATA_VALUE_MASK` is defined as `(~(uint64_t)0)`. Truncation to uint32_t makes it so the comparisons with the constant don't work. Change-Id: I19c414c351f52aff72a60330d83c29db7bbca375 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8500 Reviewed-by: Antonio Borneo Reviewed-by: Jan Matyas Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Karl Palsson --- src/target/breakpoints.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 2fbb69e07a..9378abcb14 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -500,7 +500,7 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) } static int watchpoint_add_internal(struct target *target, target_addr_t address, - unsigned int length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) + unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; From d4a64e3f38a9ad7a27554547c2720f17ed3580a3 Mon Sep 17 00:00:00 2001 From: Jan Matyas Date: Thu, 10 Oct 2024 20:35:19 +0200 Subject: [PATCH 1004/1312] autoconf: Add support for code coverage Add support for code coverage collection. This helps developers to check if their test scenarios really exercised all the OpenOCD functionality that they intended to test. - Option --enable-gcov has been added to configure.ac which enables the coverage collection using Gcov. (Disabled by default.) - The steps to collect and inspect the coverage have been described in HACKING file. Change-Id: I259e401937a255e7ad7f155359a0b7787e4d0752 Signed-off-by: Jan Matyas Reviewed-on: https://review.openocd.org/c/openocd/+/8521 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov Reviewed-by: Antonio Borneo --- .gitignore | 4 ++++ HACKING | 16 ++++++++++++++++ Makefile.am | 7 +++++++ configure.ac | 21 ++++++++++++++++++++- src/openocd.c | 7 +++++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5de33077e3..1b4e08ba3c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,10 @@ src/jtag/minidriver_imp.h src/jtag/jtag_minidriver.h +# coverage files (gcov) +*.gcda +*.gcno + # OpenULINK driver files generated by SDCC src/jtag/drivers/OpenULINK/*.rel src/jtag/drivers/OpenULINK/*.asm diff --git a/HACKING b/HACKING index 9e8cd357ff..8988b1617d 100644 --- a/HACKING +++ b/HACKING @@ -92,6 +92,22 @@ patch: make @endcode +- Code coverage analysis + + By inspecting the code coverage, you can identify potential gaps in your testing + and use that information to improve your test scenarios. + + Example usage: + @code + mkdir build-gcov; cd build-gcov + ../configure --enable-gcov [...] + make + # ... Now execute your test scenarios to collect OpenOCD code coverage ... + lcov --capture --directory ./src --output-file openocd-coverage.info + genhtml openocd-coverage.info --output-directory coverage_report + # ... Open coverage_report/index.html in a web browser ... + @endcode + Please consider performing these additional checks where appropriate (especially Clang Static Analyzer for big portions of new code) and mention the results (e.g. "Valgrind-clean, no new Clang analyzer diff --git a/Makefile.am b/Makefile.am index 2230e628f8..ab0a2373d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,6 +38,7 @@ endif # common flags used in openocd build AM_CFLAGS = $(GCC_WARNINGS) +AM_LDFLAGS = AM_CPPFLAGS = $(HOST_CPPFLAGS)\ -I$(top_srcdir)/src \ @@ -51,6 +52,12 @@ AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \ else AM_CPPFLAGS += $(JIMTCL_CFLAGS) endif + +if USE_GCOV +AM_CFLAGS += --coverage +AM_LDFLAGS += --coverage +endif + EXTRA_DIST += \ BUGS \ HACKING \ diff --git a/configure.ac b/configure.ac index 9355ffb932..291e854a42 100644 --- a/configure.ac +++ b/configure.ac @@ -171,6 +171,9 @@ m4_define([DUMMY_ADAPTER], m4_define([OPTIONAL_LIBRARIES], [[[capstone], [Use Capstone disassembly framework], []]]) +m4_define([COVERAGE], + [[[gcov], [Collect coverage using gcov], []]]) + AC_ARG_ENABLE([doxygen-html], AS_HELP_STRING([--disable-doxygen-html], [Disable building Doxygen manual as HTML.]), @@ -199,6 +202,19 @@ AC_ARG_ENABLE([werror], AS_HELP_STRING([--disable-werror], [Do not treat warnings as errors]), [gcc_werror=$enableval], [gcc_werror=$gcc_warnings]) +AC_ARG_ENABLE([gcov], + AS_HELP_STRING([--enable-gcov], [Enable runtime coverage collection via gcov]), + [enable_gcov=$enableval], [enable_gcov=no]) + +AS_IF([test "x$enable_gcov" = "xyes"], [ + AC_DEFINE([USE_GCOV], [1], [1 to enable coverage collection using gcov.]) + dnl When collecting coverage, disable optimizations. + dnl This overrides the "-O2" that autoconf uses by default: + CFLAGS+=" -O0" +], [ + AC_DEFINE([USE_GCOV], [0], [0 to leave coverage collection disabled.]) +]) + # set default verbose options, overridden by following options debug_usb_io=no debug_usb_comms=no @@ -787,6 +803,8 @@ AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"]) AM_CONDITIONAL([HAVE_JIMTCL_PKG_CONFIG], [test "x$have_jimtcl_pkg_config" = "xyes"]) AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"]) +AM_CONDITIONAL([USE_GCOV], [test "x$enable_gcov" = "xyes"]) + # Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h? AC_MSG_CHECKING([for environ in unistd.h and stdlib.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -862,7 +880,8 @@ m4_foreach([adapter], [USB1_ADAPTERS, LIBGPIOD_ADAPTERS, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, DUMMY_ADAPTER, - OPTIONAL_LIBRARIES], + OPTIONAL_LIBRARIES, + COVERAGE], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) AS_CASE([$ADAPTER_VAR([adapter])], [auto], [ diff --git a/src/openocd.c b/src/openocd.c index 7a51470502..9fd709e323 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -375,6 +375,13 @@ int openocd_main(int argc, char *argv[]) log_exit(); +#if USE_GCOV + /* Always explicitly dump coverage data before terminating. + * Otherwise coverage would not be dumped when exit_on_signal occurs. */ + void __gcov_dump(void); + __gcov_dump(); +#endif + if (ret == ERROR_FAIL) return EXIT_FAILURE; else if (ret != ERROR_OK) From 564b24e7f899f401ec6e5adda7906244f60c0135 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Fri, 1 Nov 2024 20:21:56 +0100 Subject: [PATCH 1005/1312] Makefile.am: generate ChangeLog with git log instead of git2cl git log is faster than git2cl and the result has a better format. Change-Id: I465ca62e3e30fed230fe9661e82a987980c05459 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8531 Tested-by: jenkins Reviewed-by: R. Diez Reviewed-by: Antonio Borneo --- .gitmodules | 3 --- Makefile.am | 11 +++++------ tools/git2cl | 1 - 3 files changed, 5 insertions(+), 10 deletions(-) delete mode 160000 tools/git2cl diff --git a/.gitmodules b/.gitmodules index f2da17ed7a..abb7735382 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "tools/git2cl"] - path = tools/git2cl - url = https://git.savannah.nongnu.org/git/git2cl.git [submodule "jimtcl"] path = jimtcl url = https://github.com/msteveb/jimtcl.git diff --git a/Makefile.am b/Makefile.am index ab0a2373d5..155a2b3bb7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -123,14 +123,13 @@ TCL_PATH = tcl TCL_FILES = find $(srcdir)/$(TCL_PATH) -name '*.cfg' -o -name '*.tcl' -o -name '*.txt' | \ sed -e 's,^$(srcdir)/$(TCL_PATH),,' -# Without the PERL_UNICODE="IO" workaround below when running git2cl, you get several -# "Wide character" warnings and you also risk an invalid character encoding in -# the generated ChangeLog file. For more information, see this bug report: -# Warning "Wide character in print" -# https://savannah.nongnu.org/bugs/?65689 +# The git log command below generates many empty text lines with only some space characters +# for indentation purposes, so use sed to trim all trailing whitespace. dist-hook: if test -d $(srcdir)/.git -a \( ! -e $(distdir)/ChangeLog -o -w $(distdir)/ChangeLog \) ; then \ - git --git-dir $(srcdir)/.git log | PERL_UNICODE="IO" $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \ + git --git-dir $(srcdir)/.git log --date=short --pretty="format:%ad %aN <%aE>%n%n%w(0,4,6)* %B" \ + | sed 's/[[:space:]]*$$//' > $(distdir)/ChangeLog.tmp && \ + mv $(distdir)/ChangeLog.tmp $(distdir)/ChangeLog; \ fi for i in $$($(TCL_FILES)); do \ j="$(distdir)/$(TCL_PATH)/$$i" && \ diff --git a/tools/git2cl b/tools/git2cl deleted file mode 160000 index 8373c9f749..0000000000 --- a/tools/git2cl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8373c9f74993e218a08819cbcdbab3f3564bbeba From 6d60ac5c08e6343008f40ee3d8daa5e8e00eb148 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Fri, 1 Nov 2024 09:46:05 +0100 Subject: [PATCH 1006/1312] Make bootstrap more robust Change-Id: I67cc22752b34dd49c277e247f0b648047927a02b Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8532 Reviewed-by: R. Diez Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Antonio Borneo --- bootstrap | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/bootstrap b/bootstrap index 7d4ca37bd8..9dfdc41aca 100755 --- a/bootstrap +++ b/bootstrap @@ -3,8 +3,8 @@ # Run the autotools bootstrap sequence to create the configure script -# Abort execution on error -set -e +set -e # Abort execution on error. +set -u # Abort if you reference an undefined variable. if which libtoolize > /dev/null; then libtoolize="libtoolize" @@ -15,13 +15,21 @@ else exit 1 fi -if [ "$1" = "nosubmodule" ]; then - SKIP_SUBMODULE=1 -elif [ -n "$1" ]; then - echo "$0: Illegal argument $1" - echo "USAGE: $0 [nosubmodule]" - exit 1 -fi +SKIP_SUBMODULE=0 + +case "$#" in + 0) ;; + 1) if [ "$1" = "nosubmodule" ]; then + SKIP_SUBMODULE=1 + else + echo "$0: Illegal argument $1" >&2 + echo "USAGE: $0 [nosubmodule]" >&2 + exit 1 + fi;; + *) echo "$0: Wrong number of command-line arguments." >&2 + echo "USAGE: $0 [nosubmodule]" >&2 + exit 1;; +esac # bootstrap the autotools ( @@ -34,7 +42,7 @@ autoheader --warnings=all automake --warnings=all --gnu --add-missing --copy ) -if [ -n "$SKIP_SUBMODULE" ]; then +if [ "$SKIP_SUBMODULE" -ne 0 ]; then echo "Skipping submodule setup" else echo "Setting up submodules" From 8a3723022689dd078c3e61268615616d5566fc94 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 10 Apr 2023 12:02:55 +0200 Subject: [PATCH 1007/1312] checkpatch: exclude gerrit's Change-Id line from commit description Checkpatch rejects patches that have empty commit description and logs them with: WARNING:COMMIT_MESSAGE: Missing commit description - Add an appropriate one But if the patch has a gerrit's Change-Id line placed before the line Signed-off-by, then checkpatch considers the Change-Id line as a valid commit description text. Use the Change-Id tag as a marker of the end of the commit message, thus not counting its line as part of the commit description. This patch is not relevant for the Linux kernel development process as gerrit is not involved and the Change-Id tag is rejected. But other projects, like OpenOCD, base the development on gerrit and reuse kernel's checkpatch with flag '--ignore GERRIT_CHANGE_ID'. This patch has been refused [1] in Linux upstream because it has not been considered relevant for that project. Let's take it as another add-on in OpenOCD checkpatch. Change-Id: I3b55b8fffa07ce67177c108e7c9554ca46674246 Signed-off-by: Antonio Borneo Link: [1] https://lore.kernel.org/lkml/20230410100255.16755-1-borneo.antonio@gmail.com/ Reviewed-on: https://review.openocd.org/c/openocd/+/8539 Tested-by: jenkins --- tools/scripts/checkpatch.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl index 01bd547ff5..1011b33055 100755 --- a/tools/scripts/checkpatch.pl +++ b/tools/scripts/checkpatch.pl @@ -3251,6 +3251,9 @@ sub process { # Check for Gerrit Change-Ids not in any patch context if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) { + # OpenOCD specific: Begin: exclude gerrit's Change-Id line from commit description + $in_commit_log = 0; + # OpenOCD specific: End if (ERROR("GERRIT_CHANGE_ID", "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr) && $fix) { From 989e9e8b5488be6dbf4ed2e9f5cbda208b841860 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 11 Oct 2024 10:10:12 +0200 Subject: [PATCH 1008/1312] gitignore: drop ignoring files not generated anymore With the drop of the code for the probe zy1000 [1] and then the drop of minidriver code [2], there are no more auto-generated source files. Remove them from the list of generated files to be ignored. Change-Id: Iee65e21528674ea4cc94018e52126f882da4f07c Signed-off-by: Antonio Borneo [1] b0fe92dba7c0 ("zy1000: drop the code, deprecated in v0.10.0") [2] 25218e893503 ("jtag: remove minidriver code and minidriver-dummy") Reviewed-on: https://review.openocd.org/c/openocd/+/8522 Tested-by: jenkins --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index 1b4e08ba3c..f0746c1950 100644 --- a/.gitignore +++ b/.gitignore @@ -11,10 +11,6 @@ *.la *.in -# generated source files -src/jtag/minidriver_imp.h -src/jtag/jtag_minidriver.h - # coverage files (gcov) *.gcda *.gcno From 2465f1851549e16337e0eef84e581b62d541a187 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 18:49:11 +0100 Subject: [PATCH 1009/1312] adapter: make adapter_config_khz() static The function is not referenced outside the file. Make it static. Change-Id: I72e96624749ae4cc7f4566d737a88186e899616a Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8541 Tested-by: jenkins --- src/jtag/adapter.c | 5 ++++- src/jtag/adapter.h | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 996a23f1ff..04942f753b 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -66,6 +66,8 @@ static const struct gpio_map { [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, }; +static int adapter_config_khz(unsigned int khz); + bool is_adapter_initialized(void) { return adapter_config.adapter_initialized; @@ -245,7 +247,8 @@ static int adapter_set_speed(int speed) return is_adapter_initialized() ? adapter_driver->speed(speed) : ERROR_OK; } -int adapter_config_khz(unsigned int khz) +/** Attempt to configure the adapter for the specified kHz. */ +static int adapter_config_khz(unsigned int khz) { LOG_DEBUG("handle adapter khz"); adapter_config.clock_mode = CLOCK_MODE_KHZ; diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h index 23ffe2cc51..556952f8d7 100644 --- a/src/jtag/adapter.h +++ b/src/jtag/adapter.h @@ -97,9 +97,6 @@ int adapter_get_speed(int *speed); */ int adapter_get_speed_readable(int *speed); -/** Attempt to configure the adapter for the specified kHz. */ -int adapter_config_khz(unsigned int khz); - /** * Attempt to enable RTCK/RCLK. If that fails, fallback to the * specified frequency. From f82664ff827ba76f773c51b74705c13b9c813758 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:29:43 +0100 Subject: [PATCH 1010/1312] jtag: core: make local functions static The functions: - jtag_error_clear(); - jtag_tap_count(); are not referenced outside the file. Make them static. Change-Id: I00fcf06b1838b9f6c955c19772f1d41d486459e9 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8542 Tested-by: jenkins --- src/jtag/core.c | 10 ++++++++-- src/jtag/jtag.h | 6 ------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index 907883f099..769e07571f 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -51,6 +51,8 @@ static void jtag_add_scan_check(struct jtag_tap *active, tap_state_t state), int in_num_fields, struct scan_field *in_fields, tap_state_t state); +static int jtag_error_clear(void); + /** * The jtag_error variable is set when an error occurs while executing * the queue. Application code may set this using jtag_set_error(), @@ -127,7 +129,11 @@ void jtag_set_error(int error) jtag_error = error; } -int jtag_error_clear(void) +/** + * Resets jtag_error to ERROR_OK, returning its previous value. + * @returns The previous value of @c jtag_error. + */ +static int jtag_error_clear(void) { int temp = jtag_error; jtag_error = ERROR_OK; @@ -186,7 +192,7 @@ struct jtag_tap *jtag_all_taps(void) return __jtag_all_taps; }; -unsigned int jtag_tap_count(void) +static unsigned int jtag_tap_count(void) { struct jtag_tap *t = jtag_all_taps(); unsigned int n = 0; diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index b9d37b32ae..86526a09a1 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -153,7 +153,6 @@ struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj); struct jtag_tap *jtag_tap_by_position(unsigned int abs_position); struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p); unsigned int jtag_tap_count_enabled(void); -unsigned int jtag_tap_count(void); /* * - TRST_ASSERTED triggers two sets of callbacks, after operations to @@ -568,11 +567,6 @@ void jtag_sleep(uint32_t us); * called with a non-zero error code. */ void jtag_set_error(int error); -/** - * Resets jtag_error to ERROR_OK, returning its previous value. - * @returns The previous value of @c jtag_error. - */ -int jtag_error_clear(void); /** * Return true if it's safe for a background polling task to access the From f4ac0c7022933adcbc68140ca565e93ece726ab5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:39:11 +0100 Subject: [PATCH 1011/1312] jtag: driver: make local functions static The functions: - interface_jtag_add_callback(); - interface_jtag_add_callback4(); are not referenced outside the file. Make them static. Change-Id: I84f738309d23c8d0b5329aa04436db750cf185e5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8543 Tested-by: jenkins --- src/jtag/drivers/driver.c | 4 ++-- src/jtag/drivers/minidriver_imp.h | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index d52a345a0a..58e59a559f 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -341,7 +341,7 @@ int interface_jtag_add_sleep(uint32_t us) } /* add callback to end of queue */ -void interface_jtag_add_callback4(jtag_callback_t callback, +static void interface_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { @@ -395,7 +395,7 @@ static int jtag_convert_to_callback4(jtag_callback_data_t data0, return ERROR_OK; } -void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) +static void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) { jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0); } diff --git a/src/jtag/drivers/minidriver_imp.h b/src/jtag/drivers/minidriver_imp.h index b29b3c9cca..f3582f6e34 100644 --- a/src/jtag/drivers/minidriver_imp.h +++ b/src/jtag/drivers/minidriver_imp.h @@ -17,12 +17,6 @@ static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field) field->in_value = cmd_queue_alloc(num_bytes); } -void interface_jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0); - -void interface_jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, - jtag_callback_data_t data1, jtag_callback_data_t data2, - jtag_callback_data_t data3); - void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3); From 644742b4b218eefd855dc636ccea25b769e80315 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:33:58 +0100 Subject: [PATCH 1012/1312] driver: mpsse: make local functions static The functions: - mpsse_divide_by_5_config(); - mpsse_purge(); - mpsse_rtck_config(); - mpsse_set_divisor(); are not referenced outside the file. Make them static. Change-Id: Id6930183a3ce26693b2113f622046168ba289df8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8544 Tested-by: jenkins --- src/jtag/drivers/mpsse.c | 10 ++++++---- src/jtag/drivers/mpsse.h | 4 ---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 1ef9550a08..38393ad0ae 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -75,6 +75,8 @@ struct mpsse_ctx { int retval; }; +static void mpsse_purge(struct mpsse_ctx *ctx); + /* Returns true if the string descriptor indexed by str_index in device matches string */ static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index, const char *string) @@ -421,7 +423,7 @@ bool mpsse_is_high_speed(struct mpsse_ctx *ctx) return ctx->type != TYPE_FT2232C; } -void mpsse_purge(struct mpsse_ctx *ctx) +static void mpsse_purge(struct mpsse_ctx *ctx) { int err; LOG_DEBUG("-"); @@ -709,7 +711,7 @@ void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable) single_byte_boolean_helper(ctx, enable, 0x84, 0x85); } -void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) +static void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) { LOG_DEBUG("%d", divisor); @@ -726,7 +728,7 @@ void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) buffer_write_byte(ctx, divisor >> 8); } -int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) +static int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) { if (!mpsse_is_high_speed(ctx)) return ERROR_FAIL; @@ -737,7 +739,7 @@ int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) return ERROR_OK; } -int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable) +static int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable) { if (!mpsse_is_high_speed(ctx)) return ERROR_FAIL; diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index 4a625d890b..e95f842c9b 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -59,9 +59,6 @@ void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data); void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data); void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable); -void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor); -int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable); -int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable); /* Helper to set frequency in Hertz. Returns actual realizable frequency or negative error. * Frequency 0 means RTCK. */ @@ -69,6 +66,5 @@ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency); /* Queue handling */ int mpsse_flush(struct mpsse_ctx *ctx); -void mpsse_purge(struct mpsse_ctx *ctx); #endif /* OPENOCD_JTAG_DRIVERS_MPSSE_H */ From 4da8f6d27a076a4a64c0d334cb647fdde08938a1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 18:51:52 +0100 Subject: [PATCH 1013/1312] rtt: drop unused function rtt_started() The function is not used. Drop it! Change-Id: I176c9d6ba077e36b762c14f9b877d5152992763c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8545 Tested-by: jenkins Reviewed-by: zapb --- src/rtt/rtt.c | 5 ----- src/rtt/rtt.h | 7 ------- 2 files changed, 12 deletions(-) diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c index e31e75410d..42c3ee3ad4 100644 --- a/src/rtt/rtt.c +++ b/src/rtt/rtt.c @@ -297,11 +297,6 @@ int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer, length, NULL); } -bool rtt_started(void) -{ - return rtt.started; -} - bool rtt_configured(void) { return rtt.configured; diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h index a5630a9515..49409074c4 100644 --- a/src/rtt/rtt.h +++ b/src/rtt/rtt.h @@ -194,13 +194,6 @@ int rtt_get_polling_interval(unsigned int *interval); */ int rtt_set_polling_interval(unsigned int interval); -/** - * Get whether RTT is started. - * - * @returns Whether RTT is started. - */ -bool rtt_started(void); - /** * Get whether RTT is configured. * From a34d4b8cb41d99a55ae4dd4ee9f13478a34337a7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 18:54:14 +0100 Subject: [PATCH 1014/1312] pld: make get_pld_device_by_num() static The function is not referenced outside the file. Make it static. Change-Id: I5f2a2c70085b9158df8806432bb9ed09bb256ab5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8546 Tested-by: jenkins --- src/pld/pld.c | 2 +- src/pld/pld.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pld/pld.c b/src/pld/pld.c index 81fb0c4632..edd7796139 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -28,7 +28,7 @@ static struct pld_driver *pld_drivers[] = { static struct pld_device *pld_devices; -struct pld_device *get_pld_device_by_num(int num) +static struct pld_device *get_pld_device_by_num(int num) { struct pld_device *p; int i = 0; diff --git a/src/pld/pld.h b/src/pld/pld.h index 5e2fcd20cc..a6e2e0fc8d 100644 --- a/src/pld/pld.h +++ b/src/pld/pld.h @@ -54,7 +54,6 @@ struct pld_device { int pld_register_commands(struct command_context *cmd_ctx); -struct pld_device *get_pld_device_by_num(int num); struct pld_device *get_pld_device_by_name(const char *name); struct pld_device *get_pld_device_by_name_or_numstr(const char *str); From f3aeb3d67619510a2601e2a1055479b84a47fbf3 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:06:29 +0100 Subject: [PATCH 1015/1312] target: dsp563xx: make dsp563xx_once_reg_read_ex() static The function is not referenced outside the file. Make it static. Change-Id: Ifeccc5e38f3da4b4111422860bc1c1447d00f7fe Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8547 Tested-by: jenkins --- src/target/dsp563xx_once.c | 4 +++- src/target/dsp563xx_once.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/dsp563xx_once.c b/src/target/dsp563xx_once.c index 866f33152d..bb41ae8c7c 100644 --- a/src/target/dsp563xx_once.c +++ b/src/target/dsp563xx_once.c @@ -34,6 +34,8 @@ #define JTAG_INSTR_DEBUG_REQUEST 0x07 #define JTAG_INSTR_BYPASS 0x0F +static int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data); + /** */ static inline int dsp563xx_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti) { @@ -185,7 +187,7 @@ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg } /** once read register with register len */ -int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data) +static int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data) { int err; diff --git a/src/target/dsp563xx_once.h b/src/target/dsp563xx_once.h index 8715488374..4f27e1db78 100644 --- a/src/target/dsp563xx_once.h +++ b/src/target/dsp563xx_once.h @@ -65,8 +65,6 @@ int dsp563xx_once_target_status(struct jtag_tap *tap); /** once read registers */ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len); /** once read register */ -int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data); -/** once read register */ int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t *data); /** once write register */ int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data); From c5babec7949d3fc23fd3fe43d5452897b7c94553 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:08:25 +0100 Subject: [PATCH 1016/1312] target: x86_32: make x86_32_common_read_io() static The function is not referenced outside the file. Make it static. Change-Id: Ic2552c040b6b46c0334851a4fc0fdaa400e11e4c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8548 Tested-by: jenkins --- src/target/x86_32_common.c | 2 +- src/target/x86_32_common.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index 2c60b9f7e0..8cca9a5e91 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -677,7 +677,7 @@ int x86_32_common_write_memory(struct target *t, target_addr_t addr, return retval; } -int x86_32_common_read_io(struct target *t, uint32_t addr, +static int x86_32_common_read_io(struct target *t, uint32_t addr, uint32_t size, uint8_t *buf) { struct x86_32_common *x86_32 = target_to_x86_32(t); diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index 7392447a68..e232747697 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -309,8 +309,6 @@ int x86_32_common_read_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buf); int x86_32_common_write_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buf); -int x86_32_common_read_io(struct target *t, uint32_t addr, - uint32_t size, uint8_t *buf); int x86_32_common_write_io(struct target *t, uint32_t addr, uint32_t size, const uint8_t *buf); int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp); From df42faf51d20d879beefacbd88b11271bcee181a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:12:46 +0100 Subject: [PATCH 1017/1312] target: aarch64: drop unused armv8_mmu_translate_va() The function is not used. Drop it! Change-Id: I1625e03714b5a842f668098191c39cce34f815e8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8549 Tested-by: jenkins --- src/target/armv8.c | 6 ------ src/target/armv8.h | 1 - 2 files changed, 7 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 61d72741a9..88534d9626 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1021,12 +1021,6 @@ static __attribute__((unused)) void armv8_show_fault_registers(struct target *ta armv8_show_fault_registers32(armv8); } -/* method adapted to cortex A : reused arm v4 v5 method*/ -int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val) -{ - return ERROR_OK; -} - static void armv8_decode_cacheability(int attr) { if (attr == 0) { diff --git a/src/target/armv8.h b/src/target/armv8.h index 349c8f002c..49ab3e5cb7 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -298,7 +298,6 @@ int armv8_identify_cache(struct armv8_common *armv8); int armv8_init_arch_info(struct target *target, struct armv8_common *armv8); int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, target_addr_t *val, int meminfo); -int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val); int armv8_handle_cache_info_command(struct command_invocation *cmd, struct armv8_cache_common *armv8_cache); From b04a58e3fcbfd9a701126473279fa17d37f23784 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:46:03 +0100 Subject: [PATCH 1018/1312] target: esirisc: make local functions static The function esirisc_jtag_get_eid() is not used outside the file. Make it static. The function esirisc_jtag_disable_debug() is never used. Make it static and mark it as unused. Change-Id: I5c99cbf77cc9c527b6e18a3f67caa24f8551d09c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8550 Tested-by: jenkins --- src/target/esirisc_jtag.c | 6 ++++-- src/target/esirisc_jtag.h | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/esirisc_jtag.c b/src/target/esirisc_jtag.c index 5960e26cb4..ad2bef543e 100644 --- a/src/target/esirisc_jtag.c +++ b/src/target/esirisc_jtag.c @@ -19,6 +19,8 @@ #include "esirisc_jtag.h" +static uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info); + static void esirisc_jtag_set_instr(struct esirisc_jtag *jtag_info, uint32_t new_instr) { struct jtag_tap *tap = jtag_info->tap; @@ -221,7 +223,7 @@ bool esirisc_jtag_is_stopped(struct esirisc_jtag *jtag_info) return !!(jtag_info->status & 1<<6); /* S */ } -uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info) +static uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info) { return jtag_info->status & 0x3f; /* EID */ } @@ -490,7 +492,7 @@ int esirisc_jtag_enable_debug(struct esirisc_jtag *jtag_info) return esirisc_jtag_send_ctrl(jtag_info, DEBUG_ENABLE_DEBUG); } -int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info) +static __attribute__((unused)) int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info) { return esirisc_jtag_send_ctrl(jtag_info, DEBUG_DISABLE_DEBUG); } diff --git a/src/target/esirisc_jtag.h b/src/target/esirisc_jtag.h index 98ec8af8d6..d59b75fbee 100644 --- a/src/target/esirisc_jtag.h +++ b/src/target/esirisc_jtag.h @@ -54,7 +54,6 @@ struct esirisc_jtag { bool esirisc_jtag_is_debug_active(struct esirisc_jtag *jtag_info); bool esirisc_jtag_is_stopped(struct esirisc_jtag *jtag_info); -uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info); int esirisc_jtag_read_byte(struct esirisc_jtag *jtag_info, uint32_t address, uint8_t *data); @@ -81,7 +80,6 @@ int esirisc_jtag_write_csr(struct esirisc_jtag *jtag_info, uint8_t bank, uint8_t csr, uint32_t data); int esirisc_jtag_enable_debug(struct esirisc_jtag *jtag_info); -int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info); int esirisc_jtag_assert_reset(struct esirisc_jtag *jtag_info); int esirisc_jtag_deassert_reset(struct esirisc_jtag *jtag_info); From 61fbcbeca83452f3a035f3f4982703096fb5d8ef Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 9 Nov 2024 19:21:30 +0100 Subject: [PATCH 1019/1312] semihosting: make local functions static The functions: - semihosting_opcode_to_str(); - semihosting_write_fields(); - semihosting_set_field(); are not referenced outside the file. Make them static. Change-Id: Ia8d35554673145fdfe0e501543eb18919863039f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8551 Tested-by: jenkins --- src/target/semihosting_common.c | 16 ++++++++++------ src/target/semihosting_common.h | 12 ------------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index 1eb195712e..ffcd3aafde 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -92,6 +92,8 @@ static int semihosting_common_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); static int semihosting_common_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c); +static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields); +static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields); /** * Initialize common semihosting support. @@ -298,7 +300,12 @@ static inline int semihosting_getchar(struct semihosting *semihosting, int fd) */ static char *semihosting_user_op_params; -const char *semihosting_opcode_to_str(const uint64_t opcode) +/** + * @brief Convert the syscall opcode to a human-readable string + * @param[in] opcode Syscall opcode + * @return String representation of syscall opcode + */ +static const char *semihosting_opcode_to_str(const uint64_t opcode) { switch (opcode) { case SEMIHOSTING_SYS_CLOSE: @@ -1729,8 +1736,7 @@ int semihosting_read_fields(struct target *target, size_t number, /** * Write all fields of a command from buffer to target. */ -int semihosting_write_fields(struct target *target, size_t number, - uint8_t *fields) +static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; /* Use 4-byte multiples to trigger fast memory access. */ @@ -1754,9 +1760,7 @@ uint64_t semihosting_get_field(struct target *target, size_t index, /** * Store a field in the buffer, considering register size and endianness. */ -void semihosting_set_field(struct target *target, uint64_t value, - size_t index, - uint8_t *fields) +static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; if (semihosting->word_size_bytes == 8) diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index a1848b4881..1821ca4e2e 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -188,13 +188,6 @@ struct semihosting { int (*post_result)(struct target *target); }; -/** - * @brief Convert the syscall opcode to a human-readable string - * @param[in] opcode Syscall opcode - * @return String representation of syscall opcode - */ -const char *semihosting_opcode_to_str(uint64_t opcode); - int semihosting_common_init(struct target *target, void *setup, void *post_result); int semihosting_common(struct target *target); @@ -202,13 +195,8 @@ int semihosting_common(struct target *target); /* utility functions which may also be used by semihosting extensions (custom vendor-defined syscalls) */ int semihosting_read_fields(struct target *target, size_t number, uint8_t *fields); -int semihosting_write_fields(struct target *target, size_t number, - uint8_t *fields); uint64_t semihosting_get_field(struct target *target, size_t index, uint8_t *fields); -void semihosting_set_field(struct target *target, uint64_t value, - size_t index, - uint8_t *fields); extern const struct command_registration semihosting_common_handlers[]; From 8c739a45a042cf7a9b5bba48f0e20cbc3168ee73 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 21 Oct 2024 10:39:28 +0200 Subject: [PATCH 1020/1312] helper/jim-nvp.h: Rework 'isconfigure' variable Change the variable name to 'is_configure' to be compatible with the coding style and use 'bool' as data type. Change-Id: I8609f9807c8bd14eaf6c93acf63fd51b55c9bbbb Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8573 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/jim-nvp.h | 3 ++- src/rtos/rtos.c | 2 +- src/target/aarch64.c | 2 +- src/target/arm_adi_v5.c | 6 +++--- src/target/arm_cti.c | 2 +- src/target/arm_tpiu_swo.c | 22 +++++++++++----------- src/target/target.c | 30 +++++++++++++++--------------- 7 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/helper/jim-nvp.h b/src/helper/jim-nvp.h index 11824cabf4..45af6c867f 100644 --- a/src/helper/jim-nvp.h +++ b/src/helper/jim-nvp.h @@ -19,6 +19,7 @@ #ifndef OPENOCD_HELPER_JIM_NVP_H #define OPENOCD_HELPER_JIM_NVP_H +#include #include /** Name Value Pairs, aka: NVP @@ -136,7 +137,7 @@ struct jim_getopt_info { Jim_Interp *interp; int argc; Jim_Obj *const *argv; - int isconfigure; /* non-zero if configure */ + bool is_configure; }; /** GetOpt - how to. diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 54e31e4268..cc0fecebea 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -103,7 +103,7 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target) Jim_Obj *res; int e; - if (!goi->isconfigure && goi->argc != 0) { + if (!goi->is_configure && goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); return JIM_ERR; } diff --git a/src/target/aarch64.c b/src/target/aarch64.c index f0d486f58e..9f122070aa 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2940,7 +2940,7 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info * switch (n->value) { case CFG_CTI: { - if (goi->isconfigure) { + if (goi->is_configure) { Jim_Obj *o_cti; struct arm_cti *cti; e = jim_getopt_obj(goi, &o_cti); diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index eaaa209b9a..0c7633beab 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -2359,7 +2359,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, switch (n->value) { case CFG_DAP: - if (goi->isconfigure) { + if (goi->is_configure) { Jim_Obj *o_t; struct adiv5_dap *dap; e = jim_getopt_obj(goi, &o_t); @@ -2388,7 +2388,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, break; case CFG_AP_NUM: - if (goi->isconfigure) { + if (goi->is_configure) { /* jim_wide is a signed 64 bits int, ap_num is unsigned with max 52 bits */ jim_wide ap_num; e = jim_getopt_wide(goi, &ap_num); @@ -2415,7 +2415,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, LOG_WARNING("DEPRECATED! use \'-baseaddr' not \'-ctibase\'"); /* fall through */ case CFG_BASEADDR: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide base; e = jim_getopt_wide(goi, &base); if (e != JIM_OK) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 97d1fb34bf..88eec832ef 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -468,7 +468,7 @@ static int cti_create(struct jim_getopt_info *goi) adiv5_mem_ap_spot_init(&cti->spot); /* Do the rest as "configure" options */ - goi->isconfigure = 1; + goi->is_configure = true; e = cti_configure(goi, cti); if (e != JIM_OK) { free(cti); diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 55a9778447..c14fd5fc84 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -358,7 +358,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s { assert(obj); - if (goi->isconfigure && obj->enabled) { + if (goi->is_configure && obj->enabled) { Jim_SetResultFormatted(goi->interp, "Cannot configure TPIU/SWO; %s is enabled!", obj->name); return JIM_ERR; } @@ -382,7 +382,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s switch (n->value) { case CFG_PORT_WIDTH: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide port_width; e = jim_getopt_wide(goi, &port_width); if (e != JIM_OK) @@ -399,7 +399,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_PROTOCOL: - if (goi->isconfigure) { + if (goi->is_configure) { struct jim_nvp *p; e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_protocol_opts, &p); if (e != JIM_OK) @@ -418,7 +418,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_FORMATTER: - if (goi->isconfigure) { + if (goi->is_configure) { struct jim_nvp *p; e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_bool_opts, &p); if (e != JIM_OK) @@ -437,7 +437,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_TRACECLKIN: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide clk; e = jim_getopt_wide(goi, &clk); if (e != JIM_OK) @@ -450,7 +450,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_BITRATE: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide clk; e = jim_getopt_wide(goi, &clk); if (e != JIM_OK) @@ -463,7 +463,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_OUTFILE: - if (goi->isconfigure) { + if (goi->is_configure) { const char *s; e = jim_getopt_string(goi, &s, NULL); if (e != JIM_OK) @@ -491,7 +491,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_EVENT: - if (goi->isconfigure) { + if (goi->is_configure) { if (goi->argc < 2) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); return JIM_ERR; @@ -521,7 +521,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s ea = ea->next; } - if (goi->isconfigure) { + if (goi->is_configure) { if (!ea) { ea = calloc(1, sizeof(*ea)); if (!ea) { @@ -560,7 +560,7 @@ static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * co struct jim_getopt_info goi; jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(c->name, "configure"); + goi.is_configure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); @@ -977,7 +977,7 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const } /* Do the rest as "configure" options */ - goi.isconfigure = 1; + goi.is_configure = true; int e = arm_tpiu_swo_configure(&goi, obj); if (e != JIM_OK) goto err_exit; diff --git a/src/target/target.c b/src/target/target.c index 49611dfb45..6c474899a4 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4937,7 +4937,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) switch (n->value) { case TCFG_TYPE: /* not settable */ - if (goi->isconfigure) { + if (goi->is_configure) { Jim_SetResultFormatted(goi->interp, "not settable: %s", n->name); return JIM_ERR; @@ -4966,7 +4966,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) return e; } - if (goi->isconfigure) { + if (goi->is_configure) { if (goi->argc != 1) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); return JIM_ERR; @@ -4989,7 +4989,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) teap = teap->next; } - if (goi->isconfigure) { + if (goi->is_configure) { /* START_DEPRECATED_TPIU */ if (n->value == TARGET_EVENT_TRACE_CONFIG) LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); @@ -5037,7 +5037,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_WORK_AREA_VIRT: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5053,7 +5053,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_WORK_AREA_PHYS: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5069,7 +5069,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_WORK_AREA_SIZE: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5084,7 +5084,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_WORK_AREA_BACKUP: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5101,7 +5101,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) case TCFG_ENDIAN: - if (goi->isconfigure) { + if (goi->is_configure) { e = jim_getopt_nvp(goi, nvp_target_endian, &n); if (e != JIM_OK) { jim_getopt_nvp_unknown(goi, nvp_target_endian, 1); @@ -5122,7 +5122,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_COREID: - if (goi->isconfigure) { + if (goi->is_configure) { e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5136,7 +5136,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_CHAIN_POSITION: - if (goi->isconfigure) { + if (goi->is_configure) { Jim_Obj *o_t; struct jtag_tap *tap; @@ -5163,7 +5163,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) /* loop for more e*/ break; case TCFG_DBGBASE: - if (goi->isconfigure) { + if (goi->is_configure) { e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5193,7 +5193,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_GDB_PORT: - if (goi->isconfigure) { + if (goi->is_configure) { struct command_context *cmd_ctx = current_command_context(goi->interp); if (cmd_ctx->mode != COMMAND_CONFIG) { Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1); @@ -5215,7 +5215,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) break; case TCFG_GDB_MAX_CONNECTIONS: - if (goi->isconfigure) { + if (goi->is_configure) { struct command_context *cmd_ctx = current_command_context(goi->interp); if (cmd_ctx->mode != COMMAND_CONFIG) { Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1); @@ -5246,7 +5246,7 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a struct jim_getopt_info goi; jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(c->name, "configure"); + goi.is_configure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); @@ -5823,7 +5823,7 @@ static int target_create(struct jim_getopt_info *goi) target->gdb_max_connections = 1; /* Do the rest as "configure" options */ - goi->isconfigure = 1; + goi->is_configure = true; e = target_configure(goi, target); if (e == JIM_OK) { From c582cfbf758fdf188b02d8e57e0f57ce9c36663e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 10 Nov 2024 14:30:25 +0100 Subject: [PATCH 1021/1312] driver: stlink: get adapter speed through adapter_get_speed_khz() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stlink driver, both in dapdirect and in HLA modes, pretends to store locally the value of the adapter speed in order to use it later-on during adapter initialization. It doesn't work in dapdirect mode since the code to store locally the value will not be executed until the adapter is already fully initialized. This cause an issue in dapdirect mode: - due to the local value, still kept at -1, the adapter will be initialized to the lowest clock speed (5 KHz on stlink v2 in SWD mode); - after the adapter initialization the framework will again set the speed with the value requested by the user. Some target, like nRF51822, only accepts JTAG/SWD speed in a defined range of frequencies. The initial speed of 5 KHz used by dapdirect can be out of range, making the target debug port not working. The adapter framework already stores the value of speed and makes it available through adapter_get_speed_khz(). Drop struct hl_interface_param::initial_interface_speed. Let the code to use adapter_get_speed_khz(). Change-Id: Ie11bf0234574f2a9180d3d3a16efb78e08dfcd86 Reported-by: Andrzej Sierżęga Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8574 Reviewed-by: Andrzej Sierżęga Tested-by: jenkins --- src/jtag/drivers/stlink_usb.c | 3 +-- src/jtag/hla/hla_interface.c | 6 +----- src/jtag/hla/hla_interface.h | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 0385e4d857..d77f28b0f4 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -3781,7 +3781,7 @@ static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode, } /* initialize the debug hardware */ - err = stlink_usb_init_mode(h, param->connect_under_reset, param->initial_interface_speed); + err = stlink_usb_init_mode(h, param->connect_under_reset, adapter_get_speed_khz()); if (err != ERROR_OK) { LOG_ERROR("init mode failed (unable to connect to the target)"); @@ -5174,7 +5174,6 @@ static int stlink_dap_speed(int speed) return ERROR_JTAG_NOT_IMPLEMENTED; } - stlink_dap_param.initial_interface_speed = speed; stlink_speed(stlink_dap_handle, speed, false); return ERROR_OK; } diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index e826f79103..96862b0d05 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -30,7 +30,6 @@ static struct hl_interface hl_if = { .pid = { 0 }, .transport = HL_TRANSPORT_UNKNOWN, .connect_under_reset = false, - .initial_interface_speed = -1, .use_stlink_tcp = false, .stlink_tcp_port = 7184, }, @@ -165,11 +164,8 @@ static int hl_interface_speed(int speed) if (!hl_if.layout->api->speed) return ERROR_OK; - if (!hl_if.handle) { - /* pass speed as initial param as interface not open yet */ - hl_if.param.initial_interface_speed = speed; + if (!hl_if.handle) return ERROR_OK; - } hl_if.layout->api->speed(hl_if.handle, speed, false); diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index c95638b92a..f1550d9915 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -31,8 +31,6 @@ struct hl_interface_param { enum hl_transports transport; /** */ bool connect_under_reset; - /** Initial interface clock clock speed */ - int initial_interface_speed; /** */ bool use_stlink_tcp; /** */ From 9ff79fd61fb0bd763d09820672e9e7ce50df4c41 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 2 Nov 2024 23:34:23 +0100 Subject: [PATCH 1022/1312] enable the Bus Pirate adapter by default on most systems Also convert the Bus Pirate to the common PROCESS_ADAPTERS logic. Change-Id: Ifa8ebcee380c16d7e308ba7a75dbffdb74208285 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8533 Reviewed-by: Antonio Borneo Reviewed-by: R. Diez Tested-by: jenkins --- configure.ac | 19 ++++++++----------- src/jtag/drivers/Makefile.am | 2 +- src/jtag/interfaces.c | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 291e854a42..687c5c9742 100644 --- a/configure.ac +++ b/configure.ac @@ -414,6 +414,8 @@ AS_CASE(["${host_cpu}"], parport_use_ppdev=yes ]) +can_build_buspirate=yes + AS_CASE([$host], [*-cygwin*], [ is_win32=yes @@ -445,12 +447,12 @@ AS_CASE([$host], ]) parport_use_giveio=yes - AS_IF([test "x$enable_buspirate" = "xyes"], [ - AC_MSG_ERROR([buspirate currently not supported by MinGW32 hosts]) + AS_IF([test "x$ADAPTER_VAR([buspirate])" = "xyes"], [ + AC_MSG_ERROR([The Bus Pirate adapter is currently not supported by MinGW32 hosts.]) ]) # In case enable_buspirate=auto, make sure it will not be built. - enable_buspirate=no + can_build_buspirate=no AC_SUBST([HOST_CPPFLAGS], ["-D__USE_MINGW_ANSI_STDIO -DFD_SETSIZE=128"]) ], @@ -594,12 +596,6 @@ AS_IF([test "x$build_gw16012" = "xyes"], [ AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.]) ]) -AS_IF([test "x$enable_buspirate" != "xno"], [ - AC_DEFINE([BUILD_BUSPIRATE], [1], [1 if you want the Buspirate JTAG driver.]) -], [ - AC_DEFINE([BUILD_BUSPIRATE], [0], [0 if you don't want the Buspirate JTAG driver.]) -]) - AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ AS_IF([test -f "$srcdir/jimtcl/configure"], [ AS_IF([test "x$use_internal_jimtcl_maintainer" = "xyes"], [ @@ -712,7 +708,7 @@ m4_define([PROCESS_ADAPTERS], [ ]) ], [ AS_IF([test "x$ADAPTER_VAR([adapter])" = "xyes"], [ - AC_MSG_ERROR([$3 is required for [adapter] ADAPTER_DESC([adapter]).]) + AC_MSG_ERROR([$3 is required for [adapter] "ADAPTER_DESC([adapter])".]) ]) ADAPTER_VAR([adapter])=no AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).) @@ -729,6 +725,8 @@ PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_li PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [libgpiod]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) +PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], + [internal error: validation should happen beforehand]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -783,7 +781,6 @@ AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"]) AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"]) -AM_CONDITIONAL([BUSPIRATE], [test "x$enable_buspirate" != "xno"]) AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index e404afe9f0..8be834859c 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -143,7 +143,7 @@ endif if ARMJTAGEW DRIVERFILES += %D%/arm-jtag-ew.c endif -if BUSPIRATE +if BUS_PIRATE DRIVERFILES += %D%/buspirate.c endif if REMOTE_BITBANG diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index c24ead8cd9..67f0838e39 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -102,7 +102,7 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_ARMJTAGEW == 1 &armjtagew_adapter_driver, #endif -#if BUILD_BUSPIRATE == 1 +#if BUILD_BUS_PIRATE == 1 &buspirate_adapter_driver, #endif #if BUILD_REMOTE_BITBANG == 1 From 2627f8ce6daebd4ab148165a8797595c04052695 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 3 Nov 2024 10:52:45 +0100 Subject: [PATCH 1023/1312] configure.ac: show the linuxgpiod adapter in the configuration summary List AC_ARG_ADAPTERS was missing a comma separating two of the elements. Also verify that each adapter is set to either 'auto', 'yes' or 'no', which should prevent such issues from going unnoticed in the future. Change-Id: I0d407e03b1e5a3edc61d7dc93d5ffa70fe079b3c Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8534 Tested-by: jenkins Reviewed-by: R. Diez Reviewed-by: Antonio Borneo --- configure.ac | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 687c5c9742..31e57a3cd0 100644 --- a/configure.ac +++ b/configure.ac @@ -283,7 +283,7 @@ AC_ARG_ADAPTERS([ HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, - LIBFTDI_USB1_ADAPTERS + LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, SERIAL_PORT_ADAPTERS, PCIE_ADAPTERS, @@ -372,10 +372,6 @@ AS_CASE([$host_os], AC_MSG_ERROR([sysfsgpio is only available on linux]) ]) - AS_IF([test "x$enable_linuxgpiod" = "xyes"], [ - AC_MSG_ERROR([linuxgpiod is only available on linux]) - ]) - AS_CASE([$host_os], [freebsd*], [], [ AS_IF([test "x$build_rshim" = "xyes"], [ @@ -722,7 +718,7 @@ PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi]) PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x]) PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x]) -PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [libgpiod]) +PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpiod]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], @@ -889,6 +885,11 @@ m4_foreach([adapter], [USB1_ADAPTERS, ], [no], [ echo "$s"no + ], + [ + AC_MSG_ERROR(m4_normalize([ + Error in [adapter] "ADAPTER_ARG([adapter])": Variable "ADAPTER_VAR([adapter])" + has invalid value "$ADAPTER_VAR([adapter])".])) ]) ]) echo From 11f24fc2f2bef1868e17f9b3b53ec8264b164611 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Tue, 5 Nov 2024 14:40:50 +0100 Subject: [PATCH 1024/1312] configure.ac: improve validation of some --enable-xxx options Catch an invalid option like "--enable-buspirate=rubbish". Also mention all valid values in the help text for those options. Change-Id: Ib0fb8904132d07cc5cde421aa816ca6971a08769 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8540 Reviewed-by: R. Diez Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 31e57a3cd0..567152b0a6 100644 --- a/configure.ac +++ b/configure.ac @@ -272,9 +272,13 @@ AC_ARG_ENABLE([dmem], m4_define([AC_ARG_ADAPTERS], [ m4_foreach([adapter], [$1], [AC_ARG_ENABLE(ADAPTER_OPT([adapter]), - AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])], + AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])[[[=yes/no/auto]]]], [Enable building support for the ]ADAPTER_DESC([adapter])[ (default is $2)]), - [], [ADAPTER_VAR([adapter])=$2]) + [case "${enableval}" in + yes|no|auto) ;; + *) AC_MSG_ERROR([Option --enable-ADAPTER_OPT([adapter]) has invalid value "${enableval}".]) ;; + esac], + [ADAPTER_VAR([adapter])=$2]) ]) ]) From f5036aff3a83f9b92ee5939e5a32a13396b53dd5 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 17:32:37 +0200 Subject: [PATCH 1025/1312] target/xtensa: Remove 'ERROR: ' prefix in error log Remove the prefix since it is redundant. Change-Id: I9c23c0479ba40be24e471309e720060cd03763ee Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8577 Tested-by: jenkins Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo --- src/target/xtensa/xtensa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 8369cc4e5c..284bfc9c62 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -3000,13 +3000,13 @@ static int xtensa_build_reg_cache(struct target *target) /* Construct empty-register list for handling unknown register requests */ xtensa->empty_regs = calloc(xtensa->dbregs_num, sizeof(struct reg)); if (!xtensa->empty_regs) { - LOG_TARGET_ERROR(target, "ERROR: Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); goto fail; } for (unsigned int i = 0; i < xtensa->dbregs_num; i++) { xtensa->empty_regs[i].name = calloc(8, sizeof(char)); if (!xtensa->empty_regs[i].name) { - LOG_TARGET_ERROR(target, "ERROR: Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); goto fail; } sprintf((char *)xtensa->empty_regs[i].name, "?0x%04x", i & 0x0000FFFF); @@ -3024,7 +3024,7 @@ static int xtensa_build_reg_cache(struct target *target) if (xtensa->regmap_contiguous && xtensa->contiguous_regs_desc) { xtensa->contiguous_regs_list = calloc(xtensa->total_regs_num, sizeof(struct reg *)); if (!xtensa->contiguous_regs_list) { - LOG_TARGET_ERROR(target, "ERROR: Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); goto fail; } for (unsigned int i = 0; i < xtensa->total_regs_num; i++) { From 69736131754c1b742beb8bf3058b72ae4ffc3d32 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 23 Oct 2024 15:02:10 +0200 Subject: [PATCH 1026/1312] rtos: Remove 'ERROR: ' prefix in error log Remove the prefix since it is redundant. While at it, also get rid of the useless exclamation mark. Change-Id: I8707342c602cea735c5a423b37ebe40a3aafb137 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8578 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtos/rtos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index cc0fecebea..0dd538e8f2 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -309,7 +309,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s reply_len += 2 * strlen(next_suffix); /* hexify(..., next_suffix, ...) */ reply_len += 1; /* Terminating NUL */ if (reply_len > sizeof(reply)) { - LOG_ERROR("ERROR: RTOS symbol '%s%s' name is too long for GDB!", next_sym->symbol_name, next_suffix); + LOG_ERROR("RTOS symbol '%s%s' name is too long for GDB", next_sym->symbol_name, next_suffix); goto done; } From c837beaf5d70685a4c3236b1680897985adafe5f Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 17:31:20 +0200 Subject: [PATCH 1027/1312] target/breakpoints: Use LOG_TARGET_ERROR() Use LOG_TARGET_xxx() for the remaining log messages. Change-Id: I4b86b206d17dead0662388e827204b40a7d29edd Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8579 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/breakpoints.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 9378abcb14..a080416291 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -114,7 +114,7 @@ static int context_breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_TARGET_ERROR(target, "Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); return ERROR_TARGET_DUPLICATE_BREAKPOINT; } @@ -643,8 +643,7 @@ int watchpoint_remove(struct target *target, target_addr_t address) int watchpoint_clear_target(struct target *target) { - LOG_DEBUG("Delete all watchpoints for target: %s", - target_name(target)); + LOG_TARGET_DEBUG(target, "Delete all watchpoints"); struct watchpoint *watchpoint = target->watchpoints; int retval = ERROR_OK; From 76e228f733af8f685cfd96a25c92f17256562d1c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 18:22:36 +0200 Subject: [PATCH 1028/1312] target/cortex_m: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() for the remaining log messages. Change-Id: If52e3935b57e4c39212ce6b5111ff65159de1373 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8580 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index e78d2e29ba..fa95fcbc7e 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1469,7 +1469,7 @@ static int cortex_m_resume(struct target *target, int current, if (target->smp && !debug_execution) { retval = cortex_m_restore_smp(target, !!handle_breakpoints); if (retval != ERROR_OK) - LOG_WARNING("resume of a SMP target failed, trying to resume current one"); + LOG_TARGET_WARNING(target, "resume of a SMP target failed, trying to resume current one"); } cortex_m_restart_one(target, !!debug_execution); @@ -2553,7 +2553,7 @@ static bool cortex_m_has_tz(struct target *target) int retval = target_read_u32(target, DAUTHSTATUS, &dauthstatus); if (retval != ERROR_OK) { - LOG_WARNING("Error reading DAUTHSTATUS register"); + LOG_TARGET_WARNING(target, "Error reading DAUTHSTATUS register"); return false; } return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0; @@ -2602,7 +2602,7 @@ int cortex_m_examine(struct target *target) } else { armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel); if (!armv7m->debug_ap) { - LOG_ERROR("Cannot get AP"); + LOG_TARGET_ERROR(target, "Cannot get AP"); return ERROR_FAIL; } } @@ -2659,9 +2659,9 @@ int cortex_m_examine(struct target *target) LOG_TARGET_WARNING(target, "Erratum 3092511: Cortex-M7 can halt in an incorrect address when breakpoint and exception occurs simultaneously"); cortex_m->incorrect_halt_erratum = true; if (armv7m->is_hla_target) - LOG_WARNING("No erratum 3092511 workaround on hla adapter"); + LOG_TARGET_WARNING(target, "No erratum 3092511 workaround on hla adapter"); else - LOG_INFO("The erratum 3092511 workaround will resume after an incorrect halt"); + LOG_TARGET_INFO(target, "The erratum 3092511 workaround will resume after an incorrect halt"); } LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid); From 133dd9d669e5b8beb7c7787b0be677621808e72d Mon Sep 17 00:00:00 2001 From: Henrik Mau Date: Wed, 13 Nov 2024 15:43:23 +0000 Subject: [PATCH 1029/1312] target/xtensa: add maskisr command support for NX Add maskisr command support to Xtensa NX targets allowing masking of interrupts during single stepping. Change-Id: I3835479de8015f1a2842afd1aeab24829e385031 Signed-off-by: Henrik Mau Reviewed-on: https://review.openocd.org/c/openocd/+/8575 Reviewed-by: Ian Thompson Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/xtensa/xtensa.c | 41 +++++++++++++++++++++----------------- src/target/xtensa/xtensa.h | 1 + 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 284bfc9c62..fe1b83bc3e 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -1727,7 +1727,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in xtensa_reg_val_t dbreakc[XT_WATCHPOINTS_NUM_MAX]; xtensa_reg_val_t icountlvl, cause; xtensa_reg_val_t oldps, oldpc, cur_pc; - bool ps_lowered = false; + bool ps_modified = false; LOG_TARGET_DEBUG(target, "current=%d, address=" TARGET_ADDR_FMT ", handle_breakpoints=%i", current, address, handle_breakpoints); @@ -1783,14 +1783,23 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in * RFI >= DBGLEVEL. */ if (xtensa->stepping_isr_mode == XT_STEPPING_ISR_OFF) { - if (!xtensa->core_config->high_irq.enabled) { - LOG_TARGET_WARNING( - target, - "disabling IRQs while stepping is not implemented w/o high prio IRQs option!"); - return ERROR_FAIL; + if (xtensa->core_config->core_type == XT_LX) { + if (!xtensa->core_config->high_irq.enabled) { + LOG_TARGET_WARNING(target, + "disabling IRQs while stepping is not implemented w/o high prio IRQs option!"); + return ERROR_FAIL; + } + /* Update ICOUNTLEVEL accordingly */ + icountlvl = MIN((oldps & 0xF) + 1, xtensa->core_config->debug.irq_level); + } else { + /* Xtensa NX does not have the ICOUNTLEVEL feature present in Xtensa LX + * and instead disable interrupts while stepping. This could change + * the timing of the system while under debug */ + xtensa_reg_val_t newps = oldps | XT_PS_DI_MSK; + xtensa_reg_set(target, XT_REG_IDX_PS, newps); + icountlvl = xtensa->core_config->debug.irq_level; + ps_modified = true; } - /* Update ICOUNTLEVEL accordingly */ - icountlvl = MIN((oldps & 0xF) + 1, xtensa->core_config->debug.irq_level); } else { icountlvl = xtensa->core_config->debug.irq_level; } @@ -1815,7 +1824,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in xtensa_cause_clear(target); /* so we don't recurse into the same routine */ if (xtensa->core_config->core_type == XT_LX && ((oldps & 0xf) >= icountlvl)) { /* Lower interrupt level to allow stepping, but flag eps[dbglvl] to be restored */ - ps_lowered = true; + ps_modified = true; uint32_t newps = (oldps & ~0xf) | (icountlvl - 1); xtensa_reg_set(target, xtensa->eps_dbglevel_idx, newps); LOG_TARGET_DEBUG(target, @@ -1916,11 +1925,12 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in } /* Restore int level */ - if (ps_lowered) { + if (ps_modified) { LOG_DEBUG("Restoring %s after stepping: 0x%08" PRIx32, - xtensa->core_cache->reg_list[xtensa->eps_dbglevel_idx].name, - oldps); - xtensa_reg_set(target, xtensa->eps_dbglevel_idx, oldps); + xtensa->core_cache->reg_list[(xtensa->core_config->core_type == XT_LX) ? + xtensa->eps_dbglevel_idx : XT_REG_IDX_PS].name, oldps); + xtensa_reg_set(target, (xtensa->core_config->core_type == XT_LX) ? + xtensa->eps_dbglevel_idx : XT_REG_IDX_PS, oldps); } /* write ICOUNTLEVEL back to zero */ @@ -4191,11 +4201,6 @@ COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa) return ERROR_OK; } - if (xtensa->core_config->core_type == XT_NX) { - command_print(CMD, "ERROR: ISR step mode only supported on Xtensa LX"); - return ERROR_FAIL; - } - /* Masking is ON -> interrupts during stepping are OFF, and vice versa */ if (!strcasecmp(CMD_ARGV[0], "off")) state = XT_STEPPING_ISR_ON; diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 1d56f83682..419277675c 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -45,6 +45,7 @@ /* PS register bits (NX) */ #define XT_PS_DIEXC_MSK BIT(2) +#define XT_PS_DI_MSK BIT(3) /* MS register bits (NX) */ #define XT_MS_DE_MSK BIT(5) From d60e1f6693e52800603eac7c8de3ade14eb6a514 Mon Sep 17 00:00:00 2001 From: Pete Moore Date: Mon, 16 Dec 2024 16:55:06 +0100 Subject: [PATCH 1030/1312] flash/nor/sfdp: Fix broken DEBUG log line on macOS https://review.openocd.org/c/openocd/+/8439 changed variable `words` from uint8_t to unsigned int in sfdp.c but failed to update the LOG_DEBUG line to reflect the new type. On macOS this caused: src/flash/nor/sfdp.c:107:28: error: format specifies type 'unsigned char' but the argument has type 'unsigned int' [-Werror,-Wformat] The formatting of the debug line has been updated to reflect the updated type. Change-Id: Ifc7ddb1279ab2603901c969d9c09af847f3a3caf Signed-off-by: Pete Moore Reviewed-on: https://review.openocd.org/c/openocd/+/8660 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/flash/nor/sfdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/sfdp.c b/src/flash/nor/sfdp.c index 917f1626fb..8e25ba680b 100644 --- a/src/flash/nor/sfdp.c +++ b/src/flash/nor/sfdp.c @@ -103,7 +103,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, uint16_t id = (((pheaders[k].ptr) >> 16) & 0xFF00) | (pheaders[k].revision & 0xFF); uint32_t ptr = pheaders[k].ptr & 0xFFFFFF; - LOG_DEBUG("pheader %d len=0x%02" PRIx8 " id=0x%04" PRIx16 + LOG_DEBUG("pheader %d len=0x%02x id=0x%04" PRIx16 " ptr=0x%06" PRIx32, k, words, id, ptr); /* retrieve parameter table */ From cb3b8afe47ef791b2671f1af9415bd28dedffb6d Mon Sep 17 00:00:00 2001 From: Pete Moore Date: Mon, 16 Dec 2024 14:02:14 +0100 Subject: [PATCH 1031/1312] jimtcl: Fix command not found During the ./configure build stage, error './configure.gnu: line 1: -e: command not found' can occur. Problem: the -e flag with echo is not portable. While some shells support it (e.g., Bash), others (e.g., POSIX /bin/sh on some systems) do not. Solution: replacing echo -e with printf, since printf is POSIX-compliant and works consistently across different shells. Change-Id: I9efbba662599a61bbe1fc56a33dc1ee7ad58826c Signed-off-by: Pete Moore Reviewed-on: https://review.openocd.org/c/openocd/+/8653 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Andreas Fritiofson --- config_subdir.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_subdir.m4 b/config_subdir.m4 index 2be590e44a..5549c760af 100644 --- a/config_subdir.m4 +++ b/config_subdir.m4 @@ -7,6 +7,6 @@ AC_DEFUN([AX_CONFIG_SUBDIR_OPTION], AC_CONFIG_SUBDIRS([$1]) m4_ifblank([$2], [rm -f $srcdir/$1/configure.gnu], -[echo -e '#!/bin/sh\nexec "`dirname "'\$'0"`/configure" '"$2"' "'\$'@"' > "$srcdir/$1/configure.gnu" +[printf '#!/bin/sh\nexec "`dirname "'\$'0"`/configure" '"$2"' "'\$'@"\n' > "$srcdir/$1/configure.gnu" ]) ]) From cc02bd752c13e1810b0b56593e6c5edcd179f484 Mon Sep 17 00:00:00 2001 From: fanoush Date: Mon, 2 Sep 2024 13:49:19 +0200 Subject: [PATCH 1032/1312] rtt server: fix for dropped data when target has no space rtt_write_channel may write less data than requested, default device buffer size for channel 0 is 16 bytes, so currently anything larger than this is dropped. This fix implements per connection buffer and uses the connection->input_pending flag to retry writes. Change-Id: I00c845fccb0248550ad0f0fd9cda7bac7976b92b Signed-off-by: fanoush Reviewed-on: https://review.openocd.org/c/openocd/+/8360 Reviewed-by: zapb Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/rtt_server.c | 69 ++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c index 9769153475..b44101c3dc 100644 --- a/src/server/rtt_server.c +++ b/src/server/rtt_server.c @@ -28,6 +28,12 @@ struct rtt_service { char *hello_message; }; +struct rtt_connection_data { + unsigned char buffer[64]; + unsigned int length; + unsigned int offset; +}; + static int read_callback(unsigned int channel, const uint8_t *buffer, size_t length, void *user_data) { @@ -56,7 +62,16 @@ static int rtt_new_connection(struct connection *connection) { int ret; struct rtt_service *service; + struct rtt_connection_data *data; + + data = calloc(1, sizeof(struct rtt_connection_data)); + if (!data) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + connection->priv = data; service = connection->service->priv; LOG_DEBUG("rtt: New connection for channel %u", service->channel); @@ -79,31 +94,53 @@ static int rtt_connection_closed(struct connection *connection) service = (struct rtt_service *)connection->service->priv; rtt_unregister_sink(service->channel, &read_callback, connection); - LOG_DEBUG("rtt: Connection for channel %u closed", service->channel); + free(connection->priv); + LOG_DEBUG("rtt: Connection for channel %u closed", service->channel); return ERROR_OK; } static int rtt_input(struct connection *connection) { - int bytes_read; - unsigned char buffer[1024]; struct rtt_service *service; - size_t length; + struct rtt_connection_data *data; - service = (struct rtt_service *)connection->service->priv; - bytes_read = connection_read(connection, buffer, sizeof(buffer)); + data = connection->priv; + service = connection->service->priv; - if (!bytes_read) - return ERROR_SERVER_REMOTE_CLOSED; - else if (bytes_read < 0) { - LOG_ERROR("error during read: %s", strerror(errno)); - return ERROR_SERVER_REMOTE_CLOSED; - } + if (!connection->input_pending) { + int bytes_read; - length = bytes_read; - rtt_write_channel(service->channel, buffer, &length); + bytes_read = connection_read(connection, data->buffer, sizeof(data->buffer)); + + if (!bytes_read) { + return ERROR_SERVER_REMOTE_CLOSED; + } else if (bytes_read < 0) { + LOG_ERROR("error during read: %s", strerror(errno)); + return ERROR_SERVER_REMOTE_CLOSED; + } + data->length = bytes_read; + data->offset = 0; + } + if (data->length > 0) { + unsigned char *ptr; + size_t length, to_write; + + ptr = data->buffer + data->offset; + length = data->length - data->offset; + to_write = length; + rtt_write_channel(service->channel, ptr, &length); + + if (length < to_write) { + data->offset += length; + connection->input_pending = true; + } else { + data->offset = 0; + data->length = 0; + connection->input_pending = false; + } + } return ERROR_OK; } @@ -126,8 +163,10 @@ COMMAND_HANDLER(handle_rtt_start_command) service = calloc(1, sizeof(struct rtt_service)); - if (!service) + if (!service) { + LOG_ERROR("Out of memory"); return ERROR_FAIL; + } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); From 1710954977a0262e6987426f117aab0f73b27024 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 23 Oct 2024 15:42:16 +0200 Subject: [PATCH 1033/1312] doc/manual: Add section about logging The log messages are very inconsistent across the code base. Add a guideline for log messages to help improve consistency. The guideline is based on the most commonly used style in the current code base. Change-Id: I076d68abe588dd04b59580379e97b82d537def23 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8576 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/manual/style.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/manual/style.txt b/doc/manual/style.txt index a1e6b8f016..dc27e8767a 100644 --- a/doc/manual/style.txt +++ b/doc/manual/style.txt @@ -225,6 +225,21 @@ if (!buf) { } @endcode +@section stylelogging Logging + +Logging is intended to provide human-readable information to users. +Do not confuse logging with the output of commands. +The latter is intended for the result of a command and should be able to be processed by Tcl scripts. + + - Use one of the following functions to generate log messages, never use `printf()` or similar functions. + - Use `LOG_ERROR()` to provide information in case an operation failed in an unrecoverable way. For example, if necessary memory cannot be allocated. + - Use `LOG_WARNING()` to inform the user of about an unexpected behavior that can be handled and the intended operation is still be performed. For example, in case a command is deprecated but is nevertheless executed. + - Use `LOG_INFO()` to provide insightful or necessary information to the user. For example, features or capabilities of a discovered target. + - Use `LOG_DEBUG()` to provide information for troubleshooting. For example, detailed information which makes it easier to debug a specific operation. Try to avoid flooding the log with frequently generated messages. For example, do not use LOG_DEBUG() in operations used for polling the target. Use LOG_DEBUG_IO() for such frequent messages. + - Use `LOG_DEBUG_IO()` to provide I/O related information for troubleshooting. For example, details about the communication between OpenOCD and a debug adapter. + - If the log message is related to a target, use the corresponding `LOG_TARGET_xxx()` functions. + - Do not use a period or exclamation mark at the end of a message. + */ /** @page styledoxygen Doxygen Style Guide From 42f70a3b95ea708d0e4fd5d83a6bc6965fd65ac6 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 22 Nov 2024 18:06:40 +0100 Subject: [PATCH 1034/1312] target: aarch64: fix out-of-bound access to array The command 'arm core_state' uses the enum in 'arm->core_state' as an index in the table of strings to print the core state. With [1] the enum has been extended with the new state for AArch64 but not the corresponding table of strings. This causes an access after the limit of arm_state_strings[]. Rewrite the table using c99 array designators to better show the link between the enum list and the table. Add the function arm_core_state_string() to check for out-of-bound values allover the file. Change-Id: I06473c2c8088b38ee07118bcc9e49bc8eafbc6e2 Fixes: [1] 9cbfc9feb35c ("arm_dpm: Add new state ARM_STATE_AARCH64") Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8594 Tested-by: jenkins --- src/target/armv4_5.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index c1836bc7ae..ceec3619b5 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -248,7 +248,11 @@ enum arm_mode armv4_5_number_to_mode(int number) } static const char *arm_state_strings[] = { - "ARM", "Thumb", "Jazelle", "ThumbEE", + [ARM_STATE_ARM] = "ARM", + [ARM_STATE_THUMB] = "Thumb", + [ARM_STATE_JAZELLE] = "Jazelle", + [ARM_STATE_THUMB_EE] = "ThumbEE", + [ARM_STATE_AARCH64] = "AArch64", }; /* Templates for ARM core registers. @@ -430,6 +434,16 @@ const int armv4_5_core_reg_map[9][17] = { } }; +static const char *arm_core_state_string(struct arm *arm) +{ + if (arm->core_state > ARRAY_SIZE(arm_state_strings)) { + LOG_ERROR("core_state exceeds table size"); + return "Unknown"; + } + + return arm_state_strings[arm->core_state]; +} + /** * Configures host-side ARM records to reflect the specified CPSR. * Later, code can use arm_reg_current() to map register numbers @@ -484,7 +498,7 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) LOG_DEBUG("set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, arm_mode_name(mode), - arm_state_strings[arm->core_state]); + arm_core_state_string(arm)); } /** @@ -794,7 +808,7 @@ int arm_arch_state(struct target *target) LOG_USER("target halted in %s state due to %s, current mode: %s\n" "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s%s", - arm_state_strings[arm->core_state], + arm_core_state_string(arm), debug_reason_name(target), arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), @@ -929,7 +943,7 @@ COMMAND_HANDLER(handle_arm_core_state_command) arm->core_state = ARM_STATE_THUMB; } - command_print(CMD, "core state: %s", arm_state_strings[arm->core_state]); + command_print(CMD, "core state: %s", arm_core_state_string(arm)); return ret; } From dca76cd5dad974996e7231ba0ede544c626ba43d Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 26 Nov 2024 22:55:55 +0200 Subject: [PATCH 1035/1312] rtos: mqx: replace malloc+strcpy with strdup Using strcpy is potentially dangerous so just use a safer and easier way to do the same. Signed-off-by: Paul Fertser Change-Id: Id85f3b7f8af1eaf14c9951ae710546d2437c70b5 Reviewed-on: https://review.openocd.org/c/openocd/+/8597 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/rtos/mqx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c index b4a1821352..90154db3ff 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -380,10 +380,9 @@ static int mqx_update_threads( rtos->thread_details[i].threadid = task_id; rtos->thread_details[i].exists = true; /* set thread name */ - rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1); + rtos->thread_details[i].thread_name_str = strdup((char *)task_name); if (!rtos->thread_details[i].thread_name_str) return ERROR_FAIL; - strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name); /* set thread extra info * - task state * - task address From cd9e64a25ac167d188859e991201d3fe492a91e1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 27 Nov 2024 09:25:01 +0100 Subject: [PATCH 1036/1312] rtos: mqx: minor rework to avoid a cast Change the type of task_name[] to char in order to drop a cast. Change-Id: I233fc862e972e52130fd4ffcb29a3da36f4f8923 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8599 Reviewed-by: Paul Fertser Tested-by: jenkins --- src/rtos/mqx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c index 90154db3ff..017fd2b01c 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -319,7 +319,7 @@ static int mqx_update_threads( i < (uint32_t)rtos->thread_count; i++ ) { - uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1]; + char task_name[MQX_THREAD_NAME_LENGTH + 1]; uint32_t task_addr = 0, task_template = 0, task_state = 0; uint32_t task_name_addr = 0, task_id = 0, task_errno = 0; uint32_t state_index = 0; @@ -380,7 +380,7 @@ static int mqx_update_threads( rtos->thread_details[i].threadid = task_id; rtos->thread_details[i].exists = true; /* set thread name */ - rtos->thread_details[i].thread_name_str = strdup((char *)task_name); + rtos->thread_details[i].thread_name_str = strdup(task_name); if (!rtos->thread_details[i].thread_name_str) return ERROR_FAIL; /* set thread extra info From bb2fc63357a01a106ea628fb4b7e789f6a747901 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Fri, 29 Nov 2024 21:24:23 +0100 Subject: [PATCH 1037/1312] configure.ac: enable the Dummy adapter by default The Dummy adapter is useful when developing generic JimTcl code. Besides, the distributed BUGS file states that you should try to reproduce any crashes with the Dummy adapter, so it does not make sense that it is not enabled by default. Change-Id: I145de06de4d2c0011619b1b941200b63e200db23 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8608 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 567152b0a6..1e545dcc45 100644 --- a/configure.ac +++ b/configure.ac @@ -290,12 +290,11 @@ AC_ARG_ADAPTERS([ LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, SERIAL_PORT_ADAPTERS, + DUMMY_ADAPTER, PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) -AC_ARG_ADAPTERS([DUMMY_ADAPTER],[no]) - AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), [build_parport=$enableval], [build_parport=no]) From 7f9d25d58aeaba8eb0856604ce6e8abe739ead8d Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Fri, 29 Nov 2024 21:09:50 +0100 Subject: [PATCH 1038/1312] configure.ac: switch from $host to $host_os Suggested during review https://review.openocd.org/c/openocd/+/8533 Only the OS part was being checked anyway. The aim is to facilitate merging all $host_os checks in the future. Change-Id: Idce1d5872cf19ef423429fa0c3b2ff7ee3945332 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8607 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 1e545dcc45..b353bced70 100644 --- a/configure.ac +++ b/configure.ac @@ -415,8 +415,8 @@ AS_CASE(["${host_cpu}"], can_build_buspirate=yes -AS_CASE([$host], - [*-cygwin*], [ +AS_CASE([$host_os], + [cygwin*], [ is_win32=yes parport_use_ppdev=no @@ -436,7 +436,7 @@ AS_CASE([$host], ]) ]) ], - [*-mingw* | *-msys*], [ + [mingw* | msys*], [ is_mingw=yes is_win32=yes parport_use_ppdev=no @@ -455,7 +455,7 @@ AS_CASE([$host], AC_SUBST([HOST_CPPFLAGS], ["-D__USE_MINGW_ANSI_STDIO -DFD_SETSIZE=128"]) ], - [*darwin*], [ + [darwin*], [ is_darwin=yes AS_IF([test "x$parport_use_giveio" = "xyes"], [ From 9cd0b37112dc49e41c84d673ae24e473e757a920 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 30 Nov 2024 15:32:09 +0100 Subject: [PATCH 1039/1312] target/xtensa: Remove 'ERROR: ' prefix in error log Remove the prefix since it is redundant. While at it, also get rid of the useless exclamation mark. Change-Id: I16fd6a88b533fac19b4c622cf9740fd32ba7892c Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8611 Reviewed-by: Richard Allen Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/xtensa/xtensa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index fe1b83bc3e..3b888fe5f0 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -503,7 +503,7 @@ static enum xtensa_reg_id xtensa_windowbase_offset_to_canonical(struct xtensa *x } else if (reg_idx >= XT_REG_IDX_A0 && reg_idx <= XT_REG_IDX_A15) { idx = reg_idx - XT_REG_IDX_A0; } else { - LOG_ERROR("Error: can't convert register %d to non-windowbased register!", reg_idx); + LOG_ERROR("Can't convert register %d to non-windowbased register", reg_idx); return -1; } /* Each windowbase value represents 4 registers on LX and 8 on NX */ From 3be1bee75347ab1eac835591eae3ca53a58008c5 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 30 Nov 2024 15:34:20 +0100 Subject: [PATCH 1040/1312] target/mips: Remove 'ERROR: ' prefix in error log Remove the prefix since it is redundant. Change-Id: Ieecfb3583d484847514f1298e819ccf6d26abd84 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8632 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/mips32_pracc.c | 2 +- src/target/mips64_pracc.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 587e20d2be..ea90d6f83a 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -400,7 +400,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) { - LOG_ERROR("Error: access not pending count: %d", scan_count); + LOG_ERROR("Access not pending, count: %d", scan_count); retval = ERROR_FAIL; goto exit; } diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index 8cfce32e3f..11783fe972 100644 --- a/src/target/mips64_pracc.c +++ b/src/target/mips64_pracc.c @@ -76,12 +76,12 @@ static int mips64_pracc_exec_read(struct mips64_pracc_context *ctx, uint64_t add offset = (address - MIPS64_PRACC_PARAM_IN) / MIPS64_PRACC_DATA_STEP; if (offset >= MIPS64_PRACC_PARAM_IN_SIZE) { - LOG_ERROR("Error: iparam size exceeds MIPS64_PRACC_PARAM_IN_SIZE"); + LOG_ERROR("iparam size exceeds MIPS64_PRACC_PARAM_IN_SIZE"); return ERROR_JTAG_DEVICE_ERROR; } if (!ctx->local_iparam) { - LOG_ERROR("Error: unexpected reading of input parameter"); + LOG_ERROR("unexpected reading of input parameter"); return ERROR_JTAG_DEVICE_ERROR; } @@ -93,7 +93,7 @@ static int mips64_pracc_exec_read(struct mips64_pracc_context *ctx, uint64_t add offset = (address - MIPS64_PRACC_PARAM_OUT) / MIPS64_PRACC_DATA_STEP; if (!ctx->local_oparam) { - LOG_ERROR("Error: unexpected reading of output parameter"); + LOG_ERROR("unexpected reading of output parameter"); return ERROR_JTAG_DEVICE_ERROR; } @@ -181,7 +181,7 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad && (address < MIPS64_PRACC_PARAM_IN + ctx->num_iparam * MIPS64_PRACC_DATA_STEP)) { offset = (address - MIPS64_PRACC_PARAM_IN) / MIPS64_PRACC_DATA_STEP; if (!ctx->local_iparam) { - LOG_ERROR("Error: unexpected writing of input parameter"); + LOG_ERROR("unexpected writing of input parameter"); return ERROR_JTAG_DEVICE_ERROR; } ctx->local_iparam[offset] = data; @@ -189,14 +189,14 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad && (address < MIPS64_PRACC_PARAM_OUT + ctx->num_oparam * MIPS64_PRACC_DATA_STEP)) { offset = (address - MIPS64_PRACC_PARAM_OUT) / MIPS64_PRACC_DATA_STEP; if (!ctx->local_oparam) { - LOG_ERROR("Error: unexpected writing of output parameter"); + LOG_ERROR("unexpected writing of output parameter"); return ERROR_JTAG_DEVICE_ERROR; } ctx->local_oparam[offset] = data; } else if (address == MIPS64_PRACC_STACK) { /* save data onto our stack */ if (ctx->stack_offset >= STACK_DEPTH) { - LOG_ERROR("Error: PrAcc stack depth exceeded"); + LOG_ERROR("PrAcc stack depth exceeded"); return ERROR_FAIL; } ctx->stack[ctx->stack_offset++] = data; From 1f2db5d59a51262ef824a99fb6b77ce241250e47 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 30 Nov 2024 15:35:39 +0100 Subject: [PATCH 1041/1312] rtos/rtos: Remove 'ERROR: ' prefix in error log Remove the prefix since it is redundant. Change-Id: Ib064d1031f5ad14ed7711c09bb5f5254d0054d59 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8633 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/rtos/rtos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 0dd538e8f2..f218f63694 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -608,7 +608,7 @@ int rtos_generic_stack_read(struct target *target, int retval; if (stack_ptr == 0) { - LOG_ERROR("Error: null stack pointer in thread"); + LOG_ERROR("null stack pointer in thread"); return -5; } /* Read the stack */ From 4d1b3cbafc7a1bf44ca695103cf4701d8e8ef8e9 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 29 Nov 2024 20:29:18 +0000 Subject: [PATCH 1042/1312] tcl/target: Add support for Nordic nRF54L series The RISC-V coprocessor is currently not supported. It is attached to the DAP via AP#2 but the AP implementation is unknown. The nRFL54L series uses resistive RAM (RRAM) as non-volatile memory which can be programmed directly. Since it does not fit in the current flash memory infrastructure of OpenOCD there is no NVM support so far. Change-Id: I9934af4fd3bb8b7272954fc4b17638c7dabbbee0 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8609 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/nordic/nrf54l.cfg | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tcl/target/nordic/nrf54l.cfg diff --git a/tcl/target/nordic/nrf54l.cfg b/tcl/target/nordic/nrf54l.cfg new file mode 100644 index 0000000000..70ead1365c --- /dev/null +++ b/tcl/target/nordic/nrf54l.cfg @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic nRF54L series +# +# Arm Cortex-M33 processor with RISC-V coprocessor +# +# The device uses resistive RAM (RRAM) as non-volatile memory. +# + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME nrf54l +} + +# Work-area is a space in RAM used for flash programming, by default use 16 KiB. +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x4000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x6ba02477 +} + +transport select swd + +swd newdap $_CHIPNAME cpu -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap -ap-num 0 + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# Create target for the control access port (CTRL-AP). +target create $_CHIPNAME.ctrl mem_ap -dap $_CHIPNAME.dap -ap-num 1 + +adapter speed 1000 + +# Use main processor as default target. +targets $_TARGETNAME + +if {![using_hla]} { + $_TARGETNAME cortex_m reset_config sysresetreq +} From 7d5a0b6a27455aec21d0900183dc6812ccb031b6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 29 Nov 2024 20:39:21 +0000 Subject: [PATCH 1043/1312] tcl/board: Add nRF54L15-DK config file This patch adds support for the nRF54L15 development kit from Nordic Semiconductor. Change-Id: I5e362227fed3982ef21f36e41aade196e0ac7031 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8610 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/nordic/nrf54l15-dk.cfg | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tcl/board/nordic/nrf54l15-dk.cfg diff --git a/tcl/board/nordic/nrf54l15-dk.cfg b/tcl/board/nordic/nrf54l15-dk.cfg new file mode 100644 index 0000000000..d785d852db --- /dev/null +++ b/tcl/board/nordic/nrf54l15-dk.cfg @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic Semiconductor nRF54L15 Development kit +# https://www.nordicsemi.com/Products/Development-hardware/nRF54L15-DK +# + +source [find interface/jlink.cfg] +source [find target/nordic/nrf54l.cfg] From 66faa420a468d5961a0799785042e130cb7441f8 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 13 Dec 2024 07:14:02 +0000 Subject: [PATCH 1044/1312] flash/nor/stm32l4x: Add support for STM32U0 series Tested flash programming / erasing and write protection feature on the STM32U083RC microcontroller. Change-Id: I3af51452f76d1f046d34d61b22d51abe2d0db3e8 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8647 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/openocd.texi | 2 +- src/flash/nor/stm32l4x.c | 38 +++++++++++++++++++++++++++++++++++++- src/flash/nor/stm32l4x.h | 2 ++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 9b5cfbb83e..594f7a7f0c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8001,7 +8001,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn {Flash Driver} {stm32l4x} -All members of the STM32 G0, G4, L4, L4+, L5, U5, WB and WL +All members of the STM32 G0, G4, L4, L4+, L5, U0, U5, WB and WL microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M0+, M4 and M33 cores. The driver automatically recognizes a number of these chips using diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index d66a83dd34..d2e8f30503 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -120,6 +120,12 @@ * http://www.st.com/resource/en/reference_manual/dm00346336.pdf */ +/* STM32U0xxx series for reference. + * + * RM0503 (STM32U0xx) + * https://www.st.com/resource/en/reference_manual/rm0503-stm32u0-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf + */ + /* STM32U5xxx series for reference. * * RM0456 (STM32U5xx) @@ -278,7 +284,7 @@ struct stm32l4_wrp { }; /* human readable list of families this drivers supports (sorted alphabetically) */ -static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U5/WB/WL"; +static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U0/U5/WB/WL"; static const struct stm32l4_rev stm32l47_l48xx_revs[] = { { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } @@ -325,6 +331,10 @@ static const struct stm32l4_rev stm32g0b_g0cxx_revs[] = { { 0x1000, "A" }, }; +static const struct stm32l4_rev stm32u0xx_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32g43_g44xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" }, }; @@ -600,6 +610,30 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = DEVID_STM32U031XX, + .revs = stm32u0xx_revs, + .num_revs = ARRAY_SIZE(stm32u0xx_revs), + .device_str = "STM32U031xx", + .max_flash_size_kb = 64, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF3EA0, + .otp_base = 0x1FFF6800, + .otp_size = 1024, + }, + { + .id = DEVID_STM32U073_U083XX, + .revs = stm32u0xx_revs, + .num_revs = ARRAY_SIZE(stm32u0xx_revs), + .device_str = "STM32U073/U083xx", + .max_flash_size_kb = 256, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF6EA0, + .otp_base = 0x1FFF6800, + .otp_size = 1024, + }, { .id = DEVID_STM32U59_U5AXX, .revs = stm32u59_u5axx_revs, @@ -1957,6 +1991,8 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32C03XX: case DEVID_STM32G05_G06XX: case DEVID_STM32G07_G08XX: + case DEVID_STM32U031XX: + case DEVID_STM32U073_U083XX: case DEVID_STM32L45_L46XX: case DEVID_STM32L41_L42XX: case DEVID_STM32G03_G04XX: diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 5f3bc26576..b1e8f9870d 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -91,6 +91,7 @@ #define DEVID_STM32C03XX 0x453 #define DEVID_STM32U53_U54XX 0x455 #define DEVID_STM32G05_G06XX 0x456 +#define DEVID_STM32U031XX 0x459 #define DEVID_STM32G07_G08XX 0x460 #define DEVID_STM32L49_L4AXX 0x461 #define DEVID_STM32L45_L46XX 0x462 @@ -105,6 +106,7 @@ #define DEVID_STM32G49_G4AXX 0x479 #define DEVID_STM32U59_U5AXX 0x481 #define DEVID_STM32U57_U58XX 0x482 +#define DEVID_STM32U073_U083XX 0x489 #define DEVID_STM32WBA5X 0x492 #define DEVID_STM32WB1XX 0x494 #define DEVID_STM32WB5XX 0x495 From 15d90dd21cfc480714fbefa238998e6b00b9c4b1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 13 Dec 2024 07:34:03 +0000 Subject: [PATCH 1045/1312] tcl/target: Add config for STM32U0x Tested with NUCLEO-U083RC development board. Change-Id: Iec668b45166543adcd1fa5077d41c57a35d3becf Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8648 Tested-by: jenkins Reviewed-by: Tomas Vanek --- tcl/target/stm32u0x.cfg | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tcl/target/stm32u0x.cfg diff --git a/tcl/target/stm32u0x.cfg b/tcl/target/stm32u0x.cfg new file mode 100644 index 0000000000..d3aaed3cbb --- /dev/null +++ b/tcl/target/stm32u0x.cfg @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Configuration file for STM32U0x series. +# +# STM32U0 devices support only SWD transport. +# + +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32u0x +} + +# Work-area is a space in RAM used for flash programming, by default use 4 KiB. +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x6ba02477 +} + +swd newdap $_CHIPNAME cpu -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +flash bank $_CHIPNAME.flash stm32l4x 0x08000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.otp stm32l4x 0x1FFF6800 0 0 0 $_TARGETNAME + +adapter speed 2000 + +if {![using_hla]} { + # Use SYSRESETREQ to perform a soft reset if SRST is not fitted. + cortex_m reset_config sysresetreq +} + +$_TARGETNAME configure -event examine-end { + # Enable debug during low power modes (uses more power). + # DBGMCU_CR |= DBG_STANDBY | DBG_STOP + mmw 0x40015804 0x00000006 0 + + # Stop watchdog counters when core is halted. + # DBGMCU_APB1_FZR |= DBG_IWDG_STOP | DBG_WWDG_STOP + mmw 0x40015808 0x00001800 0 +} From 5284a5f3eca63099fc0f3e19e69d1c55a99b214b Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 25 Oct 2024 17:17:22 +0200 Subject: [PATCH 1046/1312] tcl/interface: Find proper alias for RP1 on Raspberry Pi 5 Previously, Linux assigned gpiochip numbers sequentially depending on when the chip driver was probed. As RP1 is on the end of a PCIe link, it is probed later than the on-board chips (including expanders connected over SPI/I2C). This meant that RP1's gpiochip assignment was at an offset that could potentially change. A downstream kernel patch now assigns fixed offsets for RP1 and the onboard gpiochips. Query the device tree to get proper GPIO_CHIP index. Change-Id: I759978d4b3021c815a7d9febb41961cd1d3d185c Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8650 Reviewed-by: Jonathan Bell Tested-by: jenkins --- tcl/interface/raspberrypi5-gpiod.cfg | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tcl/interface/raspberrypi5-gpiod.cfg b/tcl/interface/raspberrypi5-gpiod.cfg index 9624ad5114..03f3fdb6e6 100644 --- a/tcl/interface/raspberrypi5-gpiod.cfg +++ b/tcl/interface/raspberrypi5-gpiod.cfg @@ -18,11 +18,19 @@ proc read_file { name } { return $result } +proc find_rp1_alias {} { + foreach f [glob -directory "/proc/device-tree/aliases" "gpio\[0-9\]"] { + if {[string match "*/rp1/*" [read_file $f]]} { + return $f + } + } +} + set pcie_aspm [read_file /sys/module/pcie_aspm/parameters/policy] if {![string match {*\[performance\]*} $pcie_aspm]} { echo "Warn : Switch PCIe power saving off or the first couple of pulses gets clocked as fast as 20 MHz" echo "Warn : Issue 'echo performance | sudo tee /sys/module/pcie_aspm/parameters/policy'" } -set GPIO_CHIP 4 +set GPIO_CHIP [string index [find_rp1_alias] end] source [find interface/raspberrypi-gpio-connector.cfg] From e4ad10e0a1c9ea81279d551076c83c7da932def4 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 16:36:15 +0200 Subject: [PATCH 1047/1312] helper/log: Add LOG_TARGET_USER() Add a target-related log function for user messages as it already exists for other log levels. Change-Id: I9076677d6451b900332583e748bab3f83df56d3b Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8661 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/helper/log.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/helper/log.h b/src/helper/log.h index dc8df6fbb6..e2bb131ed3 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -152,6 +152,9 @@ extern int debug_level; #define LOG_TARGET_INFO(target, fmt_str, ...) \ LOG_INFO("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) +#define LOG_TARGET_USER(target, fmt_str, ...) \ + LOG_USER("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + #define LOG_TARGET_WARNING(target, fmt_str, ...) \ LOG_WARNING("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) From 4193322315660436983a16bdc5e18e7252e92a55 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 18:23:14 +0200 Subject: [PATCH 1048/1312] target/mem_ap: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() for log messages as it is used for other targets. Change-Id: I2f937c937a5c09d91dc82b4323be3276ab60b01a Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8662 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/mem_ap.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 4114020776..5b2bbb1ae0 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -34,13 +34,13 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp) return ERROR_FAIL; if (pc->ap_num == DP_APSEL_INVALID) { - LOG_ERROR("AP number not specified"); + LOG_TARGET_ERROR(target, "AP number not specified"); return ERROR_FAIL; } mem_ap = calloc(1, sizeof(struct mem_ap)); if (!mem_ap) { - LOG_ERROR("Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); return ERROR_FAIL; } @@ -58,7 +58,7 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp) static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *target) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED; return ERROR_OK; @@ -68,7 +68,7 @@ static void mem_ap_deinit_target(struct target *target) { struct mem_ap *mem_ap = target->arch_info; - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); if (mem_ap->ap) dap_put_ap(mem_ap->ap); @@ -79,7 +79,7 @@ static void mem_ap_deinit_target(struct target *target) static int mem_ap_arch_state(struct target *target) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); return ERROR_OK; } @@ -95,7 +95,7 @@ static int mem_ap_poll(struct target *target) static int mem_ap_halt(struct target *target) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; target_call_event_callbacks(target, TARGET_EVENT_HALTED); @@ -105,7 +105,7 @@ static int mem_ap_halt(struct target *target) static int mem_ap_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; return ERROR_OK; @@ -114,7 +114,7 @@ static int mem_ap_resume(struct target *target, int current, target_addr_t addre static int mem_ap_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; target_call_event_callbacks(target, TARGET_EVENT_HALTED); @@ -126,7 +126,7 @@ static int mem_ap_assert_reset(struct target *target) target->state = TARGET_RESET; target->debug_reason = DBG_REASON_UNDEFINED; - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); return ERROR_OK; } @@ -138,7 +138,7 @@ static int mem_ap_examine(struct target *target) if (!mem_ap->ap) { mem_ap->ap = dap_get_ap(mem_ap->dap, mem_ap->ap_num); if (!mem_ap->ap) { - LOG_ERROR("Cannot get AP"); + LOG_TARGET_ERROR(target, "Cannot get AP"); return ERROR_FAIL; } } @@ -162,7 +162,7 @@ static int mem_ap_deassert_reset(struct target *target) target->debug_reason = DBG_REASON_NOTHALTED; } - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); return ERROR_OK; } @@ -212,7 +212,7 @@ static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[ { struct mem_ap_alloc_reg_list *mem_ap_alloc = calloc(1, sizeof(struct mem_ap_alloc_reg_list)); if (!mem_ap_alloc) { - LOG_ERROR("Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); return ERROR_FAIL; } @@ -237,7 +237,7 @@ static int mem_ap_read_memory(struct target *target, target_addr_t address, { struct mem_ap *mem_ap = target->arch_info; - LOG_DEBUG("Reading memory at physical address " TARGET_ADDR_FMT + LOG_TARGET_DEBUG(target, "Reading memory at physical address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32, address, size, count); if (count == 0 || !buffer) @@ -252,7 +252,7 @@ static int mem_ap_write_memory(struct target *target, target_addr_t address, { struct mem_ap *mem_ap = target->arch_info; - LOG_DEBUG("Writing memory at physical address " TARGET_ADDR_FMT + LOG_TARGET_DEBUG(target, "Writing memory at physical address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32, address, size, count); if (count == 0 || !buffer) From 78bc6f34d46cb1681143b548dab8c43cca622e43 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 18:24:11 +0200 Subject: [PATCH 1049/1312] target/esirisc: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() for log messages as it is used for other targets. Change-Id: Ia7e9629d89f2e6cb3f9c156e74ac1a02960f9373 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8663 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/esirisc.c | 242 ++++++++++++++++++------------------- src/target/esirisc_trace.c | 36 +++--- 2 files changed, 138 insertions(+), 140 deletions(-) diff --git a/src/target/esirisc.c b/src/target/esirisc.c index 6111414398..fc2d20105a 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -160,11 +160,11 @@ static int esirisc_disable_interrupts(struct target *target) uint32_t etc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETC"); return retval; } @@ -172,7 +172,7 @@ static int esirisc_disable_interrupts(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: ETC"); return retval; } @@ -187,11 +187,11 @@ static int esirisc_enable_interrupts(struct target *target) uint32_t etc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETC"); return retval; } @@ -199,7 +199,7 @@ static int esirisc_enable_interrupts(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: ETC"); return retval; } @@ -212,12 +212,12 @@ static int esirisc_save_interrupts(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &esirisc->etc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETC"); return retval; } @@ -229,12 +229,12 @@ static int esirisc_restore_interrupts(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, esirisc->etc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: ETC"); return retval; } @@ -247,12 +247,12 @@ static int esirisc_save_hwdc(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_HWDC, &esirisc->hwdc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: HWDC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: HWDC"); return retval; } @@ -265,12 +265,12 @@ static int esirisc_restore_hwdc(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_HWDC, esirisc->hwdc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: HWDC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: HWDC"); return retval; } @@ -281,7 +281,7 @@ static int esirisc_save_context(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); for (unsigned int i = 0; i < esirisc->reg_cache->num_regs; ++i) { struct reg *reg = esirisc->reg_cache->reg_list + i; @@ -298,7 +298,7 @@ static int esirisc_restore_context(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); for (unsigned int i = 0; i < esirisc->reg_cache->num_regs; ++i) { struct reg *reg = esirisc->reg_cache->reg_list + i; @@ -316,7 +316,7 @@ static int esirisc_flush_caches(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) { LOG_TARGET_ERROR(target, "not halted"); @@ -325,7 +325,7 @@ static int esirisc_flush_caches(struct target *target) int retval = esirisc_jtag_flush_caches(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to flush caches", target_name(target)); + LOG_TARGET_ERROR(target, "failed to flush caches"); return retval; } @@ -337,7 +337,7 @@ static int esirisc_wait_debug_active(struct esirisc_common *esirisc, int ms) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int64_t t; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(esirisc->target, "-"); t = timeval_ms(); for (;;) { @@ -359,7 +359,7 @@ static int esirisc_read_memory(struct target *target, target_addr_t address, struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int num_bits = 8 * size; for (uint32_t i = 0; i < count; ++i) { @@ -383,12 +383,12 @@ static int esirisc_read_memory(struct target *target, target_addr_t address, break; default: - LOG_ERROR("%s: unsupported size: %" PRIu32, target_name(target), size); + LOG_TARGET_ERROR(target, "unsupported size: %" PRIu32, size); return ERROR_FAIL; } if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read address: 0x%" TARGET_PRIxADDR, target_name(target), + LOG_TARGET_ERROR(target, "failed to read address: 0x%" TARGET_PRIxADDR, address); return retval; } @@ -408,7 +408,7 @@ static int esirisc_write_memory(struct target *target, target_addr_t address, struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int num_bits = 8 * size; for (uint32_t i = 0; i < count; ++i) { @@ -431,12 +431,12 @@ static int esirisc_write_memory(struct target *target, target_addr_t address, break; default: - LOG_ERROR("%s: unsupported size: %" PRIu32, target_name(target), size); + LOG_TARGET_ERROR(target, "unsupported size: %" PRIu32, size); return ERROR_FAIL; } if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write address: 0x%" TARGET_PRIxADDR, target_name(target), + LOG_TARGET_ERROR(target, "failed to write address: 0x%" TARGET_PRIxADDR, address); return retval; } @@ -460,7 +460,7 @@ static int esirisc_next_breakpoint(struct target *target) struct breakpoint **breakpoints_p = esirisc->breakpoints_p; struct breakpoint **breakpoints_e = breakpoints_p + esirisc->num_breakpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); for (int bp_index = 0; breakpoints_p < breakpoints_e; ++breakpoints_p, ++bp_index) if (!*breakpoints_p) @@ -477,7 +477,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea uint32_t ibc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* * The default linker scripts provided by the eSi-RISC toolchain do @@ -491,7 +491,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea bp_index = esirisc_next_breakpoint(target); if (bp_index < 0) { - LOG_ERROR("%s: out of hardware breakpoints", target_name(target)); + LOG_TARGET_ERROR(target, "out of hardware breakpoints"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -502,14 +502,14 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBA_N + bp_index, breakpoint->address); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBA", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBA"); return retval; } /* enable instruction breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, &ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: IBC"); return retval; } @@ -517,7 +517,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBC"); return retval; } @@ -528,7 +528,7 @@ static int esirisc_add_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); while (breakpoint) { if (!breakpoint->is_set) @@ -548,12 +548,12 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b uint32_t ibc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* disable instruction breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, &ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: IBC"); return retval; } @@ -561,7 +561,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBC"); return retval; } @@ -576,12 +576,12 @@ static int esirisc_remove_breakpoints(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* clear instruction breakpoints */ int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, 0); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBC"); return retval; } @@ -596,7 +596,7 @@ static int esirisc_next_watchpoint(struct target *target) struct watchpoint **watchpoints_p = esirisc->watchpoints_p; struct watchpoint **watchpoints_e = watchpoints_p + esirisc->num_watchpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); for (int wp_index = 0; watchpoints_p < watchpoints_e; ++watchpoints_p, ++wp_index) if (!*watchpoints_p) @@ -613,11 +613,11 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc uint32_t dbs, dbc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); wp_index = esirisc_next_watchpoint(target); if (wp_index < 0) { - LOG_ERROR("%s: out of hardware watchpoints", target_name(target)); + LOG_TARGET_ERROR(target, "out of hardware watchpoints"); return ERROR_FAIL; } @@ -628,14 +628,14 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBA_N + wp_index, watchpoint->address); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBA", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBA"); return retval; } /* specify data breakpoint size */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBS, &dbs); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DBS", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DBS"); return retval; } @@ -657,7 +657,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc break; default: - LOG_ERROR("%s: unsupported length: %" PRIu32, target_name(target), + LOG_TARGET_ERROR(target, "unsupported length: %" PRIu32, watchpoint->length); return ERROR_FAIL; } @@ -666,14 +666,14 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBS, dbs); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBS", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBS"); return retval; } /* enable data breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, &dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DBC"); return retval; } @@ -692,8 +692,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc break; default: - LOG_ERROR("%s: unsupported rw: %" PRId32, target_name(target), - watchpoint->rw); + LOG_TARGET_ERROR(target, "unsupported rw: %" PRId32, watchpoint->rw); return ERROR_FAIL; } @@ -701,7 +700,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBC"); return retval; } @@ -712,7 +711,7 @@ static int esirisc_add_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); while (watchpoint) { if (!watchpoint->is_set) @@ -732,12 +731,12 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w uint32_t dbc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* disable data breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, &dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DBC"); return retval; } @@ -745,7 +744,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBC"); return retval; } @@ -760,12 +759,12 @@ static int esirisc_remove_watchpoints(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* clear data breakpoints */ int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, 0); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBC"); return retval; } @@ -779,14 +778,14 @@ static int esirisc_halt(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state == TARGET_HALTED) return ERROR_OK; int retval = esirisc_jtag_break(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to halt target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to halt target"); return retval; } @@ -802,11 +801,11 @@ static int esirisc_disable_step(struct target *target) uint32_t dc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, &dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DC"); return retval; } @@ -814,7 +813,7 @@ static int esirisc_disable_step(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DC"); return retval; } @@ -828,11 +827,11 @@ static int esirisc_enable_step(struct target *target) uint32_t dc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, &dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DC"); return retval; } @@ -840,7 +839,7 @@ static int esirisc_enable_step(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DC"); return retval; } @@ -855,7 +854,7 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add struct breakpoint *breakpoint = NULL; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) { LOG_TARGET_ERROR(target, "not halted"); @@ -901,7 +900,7 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } @@ -921,7 +920,7 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add static int esirisc_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); return esirisc_resume_or_step(target, current, address, handle_breakpoints, debug_execution, false); @@ -930,7 +929,7 @@ static int esirisc_resume(struct target *target, int current, target_addr_t addr static int esirisc_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); return esirisc_resume_or_step(target, current, address, handle_breakpoints, 0, true); @@ -942,20 +941,20 @@ static int esirisc_debug_step(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); esirisc_disable_interrupts(target); esirisc_enable_step(target); retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } retval = esirisc_wait_debug_active(esirisc, STEP_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("%s: step timed out", target_name(target)); + LOG_TARGET_ERROR(target, "step timed out"); return retval; } @@ -971,23 +970,23 @@ static int esirisc_debug_reset(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_assert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to assert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to assert reset"); return retval; } retval = esirisc_jtag_deassert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to deassert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to deassert reset"); return retval; } retval = esirisc_wait_debug_active(esirisc, RESET_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("%s: reset timed out", target_name(target)); + LOG_TARGET_ERROR(target, "reset timed out"); return retval; } @@ -1000,11 +999,11 @@ static int esirisc_debug_enable(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_enable_debug(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to enable debug mode", target_name(target)); + LOG_TARGET_ERROR(target, "failed to enable debug mode"); return retval; } @@ -1015,13 +1014,13 @@ static int esirisc_debug_enable(struct target *target) * targets, which will respond with all ones and appear active. */ if (esirisc_jtag_is_stopped(jtag_info)) { - LOG_INFO("%s: debug clock inactive; attempting debug reset", target_name(target)); + LOG_TARGET_INFO(target, "debug clock inactive; attempting debug reset"); retval = esirisc_debug_reset(target); if (retval != ERROR_OK) return retval; if (esirisc_jtag_is_stopped(jtag_info)) { - LOG_ERROR("%s: target unresponsive; giving up", target_name(target)); + LOG_TARGET_ERROR(target, "target unresponsive; giving up"); return ERROR_FAIL; } } @@ -1034,7 +1033,7 @@ static int esirisc_debug_entry(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct breakpoint *breakpoint; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); esirisc_save_context(target); @@ -1087,12 +1086,12 @@ static int esirisc_poll(struct target *target) retval = esirisc_jtag_enable_debug(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to poll target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to poll target"); return retval; } if (esirisc_jtag_is_stopped(jtag_info)) { - LOG_ERROR("%s: target has stopped; reset required", target_name(target)); + LOG_TARGET_ERROR(target, "target has stopped; reset required"); target->state = TARGET_UNKNOWN; return ERROR_TARGET_FAILURE; } @@ -1122,7 +1121,7 @@ static int esirisc_assert_reset(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (jtag_get_reset_config() & RESET_HAS_SRST) { jtag_add_reset(1, 1); @@ -1134,7 +1133,7 @@ static int esirisc_assert_reset(struct target *target) retval = esirisc_jtag_assert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to assert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to assert reset"); return retval; } } @@ -1153,19 +1152,19 @@ static int esirisc_reset_entry(struct target *target) uint32_t eta, epc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* read exception table address */ retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETA, &eta); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETA", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETA"); return retval; } /* read reset entry point */ retval = esirisc_jtag_read_word(jtag_info, eta + ENTRY_RESET, &epc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read address: 0x%" TARGET_PRIxADDR, target_name(target), + LOG_TARGET_ERROR(target, "failed to read address: 0x%" TARGET_PRIxADDR, (target_addr_t)epc); return retval; } @@ -1173,7 +1172,7 @@ static int esirisc_reset_entry(struct target *target) /* write reset entry point */ retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_EPC, epc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: EPC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: EPC"); return retval; } @@ -1186,7 +1185,7 @@ static int esirisc_deassert_reset(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (jtag_get_reset_config() & RESET_HAS_SRST) { jtag_add_reset(0, 0); @@ -1202,14 +1201,14 @@ static int esirisc_deassert_reset(struct target *target) } else { retval = esirisc_jtag_deassert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to deassert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to deassert reset"); return retval; } } retval = esirisc_wait_debug_active(esirisc, RESET_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("%s: reset timed out", target_name(target)); + LOG_TARGET_ERROR(target, "reset timed out"); return retval; } @@ -1225,7 +1224,7 @@ static int esirisc_deassert_reset(struct target *target) if (!target->reset_halt) { retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } } @@ -1241,7 +1240,7 @@ static int esirisc_arch_state(struct target *target) uint32_t eid = buf_get_u32(esirisc->eid->value, 0, esirisc->eid->size); uint32_t ed = buf_get_u32(esirisc->ed->value, 0, esirisc->ed->size); - LOG_USER("target halted due to %s, exception: %s\n" + LOG_TARGET_USER(target, "target halted due to %s, exception: %s\n" "EPC: 0x%" PRIx32 ", ECAS: 0x%" PRIx32 ", EID: 0x%" PRIx32 ", ED: 0x%" PRIx32, debug_reason_name(target), esirisc_exception_strings[eid], epc, ecas, eid, ed); @@ -1252,7 +1251,7 @@ static const char *esirisc_get_gdb_arch(const struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* * Targets with the UNIFIED_ADDRESS_SPACE option disabled employ a @@ -1272,7 +1271,7 @@ static int esirisc_get_gdb_reg_list(struct target *target, struct reg **reg_list { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); *reg_list_size = ESIRISC_NUM_REGS; @@ -1302,11 +1301,11 @@ static int esirisc_read_reg(struct reg *reg) struct target *target = esirisc->target; uint32_t data; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_reg(jtag_info, reg->number, &data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read register: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to read register: %s", reg->name); return retval; } @@ -1325,11 +1324,11 @@ static int esirisc_write_reg(struct reg *reg) struct target *target = esirisc->target; uint32_t data = buf_get_u32(reg->value, 0, reg->size); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_reg(jtag_info, reg->number, data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write register: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to write register: %s", reg->name); return retval; } @@ -1347,11 +1346,11 @@ static int esirisc_read_csr(struct reg *reg) struct target *target = esirisc->target; uint32_t data; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_csr(jtag_info, reg_info->bank, reg_info->csr, &data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read CSR: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to read CSR: %s", reg->name); return retval; } @@ -1370,11 +1369,11 @@ static int esirisc_write_csr(struct reg *reg) struct target *target = esirisc->target; uint32_t data = buf_get_u32(reg->value, 0, reg->size); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_csr(jtag_info, reg_info->bank, reg_info->csr, data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write CSR: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to write CSR: %s", reg->name); return retval; } @@ -1390,7 +1389,7 @@ static int esirisc_get_reg(struct reg *reg) struct esirisc_common *esirisc = reg_info->esirisc; struct target *target = esirisc->target; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; @@ -1405,7 +1404,7 @@ static int esirisc_set_reg(struct reg *reg, uint8_t *buf) struct target *target = esirisc->target; uint32_t value = buf_get_u32(buf, 0, reg->size); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; @@ -1429,7 +1428,7 @@ static struct reg_cache *esirisc_build_reg_cache(struct target *target) struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(ESIRISC_NUM_REGS, sizeof(struct reg)); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); cache->name = "eSi-RISC registers"; cache->next = NULL; @@ -1519,11 +1518,11 @@ static int esirisc_identify(struct target *target) uint32_t csr; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_ARCH0, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: ARCH0", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: ARCH0"); return retval; } @@ -1532,7 +1531,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_MEM, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: MEM", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: MEM"); return retval; } @@ -1541,7 +1540,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_IC, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: IC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: IC"); return retval; } @@ -1549,7 +1548,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_DC, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: DC"); return retval; } @@ -1557,7 +1556,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_DBG, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: DBG", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: DBG"); return retval; } @@ -1566,7 +1565,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_TRACE, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: TRACE", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: TRACE"); return retval; } @@ -1584,8 +1583,7 @@ static int esirisc_target_create(struct target *target, Jim_Interp *interp) return ERROR_FAIL; if (tap->ir_length != INSTR_LENGTH) { - LOG_ERROR("%s: invalid IR length; expected %d", target_name(target), - INSTR_LENGTH); + LOG_TARGET_ERROR(target, "invalid IR length; expected %d", INSTR_LENGTH); return ERROR_FAIL; } @@ -1629,7 +1627,7 @@ static int esirisc_examine(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (!target_was_examined(target)) { retval = esirisc_debug_enable(target); @@ -1649,7 +1647,7 @@ static int esirisc_examine(struct target *target) } else { retval = esirisc_jtag_break(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to halt target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to halt target"); return retval; } @@ -1658,7 +1656,7 @@ static int esirisc_examine(struct target *target) retval = esirisc_identify(target); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to identify target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to identify target"); return retval; } @@ -1675,20 +1673,20 @@ static int esirisc_examine(struct target *target) else { retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } } target_set_examined(target); - LOG_INFO("%s: %d bit, %d registers, %s%s%s", target_name(target), + LOG_TARGET_INFO(target, "%d bit, %d registers, %s%s%s", esirisc->num_bits, esirisc->num_regs, target_endianness(target), esirisc->has_icache ? ", icache" : "", esirisc->has_dcache ? ", dcache" : ""); - LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints%s", target_name(target), + LOG_TARGET_INFO(target, "hardware has %d breakpoints, %d watchpoints%s", esirisc->num_breakpoints, esirisc->num_watchpoints, esirisc->has_trace ? ", trace" : ""); } @@ -1707,7 +1705,7 @@ COMMAND_HANDLER(handle_esirisc_cache_arch_command) else if (strcmp(*CMD_ARGV, "von_neumann") == 0) esirisc->cache_arch = ESIRISC_CACHE_VON_NEUMANN; else { - LOG_ERROR("invalid cache_arch: %s", *CMD_ARGV); + LOG_TARGET_ERROR(target, "invalid cache_arch: %s", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } } @@ -1724,7 +1722,7 @@ COMMAND_HANDLER(handle_esirisc_flush_caches_command) int retval; if (!esirisc_has_cache(esirisc)) { - LOG_ERROR("target does not support caching"); + LOG_TARGET_ERROR(target, "target does not support caching"); return ERROR_FAIL; } @@ -1770,7 +1768,7 @@ COMMAND_HANDLER(handle_esirisc_hwdc_command) while (CMD_ARGC-- > 0) { int mask = esirisc_find_hwdc_mask(CMD_ARGV[CMD_ARGC]); if (mask < 0) { - LOG_ERROR("invalid mask: %s", CMD_ARGV[CMD_ARGC]); + LOG_TARGET_ERROR(target, "invalid mask: %s", CMD_ARGV[CMD_ARGC]); return ERROR_COMMAND_SYNTAX_ERROR; } esirisc->hwdc_save |= mask; diff --git a/src/target/esirisc_trace.c b/src/target/esirisc_trace.c index a70d9d74bf..a1d92d1ca9 100644 --- a/src/target/esirisc_trace.c +++ b/src/target/esirisc_trace.c @@ -85,7 +85,7 @@ static int esirisc_trace_clear_status(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, ~0); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Status", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Status"); return retval; } @@ -102,7 +102,7 @@ static int esirisc_trace_get_status(struct target *target, uint32_t *status) int retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, status); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: Status", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: Status"); return retval; } @@ -121,7 +121,7 @@ static int esirisc_trace_start(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: Control"); return retval; } @@ -129,7 +129,7 @@ static int esirisc_trace_start(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Control"); return retval; } @@ -148,7 +148,7 @@ static int esirisc_trace_stop(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: Control"); return retval; } @@ -156,7 +156,7 @@ static int esirisc_trace_stop(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Control"); return retval; } @@ -195,7 +195,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Control"); return retval; } @@ -203,14 +203,14 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_START, trace_info->buffer_start); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: BufferStart", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: BufferStart"); return retval; } retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_END, trace_info->buffer_end); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: BufferEnd", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: BufferEnd"); return retval; } @@ -221,7 +221,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR, trace_info->buffer_start); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: BufferCurrent", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: BufferCurrent"); return retval; } @@ -241,7 +241,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_TRIGGER, trigger); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Trigger", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Trigger"); return retval; } @@ -249,14 +249,14 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_DATA, trace_info->start_data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StartData", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StartData"); return retval; } retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_MASK, trace_info->start_mask); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StartMask", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StartMask"); return retval; } @@ -264,14 +264,14 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_DATA, trace_info->stop_data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StopData", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StopData"); return retval; } retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_MASK, trace_info->stop_mask); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StopMask", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StopMask"); return retval; } @@ -279,7 +279,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_DELAY, trace_info->delay_cycles); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Delay", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Delay"); return retval; } @@ -326,7 +326,7 @@ static int esirisc_trace_read_memory(struct target *target, target_addr_t addres retval = target_read_memory(target, address, 1, size, buffer); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read trace data", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read trace data"); return retval; } @@ -346,7 +346,7 @@ static int esirisc_trace_read_buffer(struct target *target, uint8_t *buffer) retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR, &buffer_cur); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: BufferCurrent", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: BufferCurrent"); return retval; } From a75feb0bfd34c4069834fce0089367aa57102f10 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 22 Oct 2024 18:22:12 +0200 Subject: [PATCH 1050/1312] target/armv7m: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() to indicate which target the message belongs to. Change-Id: Ib1cd37fe6eca2ea42095d2d371116446a936e20a Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8664 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv7m.c | 52 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index a403b25a91..49a8a4bba5 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -171,7 +171,7 @@ int armv7m_restore_context(struct target *target) struct armv7m_common *armv7m = target_to_armv7m(target); struct reg_cache *cache = armv7m->arm.core_cache; - LOG_DEBUG(" "); + LOG_TARGET_DEBUG(target, " "); if (armv7m->pre_restore_context) armv7m->pre_restore_context(target); @@ -366,9 +366,9 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r, buf_set_u32(r->value + 4, 0, 32, reg_value); uint64_t q = buf_get_u64(r->value, 0, 64); - LOG_DEBUG("read %s value 0x%016" PRIx64, r->name, q); + LOG_TARGET_DEBUG(target, "read %s value 0x%016" PRIx64, r->name, q); } else { - LOG_DEBUG("read %s value 0x%08" PRIx32, r->name, reg_value); + LOG_TARGET_DEBUG(target, "read %s value 0x%08" PRIx32, r->name, reg_value); } } @@ -436,9 +436,9 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, goto out_error; uint64_t q = buf_get_u64(value, 0, 64); - LOG_DEBUG("write %s value 0x%016" PRIx64, r->name, q); + LOG_TARGET_DEBUG(target, "write %s value 0x%016" PRIx64, r->name, q); } else { - LOG_DEBUG("write %s value 0x%08" PRIx32, r->name, t); + LOG_TARGET_DEBUG(target, "write %s value 0x%08" PRIx32, r->name, t); } } @@ -449,7 +449,7 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, out_error: r->dirty = true; - LOG_ERROR("Error setting register %s", r->name); + LOG_TARGET_ERROR(target, "Error setting register %s", r->name); return retval; } @@ -520,7 +520,7 @@ int armv7m_start_algorithm(struct target *target, * at the exit point */ if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { - LOG_ERROR("current target isn't an ARMV7M target"); + LOG_TARGET_ERROR(target, "current target isn't an ARMV7M target"); return ERROR_TARGET_INVALID; } @@ -563,12 +563,12 @@ int armv7m_start_algorithm(struct target *target, /* uint32_t regvalue; */ if (!reg) { - LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + LOG_TARGET_ERROR(target, "BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { - LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", + LOG_TARGET_ERROR(target, "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -600,10 +600,11 @@ int armv7m_start_algorithm(struct target *target, /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */ if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) { armv7m_algorithm_info->core_mode = ARM_MODE_THREAD; - LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead"); + LOG_TARGET_INFO(target, "ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead"); } - LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); + LOG_TARGET_DEBUG(target, "setting core_mode: 0x%2.2x", + armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true; @@ -633,7 +634,7 @@ int armv7m_wait_algorithm(struct target *target, * at the exit point */ if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { - LOG_ERROR("current target isn't an ARMV7M target"); + LOG_TARGET_ERROR(target, "current target isn't an ARMV7M target"); return ERROR_TARGET_INVALID; } @@ -653,7 +654,7 @@ int armv7m_wait_algorithm(struct target *target, /* PC value has been cached in cortex_m_debug_entry() */ uint32_t pc = buf_get_u32(armv7m->arm.pc->value, 0, 32); if (pc != exit_point) { - LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR, + LOG_TARGET_DEBUG(target, "failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR, pc, exit_point); return ERROR_TARGET_ALGO_EXIT; } @@ -678,12 +679,13 @@ int armv7m_wait_algorithm(struct target *target, false); if (!reg) { - LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + LOG_TARGET_ERROR(target, "BUG: register '%s' not found", + reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { - LOG_ERROR( + LOG_TARGET_ERROR(target, "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; @@ -701,7 +703,7 @@ int armv7m_wait_algorithm(struct target *target, uint32_t regvalue; regvalue = buf_get_u32(reg->value, 0, 32); if (regvalue != armv7m_algorithm_info->context[i]) { - LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32, + LOG_TARGET_DEBUG(target, "restoring register %s with value 0x%8.8" PRIx32, reg->name, armv7m_algorithm_info->context[i]); buf_set_u32(reg->value, 0, 32, armv7m_algorithm_info->context[i]); @@ -712,7 +714,7 @@ int armv7m_wait_algorithm(struct target *target, /* restore previous core mode */ if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) { - LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); + LOG_TARGET_DEBUG(target, "restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true; @@ -738,9 +740,8 @@ int armv7m_arch_state(struct target *target) ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32); sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32); - LOG_USER("[%s] halted due to %s, current mode: %s %s\n" + LOG_TARGET_USER(target, "halted due to %s, current mode: %s %s\n" "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s%s", - target_name(target), debug_reason_name(target), arm_mode_name(arm->core_mode), armv7m_exception_string(armv7m->exception_number), @@ -807,13 +808,13 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) feature->name = armv7m_regs[i].feature; reg_list[i].feature = feature; } else - LOG_ERROR("unable to allocate feature list"); + LOG_TARGET_ERROR(target, "unable to allocate feature list"); reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); if (reg_list[i].reg_data_type) reg_list[i].reg_data_type->type = armv7m_regs[i].type; else - LOG_ERROR("unable to allocate reg type list"); + LOG_TARGET_ERROR(target, "unable to allocate reg type list"); } arm->cpsr = reg_list + ARMV7M_XPSR; @@ -918,7 +919,7 @@ int armv7m_checksum_memory(struct target *target, if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); else - LOG_ERROR("error executing cortex_m crc algorithm"); + LOG_TARGET_ERROR(target, "error executing cortex_m crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -1003,7 +1004,7 @@ int armv7m_blank_check_memory(struct target *target, uint32_t erased_word = erased_value | (erased_value << 8) | (erased_value << 16) | (erased_value << 24); - LOG_DEBUG("Starting erase check of %d blocks, parameters@" + LOG_TARGET_DEBUG(target, "Starting erase check of %d blocks, parameters@" TARGET_ADDR_FMT, blocks_to_check, erase_check_params->address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; @@ -1044,7 +1045,8 @@ int armv7m_blank_check_memory(struct target *target, blocks[i].result = result; } if (i && timed_out) - LOG_INFO("Slow CPU clock: %d blocks checked, %d remain. Continuing...", i, num_blocks-i); + LOG_TARGET_INFO(target, "Slow CPU clock: %d blocks checked, %d remain. Continuing...", + i, num_blocks - i); retval = i; /* return number of blocks really checked */ @@ -1085,7 +1087,7 @@ int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found) r->dirty = true; r->valid = true; result = true; - LOG_DEBUG("Skipping over BKPT instruction"); + LOG_TARGET_DEBUG(target, "Skipping over BKPT instruction"); } } } From 4f2744d0fede64504ae4e9f9913eebc55c915d9a Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 23 Oct 2024 12:56:37 +0200 Subject: [PATCH 1051/1312] target/arc: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() for log messages as it is used for other targets. While at it, rework the log messages, for example by removing spaces or punctuation marks at the end of the message. Change-Id: I3dd4314d354b5628144f98325540926981778616 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8665 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arc.c | 252 +++++++++++++++++++++---------------------- src/target/arc_mem.c | 18 ++-- 2 files changed, 135 insertions(+), 135 deletions(-) diff --git a/src/target/arc.c b/src/target/arc.c index 28ce939473..5c08c5664c 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -61,7 +61,7 @@ static int arc_single_step_core(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) { - LOG_DEBUG("Adding %s reg_data_type", data_type->data_type.id); + LOG_TARGET_DEBUG(target, "Adding %s reg_data_type", data_type->data_type.id); struct arc_common *arc = target_to_arc(target); assert(arc); @@ -104,7 +104,7 @@ static int arc_reset_caches_states(struct target *target) { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("Resetting internal variables of caches states"); + LOG_TARGET_DEBUG(target, "Resetting internal variables of caches states"); /* Reset caches states. */ arc->dcache_flushed = false; @@ -127,7 +127,7 @@ static int arc_init_arch_info(struct target *target, struct arc_common *arc, /* The only allowed ir_length is 4 for ARC jtag. */ if (tap->ir_length != 4) { - LOG_ERROR("ARC jtag instruction length should be equal to 4"); + LOG_TARGET_ERROR(target, "ARC jtag instruction length should be equal to 4"); return ERROR_FAIL; } @@ -146,7 +146,7 @@ static int arc_init_arch_info(struct target *target, struct arc_common *arc, sizeof(*std_types)); if (!std_types) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } @@ -205,7 +205,7 @@ int arc_reg_add(struct target *target, struct arc_reg_desc *arc_reg, } arc->num_regs += 1; - LOG_DEBUG( + LOG_TARGET_DEBUG(target, "added register {name=%s, num=0x%" PRIx32 ", type=%s%s%s%s}", arc_reg->name, arc_reg->arch_num, arc_reg->data_type->id, arc_reg->is_core ? ", core" : "", arc_reg->is_bcr ? ", bcr" : "", @@ -227,7 +227,7 @@ static int arc_get_register(struct reg *reg) uint32_t value; if (reg->valid) { - LOG_DEBUG("Get register (cached) gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Get register (cached) gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, reg->number, desc->name, target_buffer_get_u32(target, reg->value)); return ERROR_OK; } @@ -235,7 +235,7 @@ static int arc_get_register(struct reg *reg) if (desc->is_core) { /* Accessing to R61/R62 registers causes Jtag hang */ if (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62) { - LOG_ERROR("It is forbidden to read core registers 61 and 62."); + LOG_TARGET_ERROR(target, "It is forbidden to read core registers 61 and 62"); return ERROR_FAIL; } CHECK_RETVAL(arc_jtag_read_core_reg_one(&arc->jtag_info, desc->arch_num, @@ -255,7 +255,7 @@ static int arc_get_register(struct reg *reg) reg->dirty = false; - LOG_DEBUG("Get register gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Get register gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, reg->number, desc->name, value); @@ -276,12 +276,12 @@ static int arc_set_register(struct reg *reg, uint8_t *buf) /* Accessing to R61/R62 registers causes Jtag hang */ if (desc->is_core && (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62)) { - LOG_ERROR("It is forbidden to write core registers 61 and 62."); + LOG_TARGET_ERROR(target, "It is forbidden to write core registers 61 and 62"); return ERROR_FAIL; } target_buffer_set_u32(target, reg->value, value); - LOG_DEBUG("Set register gdb_num=%" PRIu32 ", name=%s, value=0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "Set register gdb_num=%" PRIu32 ", name=%s, value=0x%08" PRIx32, reg->number, desc->name, value); reg->valid = true; @@ -355,7 +355,7 @@ static int arc_build_reg_cache(struct target *target) struct reg *reg_list = calloc(num_regs, sizeof(*reg_list)); if (!cache || !reg_list) { - LOG_ERROR("Not enough memory"); + LOG_TARGET_ERROR(target, "Not enough memory"); goto fail; } @@ -368,14 +368,14 @@ static int arc_build_reg_cache(struct target *target) (*cache_p) = cache; if (list_empty(&arc->core_reg_descriptions)) { - LOG_ERROR("No core registers were defined"); + LOG_TARGET_ERROR(target, "No core registers were defined"); goto fail; } list_for_each_entry(reg_desc, &arc->core_reg_descriptions, list) { CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); - LOG_DEBUG("reg n=%3li name=%3s group=%s feature=%s", i, + LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, reg_list[i].feature->name); @@ -383,27 +383,27 @@ static int arc_build_reg_cache(struct target *target) } if (list_empty(&arc->aux_reg_descriptions)) { - LOG_ERROR("No aux registers were defined"); + LOG_TARGET_ERROR(target, "No aux registers were defined"); goto fail; } list_for_each_entry(reg_desc, &arc->aux_reg_descriptions, list) { CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); - LOG_DEBUG("reg n=%3li name=%3s group=%s feature=%s", i, + LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, reg_list[i].feature->name); /* PC and DEBUG are essential so we search for them. */ if (!strcmp("pc", reg_desc->name)) { if (arc->pc_index_in_cache != ULONG_MAX) { - LOG_ERROR("Double definition of PC in configuration"); + LOG_TARGET_ERROR(target, "Double definition of PC in configuration"); goto fail; } arc->pc_index_in_cache = i; } else if (!strcmp("debug", reg_desc->name)) { if (arc->debug_index_in_cache != ULONG_MAX) { - LOG_ERROR("Double definition of DEBUG in configuration"); + LOG_TARGET_ERROR(target, "Double definition of DEBUG in configuration"); goto fail; } arc->debug_index_in_cache = i; @@ -413,7 +413,7 @@ static int arc_build_reg_cache(struct target *target) if (arc->pc_index_in_cache == ULONG_MAX || arc->debug_index_in_cache == ULONG_MAX) { - LOG_ERROR("`pc' and `debug' registers must be present in target description."); + LOG_TARGET_ERROR(target, "`pc' and `debug' registers must be present in target description"); goto fail; } @@ -446,7 +446,7 @@ static int arc_build_bcr_reg_cache(struct target *target) unsigned long gdb_regnum = arc->core_and_aux_cache->num_regs; if (!cache || !reg_list) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); goto fail; } @@ -459,7 +459,7 @@ static int arc_build_bcr_reg_cache(struct target *target) (*cache_p) = cache; if (list_empty(&arc->bcr_reg_descriptions)) { - LOG_ERROR("No BCR registers are defined"); + LOG_TARGET_ERROR(target, "No BCR registers are defined"); goto fail; } @@ -469,7 +469,7 @@ static int arc_build_bcr_reg_cache(struct target *target) * not real register. */ reg_list[i].exist = true; - LOG_DEBUG("reg n=%3li name=%3s group=%s feature=%s", i, + LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, reg_list[i].feature->name); i += 1; @@ -501,7 +501,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], *reg_list = calloc(*reg_list_size, sizeof(struct reg *)); if (!*reg_list) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } @@ -521,7 +521,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], reg_cache = reg_cache->next; } assert(i == arc->num_regs); - LOG_DEBUG("REG_CLASS_ALL: number of regs=%i", *reg_list_size); + LOG_TARGET_DEBUG(target, "REG_CLASS_ALL: number of regs=%i", *reg_list_size); } else { unsigned long i = 0; unsigned long gdb_reg_number = 0; @@ -539,7 +539,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], reg_cache = reg_cache->next; } *reg_list_size = i; - LOG_DEBUG("REG_CLASS_GENERAL: number of regs=%i", *reg_list_size); + LOG_TARGET_DEBUG(target, "REG_CLASS_GENERAL: number of regs=%i", *reg_list_size); } return ERROR_OK; @@ -551,13 +551,13 @@ int arc_reg_get_field(struct target *target, const char *reg_name, { struct reg_data_type_struct_field *field; - LOG_DEBUG("getting register field (reg_name=%s, field_name=%s)", reg_name, field_name); + LOG_TARGET_DEBUG(target, "getting register field (reg_name=%s, field_name=%s)", reg_name, field_name); /* Get register */ struct reg *reg = arc_reg_get_by_name(target->reg_cache, reg_name, true); if (!reg) { - LOG_ERROR("Requested register `%s' doesn't exist.", reg_name); + LOG_TARGET_ERROR(target, "Requested register `%s' doesn't exist", reg_name); return ERROR_ARC_REGISTER_NOT_FOUND; } @@ -597,7 +597,7 @@ int arc_reg_get_field(struct target *target, const char *reg_name, static int arc_get_register_value(struct target *target, const char *reg_name, uint32_t *value_ptr) { - LOG_DEBUG("reg_name=%s", reg_name); + LOG_TARGET_DEBUG(target, "reg_name=%s", reg_name); struct reg *reg = arc_reg_get_by_name(target->reg_cache, reg_name, true); @@ -615,10 +615,10 @@ static int arc_get_register_value(struct target *target, const char *reg_name, static int arc_set_register_value(struct target *target, const char *reg_name, uint32_t value) { - LOG_DEBUG("reg_name=%s value=0x%08" PRIx32, reg_name, value); + LOG_TARGET_DEBUG(target, "reg_name=%s value=0x%08" PRIx32, reg_name, value); if (!(target && reg_name)) { - LOG_ERROR("Arguments cannot be NULL."); + LOG_TARGET_ERROR(target, "Arguments cannot be NULL"); return ERROR_FAIL; } @@ -655,7 +655,7 @@ static int arc_configure_dccm(struct target *target) if (dccm_build_size0 == 0xF) dccm_size <<= dccm_build_size1; arc->dccm_end = arc->dccm_start + dccm_size; - LOG_DEBUG("DCCM detected start=0x%" PRIx32 " end=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "DCCM detected start=0x%" PRIx32 " end=0x%" PRIx32, arc->dccm_start, arc->dccm_end); } @@ -687,7 +687,7 @@ static int arc_configure_iccm(struct target *target) /* iccm0 start is located in highest 4 bits of aux_iccm */ arc->iccm0_start = aux_iccm & 0xF0000000; arc->iccm0_end = arc->iccm0_start + iccm0_size; - LOG_DEBUG("ICCM0 detected start=0x%" PRIx32 " end=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "ICCM0 detected start=0x%" PRIx32 " end=0x%" PRIx32, arc->iccm0_start, arc->iccm0_end); } @@ -707,7 +707,7 @@ static int arc_configure_iccm(struct target *target) iccm1_size <<= iccm_build_size11; arc->iccm1_start = aux_iccm & 0x0F000000; arc->iccm1_end = arc->iccm1_start + iccm1_size; - LOG_DEBUG("ICCM1 detected start=0x%" PRIx32 " end=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "ICCM1 detected start=0x%" PRIx32 " end=0x%" PRIx32, arc->iccm1_start, arc->iccm1_end); } return ERROR_OK; @@ -716,7 +716,7 @@ static int arc_configure_iccm(struct target *target) /* Configure some core features, depending on BCRs. */ static int arc_configure(struct target *target) { - LOG_DEBUG("Configuring ARC ICCM and DCCM"); + LOG_TARGET_DEBUG(target, "Configuring ARC ICCM and DCCM"); /* Configuring DCCM if DCCM_BUILD and AUX_DCCM are known registers. */ if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true) && @@ -770,9 +770,9 @@ static int arc_exit_debug(struct target *target) CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); if (debug_level >= LOG_LVL_DEBUG) { - LOG_DEBUG("core stopped (halted) debug-reg: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core stopped (halted) debug-reg: 0x%08" PRIx32, value); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); - LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core STATUS32: 0x%08" PRIx32, value); } return ERROR_OK; @@ -783,19 +783,19 @@ static int arc_halt(struct target *target) uint32_t value, irq_state; struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("target->state: %s", target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { - LOG_DEBUG("target was already halted"); + LOG_TARGET_DEBUG(target, "target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) - LOG_WARNING("target was in unknown state when halt was requested"); + LOG_TARGET_WARNING(target, "target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { - LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); + LOG_TARGET_ERROR(target, "can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { target->debug_reason = DBG_REASON_DBGRQ; @@ -825,9 +825,9 @@ static int arc_halt(struct target *target) /* some more debug information */ if (debug_level >= LOG_LVL_DEBUG) { - LOG_DEBUG("core stopped (halted) DEGUB-REG: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core stopped (halted) DEGUB-REG: 0x%08" PRIx32, value); CHECK_RETVAL(arc_get_register_value(target, "status32", &value)); - LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core STATUS32: 0x%08" PRIx32, value); } return ERROR_OK; @@ -846,7 +846,7 @@ static int arc_save_context(struct target *target) struct arc_common *arc = target_to_arc(target); struct reg *reg_list = arc->core_and_aux_cache->reg_list; - LOG_DEBUG("Saving aux and core registers values"); + LOG_TARGET_DEBUG(target, "Saving aux and core registers values"); assert(reg_list); /* It is assumed that there is at least one AUX register in the list, for @@ -865,7 +865,7 @@ static int arc_save_context(struct target *target) unsigned int aux_cnt = 0; if (!core_values || !core_addrs || !aux_values || !aux_addrs) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); retval = ERROR_FAIL; goto exit; } @@ -893,7 +893,7 @@ static int arc_save_context(struct target *target) if (core_cnt > 0) { retval = arc_jtag_read_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to read core registers failed."); + LOG_TARGET_ERROR(target, "Attempt to read core registers failed"); retval = ERROR_FAIL; goto exit; } @@ -901,7 +901,7 @@ static int arc_save_context(struct target *target) if (aux_cnt > 0) { retval = arc_jtag_read_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to read aux registers failed."); + LOG_TARGET_ERROR(target, "Attempt to read aux registers failed"); retval = ERROR_FAIL; goto exit; } @@ -916,7 +916,7 @@ static int arc_save_context(struct target *target) target_buffer_set_u32(target, reg->value, core_values[core_cnt]); reg->valid = true; reg->dirty = false; - LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "Get core register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, core_values[core_cnt]); core_cnt++; } @@ -931,7 +931,7 @@ static int arc_save_context(struct target *target) target_buffer_set_u32(target, reg->value, aux_values[aux_cnt]); reg->valid = true; reg->dirty = false; - LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "Get aux register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, aux_values[aux_cnt]); aux_cnt++; } @@ -1009,14 +1009,14 @@ static int arc_examine_debug_reason(struct target *target) if (actionpoint) { if (!actionpoint->used) - LOG_WARNING("Target halted by an unused actionpoint."); + LOG_TARGET_WARNING(target, "Target halted by an unused actionpoint"); if (actionpoint->type == ARC_AP_BREAKPOINT) target->debug_reason = DBG_REASON_BREAKPOINT; else if (actionpoint->type == ARC_AP_WATCHPOINT) target->debug_reason = DBG_REASON_WATCHPOINT; else - LOG_WARNING("Unknown type of actionpoint."); + LOG_TARGET_WARNING(target, "Unknown type of actionpoint"); } } @@ -1046,7 +1046,7 @@ static int arc_poll(struct target *target) /* check for processor halted */ if (status & ARC_JTAG_STAT_RU) { if (target->state != TARGET_RUNNING) { - LOG_WARNING("target is still running!"); + LOG_TARGET_WARNING(target, "target is still running"); target->state = TARGET_RUNNING; } return ERROR_OK; @@ -1057,21 +1057,21 @@ static int arc_poll(struct target *target) if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { CHECK_RETVAL(arc_get_register_value(target, "status32", &value)); if (value & AUX_STATUS32_REG_HALT_BIT) { - LOG_DEBUG("ARC core in halt or reset state."); + LOG_TARGET_DEBUG(target, "ARC core in halt or reset state"); /* Save context if target was not in reset state */ if (target->state == TARGET_RUNNING) CHECK_RETVAL(arc_debug_entry(target)); target->state = TARGET_HALTED; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); } else { - LOG_DEBUG("Discrepancy of STATUS32[0] HALT bit and ARC_JTAG_STAT_RU, " + LOG_TARGET_DEBUG(target, "Discrepancy of STATUS32[0] HALT bit and ARC_JTAG_STAT_RU, " "target is still running"); } } else if (target->state == TARGET_DEBUG_RUNNING) { target->state = TARGET_HALTED; - LOG_DEBUG("ARC core is in debug running mode"); + LOG_TARGET_DEBUG(target, "ARC core is in debug running mode"); CHECK_RETVAL(arc_debug_entry(target)); @@ -1087,7 +1087,7 @@ static int arc_assert_reset(struct target *target) enum reset_types jtag_reset_config = jtag_get_reset_config(); bool srst_asserted = false; - LOG_DEBUG("target->state: %s", target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* allow scripts to override the reset event */ @@ -1101,7 +1101,7 @@ static int arc_assert_reset(struct target *target) if (target->state == TARGET_HALTED && !target->reset_halt) { /* Resume the target and continue from the current * PC register value. */ - LOG_DEBUG("Starting CPU execution after reset"); + LOG_TARGET_DEBUG(target, "Starting CPU execution after reset"); CHECK_RETVAL(target_resume(target, 1, 0, 0, 0)); } target->state = TARGET_RESET; @@ -1138,7 +1138,7 @@ static int arc_assert_reset(struct target *target) static int arc_deassert_reset(struct target *target) { - LOG_DEBUG("target->state: %s", target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); /* deassert reset lines */ jtag_add_reset(0, 0); @@ -1155,7 +1155,7 @@ static int arc_arch_state(struct target *target) CHECK_RETVAL(arc_get_register_value(target, "pc", &pc_value)); - LOG_DEBUG("target state: %s; PC at: 0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "target state: %s; PC at: 0x%08" PRIx32, target_state_name(target), pc_value); @@ -1174,7 +1174,7 @@ static int arc_restore_context(struct target *target) struct arc_common *arc = target_to_arc(target); struct reg *reg_list = arc->core_and_aux_cache->reg_list; - LOG_DEBUG("Restoring registers values"); + LOG_TARGET_DEBUG(target, "Restoring registers values"); assert(reg_list); const uint32_t core_regs_size = arc->num_core_regs * sizeof(uint32_t); @@ -1187,7 +1187,7 @@ static int arc_restore_context(struct target *target) unsigned int aux_cnt = 0; if (!core_values || !core_addrs || !aux_values || !aux_addrs) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); retval = ERROR_FAIL; goto exit; } @@ -1201,7 +1201,7 @@ static int arc_restore_context(struct target *target) struct reg *reg = &(reg_list[i]); struct arc_reg_desc *arc_reg = reg->arch_info; if (reg->valid && reg->exist && reg->dirty) { - LOG_DEBUG("Will write regnum=%u", i); + LOG_TARGET_DEBUG(target, "Will write regnum=%u", i); core_addrs[core_cnt] = arc_reg->arch_num; core_values[core_cnt] = target_buffer_get_u32(target, reg->value); core_cnt += 1; @@ -1212,7 +1212,7 @@ static int arc_restore_context(struct target *target) struct reg *reg = &(reg_list[arc->num_core_regs + i]); struct arc_reg_desc *arc_reg = reg->arch_info; if (reg->valid && reg->exist && reg->dirty) { - LOG_DEBUG("Will write regnum=%lu", arc->num_core_regs + i); + LOG_TARGET_DEBUG(target, "Will write regnum=%lu", arc->num_core_regs + i); aux_addrs[aux_cnt] = arc_reg->arch_num; aux_values[aux_cnt] = target_buffer_get_u32(target, reg->value); aux_cnt += 1; @@ -1224,7 +1224,7 @@ static int arc_restore_context(struct target *target) if (core_cnt > 0) { retval = arc_jtag_write_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to write to core registers failed."); + LOG_TARGET_ERROR(target, "Attempt to write to core registers failed"); retval = ERROR_FAIL; goto exit; } @@ -1233,7 +1233,7 @@ static int arc_restore_context(struct target *target) if (aux_cnt > 0) { retval = arc_jtag_write_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to write to aux registers failed."); + LOG_TARGET_ERROR(target, "Attempt to write to aux registers failed"); retval = ERROR_FAIL; goto exit; } @@ -1260,12 +1260,12 @@ static int arc_enable_interrupts(struct target *target, int enable) /* enable interrupts */ value |= SET_CORE_ENABLE_INTERRUPTS; CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG("interrupts enabled"); + LOG_TARGET_DEBUG(target, "interrupts enabled"); } else { /* disable interrupts */ value &= ~SET_CORE_ENABLE_INTERRUPTS; CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG("interrupts disabled"); + LOG_TARGET_DEBUG(target, "interrupts disabled"); } return ERROR_OK; @@ -1279,7 +1279,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, uint32_t value; struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]; - LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," + LOG_TARGET_DEBUG(target, "current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," " debug_execution:%i", current, address, handle_breakpoints, debug_execution); /* We need to reset ARC cache variables so caches @@ -1304,7 +1304,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, target_buffer_set_u32(target, pc->value, address); pc->dirty = true; pc->valid = true; - LOG_DEBUG("Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address); + LOG_TARGET_DEBUG(target, "Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address); } if (!current) @@ -1314,13 +1314,13 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_restore_context(target)); - LOG_DEBUG("Target resumes from PC=0x%" PRIx32 ", pc.dirty=%i, pc.valid=%i", + LOG_TARGET_DEBUG(target, "Target resumes from PC=0x%" PRIx32 ", pc.dirty=%i, pc.valid=%i", resume_pc, pc->dirty, pc->valid); /* check if GDB tells to set our PC where to continue from */ if (pc->valid && resume_pc == target_buffer_get_u32(target, pc->value)) { value = target_buffer_get_u32(target, pc->value); - LOG_DEBUG("resume Core (when start-core) with PC @:0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "resume Core (when start-core) with PC @:0x%08" PRIx32, value); CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value)); } @@ -1329,7 +1329,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, /* Single step past breakpoint at current address */ struct breakpoint *breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("skipping past breakpoint at 0x%08" TARGET_PRIxADDR, + LOG_TARGET_DEBUG(target, "skipping past breakpoint at 0x%08" TARGET_PRIxADDR, breakpoint->address); CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); CHECK_RETVAL(arc_single_step_core(target)); @@ -1350,7 +1350,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); value &= ~SET_CORE_HALT_BIT; /* clear the HALT bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG("Core started to run"); + LOG_TARGET_DEBUG(target, "Core started to run"); /* registers are now invalid */ register_cache_invalidate(arc->core_and_aux_cache); @@ -1358,11 +1358,11 @@ static int arc_resume(struct target *target, int current, target_addr_t address, if (!debug_execution) { target->state = TARGET_RUNNING; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); - LOG_DEBUG("target resumed at 0x%08" PRIx32, resume_pc); + LOG_TARGET_DEBUG(target, "target resumed at 0x%08" PRIx32, resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED)); - LOG_DEBUG("target debug resumed at 0x%08" PRIx32, resume_pc); + LOG_TARGET_DEBUG(target, "target debug resumed at 0x%08" PRIx32, resume_pc); } return ERROR_OK; @@ -1386,7 +1386,7 @@ static void arc_deinit_target(struct target *target) { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("deinitialization of target"); + LOG_TARGET_DEBUG(target, "deinitialization of target"); if (arc->core_aux_cache_built) arc_free_reg_cache(arc->core_and_aux_cache); if (arc->bcr_cache_built) @@ -1431,11 +1431,11 @@ static int arc_target_create(struct target *target, Jim_Interp *interp) struct arc_common *arc = calloc(1, sizeof(*arc)); if (!arc) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } - LOG_DEBUG("Entering"); + LOG_TARGET_DEBUG(target, "Entering"); CHECK_RETVAL(arc_init_arch_info(target, arc, target->tap)); return ERROR_OK; @@ -1452,11 +1452,11 @@ static int arc_write_instruction_u32(struct target *target, uint32_t address, { uint8_t value_buf[4]; if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); + LOG_TARGET_ERROR(target, "Target not examined yet"); return ERROR_FAIL; } - LOG_DEBUG("Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, + LOG_TARGET_DEBUG(target, "Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, instr); if (target->endianness == TARGET_LITTLE_ENDIAN) @@ -1480,7 +1480,7 @@ static int arc_read_instruction_u32(struct target *target, uint32_t address, uint8_t value_buf[4]; if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); + LOG_TARGET_ERROR(target, "Target not examined yet"); return ERROR_FAIL; } @@ -1492,7 +1492,7 @@ static int arc_read_instruction_u32(struct target *target, uint32_t address, else *value = be_to_h_u32(value_buf); - LOG_DEBUG("Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, + LOG_TARGET_DEBUG(target, "Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, *value); return ERROR_OK; @@ -1513,7 +1513,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, if (control_tt != AP_AC_TT_DISABLE) { if (arc->actionpoints_num_avail < 1) { - LOG_ERROR("No free actionpoints, maximum amount is %u", + LOG_TARGET_ERROR(target, "No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1547,12 +1547,12 @@ static int arc_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (breakpoint->is_set) { - LOG_WARNING("breakpoint already set"); + LOG_TARGET_WARNING(target, "breakpoint already set"); return ERROR_OK; } if (breakpoint->type == BKPT_SOFT) { - LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32, breakpoint->unique_id); if (breakpoint->length == 4) { uint32_t verify = 0xffffffff; @@ -1566,7 +1566,7 @@ static int arc_set_breakpoint(struct target *target, CHECK_RETVAL(arc_read_instruction_u32(target, breakpoint->address, &verify)); if (verify != ARC_SDBBP_32) { - LOG_ERROR("Unable to set 32bit breakpoint at address @0x%" TARGET_PRIxADDR + LOG_TARGET_ERROR(target, "Unable to set 32bit breakpoint at address @0x%" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_FAIL; } @@ -1579,12 +1579,12 @@ static int arc_set_breakpoint(struct target *target, CHECK_RETVAL(target_read_u16(target, breakpoint->address, &verify)); if (verify != ARC_SDBBP_16) { - LOG_ERROR("Unable to set 16bit breakpoint at address @0x%" TARGET_PRIxADDR + LOG_TARGET_ERROR(target, "Unable to set 16bit breakpoint at address @0x%" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_FAIL; } } else { - LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); + LOG_TARGET_ERROR(target, "Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -1600,7 +1600,7 @@ static int arc_set_breakpoint(struct target *target, } if (bp_num >= arc->actionpoints_num) { - LOG_ERROR("No free actionpoints, maximum amount is %u", + LOG_TARGET_ERROR(target, "No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1614,12 +1614,12 @@ static int arc_set_breakpoint(struct target *target, ap_list[bp_num].bp_value = breakpoint->address; ap_list[bp_num].type = ARC_AP_BREAKPOINT; - LOG_DEBUG("bpid: %" PRIu32 ", bp_num %u bp_value 0x%" PRIx32, + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32 ", bp_num %u bp_value 0x%" PRIx32, breakpoint->unique_id, bp_num, ap_list[bp_num].bp_value); } } else { - LOG_DEBUG("ERROR: setting unknown breakpoint type"); + LOG_TARGET_ERROR(target, "setting unknown breakpoint type"); return ERROR_FAIL; } @@ -1632,13 +1632,13 @@ static int arc_unset_breakpoint(struct target *target, int retval = ERROR_OK; if (!breakpoint->is_set) { - LOG_WARNING("breakpoint not set"); + LOG_TARGET_WARNING(target, "breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_SOFT) { /* restore original instruction (kept in target endianness) */ - LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32, breakpoint->unique_id); if (breakpoint->length == 4) { uint32_t current_instr; @@ -1651,7 +1651,7 @@ static int arc_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; } else { - LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR + LOG_TARGET_WARNING(target, "Software breakpoint @0x%" TARGET_PRIxADDR " has been overwritten outside of debugger." "Expected: @0x%x, got: @0x%" PRIx32, breakpoint->address, ARC_SDBBP_32, current_instr); @@ -1667,24 +1667,24 @@ static int arc_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; } else { - LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR + LOG_TARGET_WARNING(target, "Software breakpoint @0x%" TARGET_PRIxADDR " has been overwritten outside of debugger. " "Expected: 0x%04x, got: 0x%04" PRIx16, breakpoint->address, ARC_SDBBP_16, current_instr); } } else { - LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); + LOG_TARGET_ERROR(target, "Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } breakpoint->is_set = false; - } else if (breakpoint->type == BKPT_HARD) { + } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; unsigned int bp_num = breakpoint->number; if (bp_num >= arc->actionpoints_num) { - LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32, + LOG_TARGET_DEBUG(target, "Invalid actionpoint ID: %u in breakpoint: %" PRIu32, bp_num, breakpoint->unique_id); return ERROR_OK; } @@ -1697,12 +1697,12 @@ static int arc_unset_breakpoint(struct target *target, ap_list[bp_num].used = 0; ap_list[bp_num].bp_value = 0; - LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %u", + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32 " - released actionpoint ID: %u", breakpoint->unique_id, bp_num); } } else { - LOG_DEBUG("ERROR: unsetting unknown breakpoint type"); - return ERROR_FAIL; + LOG_TARGET_ERROR(target, "unsetting unknown breakpoint type"); + return ERROR_FAIL; } return retval; @@ -1775,7 +1775,7 @@ static void arc_reset_actionpoints(struct target *target) int arc_set_actionpoints_num(struct target *target, uint32_t ap_num) { - LOG_DEBUG("target=%s actionpoints=%" PRIu32, target_name(target), ap_num); + LOG_TARGET_DEBUG(target, "actionpoints=%" PRIu32, ap_num); struct arc_common *arc = target_to_arc(target); /* Make sure that there are no enabled actionpoints in target. */ @@ -1790,7 +1790,7 @@ int arc_set_actionpoints_num(struct target *target, uint32_t ap_num) arc->actionpoints_list = calloc(ap_num, sizeof(struct arc_actionpoint)); if (!arc->actionpoints_list) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } return ERROR_OK; @@ -1813,7 +1813,7 @@ int arc_add_auxreg_actionpoint(struct target *target, ap_num++; if (ap_num >= arc->actionpoints_num) { - LOG_ERROR("No actionpoint free, maximum amount is %u", + LOG_TARGET_ERROR(target, "No actionpoint free, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1858,7 +1858,7 @@ int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr) ap_list[ap_num].bp_value = 0; } } else { - LOG_ERROR("Register actionpoint not found"); + LOG_TARGET_ERROR(target, "Register actionpoint not found"); } return retval; } @@ -1872,7 +1872,7 @@ static int arc_set_watchpoint(struct target *target, struct arc_actionpoint *ap_list = arc->actionpoints_list; if (watchpoint->is_set) { - LOG_WARNING("watchpoint already set"); + LOG_TARGET_WARNING(target, "watchpoint already set"); return ERROR_OK; } @@ -1882,13 +1882,13 @@ static int arc_set_watchpoint(struct target *target, } if (wp_num >= arc->actionpoints_num) { - LOG_ERROR("No free actionpoints, maximum amount is %u", + LOG_TARGET_ERROR(target, "No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (watchpoint->length != 4) { - LOG_ERROR("Only watchpoints of length 4 are supported"); + LOG_TARGET_ERROR(target, "Only watchpoints of length 4 are supported"); return ERROR_TARGET_UNALIGNED_ACCESS; } @@ -1904,7 +1904,7 @@ static int arc_set_watchpoint(struct target *target, enable = AP_AC_TT_READWRITE; break; default: - LOG_ERROR("BUG: watchpoint->rw neither read, write nor access"); + LOG_TARGET_ERROR(target, "BUG: watchpoint->rw neither read, write nor access"); return ERROR_FAIL; } @@ -1917,7 +1917,7 @@ static int arc_set_watchpoint(struct target *target, ap_list[wp_num].bp_value = watchpoint->address; ap_list[wp_num].type = ARC_AP_WATCHPOINT; - LOG_DEBUG("wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32, + LOG_TARGET_DEBUG(target, "wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32, watchpoint->unique_id, wp_num, ap_list[wp_num].bp_value); } @@ -1932,13 +1932,13 @@ static int arc_unset_watchpoint(struct target *target, struct arc_actionpoint *ap_list = arc->actionpoints_list; if (!watchpoint->is_set) { - LOG_WARNING("watchpoint not set"); + LOG_TARGET_WARNING(target, "watchpoint not set"); return ERROR_OK; } unsigned int wp_num = watchpoint->number; if (wp_num >= arc->actionpoints_num) { - LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32, + LOG_TARGET_DEBUG(target, "Invalid actionpoint ID: %u in watchpoint: %" PRIu32, wp_num, watchpoint->unique_id); return ERROR_OK; } @@ -1951,7 +1951,7 @@ static int arc_unset_watchpoint(struct target *target, ap_list[wp_num].used = 0; ap_list[wp_num].bp_value = 0; - LOG_DEBUG("wpid: %" PRIu32 " - releasing actionpoint ID: %u", + LOG_TARGET_DEBUG(target, "wpid: %" PRIu32 " - releasing actionpoint ID: %u", watchpoint->unique_id, wp_num); } @@ -2009,18 +2009,18 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat if (actionpoint) { if (!actionpoint->used) - LOG_WARNING("Target halted by unused actionpoint."); + LOG_TARGET_WARNING(target, "Target halted by unused actionpoint"); /* If this check fails - that is some sort of an error in OpenOCD. */ if (actionpoint->type != ARC_AP_WATCHPOINT) - LOG_WARNING("Target halted by breakpoint, but is treated as a watchpoint."); + LOG_TARGET_WARNING(target, "Target halted by breakpoint, but is treated as a watchpoint"); for (struct watchpoint *watchpoint = target->watchpoints; watchpoint; watchpoint = watchpoint->next) { if (actionpoint->bp_value == watchpoint->address) { *hit_watchpoint = watchpoint; - LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", + LOG_TARGET_DEBUG(target, "Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", watchpoint->unique_id, watchpoint->number); return ERROR_OK; } @@ -2045,7 +2045,7 @@ static int arc_config_step(struct target *target, int enable_step) value &= ~SET_CORE_AE_BIT; /* clear the AE bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG(" [status32:0x%08" PRIx32 "]", value); + LOG_TARGET_DEBUG(target, " [status32:0x%08" PRIx32 "]", value); /* Doing read-modify-write, because DEBUG might contain manually set * bits like UB or ED, which should be preserved. */ @@ -2054,7 +2054,7 @@ static int arc_config_step(struct target *target, int enable_step) value |= SET_CORE_SINGLE_INSTR_STEP; /* set the IS bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); - LOG_DEBUG("core debug step mode enabled [debug-reg:0x%08" PRIx32 "]", value); + LOG_TARGET_DEBUG(target, "core debug step mode enabled [debug-reg:0x%08" PRIx32 "]", value); } else { /* disable core debug step mode */ CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, @@ -2062,7 +2062,7 @@ static int arc_config_step(struct target *target, int enable_step) value &= ~SET_CORE_SINGLE_INSTR_STEP; /* clear the IS bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); - LOG_DEBUG("core debug step mode disabled"); + LOG_TARGET_DEBUG(target, "core debug step mode disabled"); } return ERROR_OK; @@ -2104,7 +2104,7 @@ static int arc_step(struct target *target, int current, target_addr_t address, pc->valid = true; } - LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Target steps one instruction from PC=0x%" PRIx32, buf_get_u32(pc->value, 0, 32)); /* the front-end may request us not to handle breakpoints */ @@ -2136,7 +2136,7 @@ static int arc_step(struct target *target, int current, target_addr_t address, if (breakpoint) CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); - LOG_DEBUG("target stepped "); + LOG_TARGET_DEBUG(target, "target stepped"); target->state = TARGET_HALTED; @@ -2159,7 +2159,7 @@ static int arc_icache_invalidate(struct target *target) if (!arc->has_icache || arc->icache_invalidated) return ERROR_OK; - LOG_DEBUG("Invalidating I$."); + LOG_TARGET_DEBUG(target, "Invalidating I$"); value = IC_IVIC_INVALIDATE; /* invalidate I$ */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_IC_IVIC_REG, value)); @@ -2179,7 +2179,7 @@ static int arc_dcache_invalidate(struct target *target) if (!arc->has_dcache || arc->dcache_invalidated) return ERROR_OK; - LOG_DEBUG("Invalidating D$."); + LOG_TARGET_DEBUG(target, "Invalidating D$"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DC_CTRL_REG, &value)); dc_ctrl_value = value; @@ -2208,7 +2208,7 @@ static int arc_l2cache_invalidate(struct target *target) if (!arc->has_l2cache || arc->l2cache_invalidated) return ERROR_OK; - LOG_DEBUG("Invalidating L2$."); + LOG_TARGET_DEBUG(target, "Invalidating L2$"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_CTRL, &value)); slc_ctrl_value = value; @@ -2221,7 +2221,7 @@ static int arc_l2cache_invalidate(struct target *target) /* Wait until invalidate operation ends */ do { - LOG_DEBUG("Waiting for invalidation end."); + LOG_TARGET_DEBUG(target, "Waiting for invalidation end"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_CTRL, &value)); } while (value & L2_CTRL_BS); @@ -2259,7 +2259,7 @@ static int arc_dcache_flush(struct target *target) if (!arc->has_dcache || arc->dcache_flushed) return ERROR_OK; - LOG_DEBUG("Flushing D$."); + LOG_TARGET_DEBUG(target, "Flushing D$"); /* Store current value of DC_CTRL */ CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DC_CTRL_REG, &dc_ctrl_value)); @@ -2295,14 +2295,14 @@ static int arc_l2cache_flush(struct target *target) if (!arc->has_l2cache || arc->l2cache_flushed) return ERROR_OK; - LOG_DEBUG("Flushing L2$."); + LOG_TARGET_DEBUG(target, "Flushing L2$"); /* Flush L2 cache */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_FLUSH, L2_FLUSH_FL)); /* Wait until flush operation ends */ do { - LOG_DEBUG("Waiting for flushing end."); + LOG_TARGET_DEBUG(target, "Waiting for flushing end"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_CTRL, &value)); } while (value & L2_CTRL_BS); diff --git a/src/target/arc_mem.c b/src/target/arc_mem.c index 3264b663b6..3daed1cbbf 100644 --- a/src/target/arc_mem.c +++ b/src/target/arc_mem.c @@ -35,7 +35,7 @@ static int arc_mem_write_block32(struct target *target, uint32_t addr, { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, + LOG_TARGET_DEBUG(target, "Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* Check arguments */ @@ -66,7 +66,7 @@ static int arc_mem_write_block16(struct target *target, uint32_t addr, uint8_t buffer_te[sizeof(uint32_t)]; uint8_t halfword_te[sizeof(uint16_t)]; - LOG_DEBUG("Write 2-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, + LOG_TARGET_DEBUG(target, "Write 2-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* Check arguments */ @@ -124,7 +124,7 @@ static int arc_mem_write_block8(struct target *target, uint32_t addr, uint8_t buffer_te[sizeof(uint32_t)]; - LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, + LOG_TARGET_DEBUG(target, "Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* We will read data from memory, so we need to flush the cache. */ @@ -158,7 +158,7 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size, int retval = ERROR_OK; void *tunnel = NULL; - LOG_DEBUG("address: 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: %" PRIu32, + LOG_TARGET_DEBUG(target, "address: 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { @@ -182,7 +182,7 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size, tunnel = calloc(1, count * size * sizeof(uint8_t)); if (!tunnel) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } @@ -220,7 +220,7 @@ static int arc_mem_read_block(struct target *target, target_addr_t addr, { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 + LOG_TARGET_DEBUG(target, "Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 ", count=%" PRIu32, addr, size, count); assert(!(addr & 3)); assert(size == 4); @@ -243,11 +243,11 @@ int arc_mem_read(struct target *target, target_addr_t address, uint32_t size, uint32_t words_to_read, bytes_to_read; - LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 + LOG_TARGET_DEBUG(target, "Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 ", count=%" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_WARNING(target, "target not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -268,7 +268,7 @@ int arc_mem_read(struct target *target, target_addr_t address, uint32_t size, tunnel_te = calloc(1, bytes_to_read); if (!tunnel_he || !tunnel_te) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); free(tunnel_he); free(tunnel_te); return ERROR_FAIL; From 5233312ea5725dfcb8b8e0baee103017531ba54f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 31 Dec 2024 10:38:28 +0100 Subject: [PATCH 1052/1312] configure: fix dependency of bitbang from dummy adapter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit bb2fc63357a0 ("configure.ac: enable the Dummy adapter by default") breaks the building dependency between bitbang code and dummy adapter. Fix it. Change-Id: I47587ef61d6b57b2547f6c2600d8404cad87f584 Signed-off-by: Antonio Borneo Reported-by: Jonathan Forrest Fixes: bb2fc63357a0 ("configure.ac: enable the Dummy adapter by default") BugLink: https://sourceforge.net/p/openocd/tickets/446/ Reviewed-on: https://review.openocd.org/c/openocd/+/8682 Reviewed-by: Andrzej Sierżęga Tested-by: jenkins Reviewed-by: Andy --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b353bced70..db47dcba67 100644 --- a/configure.ac +++ b/configure.ac @@ -513,7 +513,7 @@ AS_IF([test "x$build_dmem" = "xyes"], [ AC_DEFINE([BUILD_DMEM], [0], [0 if you don't want to debug via Direct Mem.]) ]) -AS_IF([test "x$ADAPTER_VAR([dummy])" = "xyes"], [ +AS_IF([test "x$ADAPTER_VAR([dummy])" != "xno"], [ build_bitbang=yes ]) From 250ab1008b4d5f9520066df28170c42fc8b40af4 Mon Sep 17 00:00:00 2001 From: "David (Pololu)" Date: Wed, 18 Dec 2024 13:49:00 -0800 Subject: [PATCH 1053/1312] flash/stm32l4x: add STM32C071xx support I successfully programmed a NUCLEO-C071RB with these changes. Change-Id: Ib57a77fa18f8a0e8c882e2250d6111c588d76887 Signed-off-by: David (Pololu) Reviewed-on: https://review.openocd.org/c/openocd/+/8525 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 2 +- src/flash/nor/stm32l4x.c | 17 +++++++++++++++++ src/flash/nor/stm32l4x.h | 1 + tcl/board/st_nucleo_c0.cfg | 9 +++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tcl/board/st_nucleo_c0.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 594f7a7f0c..7c5f84c559 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8001,7 +8001,7 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn {Flash Driver} {stm32l4x} -All members of the STM32 G0, G4, L4, L4+, L5, U0, U5, WB and WL +All members of the STM32 C0, G0, G4, L4, L4+, L5, U0, U5, WB and WL microcontroller families from STMicroelectronics include internal flash and use ARM Cortex-M0+, M4 and M33 cores. The driver automatically recognizes a number of these chips using diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index d2e8f30503..3062fca72a 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -303,6 +303,10 @@ static const struct stm32l4_rev stm32c03xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, }; +static const struct stm32l4_rev stm32c071xx_revs[] = { + { 0x1001, "Z" }, +}; + static const struct stm32l4_rev stm32g05_g06xx_revs[] = { { 0x1000, "A" }, }; @@ -442,6 +446,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = DEVID_STM32C071XX, + .revs = stm32c071xx_revs, + .num_revs = ARRAY_SIZE(stm32c071xx_revs), + .device_str = "STM32C071xx", + .max_flash_size_kb = 128, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75A0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, { .id = DEVID_STM32U53_U54XX, .revs = stm32u53_u54xx_revs, @@ -1989,6 +2005,7 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32L43_L44XX: case DEVID_STM32C01XX: case DEVID_STM32C03XX: + case DEVID_STM32C071XX: case DEVID_STM32G05_G06XX: case DEVID_STM32G07_G08XX: case DEVID_STM32U031XX: diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index b1e8f9870d..f152c9f30a 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -108,6 +108,7 @@ #define DEVID_STM32U57_U58XX 0x482 #define DEVID_STM32U073_U083XX 0x489 #define DEVID_STM32WBA5X 0x492 +#define DEVID_STM32C071XX 0x493 #define DEVID_STM32WB1XX 0x494 #define DEVID_STM32WB5XX 0x495 #define DEVID_STM32WB3XX 0x496 diff --git a/tcl/board/st_nucleo_c0.cfg b/tcl/board/st_nucleo_c0.cfg new file mode 100644 index 0000000000..7d07675920 --- /dev/null +++ b/tcl/board/st_nucleo_c0.cfg @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +source [find interface/stlink.cfg] + +transport select dapdirect_swd + +source [find target/stm32c0x.cfg] + +reset_config srst_only From 23796efa38019515e6338bb4beaa793a537a00e0 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 10 Dec 2024 08:26:48 +0100 Subject: [PATCH 1054/1312] drivers/cmsis_dap: use blocking flag instead of wait timeout CMSIS-DAP bulk backend read op used two timeouts: transfer timeout used in libusb_fill_bulk_transfer() and wait timeout used optionally in libusb_handle_events_timeout_completed(). The real usage is limited to two cases only: 1) blocking read: the same timeout is used for both transfer and wait 2) non-blocking read: transfer timeout is used in libusb_fill_bulk_transfer(), libusb_handle_events_timeout_completed() is called with zero timeout. Use blocking flag as read op parameter to distinguish between these two cases. See also [1] Link: [1] 8596: jtag: cmsis_dap: include helper/time_support.h | https://review.openocd.org/c/openocd/+/8596 Signed-off-by: Tomas Vanek Change-Id: Ia755f17dc72bb9ce8e02065fee6a064f8eec6661 Reviewed-on: https://review.openocd.org/c/openocd/+/8639 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/jtag/drivers/cmsis_dap.c | 20 +++++--------------- src/jtag/drivers/cmsis_dap.h | 8 +++++++- src/jtag/drivers/cmsis_dap_usb_bulk.c | 19 +++++++++++-------- src/jtag/drivers/cmsis_dap_usb_hid.c | 10 +++------- 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 2f776cb387..e9fd93ad1b 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -225,12 +225,6 @@ struct pending_scan_result { unsigned int buffer_offset; }; -/* Read mode */ -enum cmsis_dap_blocking { - CMSIS_DAP_NON_BLOCKING, - CMSIS_DAP_BLOCKING -}; - /* Each block in FIFO can contain up to pending_queue_len transfers */ static unsigned int pending_queue_len; static unsigned int tfer_max_command_size; @@ -321,7 +315,7 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap) * USB close/open so we need to flush up to 64 old packets * to be sure all buffers are empty */ for (i = 0; i < 64; i++) { - int retval = dap->backend->read(dap, 10, NULL); + int retval = dap->backend->read(dap, 10, CMSIS_DAP_BLOCKING); if (retval == ERROR_TIMEOUT_REACHED) break; } @@ -338,7 +332,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) if (dap->pending_fifo_block_count) { LOG_ERROR("pending %u blocks, flushing", dap->pending_fifo_block_count); while (dap->pending_fifo_block_count) { - dap->backend->read(dap, 10, NULL); + dap->backend->read(dap, 10, CMSIS_DAP_BLOCKING); dap->pending_fifo_block_count--; } dap->pending_fifo_put_idx = 0; @@ -351,7 +345,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) return retval; /* get reply */ - retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, NULL); + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, CMSIS_DAP_BLOCKING); if (retval < 0) return retval; @@ -885,7 +879,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo if (queued_retval != ERROR_OK) { /* keep reading blocks until the pipeline is empty */ - retval = dap->backend->read(dap, 10, NULL); + retval = dap->backend->read(dap, 10, CMSIS_DAP_BLOCKING); if (retval == ERROR_TIMEOUT_REACHED || retval == 0) { /* timeout means that we flushed the pipeline, * we can safely discard remaining pending requests */ @@ -896,11 +890,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo } /* get reply */ - struct timeval tv = { - .tv_sec = 0, - .tv_usec = 0 - }; - retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking ? NULL : &tv); + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking); bool timeout = (retval == ERROR_TIMEOUT_REACHED || retval == 0); if (timeout && blocking == CMSIS_DAP_NON_BLOCKING) return; diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index e47697d1f9..aded0e54a3 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -58,12 +58,18 @@ struct cmsis_dap { bool trace_enabled; }; +/* Read mode */ +enum cmsis_dap_blocking { + CMSIS_DAP_NON_BLOCKING, + CMSIS_DAP_BLOCKING +}; + struct cmsis_dap_backend { const char *name; int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial); void (*close)(struct cmsis_dap *dap); int (*read)(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout); + enum cmsis_dap_blocking blocking); int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz); void (*packet_buffer_free)(struct cmsis_dap *dap); diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 8d0cb544d7..50d4a9f8d3 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -441,7 +441,7 @@ static void LIBUSB_CALL cmsis_dap_usb_callback(struct libusb_transfer *transfer) } static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout) + enum cmsis_dap_blocking blocking) { int transferred = 0; int err; @@ -464,20 +464,23 @@ static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms, } } - struct timeval tv = { - .tv_sec = transfer_timeout_ms / 1000, - .tv_usec = transfer_timeout_ms % 1000 * 1000 - }; + struct timeval tv; + if (blocking == CMSIS_DAP_NON_BLOCKING) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = transfer_timeout_ms / 1000; + tv.tv_usec = transfer_timeout_ms % 1000 * 1000; + } while (tr->status == CMSIS_DAP_TRANSFER_PENDING) { - err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, - wait_timeout ? wait_timeout : &tv, + err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, &tr->status); if (err) { LOG_ERROR("error handling USB events: %s", libusb_strerror(err)); return ERROR_FAIL; } - if (wait_timeout) + if (tv.tv_sec == 0 && tv.tv_usec == 0) break; } diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index aeec685b9d..a4058ec803 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -206,17 +206,13 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap) } static int cmsis_dap_hid_read(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout) + enum cmsis_dap_blocking blocking) { - int timeout_ms; - if (wait_timeout) - timeout_ms = wait_timeout->tv_usec / 1000 + wait_timeout->tv_sec * 1000; - else - timeout_ms = transfer_timeout_ms; + int wait_ms = (blocking == CMSIS_DAP_NON_BLOCKING) ? 0 : transfer_timeout_ms; int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, - timeout_ms); + wait_ms); if (retval == 0) { return ERROR_TIMEOUT_REACHED; } else if (retval == -1) { From cf115c1e2b670ea8b4606cde0c9b5db735a08742 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 10 Dec 2024 08:53:49 +0100 Subject: [PATCH 1055/1312] drivers/cmsis_dap_usb_bulk: allow waiting for bulk write No driver directly working with the USB hardware needs additional time to complete the write op, they always return transfer complete status immediately after submitting the transfer. Although there is implemented correct waiting path in cmsis_dap_usb_write() it was marked by error logs to catch any suspicious behaviour during debugging of asynchronous libusb transfers. However there are drivers which need waiting to finish write op: at least usbipd-win, IP tunnelled USB driver, was reported to flood the log with the related errors. Change LOG_ERROR to LOG_DEBUG_IO in the code waiting to finish write op. Reported-by: Quentis Ghyll Signed-off-by: Tomas Vanek Change-Id: Iedf2c96d851f22e694efaf13a2d6a2a408cee1ad Reviewed-on: https://review.openocd.org/c/openocd/+/8640 Tested-by: jenkins --- src/jtag/drivers/cmsis_dap_usb_bulk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 50d4a9f8d3..8fbcb029dd 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -532,7 +532,7 @@ static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) tr = &dap->bdata->command_transfers[dap->pending_fifo_put_idx]; if (tr->status == CMSIS_DAP_TRANSFER_PENDING) { - LOG_ERROR("busy command USB transfer at %u", dap->pending_fifo_put_idx); + LOG_DEBUG_IO("busy command USB transfer at %u", dap->pending_fifo_put_idx); struct timeval tv = { .tv_sec = timeout_ms / 1000, .tv_usec = timeout_ms % 1000 * 1000 @@ -547,7 +547,7 @@ static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) tr->status = CMSIS_DAP_TRANSFER_IDLE; } if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { - LOG_ERROR("USB write: late transfer competed"); + LOG_DEBUG_IO("USB write: late transfer competed"); tr->status = CMSIS_DAP_TRANSFER_IDLE; } if (tr->status != CMSIS_DAP_TRANSFER_IDLE) { From d4b3b4ea82ba6d34b050a1cc068e0b105533e2f2 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 10 Dec 2024 13:48:53 +0100 Subject: [PATCH 1056/1312] target: free private_config if target initialisation fails Fixes private_config memory leak when xx_deinit_target() is not called Signed-off-by: Tomas Vanek Change-Id: Ie7cce7f24af24695e7d2c1cd1882474c6863b80d Reviewed-on: https://review.openocd.org/c/openocd/+/8642 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Evgeniy Naydanov --- src/target/target.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/target/target.c b/src/target/target.c index 6c474899a4..1fc8baf2c0 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5848,6 +5848,7 @@ static int target_create(struct jim_getopt_info *goi) free(target->gdb_port_override); free(target->trace_info); free(target->type); + free(target->private_config); free(target); return e; } @@ -5865,6 +5866,7 @@ static int target_create(struct jim_getopt_info *goi) free(target->gdb_port_override); free(target->trace_info); free(target->type); + free(target->private_config); free(target); return JIM_ERR; } @@ -5878,6 +5880,7 @@ static int target_create(struct jim_getopt_info *goi) free(target->gdb_port_override); free(target->trace_info); free(target->type); + free(target->private_config); free(target); return JIM_ERR; } From 8b5ea720da530d375cc5c5d4a66fb48768a421de Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 3 Nov 2024 12:06:05 +0100 Subject: [PATCH 1057/1312] make bitbang_interface const Change-Id: I5e187250d231aeefc7a206b7f7917c3b2e858d5a Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8535 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/am335xgpio.c | 2 +- src/jtag/drivers/at91rm9200.c | 2 +- src/jtag/drivers/bitbang.c | 2 +- src/jtag/drivers/bitbang.h | 2 +- src/jtag/drivers/dummy.c | 2 +- src/jtag/drivers/ep93xx.c | 2 +- src/jtag/drivers/imx_gpio.c | 2 +- src/jtag/drivers/linuxgpiod.c | 2 +- src/jtag/drivers/parport.c | 2 +- src/jtag/drivers/remote_bitbang.c | 2 +- src/jtag/drivers/sysfsgpio.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index 9bb7ea7d13..05a73aa53c 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -283,7 +283,7 @@ static int am335xgpio_blink(bool on) return ERROR_OK; } -static struct bitbang_interface am335xgpio_bitbang = { +static const struct bitbang_interface am335xgpio_bitbang = { .read = am335xgpio_read, .write = am335xgpio_write, .swdio_read = am335xgpio_swdio_read, diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c index ba9ee5e34d..57dd54c119 100644 --- a/src/jtag/drivers/at91rm9200.c +++ b/src/jtag/drivers/at91rm9200.c @@ -104,7 +104,7 @@ static int at91rm9200_write(int tck, int tms, int tdi); static int at91rm9200_init(void); static int at91rm9200_quit(void); -static struct bitbang_interface at91rm9200_bitbang = { +static const struct bitbang_interface at91rm9200_bitbang = { .read = at91rm9200_read, .write = at91rm9200_write, .blink = NULL, diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 42234a6f72..0a49feb003 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -37,7 +37,7 @@ static int bitbang_stableclocks(unsigned int num_cycles); static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk); -struct bitbang_interface *bitbang_interface; +const struct bitbang_interface *bitbang_interface; /* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work! * diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 82405eb8ab..d6fd95e279 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -67,6 +67,6 @@ extern const struct swd_driver bitbang_swd; int bitbang_execute_queue(struct jtag_command *cmd_queue); -extern struct bitbang_interface *bitbang_interface; +extern const struct bitbang_interface *bitbang_interface; #endif /* OPENOCD_JTAG_DRIVERS_BITBANG_H */ diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index 4fe598fe32..315e036974 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -77,7 +77,7 @@ static int dummy_led(bool on) return ERROR_OK; } -static struct bitbang_interface dummy_bitbang = { +static const struct bitbang_interface dummy_bitbang = { .read = &dummy_read, .write = &dummy_write, .blink = &dummy_led, diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c index c3e841d37a..ae35f4ac0c 100644 --- a/src/jtag/drivers/ep93xx.c +++ b/src/jtag/drivers/ep93xx.c @@ -55,7 +55,7 @@ struct adapter_driver ep93xx_adapter_driver = { .jtag_ops = &ep93xx_interface, }; -static struct bitbang_interface ep93xx_bitbang = { +static const struct bitbang_interface ep93xx_bitbang = { .read = ep93xx_read, .write = ep93xx_write, .blink = NULL, diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c index d44b1278c0..7aefbeb8aa 100644 --- a/src/jtag/drivers/imx_gpio.c +++ b/src/jtag/drivers/imx_gpio.c @@ -82,7 +82,7 @@ static int imx_gpio_swd_write(int swclk, int swdio); static int imx_gpio_init(void); static int imx_gpio_quit(void); -static struct bitbang_interface imx_gpio_bitbang = { +static const struct bitbang_interface imx_gpio_bitbang = { .read = imx_gpio_read, .write = imx_gpio_write, .swdio_read = imx_gpio_swdio_read, diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index fa14e42d6e..5ffbf4d2f2 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -191,7 +191,7 @@ static int linuxgpiod_blink(bool on) return retval; } -static struct bitbang_interface linuxgpiod_bitbang = { +static const struct bitbang_interface linuxgpiod_bitbang = { .read = linuxgpiod_read, .write = linuxgpiod_write, .swdio_read = linuxgpiod_swdio_read, diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index bdd3388955..f3478db51e 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -255,7 +255,7 @@ static int parport_get_giveio_access(void) } #endif -static struct bitbang_interface parport_bitbang = { +static const struct bitbang_interface parport_bitbang = { .read = &parport_read, .write = &parport_write, .blink = &parport_led, diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 91a8532b79..037c1f27f3 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -278,7 +278,7 @@ static int remote_bitbang_swd_write(int swclk, int swdio) return remote_bitbang_queue(c, NO_FLUSH); } -static struct bitbang_interface remote_bitbang_bitbang = { +static const struct bitbang_interface remote_bitbang_bitbang = { .buf_size = sizeof(remote_bitbang_recv_buf) - 1, .sample = &remote_bitbang_sample, .read_sample = &remote_bitbang_read_sample, diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c index a5f5fd3ac0..c47754bd19 100644 --- a/src/jtag/drivers/sysfsgpio.c +++ b/src/jtag/drivers/sysfsgpio.c @@ -565,7 +565,7 @@ struct adapter_driver sysfsgpio_adapter_driver = { .swd_ops = &bitbang_swd, }; -static struct bitbang_interface sysfsgpio_bitbang = { +static const struct bitbang_interface sysfsgpio_bitbang = { .read = sysfsgpio_read, .write = sysfsgpio_write, .swdio_read = sysfsgpio_swdio_read, From 0ed03df6e95bc336bbece000ffbe4028f70369d8 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Thu, 28 Nov 2024 21:47:34 +0100 Subject: [PATCH 1058/1312] amend angie build definitions to fix make dist "make dist" was broken because GNU Make was using a built-in rule to try to build angie from angie.c . This is a limitation in Automake when you add a whole subdir with the same name to EXTRA_DIST. The Automake doc actually discourages adding whole subdirs. Change-Id: I85ea4ecbd529b060c70f83bcfda7522e1730480d Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8600 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/Makefile.am | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 8be834859c..da0663fd4d 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -10,10 +10,8 @@ noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la %C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) ULINK_FIRMWARE = %D%/OpenULINK -ANGIE_FILES = %D%/angie EXTRA_DIST += $(ULINK_FIRMWARE) \ - $(ANGIE_FILES) \ %D%/usb_blaster/README.CheapClone \ %D%/Makefile.rlink \ %D%/rlink_call.m4 \ @@ -125,12 +123,17 @@ ulinkdir = $(pkgdatadir)/OpenULINK dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex %C%_libocdjtagdrivers_la_LIBADD += -lm endif + if ANGIE -DRIVERFILES += %D%/angie.c -angiedir = $(pkgdatadir)/angie -dist_angie_DATA = $(ANGIE_FILES)/angie_firmware.bin $(ANGIE_FILES)/angie_bitstream.bit -%C%_libocdjtagdrivers_la_LIBADD += -lm + angiedir = $(pkgdatadir)/angie # This is only for dist_angie_DATA. + DRIVERFILES += %D%/angie.c + DRIVERFILES += %D%/angie/include/msgtypes.h + EXTRA_DIST += %D%/angie/README + dist_angie_DATA = %D%/angie/angie_firmware.bin + dist_angie_DATA += %D%/angie/angie_bitstream.bit + %C%_libocdjtagdrivers_la_LIBADD += -lm endif + if VSLLINK DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c From 26f2df80c3f9ac54fc488ed26f6320904881c0d4 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 31 Dec 2024 14:47:02 +0100 Subject: [PATCH 1059/1312] helper: list: rename macro clashing with sys/queue.h The macro named LIST_HEAD() clashed with a macro of same name in the GNU libc file sys/queue.h. This causes a warning in MacOS build due to some other system file including sys/queue.h. Rename LIST_HEAD() as OOCD_LIST_HEAD(). Checkpatch-ignore: MACRO_ARG_REUSE Change-Id: Ic653edec77425a58251d64f56c9f5f6c645ba0cd Signed-off-by: Antonio Borneo Reported-by: Andrew Shelley Reviewed-on: https://review.openocd.org/c/openocd/+/8683 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Andy --- contrib/list_example.c | 2 +- src/helper/list.h | 2 +- src/server/telnet_server.c | 2 +- src/target/adi_v5_jtag.c | 2 +- src/target/arm_cti.c | 2 +- src/target/arm_dap.c | 2 +- src/target/arm_tpiu_swo.c | 2 +- src/target/openrisc/or1k.c | 4 ++-- src/target/riscv/riscv-013.c | 2 +- src/target/target.c | 6 +++--- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contrib/list_example.c b/contrib/list_example.c index 4fcfcdf348..1f28dc2dbd 100644 --- a/contrib/list_example.c +++ b/contrib/list_example.c @@ -12,7 +12,7 @@ #include #include -static LIST_HEAD(threads); +static OOCD_LIST_HEAD(threads); struct thread { int id; diff --git a/src/helper/list.h b/src/helper/list.h index 47290c2602..ba07f15568 100644 --- a/src/helper/list.h +++ b/src/helper/list.h @@ -46,7 +46,7 @@ struct list_head { #define LIST_HEAD_INIT(name) { &(name), &(name) } -#define LIST_HEAD(name) \ +#define OOCD_LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) static inline void diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 7818af2dbb..2c3f769801 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -570,7 +570,7 @@ static void telnet_auto_complete(struct connection *connection) struct list_head lh; }; - LIST_HEAD(matches); + OOCD_LIST_HEAD(matches); /* - user command sequence, either at line beginning * or we start over after these characters ';', '[', '{' diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index fee1a24858..c9ed5b948b 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -431,7 +431,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) struct dap_cmd *el, *tmp, *prev = NULL; int found_wait = 0; int64_t time_now; - LIST_HEAD(replay_list); + OOCD_LIST_HEAD(replay_list); /* make sure all queued transactions are complete */ retval = jtag_execute_queue(); diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 88eec832ef..b2f78eef78 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -25,7 +25,7 @@ struct arm_cti { struct adiv5_ap *ap; }; -static LIST_HEAD(all_cti); +static OOCD_LIST_HEAD(all_cti); const char *arm_cti_name(struct arm_cti *self) { diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 9f4afae743..c5bd6ccd4d 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -18,7 +18,7 @@ #include "transport/transport.h" #include "jtag/interface.h" -static LIST_HEAD(all_dap); +static OOCD_LIST_HEAD(all_dap); extern struct adapter_driver *adapter_driver; diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index c14fd5fc84..e20cd59272 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -126,7 +126,7 @@ struct arm_tpiu_swo_priv_connection { struct arm_tpiu_swo_object *obj; }; -static LIST_HEAD(all_tpiu_swo); +static OOCD_LIST_HEAD(all_tpiu_swo); #define ARM_TPIU_SWO_TRACE_BUF_SIZE 4096 diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index 8c38610805..efc076c999 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -27,8 +27,8 @@ #include "or1k.h" #include "or1k_du.h" -LIST_HEAD(tap_list); -LIST_HEAD(du_list); +OOCD_LIST_HEAD(tap_list); +OOCD_LIST_HEAD(du_list); static int or1k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 658c1fd9db..bb450ce623 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -214,7 +214,7 @@ typedef struct { dm013_info_t *dm; } riscv013_info_t; -static LIST_HEAD(dm_list); +static OOCD_LIST_HEAD(dm_list); static riscv013_info_t *get_info(const struct target *target) { diff --git a/src/target/target.c b/src/target/target.c index 1fc8baf2c0..8deab8f34d 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -108,10 +108,10 @@ struct target *all_targets; static struct target_event_callback *target_event_callbacks; static struct target_timer_callback *target_timer_callbacks; static int64_t target_timer_next_event_value; -static LIST_HEAD(target_reset_callback_list); -static LIST_HEAD(target_trace_callback_list); +static OOCD_LIST_HEAD(target_reset_callback_list); +static OOCD_LIST_HEAD(target_trace_callback_list); static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL; -static LIST_HEAD(empty_smp_targets); +static OOCD_LIST_HEAD(empty_smp_targets); enum nvp_assert { NVP_DEASSERT, From 83e0293f7ba3604b4ad98b3a8101388e3e52f9fe Mon Sep 17 00:00:00 2001 From: Richard Pasek Date: Wed, 11 Dec 2024 00:43:57 -0500 Subject: [PATCH 1060/1312] Add Linux SPI device SWD adapter support To alleviate the need to bitbang SWD, I've written a SWD SPI implementation. This code is inspired by the work of luppy@appkaki.com as shown at github.com/lupyuen/openocd-spi but with the desire to be more generic. This implementation makes use of the more common 4 wire SPI port using full duplex transfers to be able to capture the SWD ACK bits when a SWD TX operation is in progress. TEST: Connects successfully with the following combinations: Hosts: Raspberry Pi 4B Unnamed Qualcomm SoC with QUPv3 based SPI port Targets: Raspberry Pi 2040 Nordic nRF52840 NXP RT500 Change-Id: Ic2f38a1806085d527e6f999a3d15aea6f32d1019 Signed-off-by: Richard Pasek Reviewed-on: https://review.openocd.org/c/openocd/+/8645 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Reviewed-by: zapb Tested-by: jenkins --- configure.ac | 6 + doc/openocd.texi | 67 ++++ src/jtag/drivers/Makefile.am | 3 + src/jtag/drivers/linuxspidev.c | 622 +++++++++++++++++++++++++++++++ src/jtag/interface.h | 1 + src/jtag/interfaces.c | 3 + tcl/interface/spidev_example.cfg | 9 + 7 files changed, 711 insertions(+) create mode 100644 src/jtag/drivers/linuxspidev.c create mode 100644 tcl/interface/spidev_example.cfg diff --git a/configure.ac b/configure.ac index db47dcba67..49054288f7 100644 --- a/configure.ac +++ b/configure.ac @@ -163,6 +163,9 @@ m4_define([PCIE_ADAPTERS], m4_define([SERIAL_PORT_ADAPTERS], [[[buspirate], [Bus Pirate], [BUS_PIRATE]]]) +m4_define([LINUXSPIDEV_ADAPTER], + [[[linuxspidev], [Linux spidev driver], [LINUXSPIDEV]]]) + # The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter # because there is an M4 macro called 'adapter'. m4_define([DUMMY_ADAPTER], @@ -289,6 +292,7 @@ AC_ARG_ADAPTERS([ LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + LINUXSPIDEV_ADAPTER, SERIAL_PORT_ADAPTERS, DUMMY_ADAPTER, PCIE_ADAPTERS, @@ -726,6 +730,7 @@ PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], [internal error: validation should happen beforehand]) +PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -875,6 +880,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, + LINUXSPIDEV_ADAPTER, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], diff --git a/doc/openocd.texi b/doc/openocd.texi index 7c5f84c559..47a6f69ebc 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -614,6 +614,9 @@ emulation model of target hardware. @item @b{xlnx_pcie_xvc} @* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG/SWD interface. +@item @b{linuxspidev} +@* A SPI based SWD driver using Linux SPI devices. + @item @b{linuxgpiod} @* A bitbang JTAG driver using Linux GPIO through library libgpiod. @@ -3401,6 +3404,70 @@ See @file{interface/beaglebone-swd-native.cfg} for a sample configuration file. @end deffn +@deffn {Interface Driver} {linuxspidev} +Linux provides userspace access to SPI through spidev. Full duplex SPI +transactions are used to simultaneously read and write to/from the target to +emulate the SWD transport. + +@deffn {Config Command} {spidev path} path +Specifies the path to the spidev device. +@end deffn + +@deffn {Config Command} {spidev mode} value +Set the mode of the spi port with optional bit flags (default=3). +See /usr/include/linux/spi/spidev.h for all of the SPI mode options. +@end deffn + +@deffn {Config Command} {spidev queue_entries} value +Set the maximum number of queued transactions per spi exchange (default=64). +More queued transactions may offer greater performance when the target doesn't +need to wait. On the contrary higher numbers will reduce performance when the +target requests a wait as all queued transactions will need to be exchanged +before spidev can see the wait request. +@end deffn + +See @file{tcl/interface/spidev_example.cfg} for a sample configuration file. + +Electrical connections: +@example ++--------------+ +--------------+ +| | 1K | | +| MOSI|---/\/\/\---+ | | +| Host | | | Target | +| MISO|------------+---|SWDIO | +| | | | +| SCK|----------------|SWDCLK | +| | | | ++--------------+ +--------------+ +@end example + +The 1K resistor works well with most MCUs up to 3 MHz. A lower resistance +could be used to achieve higher speeds granted that the target SWDIO pin has +enough drive strength to pull the signal high while being pulled low by this +resistor. + +If you are having trouble here are some tips: + +@itemize @bullet + +@item @b{Make sure MISO and MOSI are tied together with a 1K resistor.} +MISO should be attached to the target. + +@item @b{Make sure that your host and target are using the same I/O voltage} +(for example both are using 3.3 volts). + +@item @b{Your host's SPI port may not idle low.} +This will lead to an additional clock edge being sent to the target, causing +the host and target being 1 clock off from each other. Try setting +SPI_MOSI_IDLE_LOW in spi_mode. Try using a different spi_mode (0 - 3). + +@item @b{Your target may pull SWDIO and/or SWDCLK high.} +This will create an extra edge when the host releases control of the SPI port +at the end of a transaction. You'll need to confirm this with a scope or meter. +Try installing 10K resistors on SWDIO and SWDCLK to ground to stop this. + +@end itemize +@end deffn @deffn {Interface Driver} {linuxgpiod} Linux provides userspace access to GPIO through libgpiod since Linux kernel diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index da0663fd4d..ec233b2470 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -176,6 +176,9 @@ endif if SYSFSGPIO DRIVERFILES += %D%/sysfsgpio.c endif +if LINUXSPIDEV +DRIVERFILES += %D%/linuxspidev.c +endif if XLNX_PCIE_XVC DRIVERFILES += %D%/xlnx-pcie-xvc.c endif diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c new file mode 100644 index 0000000000..737d2bef83 --- /dev/null +++ b/src/jtag/drivers/linuxspidev.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Copyright (C) 2020 by Lup Yuen Lee + * Copyright (C) 2024 by Richard Pasek + */ + +/** + * @file + * Implementation of SWD protocol with a Linux SPI device. + */ + +/* Uncomment to log SPI exchanges (very verbose, slows things down a lot) + * + * A quick note on interpreting SPI exchange messages: + * + * This implementation works by performing SPI exchanges with MOSI and MISO + * tied together with a 1K resistor. This combined signal becomes SWDIO. + * + * Since we are performing SPI exchanges, (reading and writing at the same + * time) this means when the target isn't driving SWDIO, what is written by + * the host should also be read by the host. + * + * On SWD writes: + * The TX and RX data should match except for the ACK bits from the target + * swd write reg exchange: len=6 + * tx_buf=C5 02 40 00 02 2C + * rx_buf=C5 42 40 00 02 2C + * ^ + * | + * ACK from target + * + * On SWD reads: + * Only the command byte should match + * swd read reg exchange: len=6 + * tx_buf=B1 00 00 00 00 00 + * rx_buf=B1 40 20 00 00 F8 + * ^^ + * || + * Command packet from host + * + */ +// #define LOG_SPI_EXCHANGE + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Number of bits per SPI exchange +#define SPI_BITS 8 + +// Time in uS after the last bit of transfer before deselecting the device +#define SPI_DESELECT_DELAY 0 + +// Maximum number of SWD transactions to queue together in a SPI exchange +#define MAX_QUEUE_ENTRIES 64 + +#define CMD_BITS 8 +#define TURN_BITS 1 +#define ACK_BITS 3 +#define DATA_BITS 32 +#define PARITY_BITS 1 + +#define SWD_WR_BITS (CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS + DATA_BITS + PARITY_BITS) +#define SWD_RD_BITS (CMD_BITS + TURN_BITS + ACK_BITS + DATA_BITS + PARITY_BITS + TURN_BITS) +#define SWD_OP_BITS (MAX(SWD_WR_BITS, SWD_RD_BITS)) +#define SWD_OP_BYTES (DIV_ROUND_UP(SWD_OP_BITS, SPI_BITS)) + +#define AP_DELAY_CLOCKS 8 +#define AP_DELAY_BYTES (DIV_ROUND_UP(AP_DELAY_CLOCKS, SPI_BITS)) + +#define END_IDLE_CLOCKS 8 +#define END_IDLE_BYTES (DIV_ROUND_UP(END_IDLE_CLOCKS, SPI_BITS)) + +// File descriptor for SPI device +static int spi_fd = -1; + +// SPI Configuration +static char *spi_path; +static uint32_t spi_mode = SPI_MODE_3; // Note: SPI in LSB mode is not often supported. We'll flip LSB to MSB ourselves. +static uint32_t spi_speed; + +struct queue_info { + unsigned int buf_idx; + uint32_t *rx_ptr; +}; + +static int queue_retval; +static unsigned int max_queue_entries; +static unsigned int queue_fill; +static unsigned int queue_buf_fill; +static unsigned int queue_buf_size; +static struct queue_info *queue_infos; +static uint8_t *queue_tx_buf; +static uint8_t *queue_rx_buf; +static uint8_t *tx_flip_buf; + +static int spidev_swd_switch_seq(enum swd_special_seq seq); +static void spidev_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk); + +static void spi_exchange(const uint8_t *tx_data, uint8_t *rx_data, unsigned int len) +{ +#ifdef LOG_SPI_EXCHANGE + LOG_OUTPUT("exchange: len=%u\n", len); +#endif // LOG_SPI_EXCHANGE + + if (len == 0) { + LOG_DEBUG("exchange with no length"); + return; + } + + if (!tx_data && !rx_data) { + LOG_DEBUG("exchange with no valid tx or rx pointers"); + return; + } + + if (len > queue_buf_size) { + LOG_ERROR("exchange too large len=%u ", len); + return; + } + + if (tx_data) { + // Reverse LSB to MSB + for (unsigned int i = 0; i < len; i++) + tx_flip_buf[i] = flip_u32(tx_data[i], 8); + +#ifdef LOG_SPI_EXCHANGE + if (len != 0) { + LOG_OUTPUT(" tx_buf="); + for (unsigned int i = 0; i < len; i++) + LOG_OUTPUT("%.2" PRIx8 " ", tx_flip_buf[i]); + } + LOG_OUTPUT("\n"); +#endif // LOG_SPI_EXCHANGE + } + // Transmit the MSB buffer to SPI device. + struct spi_ioc_transfer tr = { + /* The following must be cast to unsigned long to compile correctly on + * 32 and 64 bit machines (as is done in the spidev examples in Linux + * kernel code in tools/spi/). + */ + .tx_buf = (unsigned long)(tx_data ? tx_flip_buf : NULL), + .rx_buf = (unsigned long)rx_data, + .len = len, + .delay_usecs = SPI_DESELECT_DELAY, + .speed_hz = spi_speed, + .bits_per_word = SPI_BITS, + }; + int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr); + + if (ret < 1) { + LOG_ERROR("exchange failed"); + return; + } + + if (rx_data) { +#ifdef LOG_SPI_EXCHANGE + if (len != 0) { + LOG_OUTPUT(" rx_buf="); + for (unsigned int i = 0; i < len; i++) + LOG_OUTPUT("%.2" PRIx8 " ", rx_data[i]); + } + LOG_OUTPUT("\n"); +#endif // LOG_SPI_EXCHANGE + + // Reverse MSB to LSB + for (unsigned int i = 0; i < len; i++) + rx_data[i] = flip_u32(rx_data[i], 8); + } +} + +static int spidev_speed(int speed) +{ + uint32_t tmp_speed = speed; + + int ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &tmp_speed); + if (ret == -1) { + LOG_ERROR("Failed to set SPI %d speed", speed); + return ERROR_FAIL; + } + + spi_speed = speed; + + return ERROR_OK; +} + +static int spidev_speed_div(int speed, int *khz) +{ + *khz = speed / 1000; + return ERROR_OK; +} + +static int spidev_khz(int khz, int *jtag_speed) +{ + if (khz == 0) { + LOG_DEBUG("RCLK not supported"); + return ERROR_FAIL; + } + + *jtag_speed = khz * 1000; + return ERROR_OK; +} + +static void spidev_free_queue(void) +{ + max_queue_entries = 0; + queue_buf_size = 0; + + free(queue_infos); + queue_infos = NULL; + + free(queue_tx_buf); + queue_tx_buf = NULL; + + free(queue_rx_buf); + queue_rx_buf = NULL; + + free(tx_flip_buf); + tx_flip_buf = NULL; +} + +static int spidev_alloc_queue(unsigned int new_queue_entries) +{ + if (queue_fill || queue_buf_fill) { + LOG_ERROR("Can't realloc allocate queue when queue is in use"); + return ERROR_FAIL; + } + + unsigned int new_queue_buf_size = + (new_queue_entries * (SWD_OP_BYTES + AP_DELAY_BYTES)) + END_IDLE_BYTES; + + queue_infos = realloc(queue_infos, sizeof(struct queue_info) * new_queue_entries); + if (!queue_infos) + goto realloc_fail; + + queue_tx_buf = realloc(queue_tx_buf, new_queue_buf_size); + if (!queue_tx_buf) + goto realloc_fail; + + queue_rx_buf = realloc(queue_rx_buf, new_queue_buf_size); + if (!queue_rx_buf) + goto realloc_fail; + + tx_flip_buf = realloc(tx_flip_buf, new_queue_buf_size); + if (!tx_flip_buf) + goto realloc_fail; + + max_queue_entries = new_queue_entries; + queue_buf_size = new_queue_buf_size; + + LOG_DEBUG("Set queue entries to %u (buffers %u bytes)", max_queue_entries, queue_buf_size); + + return ERROR_OK; + +realloc_fail: + spidev_free_queue(); + + LOG_ERROR("Couldn't allocate queue. Out of memory."); + return ERROR_FAIL; +} + +static int spidev_init(void) +{ + LOG_INFO("SPI SWD driver"); + + if (spi_fd >= 0) + return ERROR_OK; + + if (!spi_path) { + LOG_ERROR("Path to spidev not set"); + return ERROR_JTAG_INIT_FAILED; + } + + // Open SPI device. + spi_fd = open(spi_path, O_RDWR); + if (spi_fd < 0) { + LOG_ERROR("Failed to open SPI port at %s", spi_path); + return ERROR_JTAG_INIT_FAILED; + } + + // Set SPI mode. + int ret = ioctl(spi_fd, SPI_IOC_WR_MODE32, &spi_mode); + if (ret == -1) { + LOG_ERROR("Failed to set SPI mode 0x%" PRIx32, spi_mode); + return ERROR_JTAG_INIT_FAILED; + } + + // Set SPI bits per word. + uint32_t spi_bits = SPI_BITS; + ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits); + if (ret == -1) { + LOG_ERROR("Failed to set SPI %" PRIu8 " bits per transfer", spi_bits); + return ERROR_JTAG_INIT_FAILED; + } + + LOG_INFO("Opened SPI device at %s in mode 0x%" PRIx32 " with %" PRIu8 " bits ", + spi_path, spi_mode, spi_bits); + + // Set SPI read and write max speed. + int speed; + ret = adapter_get_speed(&speed); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to get adapter speed"); + return ERROR_JTAG_INIT_FAILED; + } + + ret = spidev_speed(speed); + if (ret != ERROR_OK) + return ERROR_JTAG_INIT_FAILED; + + if (max_queue_entries == 0) { + ret = spidev_alloc_queue(MAX_QUEUE_ENTRIES); + if (ret != ERROR_OK) + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static int spidev_quit(void) +{ + spidev_free_queue(); + + if (spi_fd < 0) + return ERROR_OK; + + close(spi_fd); + spi_fd = -1; + return ERROR_OK; +} + +static int spidev_swd_init(void) +{ + LOG_DEBUG("spidev_swd_init"); + return ERROR_OK; +} + +static int spidev_swd_execute_queue(unsigned int end_idle_bytes) +{ + LOG_DEBUG_IO("Executing %u queued transactions", queue_fill); + + if (queue_retval != ERROR_OK) { + LOG_DEBUG_IO("Skipping due to previous errors: %d", queue_retval); + goto skip; + } + + /* A transaction must be followed by another transaction or at least 8 idle + * cycles to ensure that data is clocked through the AP. Since the tx + * buffer is zeroed after each queue run, every byte added to the buffer + * fill will add on an additional 8 idle cycles. + */ + queue_buf_fill += end_idle_bytes; + + spi_exchange(queue_tx_buf, queue_rx_buf, queue_buf_fill); + + for (unsigned int queue_idx = 0; queue_idx < queue_fill; queue_idx++) { + unsigned int buf_idx = queue_infos[queue_idx].buf_idx; + uint8_t *tx_ptr = &queue_tx_buf[buf_idx]; + uint8_t *rx_ptr = &queue_rx_buf[buf_idx]; + uint8_t cmd = buf_get_u32(tx_ptr, 0, CMD_BITS); + bool read = cmd & SWD_CMD_RNW ? true : false; + int ack = buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS, ACK_BITS); + uint32_t data = read ? + buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS + ACK_BITS, DATA_BITS) : + buf_get_u32(tx_ptr, CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS, DATA_BITS); + + // Devices do not reply to DP_TARGETSEL write cmd, ignore received ack + bool check_ack = swd_cmd_returns_ack(cmd); + + LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK) ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO, + "%s%s %s %s reg %X = %08" PRIx32, + check_ack ? "" : "ack ignored ", + ack == SWD_ACK_OK ? "OK" : + ack == SWD_ACK_WAIT ? "WAIT" : + ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", + cmd & SWD_CMD_APNDP ? "AP" : "DP", + read ? "read" : "write", + (cmd & SWD_CMD_A32) >> 1, + data); + + if (ack != SWD_ACK_OK && check_ack) { + queue_retval = swd_ack_to_error_code(ack); + goto skip; + + } else if (read) { + int parity = buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS + ACK_BITS + DATA_BITS, PARITY_BITS); + + if (parity != parity_u32(data)) { + LOG_ERROR("SWD Read data parity mismatch"); + queue_retval = ERROR_FAIL; + goto skip; + } + + if (queue_infos[queue_idx].rx_ptr) + *queue_infos[queue_idx].rx_ptr = data; + } + } + +skip: + // Clear everything in the queue + queue_fill = 0; + queue_buf_fill = 0; + memset(queue_infos, 0, sizeof(queue_infos[0]) * max_queue_entries); + memset(queue_tx_buf, 0, queue_buf_size); + memset(queue_rx_buf, 0, queue_buf_size); + + int retval = queue_retval; + queue_retval = ERROR_OK; + + return retval; +} + +static int spidev_swd_run_queue(void) +{ + /* Since we are unsure if another SWD transaction will follow the + * transactions we are just about to execute, we need to add on 8 idle + * cycles. + */ + return spidev_swd_execute_queue(END_IDLE_BYTES); +} + +static void spidev_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk) +{ + unsigned int swd_op_bytes = DIV_ROUND_UP(SWD_OP_BITS + ap_delay_clk, SPI_BITS); + + if (queue_fill >= max_queue_entries || + queue_buf_fill + swd_op_bytes + END_IDLE_BYTES > queue_buf_size) { + /* Not enough room in the queue. Run the queue. No idle bytes are + * needed because we are going to execute transactions right after + * the queue is emptied. + */ + queue_retval = spidev_swd_execute_queue(0); + } + + if (queue_retval != ERROR_OK) + return; + + uint8_t *tx_ptr = &queue_tx_buf[queue_buf_fill]; + + cmd |= SWD_CMD_START | SWD_CMD_PARK; + + buf_set_u32(tx_ptr, 0, CMD_BITS, cmd); + + if (cmd & SWD_CMD_RNW) { + // Queue a read transaction + queue_infos[queue_fill].rx_ptr = dst; + } else { + // Queue a write transaction + buf_set_u32(tx_ptr, + CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS, DATA_BITS, data); + buf_set_u32(tx_ptr, + CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS + DATA_BITS, PARITY_BITS, parity_u32(data)); + } + + queue_infos[queue_fill].buf_idx = queue_buf_fill; + + /* Add idle cycles after AP accesses to avoid WAIT. Buffer is already + * zeroed so we just need to advance the pointer to add idle cycles. + */ + queue_buf_fill += swd_op_bytes; + + queue_fill++; +} + +static void spidev_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk) +{ + assert(cmd & SWD_CMD_RNW); + spidev_swd_queue_cmd(cmd, value, 0, ap_delay_clk); +} + +static void spidev_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk) +{ + assert(!(cmd & SWD_CMD_RNW)); + spidev_swd_queue_cmd(cmd, NULL, value, ap_delay_clk); +} + +static int spidev_swd_switch_seq(enum swd_special_seq seq) +{ + switch (seq) { + case LINE_RESET: + LOG_DEBUG_IO("SWD line reset"); + spi_exchange(swd_seq_line_reset, NULL, swd_seq_line_reset_len / SPI_BITS); + break; + case JTAG_TO_SWD: + LOG_DEBUG("JTAG-to-SWD"); + spi_exchange(swd_seq_jtag_to_swd, NULL, swd_seq_jtag_to_swd_len / SPI_BITS); + break; + case JTAG_TO_DORMANT: + LOG_DEBUG("JTAG-to-DORMANT"); + spi_exchange(swd_seq_jtag_to_dormant, NULL, swd_seq_jtag_to_dormant_len / SPI_BITS); + break; + case SWD_TO_JTAG: + LOG_DEBUG("SWD-to-JTAG"); + spi_exchange(swd_seq_swd_to_jtag, NULL, swd_seq_swd_to_jtag_len / SPI_BITS); + break; + case SWD_TO_DORMANT: + LOG_DEBUG("SWD-to-DORMANT"); + spi_exchange(swd_seq_swd_to_dormant, NULL, swd_seq_swd_to_dormant_len / SPI_BITS); + break; + case DORMANT_TO_SWD: + LOG_DEBUG("DORMANT-to-SWD"); + spi_exchange(swd_seq_dormant_to_swd, NULL, swd_seq_dormant_to_swd_len / SPI_BITS); + break; + case DORMANT_TO_JTAG: + LOG_DEBUG("DORMANT-to-JTAG"); + spi_exchange(swd_seq_dormant_to_jtag, NULL, swd_seq_dormant_to_jtag_len / SPI_BITS); + break; + default: + LOG_ERROR("Sequence %d not supported", seq); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(spidev_handle_path_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + free(spi_path); + spi_path = strdup(CMD_ARGV[0]); + if (!spi_path) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(spidev_handle_mode_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], spi_mode); + return ERROR_OK; +} + +COMMAND_HANDLER(spidev_handle_queue_entries_command) +{ + uint32_t new_queue_entries; + + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], new_queue_entries); + + return spidev_alloc_queue(new_queue_entries); +} + +const struct swd_driver spidev_swd = { + .init = spidev_swd_init, + .switch_seq = spidev_swd_switch_seq, + .read_reg = spidev_swd_read_reg, + .write_reg = spidev_swd_write_reg, + .run = spidev_swd_run_queue, +}; + +static const struct command_registration spidev_subcommand_handlers[] = { + { + .name = "path", + .handler = &spidev_handle_path_command, + .mode = COMMAND_CONFIG, + .help = "set the path to the spidev device", + .usage = "path_to_spidev", + }, + { + .name = "mode", + .handler = &spidev_handle_mode_command, + .mode = COMMAND_CONFIG, + .help = "set the mode of the spi port with optional bit flags (default=3)", + .usage = "mode", + }, + { + .name = "queue_entries", + .handler = &spidev_handle_queue_entries_command, + .mode = COMMAND_CONFIG, + .help = "set the queue entry size (default=64)", + .usage = "queue_entries", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration spidev_command_handlers[] = { + { + .name = "spidev", + .mode = COMMAND_ANY, + .help = "perform spidev management", + .chain = spidev_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +// Only SWD transport supported +static const char *const spidev_transports[] = { "swd", NULL }; + +struct adapter_driver linuxspidev_adapter_driver = { + .name = "linuxspidev", + .transports = spidev_transports, + .commands = spidev_command_handlers, + + .init = spidev_init, + .quit = spidev_quit, + .speed = spidev_speed, + .khz = spidev_khz, + .speed_div = spidev_speed_div, + + .swd_ops = &spidev_swd, +}; diff --git a/src/jtag/interface.h b/src/jtag/interface.h index b448851dc4..f69326492a 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -386,6 +386,7 @@ extern struct adapter_driver jtag_dpi_adapter_driver; extern struct adapter_driver jtag_vpi_adapter_driver; extern struct adapter_driver kitprog_adapter_driver; extern struct adapter_driver linuxgpiod_adapter_driver; +extern struct adapter_driver linuxspidev_adapter_driver; extern struct adapter_driver opendous_adapter_driver; extern struct adapter_driver openjtag_adapter_driver; extern struct adapter_driver osbdm_adapter_driver; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 67f0838e39..e49bd9e0f3 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -123,6 +123,9 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_LINUXGPIOD == 1 &linuxgpiod_adapter_driver, #endif +#if BUILD_LINUXSPIDEV == 1 + &linuxspidev_adapter_driver, +#endif #if BUILD_XLNX_PCIE_XVC == 1 &xlnx_pcie_xvc_adapter_driver, #endif diff --git a/tcl/interface/spidev_example.cfg b/tcl/interface/spidev_example.cfg new file mode 100644 index 0000000000..2354c781bb --- /dev/null +++ b/tcl/interface/spidev_example.cfg @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Example config for using Linux spidev as a SWD adapter. + +adapter driver linuxspidev +adapter speed 3000 +spidev path "/dev/spidev0.0" +spidev mode 3 +spidev queue_entries 64 From 41f7d18161592cf3e2e6f51f0ef36d345aeed2e0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 30 Dec 2024 12:10:28 +0100 Subject: [PATCH 1061/1312] target: armv7m: add support of per register data_type Extend the struct armv7m_regs to include the optional pointer to a struct reg_data_type. Update armv7m_build_reg_cache() to check for the new optional field and to use it. Change-Id: I57c7f9abefd614308be8aa8419d687477b44679d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8680 Tested-by: jenkins --- src/target/armv7m.c | 137 +++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 66 deletions(-) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 49a8a4bba5..b4473c30a8 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -80,30 +80,31 @@ static const struct { enum reg_type type; const char *group; const char *feature; + struct reg_data_type *data_type; } armv7m_regs[] = { - { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - - { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, + { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + + { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system", NULL, }, /* A working register for packing/unpacking special regs, hidden from gdb */ - { ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL }, + { ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL, NULL }, /* WARNING: If you use armv7m_write_core_reg() on one of 4 following * special registers, the new data go to ARMV7M_PMSK_BPRI_FLTMSK_CTRL @@ -111,52 +112,52 @@ static const struct { * To trigger write to CPU HW register, add * armv7m_write_core_reg(,,ARMV7M_PMSK_BPRI_FLTMSK_CTRL,); */ - { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, + { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, /* ARMv8-M security extension (TrustZone) specific registers */ - { ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - - { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL }, - { ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - - { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL }, - { ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, + { ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + + { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL, NULL, }, + { ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + + { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL, NULL, }, + { ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, /* FPU registers */ - { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - - { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" }, + { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + + { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp", NULL, }, }; #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs) @@ -811,10 +812,14 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) LOG_TARGET_ERROR(target, "unable to allocate feature list"); reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); - if (reg_list[i].reg_data_type) - reg_list[i].reg_data_type->type = armv7m_regs[i].type; - else + if (reg_list[i].reg_data_type) { + if (armv7m_regs[i].data_type) + *reg_list[i].reg_data_type = *armv7m_regs[i].data_type; + else + reg_list[i].reg_data_type->type = armv7m_regs[i].type; + } else { LOG_TARGET_ERROR(target, "unable to allocate reg type list"); + } } arm->cpsr = reg_list + ARMV7M_XPSR; From 8e89a8af63f242290c800d6f640b432d3af9ec89 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 30 Dec 2024 12:14:24 +0100 Subject: [PATCH 1062/1312] target: cortex_m: add support of ARMv8.1-M register 'vpr' The register 'vpr' is present when MVFR1.MVE is not zero. For the moment, reuse the existing flag 'fp_feature'. To be reviewed for the case of MVE supported without floating point. The documentation of GDB [1] reports that the register 'vpr' should be represented as 3 fields. Tested on Cortex-M55 based STM32N6570. Change-Id: I8737a24d01a13eeb09a0f2075b96be400f9f91c6 Signed-off-by: Antonio Borneo Link: [1] https://sourceware.org/gdb/download/onlinedocs/gdb.html/ARM-Features.html#M_002dprofile-Vector-Extension-_0028MVE_0029 Reviewed-on: https://review.openocd.org/c/openocd/+/8681 Tested-by: jenkins --- src/target/armv7m.c | 27 +++++++++++++++++++++++++++ src/target/armv7m.h | 6 +++++- src/target/cortex_m.c | 4 ++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index b4473c30a8..440ca49d16 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -65,6 +65,28 @@ const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = { ARMV7M_XPSR, }; +static struct reg_data_type_bitfield armv8m_vpr_bits[] = { + { 0, 15, REG_TYPE_UINT }, + { 16, 19, REG_TYPE_UINT }, + { 20, 23, REG_TYPE_UINT }, +}; + +static struct reg_data_type_flags_field armv8m_vpr_fields[] = { + { "P0", armv8m_vpr_bits + 0, armv8m_vpr_fields + 1, }, + { "MASK01", armv8m_vpr_bits + 1, armv8m_vpr_fields + 2, }, + { "MASK23", armv8m_vpr_bits + 2, NULL }, +}; + +static struct reg_data_type_flags armv8m_vpr_flags[] = { + { 4, armv8m_vpr_fields }, +}; + +static struct reg_data_type armv8m_flags_vpr[] = { + { REG_TYPE_ARCH_DEFINED, "vpr_reg", REG_TYPE_CLASS_FLAGS, + { .reg_type_flags = armv8m_vpr_flags }, + }, +}; + /* * These registers are not memory-mapped. The ARMv7-M profile includes * memory mapped registers too, such as for the NVIC (interrupt controller) @@ -158,6 +180,8 @@ static const struct { { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp", NULL, }, + + { ARMV8M_VPR, "vpr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.m-profile-mve", armv8m_flags_vpr, }, }; #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs) @@ -273,6 +297,9 @@ uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) case ARMV7M_FPSCR: return ARMV7M_REGSEL_FPSCR; + case ARMV8M_VPR: + return ARMV8M_REGSEL_VPR; + case ARMV7M_D0 ... ARMV7M_D15: return ARMV7M_REGSEL_S0 + 2 * (arm_reg_id - ARMV7M_D0); diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 2878dd1c76..86c45f7f26 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -62,6 +62,7 @@ enum { ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL = 0x14, ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_S = 0x22, ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_NS = 0x23, + ARMV8M_REGSEL_VPR = 0x24, ARMV7M_REGSEL_FPSCR = 0x21, /* 32bit Floating-point registers */ @@ -196,12 +197,15 @@ enum { /* Floating-point status register */ ARMV7M_FPSCR, + /* Vector Predication Status and Control Register */ + ARMV8M_VPR, + /* for convenience add registers' block delimiters */ ARMV7M_LAST_REG, ARMV7M_CORE_FIRST_REG = ARMV7M_R0, ARMV7M_CORE_LAST_REG = ARMV7M_XPSR, ARMV7M_FPU_FIRST_REG = ARMV7M_D0, - ARMV7M_FPU_LAST_REG = ARMV7M_FPSCR, + ARMV7M_FPU_LAST_REG = ARMV8M_VPR, ARMV8M_FIRST_REG = ARMV8M_MSP_NS, ARMV8M_LAST_REG = ARMV8M_CONTROL_NS, }; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index fa95fcbc7e..2cea203a29 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2708,6 +2708,10 @@ int cortex_m_examine(struct target *target) for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++) armv7m->arm.core_cache->reg_list[idx].exist = false; + /* TODO: MVE can be present without floating points. Revisit this test */ + if (armv7m->fp_feature != FPV5_MVE_F && armv7m->fp_feature != FPV5_MVE_I) + armv7m->arm.core_cache->reg_list[ARMV8M_VPR].exist = false; + if (!cortex_m_has_tz(target)) for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++) armv7m->arm.core_cache->reg_list[idx].exist = false; From 3099547069896ccff054d64bac6041fe1e20add9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 16 Sep 2024 13:45:19 +0200 Subject: [PATCH 1063/1312] OpenOCD: fix code indentation Fix checkpatch errors ERROR:SUSPECT_CODE_INDENT: suspect code indent for conditional statements Change-Id: I94d4fa5720c25dd2fb0334a824cd9026babcce4e Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8497 Tested-by: jenkins --- src/flash/nor/fespi.c | 6 +++--- src/flash/nor/kinetis_ke.c | 2 +- src/flash/nor/niietcm4.c | 6 +++--- src/flash/nor/psoc4.c | 10 +++++----- src/helper/log.c | 8 ++++---- src/rtos/hwthread.c | 8 +++----- src/rtos/linux.c | 5 +++-- src/target/aarch64.c | 6 +++--- src/target/arc.c | 18 ++++++++---------- src/target/armv4_5.c | 22 +++++++++++----------- src/target/armv7a_mmu.c | 9 +++------ src/target/armv8.c | 4 ++-- src/target/cortex_a.c | 29 +++++++++++++---------------- src/target/mips32.c | 2 +- src/target/mips_m4k.c | 2 +- src/target/stm8.c | 10 ++++------ src/xsvf/xsvf.c | 8 ++++---- 17 files changed, 72 insertions(+), 83 deletions(-) diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index 6c4e8a928f..395722cb5d 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -751,9 +751,9 @@ static int fespi_probe(struct flash_bank *bank) target_device->name, bank->base); } else { - LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT - " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base, - bank->base); + LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT + " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base, + bank->base); } /* read and decode flash ID; returns in SW mode */ diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index e4dffa6d5c..8207504b5f 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -1005,7 +1005,7 @@ static int kinetis_ke_write(struct flash_bank *bank, const uint8_t *buffer, result = kinetis_ke_stop_watchdog(bank->target); if (result != ERROR_OK) - return result; + return result; result = kinetis_ke_prepare_flash(bank); if (result != ERROR_OK) diff --git a/src/flash/nor/niietcm4.c b/src/flash/nor/niietcm4.c index 0c36e2c96d..aaf0726550 100644 --- a/src/flash/nor/niietcm4.c +++ b/src/flash/nor/niietcm4.c @@ -311,7 +311,7 @@ static int niietcm4_uflash_page_erase(struct flash_bank *bank, int page_num, int /* status check */ retval = niietcm4_uopstatus_check(bank); if (retval != ERROR_OK) - return retval; + return retval; return retval; } @@ -394,7 +394,7 @@ COMMAND_HANDLER(niietcm4_handle_uflash_read_byte_command) uint32_t uflash_data; if (strcmp("info", CMD_ARGV[0]) == 0) - uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB; + uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB; else if (strcmp("main", CMD_ARGV[0]) == 0) uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ; else @@ -539,7 +539,7 @@ COMMAND_HANDLER(niietcm4_handle_uflash_erase_command) int mem_type; if (strcmp("info", CMD_ARGV[0]) == 0) - mem_type = 1; + mem_type = 1; else if (strcmp("main", CMD_ARGV[0]) == 0) mem_type = 0; else diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c index 1064fa93d3..72cf0ee05b 100644 --- a/src/flash/nor/psoc4.c +++ b/src/flash/nor/psoc4.c @@ -384,15 +384,15 @@ static int psoc4_get_silicon_id(struct flash_bank *bank, uint32_t *silicon_id, u * bit 7..0 family ID (lowest 8 bits) */ if (silicon_id) - *silicon_id = ((part0 & 0x0000ffff) << 16) - | ((part0 & 0x00ff0000) >> 8) - | (part1 & 0x000000ff); + *silicon_id = ((part0 & 0x0000ffff) << 16) + | ((part0 & 0x00ff0000) >> 8) + | (part1 & 0x000000ff); if (family_id) - *family_id = part1 & 0x0fff; + *family_id = part1 & 0x0fff; if (protection) - *protection = (part1 >> 12) & 0x0f; + *protection = (part1 >> 12) & 0x0f; return ERROR_OK; } diff --git a/src/helper/log.c b/src/helper/log.c index 9ad00ce628..e02556b6db 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -272,10 +272,10 @@ void log_init(void) if (debug_env) { int value; int retval = parse_int(debug_env, &value); - if (retval == ERROR_OK && - debug_level >= LOG_LVL_SILENT && - debug_level <= LOG_LVL_DEBUG_IO) - debug_level = value; + if (retval == ERROR_OK + && debug_level >= LOG_LVL_SILENT + && debug_level <= LOG_LVL_DEBUG_IO) + debug_level = value; } if (!log_output) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 1890a3d87a..c9f1a17920 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -154,9 +154,8 @@ static int hwthread_update_threads(struct rtos *rtos) if (curr->debug_reason == DBG_REASON_SINGLESTEP) { current_reason = curr->debug_reason; current_thread = tid; - } else - /* multiple breakpoints, prefer gdbs' threadid */ - if (curr->debug_reason == DBG_REASON_BREAKPOINT) { + } else if (curr->debug_reason == DBG_REASON_BREAKPOINT) { + /* multiple breakpoints, prefer gdbs' threadid */ if (tid == rtos->current_threadid) current_thread = tid; } @@ -176,8 +175,7 @@ static int hwthread_update_threads(struct rtos *rtos) curr->debug_reason == DBG_REASON_BREAKPOINT) { current_reason = curr->debug_reason; current_thread = tid; - } else - if (curr->debug_reason == DBG_REASON_DBGRQ) { + } else if (curr->debug_reason == DBG_REASON_DBGRQ) { if (tid == rtos->current_threadid) current_thread = tid; } diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 7517ec7a9a..5467988f3e 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -624,7 +624,7 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads { t->next = NULL; - if (!*last) + if (!*last) { if (!task_list) { task_list = t; return task_list; @@ -637,7 +637,8 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads temp->next = t; *last = t; return task_list; - } else { + } + } else { (*last)->next = t; *last = t; return task_list; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 9f122070aa..3cc8130054 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2908,9 +2908,9 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info * pc = (struct aarch64_private_config *)target->private_config; if (!pc) { - pc = calloc(1, sizeof(struct aarch64_private_config)); - pc->adiv5_config.ap_num = DP_APSEL_INVALID; - target->private_config = pc; + pc = calloc(1, sizeof(struct aarch64_private_config)); + pc->adiv5_config.ap_num = DP_APSEL_INVALID; + target->private_config = pc; } /* diff --git a/src/target/arc.c b/src/target/arc.c index 5c08c5664c..0c111d553b 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -388,7 +388,7 @@ static int arc_build_reg_cache(struct target *target) } list_for_each_entry(reg_desc, &arc->aux_reg_descriptions, list) { - CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); + CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, @@ -464,7 +464,7 @@ static int arc_build_bcr_reg_cache(struct target *target) } list_for_each_entry(reg_desc, &arc->bcr_reg_descriptions, list) { - CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, gdb_regnum)); + CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, gdb_regnum)); /* BCRs always semantically, they are just read-as-zero, if there is * not real register. */ reg_list[i].exist = true; @@ -719,14 +719,14 @@ static int arc_configure(struct target *target) LOG_TARGET_DEBUG(target, "Configuring ARC ICCM and DCCM"); /* Configuring DCCM if DCCM_BUILD and AUX_DCCM are known registers. */ - if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true) && - arc_reg_get_by_name(target->reg_cache, "aux_dccm", true)) - CHECK_RETVAL(arc_configure_dccm(target)); + if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true) + && arc_reg_get_by_name(target->reg_cache, "aux_dccm", true)) + CHECK_RETVAL(arc_configure_dccm(target)); /* Configuring ICCM if ICCM_BUILD and AUX_ICCM are known registers. */ - if (arc_reg_get_by_name(target->reg_cache, "iccm_build", true) && - arc_reg_get_by_name(target->reg_cache, "aux_iccm", true)) - CHECK_RETVAL(arc_configure_iccm(target)); + if (arc_reg_get_by_name(target->reg_cache, "iccm_build", true) + && arc_reg_get_by_name(target->reg_cache, "aux_iccm", true)) + CHECK_RETVAL(arc_configure_iccm(target)); return ERROR_OK; } @@ -1067,9 +1067,7 @@ static int arc_poll(struct target *target) LOG_TARGET_DEBUG(target, "Discrepancy of STATUS32[0] HALT bit and ARC_JTAG_STAT_RU, " "target is still running"); } - } else if (target->state == TARGET_DEBUG_RUNNING) { - target->state = TARGET_HALTED; LOG_TARGET_DEBUG(target, "ARC core is in debug running mode"); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index ceec3619b5..a258c7fd45 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1301,11 +1301,11 @@ int arm_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < 16; i++) - (*reg_list)[i] = arm_reg_current(arm, i); + (*reg_list)[i] = arm_reg_current(arm, i); /* For GDB compatibility, take FPA registers size into account and zero-fill it*/ for (i = 16; i < 24; i++) - (*reg_list)[i] = &arm_gdb_dummy_fp_reg; + (*reg_list)[i] = &arm_gdb_dummy_fp_reg; (*reg_list)[24] = &arm_gdb_dummy_fps_reg; (*reg_list)[25] = arm->cpsr; @@ -1330,25 +1330,25 @@ int arm_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < 16; i++) - (*reg_list)[i] = arm_reg_current(arm, i); + (*reg_list)[i] = arm_reg_current(arm, i); for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) { - int reg_index = arm->core_cache->reg_list[i].number; + int reg_index = arm->core_cache->reg_list[i].number; - if (arm_core_regs[i].mode == ARM_MODE_MON + if (arm_core_regs[i].mode == ARM_MODE_MON && arm->core_type != ARM_CORE_TYPE_SEC_EXT && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) - continue; - if (arm_core_regs[i].mode == ARM_MODE_HYP + continue; + if (arm_core_regs[i].mode == ARM_MODE_HYP && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) - continue; - (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); + continue; + (*reg_list)[reg_index] = &arm->core_cache->reg_list[i]; } /* When we supply the target description, there is no need for fake FPA */ for (i = 16; i < 24; i++) { - (*reg_list)[i] = &arm_gdb_dummy_fp_reg; - (*reg_list)[i]->size = 0; + (*reg_list)[i] = &arm_gdb_dummy_fp_reg; + (*reg_list)[i]->size = 0; } (*reg_list)[24] = &arm_gdb_dummy_fps_reg; (*reg_list)[24]->size = 0; diff --git a/src/target/armv7a_mmu.c b/src/target/armv7a_mmu.c index c4d294eae3..43b5dae8ef 100644 --- a/src/target/armv7a_mmu.c +++ b/src/target/armv7a_mmu.c @@ -260,8 +260,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table) /* skip empty entries in the first level table */ if ((first_lvl_descriptor & 3) == 0) { pt_idx++; - } else - if ((first_lvl_descriptor & 0x40002) == 2) { + } else if ((first_lvl_descriptor & 0x40002) == 2) { /* section descriptor */ uint32_t va_range = 1024*1024-1; /* 1MB range */ uint32_t va_start = pt_idx << 20; @@ -273,8 +272,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table) LOG_USER("SECT: VA[%8.8"PRIx32" -- %8.8"PRIx32"]: PA[%8.8"PRIx32" -- %8.8"PRIx32"] %s", va_start, va_end, pa_start, pa_end, l1_desc_bits_to_string(first_lvl_descriptor, afe)); pt_idx++; - } else - if ((first_lvl_descriptor & 0x40002) == 0x40002) { + } else if ((first_lvl_descriptor & 0x40002) == 0x40002) { /* supersection descriptor */ uint32_t va_range = 16*1024*1024-1; /* 16MB range */ uint32_t va_start = pt_idx << 20; @@ -310,8 +308,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table) if ((second_lvl_descriptor & 3) == 0) { /* skip entry */ pt2_idx++; - } else - if ((second_lvl_descriptor & 3) == 1) { + } else if ((second_lvl_descriptor & 3) == 1) { /* large page */ uint32_t va_range = 64*1024-1; /* 64KB range */ uint32_t va_start = (pt_idx << 20) + (pt2_idx << 12); diff --git a/src/target/armv8.c b/src/target/armv8.c index 88534d9626..50a9f46883 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1966,7 +1966,7 @@ int armv8_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < *reg_list_size; i++) - (*reg_list)[i] = armv8_reg_current(arm, i); + (*reg_list)[i] = armv8_reg_current(arm, i); return ERROR_OK; case REG_CLASS_ALL: @@ -1974,7 +1974,7 @@ int armv8_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < *reg_list_size; i++) - (*reg_list)[i] = armv8_reg_current(arm, i); + (*reg_list)[i] = armv8_reg_current(arm, i); return ERROR_OK; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 086aafe199..bfe6980518 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1324,21 +1324,21 @@ static int cortex_a_set_breakpoint(struct target *target, brp_list[brp_i].value); } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - /* length == 2: Thumb breakpoint */ - if (breakpoint->length == 2) + if (breakpoint->length == 2) { + /* length == 2: Thumb breakpoint */ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); - else - /* length == 3: Thumb-2 breakpoint, actual encoding is - * a regular Thumb BKPT instruction but we replace a - * 32bit Thumb-2 instruction, so fix-up the breakpoint - * length - */ - if (breakpoint->length == 3) { + } else if (breakpoint->length == 3) { + /* length == 3: Thumb-2 breakpoint, actual encoding is + * a regular Thumb BKPT instruction but we replace a + * 32bit Thumb-2 instruction, so fix-up the breakpoint + * length + */ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); breakpoint->length = 4; - } else + } else { /* length == 4, normal ARM breakpoint */ buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); + } retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, @@ -1348,8 +1348,7 @@ static int cortex_a_set_breakpoint(struct target *target, return retval; /* make sure data cache is cleaned & invalidated down to PoC */ - armv7a_cache_flush_virt(target, breakpoint->address, - breakpoint->length); + armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length); retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, @@ -1358,10 +1357,8 @@ static int cortex_a_set_breakpoint(struct target *target, return retval; /* update i-cache at breakpoint location */ - armv7a_l1_d_cache_inval_virt(target, breakpoint->address, - breakpoint->length); - armv7a_l1_i_cache_inval_virt(target, breakpoint->address, - breakpoint->length); + armv7a_l1_d_cache_inval_virt(target, breakpoint->address, breakpoint->length); + armv7a_l1_i_cache_inval_virt(target, breakpoint->address, breakpoint->length); breakpoint->is_set = true; } diff --git a/src/target/mips32.c b/src/target/mips32.c index dd40558a18..fcb7042cb1 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -2357,7 +2357,7 @@ COMMAND_HANDLER(mips32_handle_scan_delay_command) if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay); else if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay); if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index ad98089614..1543de355e 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -1397,7 +1397,7 @@ COMMAND_HANDLER(mips_m4k_handle_scan_delay_command) if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay); else if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay); if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { diff --git a/src/target/stm8.c b/src/target/stm8.c index 2b3466dacb..fb5c81f061 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -689,15 +689,13 @@ static int stm8_write_flash(struct target *target, enum mem_type type, if (stm8->flash_ncr2) stm8_write_u8(target, stm8->flash_ncr2, ~(PRG + opt)); blocksize = blocksize_param; - } else - if ((bytecnt >= 4) && ((address & 0x3) == 0)) { + } else if ((bytecnt >= 4) && ((address & 0x3) == 0)) { if (stm8->flash_cr2) stm8_write_u8(target, stm8->flash_cr2, WPRG + opt); if (stm8->flash_ncr2) stm8_write_u8(target, stm8->flash_ncr2, ~(WPRG + opt)); blocksize = 4; - } else - if (blocksize != 1) { + } else if (blocksize != 1) { if (stm8->flash_cr2) stm8_write_u8(target, stm8->flash_cr2, opt); if (stm8->flash_ncr2) @@ -1552,8 +1550,8 @@ static int stm8_set_watchpoint(struct target *target, } if (watchpoint->length != 1) { - LOG_ERROR("Only watchpoints of length 1 are supported"); - return ERROR_TARGET_UNALIGNED_ACCESS; + LOG_ERROR("Only watchpoints of length 1 are supported"); + return ERROR_TARGET_UNALIGNED_ACCESS; } enum hw_break_type enable = 0; diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index 74a4dcfde1..88275043ed 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -749,10 +749,10 @@ COMMAND_HANDLER(handle_xsvf_command) int delay; if (read(xsvf_fd, &wait_local, 1) < 0 - || read(xsvf_fd, &end, 1) < 0 - || read(xsvf_fd, delay_buf, 4) < 0) { - do_abort = 1; - break; + || read(xsvf_fd, &end, 1) < 0 + || read(xsvf_fd, delay_buf, 4) < 0) { + do_abort = 1; + break; } wait_state = xsvf_to_tap(wait_local); From 77f9da76264d4970faf22a40a31fc66fa7543b57 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 17 Jan 2025 18:02:50 +0100 Subject: [PATCH 1064/1312] flash/nor/kinetis: fix assertion during flash write If the device has at lest one FlexNVM bank and it is set as EE backup only, the bank has no protection blocks. kinetis_fill_fcf() collects protection data from all banks before flash write of the sector containing FCF block. In case it encountered a FlexNVM bank with no protection blocks assert failed. Failed flash write of previously erased FCF block could cause engaging debugging lock (if the device was run or reset). Skip banks with zero protection blocks. Replace assert() by LOG_ERROR() as we have to finish FCF write. Change-Id: Ibe7e7ec6d0db4453b8a53c8256987621b809c99d Signed-off-by: Tomas Vanek Suggested-by: Jasper v. Blanckenburg Fixes: https://sourceforge.net/p/openocd/tickets/448/ Reviewed-on: https://review.openocd.org/c/openocd/+/8719 Tested-by: jenkins Reviewed-by: Jasper v. Blanckenburg Reviewed-by: Antonio Borneo --- src/flash/nor/kinetis.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 2f88b9c1fe..85c306bd44 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -1489,7 +1489,22 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) kinetis_auto_probe(bank_iter); - assert(bank_iter->prot_blocks); + if (bank_iter->num_prot_blocks == 0) { + if (k_bank->flash_class == FC_PFLASH) { + LOG_ERROR("BUG: PFLASH bank %u has no protection blocks", + bank_idx); + } else { + LOG_DEBUG("skipping FLEX_NVM bank %u with no prot blocks (EE bkp only)", + bank_idx); + } + continue; + } + + if (!bank_iter->prot_blocks) { + LOG_ERROR("BUG: bank %u has NULL protection blocks array", + bank_idx); + continue; + } if (k_bank->flash_class == FC_PFLASH) { for (unsigned int i = 0; i < bank_iter->num_prot_blocks; i++) { From 0b97973bfbb980f987ec8e0e8d8ad32c85e9e5b0 Mon Sep 17 00:00:00 2001 From: Marek Vrbka Date: Mon, 13 Jan 2025 10:28:15 +0100 Subject: [PATCH 1065/1312] vdebug: Fix socket comparison warning on Windows On GCC version 13.2, the previous code emitted the following warning on Windows: openocd/src/jtag/drivers/vdebug.c:254:19: warning: comparison of integer expressions of different signedness: 'int' and 'long long unsigned int' [-Wsign-compare] 254 | if (hsock == INVALID_SOCKET) This patch fixes it and brings it in line with other socket handling code. Change-Id: I7e05f83c6905cfaf66b68e8988c783e80cee4a48 Signed-off-by: Marek Vrbka Reviewed-on: https://review.openocd.org/c/openocd/+/8717 Tested-by: jenkins Reviewed-by: Jan Matyas Reviewed-by: Jacek Wuwer Reviewed-by: Antonio Borneo Reviewed-by: R. Diez --- src/jtag/drivers/vdebug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index 691e576e53..20819f70bd 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -252,7 +252,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port) #ifdef _WIN32 hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (hsock == INVALID_SOCKET) + if (hsock < 0) rc = vdebug_socket_error(); #elif defined __CYGWIN__ /* SO_RCVLOWAT unsupported on CYGWIN */ From 778d2dc4bb982ffa00f5fbd343346555fcbf9113 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 17 Jan 2025 18:03:40 +0300 Subject: [PATCH 1066/1312] helper/options: drop redundant argument checks In case the option is passed with a single `:` in `optstring` argument, the call to `getopt_long()` should return `?`. Therefore the check on `optarg` is redundand in case of `l` and `c`. Change-Id: I1ac176fdae449a34db0a0496b69a9ea65ccd6aec Signed-off-by: Evgeniy Naydanov Reported-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8718 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/options.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/helper/options.c b/src/helper/options.c index 61a1014697..9e332cc8ce 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -303,12 +303,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) break; } case 'l': /* --log_output | -l */ - if (optarg) - command_run_linef(cmd_ctx, "log_output %s", optarg); + command_run_linef(cmd_ctx, "log_output %s", optarg); break; case 'c': /* --command | -c */ - if (optarg) - add_config_command(optarg); + add_config_command(optarg); break; default: /* '?' */ /* getopt will emit an error message, all we have to do is bail. */ From 345473f3ceaf6a1241f62354e31eeababfc56588 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Tue, 17 Dec 2024 18:13:00 +0300 Subject: [PATCH 1067/1312] helper/options: handle errors in `-l` Before the patch an error in opening the log file (e.g. can't write a file) was ignored when specified via `-l`. E.g.: ``` > touch log > chmod -w log > openocd -l log -c shutdown ... failed to open output log "log" shutdown command invoked > echo $? 0 ``` After the patch: ``` ... > openocd -l log -c shutdown ... failed to open output log "log" > echo $? 1 ``` Change-Id: Ibab45f580dc46a499bf967c4afad071f9c2972a2 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8666 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/options.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/helper/options.c b/src/helper/options.c index 9e332cc8ce..50977a6106 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -303,8 +303,12 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) break; } case 'l': /* --log_output | -l */ - command_run_linef(cmd_ctx, "log_output %s", optarg); + { + int retval = command_run_linef(cmd_ctx, "log_output %s", optarg); + if (retval != ERROR_OK) + return retval; break; + } case 'c': /* --command | -c */ add_config_command(optarg); break; From ac18b8cd6a3f21b97f942efdbb0ec2f362bb132b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 17 Nov 2024 21:35:45 +0100 Subject: [PATCH 1068/1312] configure: make more robust the check for elf 64 The check if 'elf.h' defines the type 'Elf64_Ehdr' is currently done through 'grep' on the file. While there is no false positive, so far, such test could incorrectly find the text inside a comment or in a block guarded by #if/#endif. Use the autoconf macro AC_CHECK_TYPE() to detect if the type is properly declared. Change-Id: Ibb74db3d90ac6d1589b9dc1e5a7ae59e47945e78 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8591 Tested-by: jenkins --- configure.ac | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 49054288f7..fc1e20ef8e 100644 --- a/configure.ac +++ b/configure.ac @@ -52,9 +52,11 @@ AC_SEARCH_LIBS([openpty], [util]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([elf.h]) -AC_EGREP_HEADER(Elf64_Ehdr, [elf.h], [ - AC_DEFINE([HAVE_ELF64], [1], [Define to 1 if the system has the type `Elf64_Ehdr'.]) -]) + +AC_CHECK_TYPE([Elf64_Ehdr], + AC_DEFINE([HAVE_ELF64], [1], [Define to 1 if the system has the type 'Elf64_Ehdr'.]), + [], [[#include ]]) + AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) From 8038e2f7548792a090bdd255ec6bfbf4128fead7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 17 Nov 2024 22:46:15 +0100 Subject: [PATCH 1069/1312] configure: allow --enable-malloc-logging only with glibc The feature for 'malloc-logging' uses functionalities that are available only in GNU libc. Detect in 'configure' if OpenOCD is being compiled with glibc. Set the macro '_DEBUG_FREE_SPACE_' only in case of glibc. Change-Id: I43e9b87c7ad47171cfe3e7c1e5f96f11e19f98d0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8592 Tested-by: jenkins --- configure.ac | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index fc1e20ef8e..a558650b37 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,11 @@ AC_CHECK_TYPE([Elf64_Ehdr], AC_DEFINE([HAVE_ELF64], [1], [Define to 1 if the system has the type 'Elf64_Ehdr'.]), [], [[#include ]]) +AC_MSG_CHECKING([for glibc]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int v = __GLIBC__;return 0;]])], + [have_glibc=yes], [have_glibc=no]) +AC_MSG_RESULT($have_glibc) + AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) @@ -262,7 +267,7 @@ AC_ARG_ENABLE([malloc_logging], AC_MSG_CHECKING([whether to enable malloc free space logging]); AC_MSG_RESULT([$debug_malloc]) -AS_IF([test "x$debug_malloc" = "xyes"], [ +AS_IF([test "x$debug_malloc" = "xyes" -a "x$have_glibc" = "xyes"], [ AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging]) ]) From fceccde0b394cff9127dca13708ef689094c9975 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 19 Feb 2024 20:11:07 -0600 Subject: [PATCH 1070/1312] helper/log: Fix build using _DEBUG_FREE_SPACE_ The glibc API 'mallinfo' is deprecated and the new 'mallinfo2' should be used from glibc 2.33 (2021-02-01). Throw an error when '--enable-malloc-logging' is used on systems that compile without glibc. Detect the glibc version and, for backward compatibility, define 'mallinfo2' as the old 'mallinfo'. Define a macro for the format of 'fordblks'. Change-Id: I68bff7b1b58f0ec2669db0b911f19c1c5a26ed30 Reported-by: Steven J. Hill Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8589 Tested-by: jenkins --- src/helper/log.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/helper/log.c b/src/helper/log.c index e02556b6db..8f7ab00397 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -30,6 +30,18 @@ #else #error "malloc.h is required to use --enable-malloc-logging" #endif + +#ifdef __GLIBC__ +#if __GLIBC_PREREQ(2, 33) +#define FORDBLKS_FORMAT " %zu" +#else +/* glibc older than 2.33 (2021-02-01) use mallinfo(). Overwrite it */ +#define mallinfo2 mallinfo +#define FORDBLKS_FORMAT " %d" +#endif +#else +#error "GNU glibc is required to use --enable-malloc-logging" +#endif #endif int debug_level = LOG_LVL_INFO; @@ -105,12 +117,11 @@ static void log_puts(enum log_levels level, /* print with count and time information */ int64_t t = timeval_ms() - start; #ifdef _DEBUG_FREE_SPACE_ - struct mallinfo info; - info = mallinfo(); + struct mallinfo2 info = mallinfo2(); #endif fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()" #ifdef _DEBUG_FREE_SPACE_ - " %d" + FORDBLKS_FORMAT #endif ": %s", log_strings[level + 1], count, t, file, line, function, #ifdef _DEBUG_FREE_SPACE_ From 77c904fd13c08077cafd0845107506db408b5bb1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 2 Jul 2024 17:12:46 +0200 Subject: [PATCH 1071/1312] Deprecate jimtcl Git submodule jimtcl was integrated as Git submodule for convenience and probably also because packages were not widely available at the time. Today, jimtcl is available in many popular package repositories [1] and the integration as Git submodule adds unnecessary complexity to the OpenOCD build process. For details, see the discussion on the mailing list in [2]. Disable the jimtcl Git submodule by default and announce it as deprecated feature that will be removed in the next release. This gives package maintainers time to adapt to the change and, if necessary, build a package for jimtcl. [1] https://repology.org/project/jimtcl/versions [2] https://sourceforge.net/p/openocd/mailman/message/58786630/ Change-Id: I07930ac07f7d7a6317c08b21dc118f4f128b331c Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8380 Tested-by: jenkins Reviewed-by: Paul Fertser Reviewed-by: Antonio Borneo --- configure.ac | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index a558650b37..4b10aabd5d 100644 --- a/configure.ac +++ b/configure.ac @@ -399,8 +399,8 @@ AS_CASE([$host_os], ]) AC_ARG_ENABLE([internal-jimtcl], - AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]), - [use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes]) + AS_HELP_STRING([--enable-internal-jimtcl], [Enable building internal jimtcl (deprecated)]), + [use_internal_jimtcl=$enableval], [use_internal_jimtcl=no]) AC_ARG_ENABLE([jimtcl-maintainer], AS_HELP_STRING([--enable-jimtcl-maintainer], [Enable maintainer mode when building internal jimtcl]), @@ -878,6 +878,10 @@ AS_IF([test "x$enable_jlink" != "xno"], [ ]]) ) +AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ + AC_MSG_WARN([Using the internal jimtcl is deprecated and will not be possible in the future.]) +]) + echo echo echo OpenOCD configuration summary From a510d51a78f14fbb8416037a587ce1bfc6016d24 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 26 Jun 2024 15:50:45 +0200 Subject: [PATCH 1072/1312] bootstrap: Do not set up Git submodules by default Building OpenOCD with jimtcl and libjaylink Git submodules is deprecated and will be removed in the upcoming releases. The remaining 'git2cl' submodule is only required during the OpenOCD release process. Only set up Git submodules when the 'with-submodules' argument is used, for example during the OpenOCD release process or for the transition period until all submodules are replaced by external dependencies. We keep the existing 'nosubmodule' argument in order to not break automatic testing with Jenkins. Change-Id: Ia4fd765e3a2d6b2c40b084a1ffdf919d5f4f35bb Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8381 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: R. Diez --- bootstrap | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/bootstrap b/bootstrap index 9dfdc41aca..0ee26d4ed3 100755 --- a/bootstrap +++ b/bootstrap @@ -15,19 +15,21 @@ else exit 1 fi -SKIP_SUBMODULE=0 +WITH_SUBMODULES=0 case "$#" in 0) ;; - 1) if [ "$1" = "nosubmodule" ]; then - SKIP_SUBMODULE=1 - else + 1) if [ "$1" = "with-submodules" ]; then + WITH_SUBMODULES=1 + elif [ "$1" = "nosubmodule" ]; then + WITH_SUBMODULES=0 + elif [ -n "$1" ]; then echo "$0: Illegal argument $1" >&2 - echo "USAGE: $0 [nosubmodule]" >&2 + echo "USAGE: $0 [with-submodules]" >&2 exit 1 fi;; *) echo "$0: Wrong number of command-line arguments." >&2 - echo "USAGE: $0 [nosubmodule]" >&2 + echo "USAGE: $0 [with-submodules]" >&2 exit 1;; esac @@ -42,12 +44,12 @@ autoheader --warnings=all automake --warnings=all --gnu --add-missing --copy ) -if [ "$SKIP_SUBMODULE" -ne 0 ]; then - echo "Skipping submodule setup" -else +if [ "$WITH_SUBMODULES" -ne 0 ]; then echo "Setting up submodules" git submodule sync git submodule update --init +else + echo "Skipping submodule setup" fi if [ -x src/jtag/drivers/libjaylink/autogen.sh ]; then From ce38758e3df929d5b27947ab7b987cc319a628aa Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 26 Nov 2024 23:16:15 +0200 Subject: [PATCH 1073/1312] rtos: chibios: replace malloc+sprintf with alloc_printf This makes it safer and simpler at the same time. Signed-off-by: Paul Fertser Change-Id: Ie294f1f6033ffc9f46b39210e2f7fc2f648e80ac Reviewed-on: https://review.openocd.org/c/openocd/+/8598 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/rtos/chibios.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c index f4ee33a490..af590c2cb1 100644 --- a/src/rtos/chibios.c +++ b/src/rtos/chibios.c @@ -421,9 +421,11 @@ static int chibios_update_threads(struct rtos *rtos) else state_desc = "Unknown"; - curr_thrd_details->extra_info_str = malloc(strlen( - state_desc)+8); - sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc); + curr_thrd_details->extra_info_str = alloc_printf("State: %s", state_desc); + if (!curr_thrd_details->extra_info_str) { + LOG_ERROR("Could not allocate space for thread state description"); + return -1; + } curr_thrd_details->exists = true; From eb6f2745b7d9924d0dddeab91c1743867c4e812c Mon Sep 17 00:00:00 2001 From: Sergey Matsievskiy Date: Wed, 18 Sep 2024 20:12:48 +0300 Subject: [PATCH 1074/1312] flash/nor: add DesignWare SPI controller driver Driver for DesignWare SPI controller, found on many SoCs (see compatible list in Linux device tree bindings Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml). This implementation only supports MIPS as it was the only one available for the tests, however, adding support for other architectures should require only few adjustments. Driver relies on flash/nor/spi.h to find Flash chip info. Driver internal functions support 24bit addressing mode, but due to limitations of flash/nor/spi.h, it is not used. The reported writing speed is about 60kb/s. Lint, sanitizer and valgrind reported warnings were not related to the driver. Change-Id: Id3df5626ab88055f034f74f274823051dedefeb1 Signed-off-by: Sergey Matsievskiy Reviewed-on: https://review.openocd.org/c/openocd/+/8400 Tested-by: jenkins Reviewed-by: Tomas Vanek --- contrib/loaders/flash/dw-spi/Makefile | 35 + contrib/loaders/flash/dw-spi/dw-spi.c | 246 +++ contrib/loaders/flash/dw-spi/dw-spi.h | 313 ++++ .../dw-spi/mipsel-linux-gnu-check_fill.inc | 39 + .../flash/dw-spi/mipsel-linux-gnu-erase.inc | 39 + .../flash/dw-spi/mipsel-linux-gnu-program.inc | 51 + .../flash/dw-spi/mipsel-linux-gnu-read.inc | 33 + .../dw-spi/mipsel-linux-gnu-transaction.inc | 21 + doc/openocd.texi | 69 + src/flash/nor/Makefile.am | 2 + src/flash/nor/driver.h | 1 + src/flash/nor/drivers.c | 1 + src/flash/nor/dw-spi-helper.h | 102 ++ src/flash/nor/dw-spi.c | 1608 +++++++++++++++++ 14 files changed, 2560 insertions(+) create mode 100644 contrib/loaders/flash/dw-spi/Makefile create mode 100644 contrib/loaders/flash/dw-spi/dw-spi.c create mode 100644 contrib/loaders/flash/dw-spi/dw-spi.h create mode 100644 contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc create mode 100644 contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc create mode 100644 contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc create mode 100644 contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc create mode 100644 contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc create mode 100644 src/flash/nor/dw-spi-helper.h create mode 100644 src/flash/nor/dw-spi.c diff --git a/contrib/loaders/flash/dw-spi/Makefile b/contrib/loaders/flash/dw-spi/Makefile new file mode 100644 index 0000000000..e86827882f --- /dev/null +++ b/contrib/loaders/flash/dw-spi/Makefile @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +TOOLCHAIN:=mipsel-linux-gnu- +CC:=$(TOOLCHAIN)gcc +OBJCOPY:=$(TOOLCHAIN)objcopy +CFLAGS:=-O2 -Wall -Wextra -fpic -Wno-int-to-pointer-cast +SRC=dw-spi.c +OBJ=$(patsubst %.c, %.o,$(SRC)) + +# sparx-iv +ifeq ($(TOOLCHAIN),mipsel-linux-gnu-) + CFLAGS+= -march=24kec +endif + +all: \ + $(TOOLCHAIN)transaction.inc \ + $(TOOLCHAIN)erase.inc \ + $(TOOLCHAIN)check_fill.inc \ + $(TOOLCHAIN)program.inc \ + $(TOOLCHAIN)read.inc + +$(TOOLCHAIN)%.bin: $(OBJ) + $(OBJCOPY) --dump-section .$*=$@ $< + +%.inc: %.bin + xxd -i > $@ < $< + +.PHONY: clean +clean: + rm -rf .ccls-cache + find . \( \ + -iname "*.o" \ + -o -iname "*.bin" \ + -o -iname "*.inc" \ + \) -delete diff --git a/contrib/loaders/flash/dw-spi/dw-spi.c b/contrib/loaders/flash/dw-spi/dw-spi.c new file mode 100644 index 0000000000..66b743913c --- /dev/null +++ b/contrib/loaders/flash/dw-spi/dw-spi.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Helper functions for DesignWare SPI Core driver. + * These helpers are loaded into CPU and execute Flash manipulation algorithms + * at full CPU speed. Due to inability to control nCS pin, this is the only way + * to communicate with Flash chips connected via DW SPI serial interface. + * + * In order to avoid using stack, all functions used in helpers are inlined. + * Software breakpoints are used to terminate helpers. + * + * Pushing byte to TX FIFO does not make byte immediately available in RX FIFO + * and nCS is only asserted when TX FIFO is not empty. General approach is to + * fill TX FIFO with as many bytes as possible, at the same time reading + * available bytes from RX FIFO. + * + * This file contains helper functions. + */ + +#include "dw-spi.h" + +#include "../../../../src/flash/nor/dw-spi-helper.h" + +/** + * @brief Generic flash transaction. + * + * @param[in] arg: Function arguments. + */ +__attribute__((section(".transaction"))) void +transaction(struct dw_spi_transaction *arg) +{ + register uint8_t *buffer_tx = (uint8_t *)arg->buffer; + register uint8_t *buffer_rx = buffer_tx; + register uint32_t size = arg->size; + register volatile uint8_t *status = (uint8_t *)arg->status_reg; + register volatile uint8_t *data = (uint8_t *)arg->data_reg; + + wait_tx_finish(status); + flush_rx(status, data); + + for (; size > 0; size--) { + send_u8(status, data, *buffer_tx++); + if (arg->read_flag && rx_available(status)) + *buffer_rx++ = rcv_byte(data); + } + + // Pushed all data to TX FIFO. Read bytes left in RX FIFO. + if (arg->read_flag) { + while (buffer_rx < buffer_tx) { + wait_rx_available(status); + *buffer_rx++ = rcv_byte(data); + } + } + + RETURN; +} + +/** + * @brief Check flash sectors are filled with pattern. Primary use for + * checking sector erase state. + * + * @param[in] arg: Function arguments. + */ +__attribute__((section(".check_fill"))) void +check_fill(struct dw_spi_check_fill *arg) +{ + register uint32_t tx_size; + register uint32_t rx_size; + register uint32_t dummy_count; + register uint8_t filled; + register uint8_t *fill_status_array = (uint8_t *)arg->fill_status_array; + register volatile uint8_t *status = (uint8_t *)arg->status_reg; + register volatile uint8_t *data = (uint8_t *)arg->data_reg; + + for (; arg->sector_count > 0; arg->sector_count--, + arg->address += arg->sector_size, + fill_status_array++) { + wait_tx_finish(status); + flush_rx(status, data); + + /* + * Command byte and address bytes make up for dummy_count number of + * bytes, that must be skipped in RX FIFO before actual data arrives. + */ + send_u8(status, data, arg->read_cmd); + if (arg->four_byte_mode) { + dummy_count = 1 + 4; // Command byte + 4 address bytes + send_u32(status, data, arg->address); + } else { + dummy_count = 1 + 3; // Command byte + 3 address bytes + send_u24(status, data, arg->address); + } + + for (tx_size = arg->sector_size, rx_size = arg->sector_size, filled = 1; + tx_size > 0; tx_size--) { + send_u8(status, data, 0); // Dummy write to push out read data. + if (rx_available(status)) { + if (dummy_count > 0) { + // Read data not arrived yet. + rcv_byte(data); + dummy_count--; + } else { + if (rcv_byte(data) != arg->pattern) { + filled = 0; + break; + } + rx_size--; + } + } + } + if (filled) { + for (; rx_size > 0; rx_size--) { + wait_rx_available(status); + if (rcv_byte(data) != arg->pattern) { + filled = 0; + break; + } + } + } + *fill_status_array = filled; + } + + RETURN; +} + +/** + * @brief Erase flash sectors. + * + * @param[in] arg: Function arguments. + */ +__attribute__((section(".erase"))) void +erase(struct dw_spi_erase *arg) +{ + register uint32_t address = arg->address; + register uint32_t count = arg->sector_count; + register volatile uint8_t *status = (uint8_t *)arg->status_reg; + register volatile uint8_t *data = (uint8_t *)arg->data_reg; + + for (; count > 0; count--, address += arg->sector_size) { + write_enable(status, data, arg->write_enable_cmd); + wait_write_enable(status, data, arg->read_status_cmd, + arg->write_enable_mask); + + erase_sector(status, data, arg->erase_sector_cmd, address, + arg->four_byte_mode); + wait_busy(status, data, arg->read_status_cmd, arg->busy_mask); + } + + RETURN; +} + +/** + * @brief Flash program. + * + * @param[in] arg: Function arguments. + */ +__attribute__((section(".program"))) void +program(struct dw_spi_program *arg) +{ + register uint8_t *buffer = (uint8_t *)arg->buffer; + register uint32_t buffer_size = arg->buffer_size; + register volatile uint8_t *status = (uint8_t *)arg->status_reg; + register volatile uint8_t *data = (uint8_t *)arg->data_reg; + register uint32_t page_size; + + while (buffer_size > 0) { + write_enable(status, data, arg->write_enable_cmd); + wait_write_enable(status, data, arg->read_status_cmd, + arg->write_enable_mask); + + wait_tx_finish(status); + + send_u8(status, data, arg->program_cmd); + if (arg->four_byte_mode) + send_u32(status, data, arg->address); + else + send_u24(status, data, arg->address); + + for (page_size = MIN(arg->page_size, buffer_size); page_size > 0; + page_size--, buffer_size--) { + send_u8(status, data, *buffer++); + } + arg->address += arg->page_size; + wait_busy(status, data, arg->read_status_cmd, arg->busy_mask); + } + + RETURN; +} + +/** + * @brief Read data from flash. + * + * @param[in] arg: Function arguments. + */ +__attribute__((section(".read"))) void +read(struct dw_spi_read *arg) +{ + register uint32_t tx_size = arg->buffer_size; + register uint32_t rx_size = arg->buffer_size; + register uint32_t dummy_count; + register uint8_t *buffer = (uint8_t *)arg->buffer; + register volatile uint8_t *status = (uint8_t *)arg->status_reg; + register volatile uint8_t *data = (uint8_t *)arg->data_reg; + + wait_tx_finish(status); + flush_rx(status, data); + + /* + * Command byte and address bytes make up for dummy_count number of + * bytes, that must be skipped in RX FIFO before actual data arrives. + */ + send_u8(status, data, arg->read_cmd); + if (arg->four_byte_mode) { + dummy_count = 1 + 4; // Command byte + 4 address bytes + send_u32(status, data, arg->address); + } else { + dummy_count = 1 + 3; // Command byte + 3 address bytes + send_u24(status, data, arg->address); + } + + for (; tx_size > 0; tx_size--) { + send_u8(status, data, 0); // Dummy write to push out read data. + if (rx_available(status)) { + if (dummy_count > 0) { + rcv_byte(data); + dummy_count--; + } else { + *buffer++ = rcv_byte(data); + rx_size--; + } + } + } + while (rx_size > 0) { + wait_rx_available(status); + if (dummy_count > 0) { + // Read data not arrived yet. + rcv_byte(data); + dummy_count--; + } else { + *buffer++ = rcv_byte(data); + rx_size--; + } + } + + RETURN; +} diff --git a/contrib/loaders/flash/dw-spi/dw-spi.h b/contrib/loaders/flash/dw-spi/dw-spi.h new file mode 100644 index 0000000000..9efa768e66 --- /dev/null +++ b/contrib/loaders/flash/dw-spi/dw-spi.h @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/** + * @file + * Helper functions for DesignWare SPI Core driver. + * These helpers are loaded into CPU and execute Flash manipulation algorithms + * at full CPU speed. Due to inability to control nCS pin, this is the only way + * to communicate with Flash chips connected via DW SPI serial interface. + * + * In order to avoid using stack, all functions used in helpers are inlined. + * Software breakpoints are used to terminate helpers. + * + * This file contains functions, common to helpers. + */ + +#ifndef _DW_SPI_H_ +#define _DW_SPI_H_ + +#include +#include + +#include "../../../../src/helper/types.h" + +/** + * @brief SI busy status bit. + * + * Set when serial transfer is in progress, cleared when master is idle or + * disabled. + */ +#define DW_SPI_STATUS_BUSY 0x01 + +/** + * @brief SI TX FIFO not full status bit. + * + * Set when TX FIFO has room for one or more data-word. + */ +#define DW_SPI_STATUS_TFNF 0x02 + +/** + * @brief SI TX FIFO empty status bit. + */ +#define DW_SPI_STATUS_TFE 0x04 + +/** + * @brief SI RX FIFO not empty status bit. + */ +#define DW_SPI_STATUS_RFNE 0x08 + +/** + * @brief Return from helper function. + */ +#define RETURN \ + do { \ + asm("sdbbp\n\t"); \ + return; \ + } while (0) + +/** + * @brief Append byte to TX FIFO. + * + * For each transferred byte, DW SPI controller receives a byte into RX FIFO. + * Slave data are read by pushing dummy bytes to TX FIFO. + * + * @param[in] dr: Pointer to DR register. + * @param[in] byte: Data to push. + */ +__attribute__((always_inline)) static inline void +_send_byte(volatile uint8_t *dr, uint8_t byte) +{ + *dr = byte; +} + +/** + * @brief Get byte from RX FIFO. + * + * Reading RX byte removes it from RX FIFO. + * + * @param[in] dr: Pointer to DR register. + * @return RX FIFO byte. + */ +__attribute__((always_inline)) static inline uint8_t +rcv_byte(volatile uint8_t *dr) +{ + return *dr; +} + +/** + * @brief Check transmission is currently in progress. + * + * @param[in] sr: Pointer to SR register. + * @retval 1: Transmission is in progress. + * @retval 0: Controller is idle or off. + */ +__attribute__((always_inline)) static inline int +tx_in_progress(volatile uint8_t *sr) +{ + return (*sr ^ DW_SPI_STATUS_TFE) & (DW_SPI_STATUS_BUSY | DW_SPI_STATUS_TFE); +} + +/** + * @brief Wait for controller to finish previous transaction. + * + * @param[in] sr: Pointer to SR register. + */ +__attribute__((always_inline)) static inline void +wait_tx_finish(volatile uint8_t *sr) +{ + while (tx_in_progress(sr)) + ; +} + +/** + * @brief Wait for room in TX FIFO. + * + * @param[in] sr: Pointer to SR register. + */ +__attribute__((always_inline)) static inline void +wait_tx_available(volatile uint8_t *sr) +{ + while (!(*sr & DW_SPI_STATUS_TFNF)) + ; +} + +/** + * @brief Check for data available in RX FIFO. + * + * @param[in] sr: Pointer to SR register. + * @retval 1: Data available. + * @retval 0: No data available. + */ +__attribute__((always_inline)) static inline int +rx_available(volatile uint8_t *sr) +{ + return *sr & DW_SPI_STATUS_RFNE; +} + +/** + * @brief Wait for data in RX FIFO. + * + * @param[in] sr: Pointer to SR register. + */ +__attribute__((always_inline)) static inline void +wait_rx_available(volatile uint8_t *sr) +{ + while (!rx_available(sr)) + ; +} + +/** + * @brief Flush RX FIFO. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + */ +__attribute__((always_inline)) static inline void +flush_rx(volatile uint8_t *sr, volatile uint8_t *dr) +{ + while (*sr & DW_SPI_STATUS_RFNE) + *dr; +} + +/** + * @brief Append variable number of bytes to TX FIFO. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] word: Data to append. + * @param[in] bytes: Number of bytes to append. + */ +__attribute__((always_inline)) static inline void +_send_bytes(volatile uint8_t *sr, volatile uint8_t *dr, uint32_t word, + int bytes) +{ + for (register int i = bytes - 1; i >= 0; i--) { + wait_tx_available(sr); + _send_byte(dr, (word >> (i * 8)) & 0xff); + } +} + +/** + * @brief Append 8 bit value to TX FIFO. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] word: Data to push. + */ +__attribute__((always_inline)) static inline void +send_u8(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t byte) +{ + wait_tx_available(sr); + _send_byte(dr, byte); +} + +/** + * @brief Append 24 bit value to TX FIFO. + * + * Used to send Flash addresses in 24 bit mode. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] word: Data to push. + */ +__attribute__((always_inline)) static inline void +send_u24(volatile uint8_t *sr, volatile uint8_t *dr, uint32_t word) +{ + _send_bytes(sr, dr, word, 3); +} + +/** + * @brief Append 32 bit value to TX FIFO. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] word: Data to push. + */ +__attribute__((always_inline)) static inline void +send_u32(volatile uint8_t *sr, volatile uint8_t *dr, uint32_t word) +{ + _send_bytes(sr, dr, word, 4); +} + +/** + * @brief Read chip status register. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] stat_cmd: Read status command. + * @return Chip status. + */ +__attribute__((always_inline)) static inline uint8_t +read_status(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t stat_cmd) +{ + wait_tx_finish(sr); + flush_rx(sr, dr); + /* + * Don't bother with wait_tx_available() as TX FIFO is empty + * and we only send two bytes. + */ + _send_byte(dr, stat_cmd); + _send_byte(dr, 0); // Dummy write to push out read data. + wait_rx_available(sr); + rcv_byte(dr); // Dummy read to skip command byte. + wait_rx_available(sr); + return rcv_byte(dr); +} + +/** + * @brief Enable Flash chip write. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] we_cmd: Write enable command. + */ +__attribute__((always_inline)) static inline void +write_enable(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t we_cmd) +{ + wait_tx_finish(sr); + _send_byte(dr, we_cmd); +} + +/** + * @brief Erase Flash sector. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] erase_cmd: Erase sector cmd. + * @param[in] address: Sector address. + * @param[in] four_byte_mode: Device is in 32 bit mode flag. + */ +__attribute__((always_inline)) static inline void +erase_sector(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t erase_cmd, + uint32_t address, uint8_t four_byte_mode) +{ + wait_tx_finish(sr); + _send_byte(dr, erase_cmd); + if (four_byte_mode) + send_u32(sr, dr, address); + else + send_u24(sr, dr, address); +} + +/** + * @brief Wait for write enable flag. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] stat_cmd: Read status command. + * @param[in] we_mask: Write enable status mask. + */ +__attribute__((always_inline)) static inline void +wait_write_enable(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t stat_cmd, + uint8_t we_mask) +{ + while (!(read_status(sr, dr, stat_cmd) & we_mask)) + ; +} + +/** + * @brief Wait while flash is busy. + * + * @param[in] sr: Pointer to SR register. + * @param[in] dr: Pointer to DR register. + * @param[in] stat_cmd: Read status command. + * @param[in] busy_mask: Flash busy mask. + */ +__attribute__((always_inline)) static inline void +wait_busy(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t stat_cmd, + uint8_t busy_mask) +{ + while (read_status(sr, dr, stat_cmd) & busy_mask) + ; +} + +#endif // _DW_SPI_H_ diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc new file mode 100644 index 0000000000..94c732fe5b --- /dev/null +++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc @@ -0,0 +1,39 @@ + 0x0b, 0x00, 0x82, 0x88, 0x1f, 0x00, 0x8a, 0x88, 0x0f, 0x00, 0x83, 0x88, + 0x17, 0x00, 0x86, 0x88, 0x08, 0x00, 0x82, 0x98, 0x1c, 0x00, 0x8a, 0x98, + 0x0c, 0x00, 0x83, 0x98, 0x14, 0x00, 0x86, 0x98, 0x25, 0x38, 0x80, 0x00, + 0x54, 0x00, 0x40, 0x10, 0xf8, 0xff, 0x09, 0x24, 0x00, 0x00, 0x64, 0x90, + 0x05, 0x00, 0x84, 0x30, 0x04, 0x00, 0x84, 0x38, 0xfc, 0xff, 0x80, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, + 0x07, 0x00, 0x40, 0x50, 0x25, 0x00, 0xe5, 0x90, 0x00, 0x00, 0xc2, 0x90, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfc, 0xff, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0xe5, 0x90, 0x00, 0x00, 0x62, 0x90, + 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc5, 0xa0, 0x26, 0x00, 0xe2, 0x90, 0x45, 0x00, 0x40, 0x10, + 0x03, 0x00, 0xe8, 0x88, 0x00, 0x00, 0xe8, 0x98, 0x18, 0x00, 0x05, 0x24, + 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, + 0x06, 0x10, 0xa8, 0x00, 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xa5, 0x24, + 0x00, 0x00, 0xc2, 0xa0, 0xf8, 0xff, 0xa9, 0x14, 0x05, 0x00, 0x0b, 0x24, + 0x07, 0x00, 0xe8, 0x88, 0x04, 0x00, 0xe8, 0x98, 0x1e, 0x00, 0x00, 0x11, + 0x25, 0x28, 0x00, 0x01, 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, + 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa0, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0x06, 0x00, 0x40, 0x50, + 0xff, 0xff, 0xa5, 0x24, 0x00, 0x00, 0xc2, 0x90, 0x25, 0x00, 0x60, 0x51, + 0x24, 0x00, 0xec, 0x90, 0xff, 0xff, 0x6b, 0x25, 0xff, 0xff, 0xa5, 0x24, + 0xf1, 0xff, 0xa0, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x51, + 0x01, 0x00, 0x04, 0x24, 0x24, 0x00, 0xe5, 0x90, 0x00, 0x00, 0x62, 0x90, + 0x08, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x90, 0xff, 0x00, 0x42, 0x30, 0x04, 0x00, 0xa2, 0x14, + 0xff, 0xff, 0x08, 0x25, 0xf7, 0xff, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x04, 0x24, 0x00, 0x00, 0x44, 0xa1, 0x0b, 0x00, 0xe2, 0x88, + 0x01, 0x00, 0x4a, 0x25, 0x08, 0x00, 0xe2, 0x98, 0xff, 0xff, 0x42, 0x24, + 0x0b, 0x00, 0xe2, 0xa8, 0x08, 0x00, 0xe2, 0xb8, 0x03, 0x00, 0xe4, 0x88, + 0x07, 0x00, 0xe5, 0x88, 0x00, 0x00, 0xe4, 0x98, 0x04, 0x00, 0xe5, 0x98, + 0x21, 0x20, 0x85, 0x00, 0x03, 0x00, 0xe4, 0xa8, 0xae, 0xff, 0x40, 0x14, + 0x00, 0x00, 0xe4, 0xb8, 0x3f, 0x00, 0x00, 0x70, 0x08, 0x00, 0xe0, 0x03, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x42, 0x30, 0xed, 0xff, 0x82, 0x55, + 0x00, 0x00, 0x44, 0xa1, 0xd9, 0xff, 0x00, 0x10, 0xff, 0xff, 0x08, 0x25, + 0x00, 0x00, 0xe8, 0x98, 0x10, 0x00, 0x05, 0x24, 0x00, 0x00, 0x62, 0x90, + 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x06, 0x10, 0xa8, 0x00, + 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xa5, 0x24, 0x00, 0x00, 0xc2, 0xa0, + 0xf8, 0xff, 0xa9, 0x14, 0x04, 0x00, 0x0b, 0x24, 0xbc, 0xff, 0x00, 0x10, + 0x07, 0x00, 0xe8, 0x88 diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc new file mode 100644 index 0000000000..b72c7ea446 --- /dev/null +++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc @@ -0,0 +1,39 @@ + 0x0b, 0x00, 0x88, 0x88, 0x25, 0x28, 0x80, 0x00, 0x03, 0x00, 0x86, 0x88, + 0x0f, 0x00, 0x82, 0x88, 0x17, 0x00, 0x84, 0x88, 0x08, 0x00, 0xa8, 0x98, + 0x00, 0x00, 0xa6, 0x98, 0x0c, 0x00, 0xa2, 0x98, 0x5f, 0x00, 0x00, 0x11, + 0x14, 0x00, 0xa4, 0x98, 0xf8, 0xff, 0x07, 0x24, 0x1d, 0x00, 0xa9, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, + 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0, + 0x1c, 0x00, 0xaa, 0x90, 0x1f, 0x00, 0xa9, 0x90, 0x00, 0x00, 0x43, 0x90, + 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, + 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfc, 0xff, 0x60, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0, 0x00, 0x00, 0x80, 0xa0, + 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, + 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x83, 0x90, 0x24, 0x18, 0x23, 0x01, 0xe4, 0xff, 0x60, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xaa, 0x90, 0x21, 0x00, 0xa9, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, + 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0, + 0x31, 0x00, 0x20, 0x11, 0x10, 0x00, 0x09, 0x24, 0x18, 0x00, 0x09, 0x24, + 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, + 0x06, 0x18, 0x26, 0x01, 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25, + 0xf9, 0xff, 0x27, 0x15, 0x00, 0x00, 0x83, 0xa0, 0x1c, 0x00, 0xaa, 0x90, + 0x20, 0x00, 0xa9, 0x90, 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, + 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0x06, 0x00, 0x60, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, + 0x08, 0x00, 0x63, 0x30, 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x8a, 0xa0, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x43, 0x90, + 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, + 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, + 0x24, 0x18, 0x23, 0x01, 0xe4, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0xa3, 0x88, 0xff, 0xff, 0x08, 0x25, 0x04, 0x00, 0xa3, 0x98, + 0xa4, 0xff, 0x00, 0x15, 0x21, 0x30, 0xc3, 0x00, 0x3f, 0x00, 0x00, 0x70, + 0x08, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, + 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x06, 0x18, 0x26, 0x01, + 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25, 0xf9, 0xff, 0x27, 0x15, + 0x00, 0x00, 0x83, 0xa0, 0xd1, 0xff, 0x00, 0x10, 0x1c, 0x00, 0xaa, 0x90 diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc new file mode 100644 index 0000000000..31500e01d8 --- /dev/null +++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc @@ -0,0 +1,51 @@ + 0x13, 0x00, 0x88, 0x88, 0x25, 0x30, 0x80, 0x00, 0x0b, 0x00, 0x85, 0x88, + 0x17, 0x00, 0x82, 0x88, 0x1f, 0x00, 0x84, 0x88, 0x10, 0x00, 0xc8, 0x98, + 0x08, 0x00, 0xc5, 0x98, 0x14, 0x00, 0xc2, 0x98, 0x1c, 0x00, 0xc4, 0x98, + 0x78, 0x00, 0x00, 0x11, 0xf8, 0xff, 0x07, 0x24, 0x25, 0x00, 0xc9, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, + 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0, + 0x24, 0x00, 0xca, 0x90, 0x27, 0x00, 0xc9, 0x90, 0x00, 0x00, 0x43, 0x90, + 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, + 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfc, 0xff, 0x60, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0, 0x00, 0x00, 0x80, 0xa0, + 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, + 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x83, 0x90, 0x24, 0x18, 0x23, 0x01, 0xe4, 0xff, 0x60, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, + 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x00, 0xc9, 0x90, 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30, + 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0, + 0x29, 0x00, 0xc3, 0x90, 0x47, 0x00, 0x60, 0x10, 0x03, 0x00, 0xca, 0x88, + 0x00, 0x00, 0xca, 0x98, 0x18, 0x00, 0x09, 0x24, 0x00, 0x00, 0x43, 0x90, + 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x06, 0x18, 0x2a, 0x01, + 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25, 0x00, 0x00, 0x83, 0xa0, + 0xf8, 0xff, 0x27, 0x15, 0x25, 0x58, 0x00, 0x01, 0x07, 0x00, 0xc3, 0x88, + 0x04, 0x00, 0xc3, 0x98, 0x2b, 0x48, 0x03, 0x01, 0x0a, 0x58, 0x69, 0x00, + 0x0d, 0x00, 0x60, 0x11, 0x21, 0x50, 0xab, 0x00, 0x00, 0x00, 0xa9, 0x90, + 0x01, 0x00, 0xa5, 0x24, 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30, + 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0, + 0xf9, 0xff, 0xaa, 0x54, 0x00, 0x00, 0xa9, 0x90, 0x07, 0x00, 0xc3, 0x88, + 0x23, 0x40, 0x0b, 0x01, 0x04, 0x00, 0xc3, 0x98, 0x03, 0x00, 0xc9, 0x88, + 0x00, 0x00, 0xc9, 0x98, 0x21, 0x18, 0x23, 0x01, 0x03, 0x00, 0xc3, 0xa8, + 0x00, 0x00, 0xc3, 0xb8, 0x24, 0x00, 0xca, 0x90, 0x28, 0x00, 0xc9, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, + 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, + 0x08, 0x00, 0x63, 0x30, 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, + 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0, + 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, + 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, + 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x24, 0x18, 0x23, 0x01, + 0xe4, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xff, 0x00, 0x55, + 0x25, 0x00, 0xc9, 0x90, 0x3f, 0x00, 0x00, 0x70, 0x08, 0x00, 0xe0, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x98, 0x10, 0x00, 0x09, 0x24, + 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, + 0x06, 0x18, 0x2a, 0x01, 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25, + 0x00, 0x00, 0x83, 0xa0, 0xf8, 0xff, 0x27, 0x15, 0x25, 0x58, 0x00, 0x01, + 0x07, 0x00, 0xc3, 0x88, 0x04, 0x00, 0xc3, 0x98, 0x2b, 0x48, 0x03, 0x01, + 0x0a, 0x58, 0x69, 0x00, 0xbb, 0xff, 0x60, 0x15, 0x21, 0x50, 0xab, 0x00, + 0xc6, 0xff, 0x00, 0x10, 0x03, 0x00, 0xc9, 0x88 diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc new file mode 100644 index 0000000000..3f18b7c2e8 --- /dev/null +++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc @@ -0,0 +1,33 @@ + 0x0f, 0x00, 0x87, 0x88, 0x07, 0x00, 0x88, 0x88, 0x13, 0x00, 0x83, 0x88, + 0x1b, 0x00, 0x85, 0x88, 0x0c, 0x00, 0x87, 0x98, 0x04, 0x00, 0x88, 0x98, + 0x10, 0x00, 0x83, 0x98, 0x18, 0x00, 0x85, 0x98, 0x00, 0x00, 0x62, 0x90, + 0x05, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x38, 0xfc, 0xff, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, + 0x07, 0x00, 0x40, 0x50, 0x20, 0x00, 0x86, 0x90, 0x00, 0x00, 0xa2, 0x90, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfc, 0xff, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x86, 0x90, 0x00, 0x00, 0x62, 0x90, + 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa6, 0xa0, 0x21, 0x00, 0x82, 0x90, 0x35, 0x00, 0x40, 0x10, + 0x03, 0x00, 0x82, 0x88, 0x18, 0x00, 0x06, 0x24, 0xf8, 0xff, 0x09, 0x24, + 0x00, 0x00, 0x82, 0x98, 0x25, 0x20, 0x40, 0x00, 0x00, 0x00, 0x62, 0x90, + 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x06, 0x10, 0xc4, 0x00, + 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xc6, 0x24, 0xf9, 0xff, 0xc9, 0x14, + 0x00, 0x00, 0xa2, 0xa0, 0x05, 0x00, 0x06, 0x24, 0x23, 0x00, 0xe0, 0x10, + 0x25, 0x20, 0xe0, 0x00, 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, + 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xa0, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0x06, 0x00, 0x40, 0x50, + 0xff, 0xff, 0x84, 0x24, 0x00, 0x00, 0xa2, 0x90, 0x14, 0x00, 0xc0, 0x50, + 0x00, 0x00, 0x02, 0xa1, 0xff, 0xff, 0xc6, 0x24, 0xff, 0xff, 0x84, 0x24, + 0xf1, 0xff, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0xe0, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, + 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x90, + 0x03, 0x00, 0xc0, 0x50, 0xff, 0xff, 0xe7, 0x24, 0xf8, 0xff, 0x00, 0x10, + 0xff, 0xff, 0xc6, 0x24, 0x06, 0x00, 0xe0, 0x10, 0x00, 0x00, 0x02, 0xa1, + 0xf4, 0xff, 0x00, 0x10, 0x01, 0x00, 0x08, 0x25, 0xff, 0xff, 0xe7, 0x24, + 0xec, 0xff, 0x00, 0x10, 0x01, 0x00, 0x08, 0x25, 0x3f, 0x00, 0x00, 0x70, + 0x08, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x24, + 0xf8, 0xff, 0x09, 0x24, 0x00, 0x00, 0x82, 0x98, 0x25, 0x20, 0x40, 0x00, + 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, + 0x06, 0x10, 0xc4, 0x00, 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xc6, 0x24, + 0xf9, 0xff, 0xc9, 0x14, 0x00, 0x00, 0xa2, 0xa0, 0xcc, 0xff, 0x00, 0x10, + 0x04, 0x00, 0x06, 0x24 diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc new file mode 100644 index 0000000000..384dbadb15 --- /dev/null +++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc @@ -0,0 +1,21 @@ + 0x03, 0x00, 0x85, 0x88, 0x0b, 0x00, 0x88, 0x88, 0x0f, 0x00, 0x83, 0x88, + 0x17, 0x00, 0x86, 0x88, 0x00, 0x00, 0x85, 0x98, 0x08, 0x00, 0x88, 0x98, + 0x0c, 0x00, 0x83, 0x98, 0x14, 0x00, 0x86, 0x98, 0x00, 0x00, 0x62, 0x90, + 0x05, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x38, 0xfc, 0xff, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, + 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x90, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfc, 0xff, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x25, 0x38, 0xa0, 0x00, 0x21, 0x40, 0x05, 0x01, 0x00, 0x00, 0xa9, 0x90, + 0x01, 0x00, 0xa5, 0x24, 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, + 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xa0, + 0x1c, 0x00, 0x82, 0x90, 0x08, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0x04, 0x00, 0x40, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x90, 0x01, 0x00, 0xe7, 0x24, + 0xff, 0xff, 0xe2, 0xa0, 0xef, 0xff, 0xa8, 0x54, 0x00, 0x00, 0xa9, 0x90, + 0x1c, 0x00, 0x82, 0x90, 0x0c, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x10, 0xe8, 0x00, 0x09, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x90, 0x01, 0x00, 0xe7, 0x24, + 0xf9, 0xff, 0x07, 0x15, 0xff, 0xff, 0xe2, 0xa0, 0x3f, 0x00, 0x00, 0x70, + 0x08, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 diff --git a/doc/openocd.texi b/doc/openocd.texi index 47a6f69ebc..2ec49a4c08 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6421,6 +6421,75 @@ flash bank $_FLASHNAME fespi 0x20000000 0 0 0 $_TARGETNAME @end example @end deffn +@deffn {Flash Driver} {dw-spi} +@cindex DesignWare SPI controller driver +@cindex DW-SPI +Driver for SPI NOR flash chips connected via DesignWare SPI Core, used +in number of MCUs. +Currently, only MIPS M4K CPU architecture is supported. + +The flash size is autodetected based on the table of known JEDEC IDs hardcoded +in the OpenOCD sources. When flash size is set to @var{0}, probed Flash +size is used. + +This driver requires configuring DRAM controller first, setting up a +working area big enough to hold read/write buffers and switching Flash +chip to 32bit mode via Tcl commands. + +@quotation Note +If chip contains Boot controller, its 24/32bit setting must match +Flash chip. If Flash chip's reset line is not connected to JTAG adapter, +CPU reset may cause these configurations to be out of sync. +@end quotation + + +Mandatory driver's arguments are + +@itemize +@item @var{-freq} ... core frequency in Hz, used in communication speed +calculation. +@item @var{-simc} ... @var{SIMC} register block absolute address. +This value is the same as for Linux's driver device tree register field. +@item @var{-spi_mst} ... @var{SPI_MST} register address. When available, +it is used for switching between SPI Boot and Master controllers. This +value is the same as for Linux's driver device tree register field +second argument. Set to @var{0} if SPI Boot controller not available. +@item @var{-if_owner_offset} ... offset of @var{if_owner} field inside +@var{SPI_MST} register. Set to @var{0} if SPI Boot controller not available. +@end itemize + +Optional driver's arguments are + +@itemize +@item @var{-speed} ... SPI device communication speed in Hz. Minimal +speed depends on the @var{-freq} variable and has the value of +@var{freq/0xfffe}. The default value is @var{1000000}. +@item @var{-chip_select} ... Chip select pin. The default value +is @var{0}. +@item @var{-timeout} ... flash communication timeout in +seconds. The default value is @var{600}. +@end itemize + +For some SoCs there are shortcuts for mandatory arguments + +@itemize +@item @var{-jaguar2} ... configuration for MSCC Jaguar2 SoC family. +@item @var{-ocelot} ... configuration for MSCC Ocelot SoC family. +@end itemize + +Driver provides shortcut arguments for MSCC @var{-jaguar2} and +@var{-ocelot} network switch SOCs, which set the correct values for @var{-freq}, +@var{-simc}, @var{-spi_mst} and @var{-if_owner_offset} arguments. + +Example of equivalent configurations for Jaguar2 SoC + +@example +flash bank $_FLASHNAME dw-spi 0x40000000 0x02000000 4 4 $_TARGETNAME -freq 250000000 -simc 0x70101000 -spi_mst 0x70000024 -if_owner_offset 6 -speed 3000000 +flash bank $_FLASHNAME dw-spi 0x40000000 0x02000000 4 4 $_TARGETNAME -jaguar2 -speed 3000000 +@end example + +@end deffn + @subsection Internal Flash (Microcontrollers) @deffn {Flash Driver} {aduc702x} diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index afa11e7d40..8296877610 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -26,6 +26,7 @@ NOR_DRIVERS = \ %D%/cc26xx.c \ %D%/cfi.c \ %D%/dsp5680xx_flash.c \ + %D%/dw-spi.c \ %D%/efm32.c \ %D%/em357.c \ %D%/eneispif.c \ @@ -89,6 +90,7 @@ NORHEADERS = \ %D%/cc26xx.h \ %D%/cfi.h \ %D%/driver.h \ + %D%/dw-spi-helper.h \ %D%/imp.h \ %D%/non_cfi.h \ %D%/ocl.h \ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 211661e214..852a55a112 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -254,6 +254,7 @@ extern const struct flash_driver cc26xx_flash; extern const struct flash_driver cc3220sf_flash; extern const struct flash_driver cfi_flash; extern const struct flash_driver dsp5680xx_flash; +extern const struct flash_driver dw_spi_flash; extern const struct flash_driver efm32_flash; extern const struct flash_driver em357_flash; extern const struct flash_driver eneispif_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index dd9995ecba..ce97b81504 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -31,6 +31,7 @@ static const struct flash_driver * const flash_drivers[] = { &cc26xx_flash, &cfi_flash, &dsp5680xx_flash, + &dw_spi_flash, &efm32_flash, &em357_flash, &eneispif_flash, diff --git a/src/flash/nor/dw-spi-helper.h b/src/flash/nor/dw-spi-helper.h new file mode 100644 index 0000000000..d3537557b6 --- /dev/null +++ b/src/flash/nor/dw-spi-helper.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/** + * @file + * Driver for SPI NOR flash chips connected via DesignWare SPI Core. + * + * In order to avoid using stack, all helper function arguments are packed + * into a single struct, passed by pointer. + * + * Pointers are represented by 64 bit integers to make structs compatible + * with 64 bit targets. + * + * This file contains helper function argument structures. + */ + +#ifndef OPENOCD_FLASH_NOR_DW_SPI_HELPER_H +#define OPENOCD_FLASH_NOR_DW_SPI_HELPER_H + +#include + +/** + * @brief Arguments for transaction helper function. + */ +struct dw_spi_transaction { + uint64_t buffer; + ///< Pointer to data buffer to send over SPI. + ///< Return values are stored in place of output data when + ///< dw_spi_transaction::read_flag is 1. + uint32_t size; ///< Size of dw_spi_transaction::buffer. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_flag; + ///< When 1, store RX FIFO data to dw_spi_transaction::buffer. +} __attribute__((packed)); + +/** + * @brief Arguments for check_fill helper function. + */ +struct dw_spi_check_fill { + uint32_t address; ///< Starting address. Sector aligned. + uint32_t sector_size; ///< Sector size. + uint32_t sector_count; ///< Number of sectors to check. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint64_t fill_status_array; + ///< Pointer to array describing sectors fill status. + ///< 1 if filled, 0 if not filled. + uint8_t pattern; ///< Fill pattern. + uint8_t read_cmd; ///< Read data command. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +/** + * @brief Arguments for erase helper function. + */ +struct dw_spi_erase { + uint32_t address; ///< First sector address. Sector aligned. + uint32_t sector_size; ///< Sector size. + uint32_t sector_count; ///< Number of sectors to erase. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_status_cmd; ///< Read status command. + uint8_t write_enable_cmd; ///< Write enable command. + uint8_t erase_sector_cmd; ///< Erase sector command. + uint8_t write_enable_mask; ///< Write enable mask. + uint8_t busy_mask; ///< Busy mask. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +/** + * @brief Arguments for program helper function. + */ +struct dw_spi_program { + uint32_t address; + ///< First page address. Page aligned when write is crossing + ///< the page boundary. + uint32_t page_size; ///< Page size. + uint64_t buffer; ///< Data buffer pointer. + uint32_t buffer_size; ///< Size of dw_spi_program::buffer. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_status_cmd; ///< Read status command. + uint8_t write_enable_cmd; ///< Write enable command. + uint8_t program_cmd; ///< Program command. + uint8_t write_enable_mask; ///< Write enable mask. + uint8_t busy_mask; ///< Busy mask. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +/** + * @brief Arguments for read helper function. + */ +struct dw_spi_read { + uint32_t address; ///< First sector address. + uint64_t buffer; ///< Data buffer pointer. + uint32_t buffer_size; ///< Size of dw_spi_read::buffer. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_cmd; ///< Read data command. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +#endif /* OPENOCD_FLASH_NOR_DW_SPI_HELPER_H */ diff --git a/src/flash/nor/dw-spi.c b/src/flash/nor/dw-spi.c new file mode 100644 index 0000000000..e1965477e1 --- /dev/null +++ b/src/flash/nor/dw-spi.c @@ -0,0 +1,1608 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Driver for SPI NOR flash chips connected via DesignWare SPI Core. + * Controller's Linux driver is located at drivers/spi/spi-dw-mmio.c. + * DW-SPI is used in a number of processors, including Microsemi Jaguar2 and + * Ocelot switch chips. + * + * Serial interface (SI) nCS0 pin, which is usually connected to the external + * flash, cannot be controlled via GPIO controller: it is asserted only when + * TX FIFO is not empty. Since JTAG is not fast enough to fill TX FIFO and + * collect data from RX FIFO at the same time even on the slowest SPI clock + * speeds, driver can only operate using functions, loaded in target's memory. + * Therefore, it requires the user to set up DRAM controller and provide + * work-area. + * + * In Microsemi devices, serial interface pins may be governed either + * by Boot or Master controller. For these devices, additional configuration of + * spi_mst address is required to switch between the two. + * + * Currently supported devices typically have much more RAM then NOR Flash + * (Jaguar2 reference design has 256MB RAM and 32MB NOR Flash), so supporting + * work-area sizes smaller then transfer buffer seems like the unnecessary + * complication. + * + * This code was tested on Jaguar2 VSC7448 connected to Macronix MX25L25635F. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dw-spi-helper.h" +#include "imp.h" +#include "spi.h" + +#include +#include +#include +#include +#include +#include + +/** + * @brief IP block placement map. + * + * Used for dynamic definition of the register map. + * + * IP block is used on different chips and placed in different locations. + * This structure defines some implementation specific variables. + */ +struct dw_spi_regmap { + uint32_t freq; ///< Clock frequency. + target_addr_t simc; ///< Absolute offset of SIMC register block. + target_addr_t spi_mst; + ///< Absolute offset of ICPU_CFG:SPI_MST register. 0 if not available. + uint8_t si_if_owner_offset; + ///< Offset of \ref si_mode bits in ICPU_CFG:SPI_MST. +}; + +/** + * @brief Register map for Jaguar2 switch devices. + */ +static const struct dw_spi_regmap jaguar2_regmap = { + .freq = 250000000UL, + .simc = 0x70101000UL, + .spi_mst = 0x70000024UL, + .si_if_owner_offset = 6, +}; + +/** + * @brief Register map for Ocelot switch devices. + */ +static const struct dw_spi_regmap ocelot_regmap = { + .freq = 250000000UL, + .simc = 0x70101000UL, + .spi_mst = 0x70000024UL, + .si_if_owner_offset = 4, +}; + +#define DW_SPI_IF_OWNER_WIDTH 2 ///< IF owner register field width. + +/** + * @brief Owner of the SI interface. + */ +enum dw_spi_si_mode { + DW_SPI_SI_MODE_BOOT = 1, + ///< Boot controller maps contents of SPI Flash to memory in read-only mode. + DW_SPI_SI_MODE_MASTER = 2, + ///< SPI controller mode for reading/writing SPI Flash. +}; + +#define DW_SPI_REG_CTRLR0 0x00 ///< General configuration register. +#define DW_SPI_REG_SIMCEN 0x08 ///< Master controller enable register. +#define DW_SPI_REG_SER 0x10 ///< Slave select register. +#define DW_SPI_REG_BAUDR 0x14 ///< Baud rate configuration register. +#define DW_SPI_REG_SR 0x28 ///< Status register. +#define DW_SPI_REG_IMR 0x2c ///< Interrupt configuration register. +#define DW_SPI_REG_DR 0x60 ///< Data register. + +#define DW_SPI_REG_CTRLR0_DFS(x) ((x) & GENMASK(3, 0)) ///< Data frame size. +#define DW_SPI_REG_CTRLR0_FRF(x) (((x) << 4) & GENMASK(5, 4)) ///< SI protocol. +#define DW_SPI_REG_CTRLR0_SCPH(x) ((!!(x)) << 6) ///< Probe position. +#define DW_SPI_REG_CTRLR0_SCPOL(x) ((!!(x)) << 7) ///< Probe polarity. +#define DW_SPI_REG_CTRLR0_TMOD(x) (((x) << 8) & GENMASK(9, 8)) ///< SI mode. +#define DW_SPI_REG_SIMCEN_SIMCEN(x) (!!(x)) ///< Controller enable. +#define DW_SPI_REG_SER_SER(x) ((x) & GENMASK(15, 0)) ///< Slave select bitmask. +#define DW_SPI_REG_BAUDR_SCKDV(x) ((x) & GENMASK(15, 0)) ///< Clock divisor. + +/** + * @brief Driver private state. + */ +struct dw_spi_driver { + bool probed; ///< Bank is probed. + uint32_t id; ///< Chip ID. + unsigned int speed; ///< Flash speed. + unsigned int timeout; ///< Flash timeout in milliseconds. + uint8_t chip_select_bitmask; ///< Chip select bitmask. + bool four_byte_mode; ///< Flash chip is in 32bit address mode. + enum dw_spi_si_mode saved_ctrl_mode; + ///< Previously selected controller mode. + struct dw_spi_regmap regmap; ///< SI controller regmap. + const struct flash_device *spi_flash; ///< SPI flash device info. +}; + +/** + * @brief Register used to pass argument struct to helper functions. + */ +#define DW_SPI_ARG_REG "r4" + +/** + * @brief Default timeout value in ms for flash transaction jobs. + */ +#define DW_SPI_TIMEOUT_DEFAULT (600 * 1000) + +/** + * @brief Timeout value in ms for short flash transactions, + * e.g. reading flash ID and status register. + */ +#define DW_SPI_TIMEOUT_TRANSACTION 1000 + +/** + * @brief Select SI interface owner. + * + * Mode selection is skipped if Boot controller not available on target + * (i.e. spi_mst command argument is not configured). + * + * @param[in] bank: Flash bank. + * @param[in] mode: New controller mode. + * @return Command execution status. + */ +static int +dw_spi_ctrl_mode(const struct flash_bank *const bank, enum dw_spi_si_mode mode) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + if (!regmap->spi_mst) + return ERROR_OK; + + uint32_t ctrl; + int ret = target_read_u32(target, regmap->spi_mst, &ctrl); + if (ret) { + LOG_ERROR("DW SPI SPI:MST register read error"); + return ret; + } + ctrl &= ~GENMASK(DW_SPI_IF_OWNER_WIDTH + driver->regmap.si_if_owner_offset, + driver->regmap.si_if_owner_offset); + ctrl |= mode << driver->regmap.si_if_owner_offset; + + ret = target_write_u32(target, regmap->spi_mst, ctrl); + if (ret) + LOG_ERROR("DW SPI controller mode configuration error"); + + return ret; +} + +/** + * @brief Select master controller as SI interface owner. + * + * Previous interface owner is restored via dw_spi_ctrl_mode_restore() function. + * Mode selection is skipped if Boot controller not available on target + * (i.e. spi_mst command argument is not configured). + * + * @param[in] bank: Flash bank. + * @param[in] mode: New controller mode. + * @return Command execution status. + */ +static int +dw_spi_ctrl_mode_configure(const struct flash_bank *const bank, + enum dw_spi_si_mode mode) +{ + struct target *const target = bank->target; + struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + if (!regmap->spi_mst) + return ERROR_OK; + + uint32_t ctrl; + int ret = target_read_u32(target, regmap->spi_mst, &ctrl); + if (ret) { + LOG_ERROR("DW SPI controller mode query error"); + return ret; + } + driver->saved_ctrl_mode = + (enum dw_spi_si_mode)((ctrl >> driver->regmap.si_if_owner_offset) & + GENMASK(DW_SPI_IF_OWNER_WIDTH, 0)); + + return dw_spi_ctrl_mode(bank, mode); +} + +/** + * @brief Restore SI controller mode. + * + * Restore initially configured SI controller mode. Undo configuration done by + * dw_spi_ctrl_mode_configure() function. + * Mode selection is skipped if Boot controller not available on target + * (i.e. spi_mst command argument is not configured). + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_mode_restore(const struct flash_bank *const bank) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + return dw_spi_ctrl_mode(bank, driver->saved_ctrl_mode); +} + +/** + * @brief Enable master controller. + * + * Configuration of the master controller must be done when it is disabled. + * + * @param[in] bank: Flash bank. + * @param[in] value: New enable state. + * @return Command execution status. + */ +static int +dw_spi_master_ctrl_enable(const struct flash_bank *const bank, bool value) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_SIMCEN, + DW_SPI_REG_SIMCEN_SIMCEN(value)); + if (ret) + LOG_ERROR("DW SPI master controller enable flag configuration error"); + + return ret; +} + +/** + * @brief Configure SI transfer mode. + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_configure_si(const struct flash_bank *const bank) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + // 8 bit frame; Motorola protocol; middle lo probe; TX RX mode + const uint32_t mode = DW_SPI_REG_CTRLR0_DFS(0x7) | + DW_SPI_REG_CTRLR0_FRF(0) | + DW_SPI_REG_CTRLR0_SCPH(0) | + DW_SPI_REG_CTRLR0_SCPOL(0) | + DW_SPI_REG_CTRLR0_TMOD(0); + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_CTRLR0, mode); + if (ret) { + LOG_ERROR("DW SPI master controller configuration query error"); + return ret; + } + + ret = target_write_u32(target, regmap->simc + DW_SPI_REG_SER, + DW_SPI_REG_SER_SER(driver->chip_select_bitmask)); + if (ret) + LOG_ERROR("DW SPI slave select configuration error"); + + return ret; +} + +/** + * @brief Configure SI transfer speed. + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_configure_speed(const struct flash_bank *const bank) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + // divisor LSB must be zero + const uint16_t div = MIN((regmap->freq / driver->speed), 0xfffe) & 0xfffe; + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_BAUDR, + DW_SPI_REG_BAUDR_SCKDV(div)); + if (ret) { + LOG_ERROR("DW SPI speed configuration error"); + return ret; + } + + unsigned int speed = regmap->freq / div; + LOG_DEBUG("DW SPI setting NOR controller speed to %u kHz", speed / 1000); + + return ret; +} + +/** + * @brief Disable SI master controller interrupts. + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_disable_interrupts(const struct flash_bank *const bank) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_IMR, 0); + if (ret) + LOG_ERROR("DW SPI disable interrupts error"); + + return ret; +} + +/** + * @brief Do data transaction. + * + * Buffer data are sent and replaced with received data. Total buffer size + * is a sum of TX and RX messages. RX portion of the buffer is initially + * filled with dummy values, which get replaced by the message. + * + * @param[in] bank: Flash bank. + * @param[in,out] buffer: Data buffer. If \p read flag is set, buffer is + * filled with received data. + * @param[in] size: \p buffer size. + * @param[in] read: The read flag. If set to true, read values will override + * \p buffer. + * @return Command execution status. + */ +static int +dw_spi_ctrl_transaction(const struct flash_bank *const bank, + uint8_t *const buffer, size_t size, bool read) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_transaction) + size; + + // allocate working area, memory args and data buffer + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_transaction), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, size, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code and buffer to working areas + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + ret = target_write_buffer(target, target_buffer->address, size, buffer); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + + struct dw_spi_transaction *helper_args_val = + (struct dw_spi_transaction *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer, + target_buffer->address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->size, size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_flag = read; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, DW_SPI_TIMEOUT_TRANSACTION, + &mips32_algo); + + if (ret) { + LOG_ERROR("DW SPI flash algorithm error"); + goto cleanup; + } + + if (read) { + ret = target_read_buffer(target, target_buffer->address, size, buffer); + if (ret) + LOG_ERROR("DW SPI target buffer read error"); + } + +cleanup: + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Check that selected region is filled with pattern. + * + * This function is used for Flash erase checking. + * + * @param[in] bank: Flash bank. + * @param[in] address: Starting address. Sector aligned. + * @param[in] sector_size: Size of sector. + * @param[in] sector_count: Number of sectors. + * @param[in] pattern: Fill pattern. + * @param[in] read_cmd: Flash read command. + * @param[out] buffer: Filled flag array. Must hold \p sector_count number + * of entries. + * @return Command execution status. + */ +static int +dw_spi_ctrl_check_sectors_fill(const struct flash_bank *const bank, + uint32_t address, size_t sector_size, + size_t sector_count, uint8_t pattern, + uint8_t read_cmd, uint8_t *buffer) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_check_fill) + sector_count; + + // allocate working area, memory args and data buffer + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_check_fill), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, sector_count, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code and buffer to working areas + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + + struct dw_spi_check_fill *helper_args_val = + (struct dw_spi_check_fill *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_size, + sector_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_count, + sector_count); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + target_buffer_set_u32(target, + (uint8_t *)&helper_args_val->fill_status_array, + target_buffer->address); + helper_args_val->pattern = pattern; + helper_args_val->read_cmd = read_cmd; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + + if (ret) { + LOG_ERROR("DW SPI flash algorithm error"); + goto cleanup; + } + + ret = target_read_buffer(target, target_buffer->address, sector_count, + buffer); + if (ret) + LOG_ERROR("DW SPI target buffer read error"); + +cleanup: + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Write flash region. + * + * @param[in] bank: Flash bank. + * @param[in] address: First page address. Page aligned when write is crossing + * the page boundary. + * @param[in] buffer: Data buffer. + * @param[in] buffer_size: \p buffer size. + * @param[in] page_size: Size of flash page. + * @param[in] stat_cmd: Flash command to read chip status. + * @param[in] we_cmd: Flash command to enable write. + * @param[in] program_cmd: Flash command to program chip. + * @param[in] we_mask: Status byte write enable mask. + * @param[in] busy_mask: Status byte write busy mask. + * @return Command execution status. + */ +static int +dw_spi_ctrl_program(const struct flash_bank *const bank, uint32_t address, + const uint8_t *const buffer, size_t buffer_size, + uint32_t page_size, uint8_t stat_cmd, uint8_t we_cmd, + uint8_t program_cmd, uint8_t we_mask, uint8_t busy_mask) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_program) + buffer_size; + + // allocate working area, memory args and data buffer + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_program), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, buffer_size, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code and buffer to working areas + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + ret = target_write_buffer(target, target_buffer->address, buffer_size, + buffer); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + struct dw_spi_program *helper_args_val = + (struct dw_spi_program *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->page_size, + page_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer, + target_buffer->address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer_size, + buffer_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_status_cmd = stat_cmd; + helper_args_val->write_enable_cmd = we_cmd; + helper_args_val->program_cmd = program_cmd; + helper_args_val->write_enable_mask = we_mask; + helper_args_val->busy_mask = busy_mask; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + if (ret) + LOG_ERROR("DW SPI flash algorithm error"); + + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Erase sectors. + * + * @param[in] bank: Flash bank. + * @param[in] address: Flash address. Must be sector aligned. + * @param[in] sector_size: Size of flash sector. + * @param[in] sector_count: Number of sectors to erase. + * @param[in] stat_cmd: Flash command to read chip status. + * @param[in] we_cmd: Flash command to set enable write. + * @param[in] erase_sector_cmd: Flash command to set erase sector. + * @param[in] we_mask: Status byte write enable mask. + * @param[in] busy_mask: Status byte write busy mask. + * @return Command execution status. + */ +static int +dw_spi_ctrl_erase_sectors(const struct flash_bank *const bank, uint32_t address, + uint32_t sector_size, size_t sector_count, + uint8_t stat_cmd, uint8_t we_cmd, + uint8_t erase_sector_cmd, uint8_t we_mask, + uint8_t busy_mask) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_erase); + + // allocate working area and memory args + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_erase), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + // write algorithm code to working area + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + struct dw_spi_erase *helper_args_val = + (struct dw_spi_erase *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_size, + sector_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_count, + sector_count); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_status_cmd = stat_cmd; + helper_args_val->write_enable_cmd = we_cmd; + helper_args_val->erase_sector_cmd = erase_sector_cmd; + helper_args_val->write_enable_mask = we_mask; + helper_args_val->busy_mask = busy_mask; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + if (ret) + LOG_ERROR("DW SPI flash algorithm error"); + + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Read flash data. + * + * @param[in] bank: Flash bank. + * @param[in] address: Flash address. + * @param[out] buffer: Data buffer. + * @param[in] buffer_size: \p buffer size. + * @param[in] read_cmd: Flash command to read data from flash. + * @return Command execution status. + */ +static int +dw_spi_ctrl_read(const struct flash_bank *const bank, uint32_t address, + uint8_t *buffer, size_t buffer_size, uint8_t read_cmd) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_read) + buffer_size; + + // allocate working area and memory args + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_read), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, buffer_size, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code to working area + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + struct dw_spi_read *helper_args_val = (struct dw_spi_read *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer, + target_buffer->address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer_size, + buffer_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_cmd = read_cmd; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + if (ret) { + LOG_ERROR("DW SPI flash algorithm error"); + goto cleanup; + } + + ret = + target_read_buffer(target, target_buffer->address, buffer_size, buffer); + if (ret) + LOG_ERROR("DW SPI target buffer read error"); + +cleanup: + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Read Flash device ID. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_read_id(const struct flash_bank *const bank) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + const size_t buffer_size = 1 + 3 + 1; + uint8_t buffer[buffer_size]; + + memset(buffer, 0, buffer_size); + buffer[0] = SPIFLASH_READ_ID; + + int ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, true); + if (ret) { + LOG_ERROR("DW SPI flash ID read error"); + return ret; + } + + buffer[buffer_size - 1] = 0; + // use le_to_h_u32 to decode flash ID as per JEDEC SFDP + driver->id = le_to_h_u32(buffer + 1); + LOG_DEBUG("DW SPI read flash ID %" PRIx32, driver->id); + + return ERROR_OK; +} + +/** + * @brief Read Flash device status. + * + * @param[in] bank: Flash bank handle. + * @param[out] status: The status byte. + * @return Command execution status. + */ +static int +dw_spi_read_status(const struct flash_bank *const bank, uint8_t *const status) +{ + const int buffer_size = 2; + uint8_t buffer[buffer_size]; + + memset(buffer, 0, buffer_size); + buffer[0] = SPIFLASH_READ_STATUS; + + int ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, true); + if (ret) { + LOG_ERROR("DW SPI flash status read error"); + return ret; + } + + *status = buffer[1]; + + return ERROR_OK; +} + +/** + * @brief Wait for Flash command to finish. + * + * @param[in] bank: Flash bank handle. + * @param[in] timeout: The timeout in ms. + * @return Command execution status. + */ +static int +dw_spi_wait_finish(const struct flash_bank *const bank, unsigned int timeout) +{ + const int64_t end_time = timeval_ms() + timeout; + while (timeval_ms() <= end_time) { + uint8_t status; + int ret = dw_spi_read_status(bank, &status); + if (ret) { + LOG_ERROR("DW SPI status query error"); + return ret; + } + if (!(status & SPIFLASH_BSY_BIT)) + return ERROR_OK; + + alive_sleep(1); + } + + LOG_ERROR("DW SPI process timeout"); + return ERROR_TIMEOUT_REACHED; +} + +/** + * @brief Flash device write enable. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_write_enable(const struct flash_bank *const bank) +{ + const int buffer_size = 1; + uint8_t buffer[buffer_size]; + + memset(buffer, 0, buffer_size); + buffer[0] = SPIFLASH_WRITE_ENABLE; + + int ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, false); + if (ret) { + LOG_ERROR("DW SPI flash write enable error"); + return ret; + } + + uint8_t status; + ret = dw_spi_read_status(bank, &status); + if (ret) + return ret; + + return status & SPIFLASH_WE_BIT ? ERROR_OK : ERROR_FAIL; +} + +/** + * @brief Erase Flash chip. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_erase_chip(const struct flash_bank *const bank) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + const int buffer_size = 1; + uint8_t buffer[buffer_size]; + + int ret = dw_spi_write_enable(bank); + if (ret) + return ret; + + memset(buffer, 0, buffer_size); + buffer[0] = driver->spi_flash->chip_erase_cmd; + + ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, false); + if (ret) { + LOG_ERROR("DW SPI erase flash error"); + return ret; + } + + ret = dw_spi_wait_finish(bank, driver->timeout); + if (ret) { + LOG_ERROR("DW SPI erase flash timeout"); + return ret; + } + + return ERROR_OK; +} + +/** + * @brief Flash device erase sectors. + * + * @param[in] bank: Flash bank handle. + * @param[in] first: The first sector to erase. + * @param[in] last: The last sector to erase. + * @return Command execution status. + */ +static int +dw_spi_erase_sectors(const struct flash_bank *const bank, unsigned int first, + unsigned int last) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + if (first == 0 && last >= (bank->num_sectors - 1)) { + // full erase + int ret = dw_spi_erase_chip(bank); + if (ret) + return ret; + } else { + // partial erase + int ret = dw_spi_ctrl_erase_sectors(bank, bank->sectors[first].offset, + driver->spi_flash->sectorsize, + last - first + 1, + SPIFLASH_READ_STATUS, + SPIFLASH_WRITE_ENABLE, + driver->spi_flash->erase_cmd, + SPIFLASH_WE_BIT, SPIFLASH_BSY_BIT); + if (ret) { + LOG_ERROR("DW SPI flash erase sectors error"); + return ret; + } + } + + return ERROR_OK; +} + +/** + * @brief Flash bank blank check. + */ +static int +dw_spi_blank_check(struct flash_bank *bank, size_t sector_count, + uint8_t pattern) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + uint8_t *erased = malloc(sector_count); + if (!erased) { + LOG_ERROR("could not allocate memory"); + return ERROR_FAIL; + } + + // set initial erased value to unknown + memset(erased, 2, sector_count); + for (unsigned int sector_idx = 0; sector_idx < sector_count; sector_idx++) + bank->sectors[sector_idx].is_erased = 2; + + int ret = dw_spi_ctrl_check_sectors_fill(bank, 0, bank->sectors[0].size, + sector_count, pattern, + driver->spi_flash->read_cmd, + erased); + if (!ret) { + for (unsigned int sector_idx = 0; sector_idx < sector_count; + sector_idx++) + bank->sectors[sector_idx].is_erased = erased[sector_idx]; + } else { + LOG_ERROR("DW SPI flash erase check error"); + } + + free(erased); + + return ret; +} + +/** + * @brief Write buffer to Flash. + * + * @param[in] bank: Flash bank handle. + * @param[in] buffer: Data buffer. + * @param[in] offset: Flash address offset. + * @param[in] count: \p buffer size. + * @return Command execution status. + */ +static int +dw_spi_write_buffer(const struct flash_bank *const bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + const size_t page_size = driver->spi_flash->pagesize; + + // Write unaligned first sector separately as helper function does + // not handle this case well. + struct { + uint32_t address; + const uint8_t *buffer; + size_t count; + } chunks[2] = { + { .address = offset, .buffer = buffer, .count = 0 }, + { .address = offset, .buffer = buffer, .count = count }, + }; + + if (offset % page_size) { + // start is not aligned + chunks[0].count = MIN(page_size - (offset % page_size), count); + chunks[1].count -= chunks[0].count; + chunks[1].address += chunks[0].count; + chunks[1].buffer += chunks[0].count; + } + + for (unsigned int chunk_idx = 0; chunk_idx < ARRAY_SIZE(chunks); + chunk_idx++) { + if (chunks[chunk_idx].count > 0) { + int ret = dw_spi_ctrl_program(bank, chunks[chunk_idx].address, + chunks[chunk_idx].buffer, + chunks[chunk_idx].count, page_size, + SPIFLASH_READ_STATUS, + SPIFLASH_WRITE_ENABLE, + driver->spi_flash->pprog_cmd, + SPIFLASH_WE_BIT, SPIFLASH_BSY_BIT); + if (ret) { + LOG_ERROR("DW SPI flash write error"); + return ret; + } + } + } + + return ERROR_OK; +} + +/** + * @brief Search for Flash chip info. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_spiflash_search(const struct flash_bank *const bank) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + int ret = dw_spi_read_id(bank); + if (ret) + return ret; + + unsigned int idx = 0; + while (flash_devices[idx].name) { + if (flash_devices[idx].device_id == driver->id) { + driver->spi_flash = &flash_devices[idx]; + return ERROR_OK; + } + idx++; + } + + LOG_ERROR("DW SPI could not find Flash with ID %" PRIx32 + " in SPI Flash table: either Flash device is not supported " + "or communication speed is too high", + driver->id); + return ERROR_FAIL; +} + +/** + * @brief Handle flash bank command. + * + * @param[in] CMD_ARGC: Number of arguments. + * @param[in] CMD_ARGV: Command arguments. + * @return Command execution status. + */ +FLASH_BANK_COMMAND_HANDLER(dw_spi_flash_bank_command) +{ + unsigned int speed = 1000000; + unsigned int timeout = DW_SPI_TIMEOUT_DEFAULT; + uint8_t chip_select_bitmask = BIT(0); + struct dw_spi_regmap regmap = { 0 }; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int idx = 6; idx < CMD_ARGC; idx++) { + if (strcmp(CMD_ARGV[idx], "-jaguar2") == 0) { + // Fast config for Jaguar2 chips. + memcpy(®map, &jaguar2_regmap, sizeof(jaguar2_regmap)); + } else if (strcmp(CMD_ARGV[idx], "-ocelot") == 0) { + // Fast config for Ocelot chips. + memcpy(®map, &ocelot_regmap, sizeof(ocelot_regmap)); + } else if (strcmp(CMD_ARGV[idx], "-freq") == 0) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[++idx], regmap.freq); + } else if (strcmp(CMD_ARGV[idx], "-simc") == 0) { + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[++idx], regmap.simc); + } else if (strcmp(CMD_ARGV[idx], "-spi_mst") == 0) { + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[++idx], regmap.spi_mst); + } else if (strcmp(CMD_ARGV[idx], "-if_owner_offset") == 0) { + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[++idx], + regmap.si_if_owner_offset); + } else if (strcmp(CMD_ARGV[idx], "-speed") == 0) { + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[++idx], speed); + } else if (strcmp(CMD_ARGV[idx], "-timeout") == 0) { + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[++idx], timeout); + timeout *= 1000; // convert to ms + } else if (strcmp(CMD_ARGV[idx], "-chip_select") == 0) { + unsigned int cs_bit; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[++idx], cs_bit); + chip_select_bitmask = BIT(cs_bit); + } else { + LOG_WARNING("DW SPI unknown argument %s", CMD_ARGV[idx]); + } + } + + if (!regmap.simc) { + LOG_ERROR("DW SPI cannot use boot controller with unconfigured simc"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + bank->driver_priv = malloc(sizeof(struct dw_spi_driver)); + if (!bank->driver_priv) { + LOG_ERROR("could not allocate memory"); + return ERROR_FAIL; + } + + struct dw_spi_driver *driver = bank->driver_priv; + memset(driver, 0, sizeof(struct dw_spi_driver)); + driver->speed = speed; + driver->timeout = timeout; + driver->chip_select_bitmask = chip_select_bitmask; + driver->four_byte_mode = true; // 24bit commands not provided by spi.h + memcpy(&driver->regmap, ®map, sizeof(regmap)); + + return ERROR_OK; +} + +/** + * @brief Assert target is halted. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_assert_halted(const struct flash_bank *const bank) +{ + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + return ERROR_OK; +} + +/** + * @brief Prepare master controller for transaction. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_master_ctrl_configure(struct flash_bank *bank) +{ + int ret = dw_spi_assert_halted(bank); + if (ret) + return ret; + ret = dw_spi_ctrl_mode_configure(bank, DW_SPI_SI_MODE_MASTER); + if (ret) { + LOG_ERROR("DW SPI switch to master controller mode error"); + return ret; + } + ret = dw_spi_master_ctrl_enable(bank, false); + if (ret) { + LOG_ERROR("DW SPI disable master controller error"); + return ret; + } + ret = dw_spi_ctrl_configure_speed(bank); + if (ret) { + LOG_ERROR("DW SPI speed configuration error"); + return ret; + } + ret = dw_spi_ctrl_disable_interrupts(bank); + if (ret) { + LOG_ERROR("DW SPI disable SPI interrupts error"); + return ret; + } + ret = dw_spi_ctrl_configure_si(bank); + if (ret) { + LOG_ERROR("DW SPI controller configuration error"); + return ret; + } + ret = dw_spi_master_ctrl_enable(bank, true); + if (ret) { + LOG_ERROR("DW SPI enable master controller error"); + return ret; + } + + return ERROR_OK; +} + +/** + * @brief Restore SI controller selection. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_master_ctrl_restore(struct flash_bank *bank) +{ + int ret = dw_spi_master_ctrl_enable(bank, false); + if (ret) { + LOG_ERROR("DW SPI disable master controller error"); + return ret; + } + ret = dw_spi_ctrl_mode_restore(bank); + if (ret) { + LOG_ERROR("DW SPI controller restore error"); + return ret; + } + + return ret; +} + +/** + * @brief Flash bank probe. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_probe(struct flash_bank *bank) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + if (!driver) + return ERROR_FAIL; + + if (strcmp(bank->target->type->name, mips_m4k_target.name) != 0 || + bank->target->endianness != TARGET_LITTLE_ENDIAN) { + LOG_ERROR("DW SPI currently only supports " + "little endian mips_m4k target"); + return ERROR_TARGET_INVALID; + } + + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_spiflash_search(bank); + if (ret) + goto err; + + bank->write_start_alignment = 0; + bank->write_end_alignment = 0; + + uint32_t flash_size = driver->spi_flash->size_in_bytes; + if (!bank->size) { + bank->size = flash_size; + LOG_INFO("DW SPI probed flash size 0x%" PRIx32, flash_size); + } else { + if (flash_size > bank->size) + LOG_WARNING("DW SPI probed flash size 0x%" PRIx32 + " is greater then declared 0x%" PRIx32, + flash_size, bank->size); + if (flash_size < bank->size) { + LOG_ERROR("DW SPI probed flash size 0x%" PRIx32 + " is smaller then declared 0x%" PRIx32, + flash_size, bank->size); + ret = ERROR_FLASH_BANK_INVALID; + goto err; + } + } + bank->num_sectors = bank->size / driver->spi_flash->sectorsize; + + // free previously allocated in case of reprobing + free(bank->sectors); + + bank->sectors = + alloc_block_array(0, driver->spi_flash->sectorsize, bank->num_sectors); + + if (!bank->sectors) { + LOG_ERROR("could not allocate memory"); + ret = ERROR_FAIL; + goto err; + } + + driver->probed = true; + +err: + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank erase sectors. + * + * @param[in] bank: Flash bank handle. + * @param[in] first: The first sector to erase. + * @param[in] last: The last sector to erase. + * @return Command execution status. + */ +static int +dw_spi_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_erase_sectors(bank, first, last); + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank write data. + * + * @param[in] bank: Flash bank handle. + * @param[in] buffer: Data buffer. + * @param[in] offset: Flash address offset. + * @param[in] count: \p buffer size. + * @return Command execution status. + */ +static int +dw_spi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, + uint32_t count) +{ + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_write_buffer(bank, buffer, offset, count); + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank read data using master controller. + * + * @param[in] bank: Flash bank handle. + * @param[out] buffer: Data buffer. + * @param[in] offset: Flash address offset. + * @param[in] count: \p buffer size. + * @return Command execution status. + */ +static int +dw_spi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, + uint32_t count) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_ctrl_read(bank, offset, buffer, count, + driver->spi_flash->read_cmd); + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank erase check. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_erase_check(struct flash_bank *bank) +{ + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_blank_check(bank, bank->num_sectors, bank->erased_value); + + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank info. + * + * @param[in] bank: Flash bank handle. + * @param[in,out] cmd Command invocation. + * @return Command execution status. + */ +static int +dw_spi_info(struct flash_bank *bank, struct command_invocation *cmd) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + command_print(cmd, "model %s", driver->spi_flash->name); + command_print(cmd, "ID 0x%" PRIx32, driver->id); + command_print_sameline(cmd, "size 0x%" PRIx32, bank->size); + return ERROR_OK; +} + +/** + * @brief Autoprobe driver. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_auto_probe(struct flash_bank *bank) +{ + struct dw_spi_driver *driver = bank->driver_priv; + if (!driver) + return ERROR_FAIL; + if (!driver->probed) + return dw_spi_probe(bank); + return ERROR_OK; +} + +/** + * @brief DW-SPI NOR flash functions. + */ +const struct flash_driver dw_spi_flash = { + .name = "dw-spi", + .flash_bank_command = dw_spi_flash_bank_command, + .erase = dw_spi_erase, + .write = dw_spi_write, + .read = dw_spi_read, + .probe = dw_spi_probe, + .auto_probe = dw_spi_auto_probe, + .erase_check = dw_spi_erase_check, + .info = dw_spi_info, + .verify = default_flash_verify, + .free_driver_priv = default_flash_free_driver_priv, +}; From 7f2db80ebc168d74a56dc8b76be5355ee4878be6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 7 Dec 2024 10:53:56 +0100 Subject: [PATCH 1075/1312] rtos/hwthread: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() to indicate which target the message belongs to. While at it, fix some coding style issues. Change-Id: Iac0296498557a689468a4a19d0bc64f03178a0d0 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8727 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/rtos/hwthread.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index c9f1a17920..6332bd8ad0 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -119,7 +119,7 @@ static int hwthread_update_threads(struct rtos *rtos) if (current_threadid <= thread_list_size) rtos->current_threadid = current_threadid; else - LOG_WARNING("SMP node change, disconnect GDB from core/thread %" PRId64, + LOG_TARGET_WARNING(target, "SMP node change, disconnect GDB from core/thread %" PRId64, current_threadid); /* create space for new thread details */ @@ -204,7 +204,8 @@ static int hwthread_update_threads(struct rtos *rtos) else rtos->current_thread = threadid_from_target(target); - LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread); + LOG_TARGET_DEBUG(target, "%s current_thread=%i", __func__, + (int)rtos->current_thread); return 0; } @@ -270,7 +271,8 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, if (!reg_list[i]->valid) { retval = reg_list[i]->type->get(reg_list[i]); if (retval != ERROR_OK) { - LOG_ERROR("Couldn't get register %s.", reg_list[i]->name); + LOG_TARGET_ERROR(curr, "Couldn't get register %s", + reg_list[i]->name); free(reg_list); free(*rtos_reg_list); return retval; @@ -297,7 +299,8 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, struct target *curr = hwthread_find_thread(target, thread_id); if (!curr) { - LOG_ERROR("Couldn't find RTOS thread for id %" PRId64 ".", thread_id); + LOG_TARGET_ERROR(target, "Couldn't find RTOS thread for id %" PRId64, + thread_id); return ERROR_FAIL; } @@ -308,8 +311,8 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id, struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true); if (!reg) { - LOG_ERROR("Couldn't find register %" PRIu32 " in thread %" PRId64 ".", reg_num, - thread_id); + LOG_TARGET_ERROR(curr, "Couldn't find register %" PRIu32 " in thread %" PRId64, + reg_num, thread_id); return ERROR_FAIL; } @@ -372,17 +375,17 @@ static bool hwthread_detect_rtos(struct target *target) static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); - - struct target *curr = NULL; - int64_t current_threadid; - if (packet[0] == 'H' && packet[1] == 'g') { + int64_t current_threadid; sscanf(packet, "Hg%16" SCNx64, ¤t_threadid); + struct target *target = get_target_from_connection(connection); + if (current_threadid > 0) { + struct target *curr = NULL; if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) { - LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid); + LOG_TARGET_ERROR(target, "hwthread: cannot find thread id %" PRId64, + current_threadid); gdb_put_packet(connection, "E01", 3); return ERROR_FAIL; } @@ -402,7 +405,7 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac static int hwthread_create(struct target *target) { - LOG_INFO("Hardware thread awareness created"); + LOG_TARGET_INFO(target, "Hardware thread awareness created"); target->rtos->rtos_specific_params = NULL; target->rtos->current_thread = 0; From 7dd875900ec252b5f332298cef3030f67a37150f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 3 Feb 2025 20:23:08 +0100 Subject: [PATCH 1076/1312] drivers/linuxspidev: fix minor memory leak free() strduped spi_path on quit. Found by valgrind. Change-Id: Iaa59c7258c920b5e60d615df790dfe815831b925 Signed-off-by: Tomas Vanek Fixes: 83e0293f7ba3 ("Add Linux SPI device SWD adapter support") Reviewed-on: https://review.openocd.org/c/openocd/+/8732 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Richard Pasek --- src/jtag/drivers/linuxspidev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c index 737d2bef83..94a0c510af 100644 --- a/src/jtag/drivers/linuxspidev.c +++ b/src/jtag/drivers/linuxspidev.c @@ -337,6 +337,10 @@ static int spidev_quit(void) close(spi_fd); spi_fd = -1; + + free(spi_path); + spi_path = NULL; + return ERROR_OK; } From 82277462b91506a9e7ee4bdcee86d6b414d59149 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 3 Feb 2025 20:28:49 +0100 Subject: [PATCH 1077/1312] drivers/linuxspidev: fix use of uninitialized speed variable Valgrind reported == Syscall param ioctl(generic) points to uninitialised byte(s) == at 0x4ABF990: ioctl (ioctl.S:26) == by 0x19D00B: spidev_speed (linuxspidev.c:181) == by 0x19D00B: spidev_init (linuxspidev.c:307) Indeed, spidev_init() uses adapter_get_speed(), it calls adapter_khz_to_speed() and it returns early without setting the output parameter if adapter is not initialized. Of course the adapter initialized flag is not set until spidev_init() returns. Simply drop this code as the adapter infrastructure initializes adapter speed just after spidev_init() return. Change-Id: I26f011ae59fc942a34d9bb517f467c22f735091d Signed-off-by: Tomas Vanek Fixes: 83e0293f7ba3 ("Add Linux SPI device SWD adapter support") Reviewed-on: https://review.openocd.org/c/openocd/+/8733 Tested-by: jenkins Reviewed-by: Richard Pasek --- src/jtag/drivers/linuxspidev.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c index 94a0c510af..73d5e8bed4 100644 --- a/src/jtag/drivers/linuxspidev.c +++ b/src/jtag/drivers/linuxspidev.c @@ -307,18 +307,6 @@ static int spidev_init(void) LOG_INFO("Opened SPI device at %s in mode 0x%" PRIx32 " with %" PRIu8 " bits ", spi_path, spi_mode, spi_bits); - // Set SPI read and write max speed. - int speed; - ret = adapter_get_speed(&speed); - if (ret != ERROR_OK) { - LOG_ERROR("Failed to get adapter speed"); - return ERROR_JTAG_INIT_FAILED; - } - - ret = spidev_speed(speed); - if (ret != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - if (max_queue_entries == 0) { ret = spidev_alloc_queue(MAX_QUEUE_ENTRIES); if (ret != ERROR_OK) From d09f53a930676817a49ae7c575c705487ea51861 Mon Sep 17 00:00:00 2001 From: Richard Pasek Date: Thu, 30 Jan 2025 05:38:08 -0500 Subject: [PATCH 1078/1312] driver/linuxspidev: Clear queue on allocation SWD idle clocks are added to the queue by advancing the queue index assuming the queue is zeroed. If the queue isn't zeroed, these idle clocks end up being filled with junk data. Lets clear the queue and associated buffers on queue allocation. TEST: Connects successfully and ran the following TCL command: dump_image /dev/null 0x20000000 0x42000 Host: Unnamed Qualcomm SoC with QUPv3 based SPI port Target: RT500 Signed-off-by: Richard Pasek Change-Id: Ie660c10c27c4d0937ab0629138935ddbf5aeb0ae Fixes: 83e0293f7ba3 ("Add Linux SPI device SWD adapter support") Reviewed-on: https://review.openocd.org/c/openocd/+/8730 Reviewed-by: Tomas Vanek Reviewed-by: Jonathon Reinhart Tested-by: jenkins --- src/jtag/drivers/linuxspidev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c index 73d5e8bed4..6a149a977b 100644 --- a/src/jtag/drivers/linuxspidev.c +++ b/src/jtag/drivers/linuxspidev.c @@ -230,10 +230,21 @@ static void spidev_free_queue(void) tx_flip_buf = NULL; } +static void spidev_clear_queue(void) +{ + queue_fill = 0; + queue_buf_fill = 0; + + memset(queue_infos, 0, sizeof(struct queue_info) * max_queue_entries); + memset(queue_tx_buf, 0, queue_buf_size); + memset(queue_rx_buf, 0, queue_buf_size); + memset(tx_flip_buf, 0, queue_buf_size); +} + static int spidev_alloc_queue(unsigned int new_queue_entries) { if (queue_fill || queue_buf_fill) { - LOG_ERROR("Can't realloc allocate queue when queue is in use"); + LOG_ERROR("Can't realloc queue when queue is in use"); return ERROR_FAIL; } @@ -259,6 +270,8 @@ static int spidev_alloc_queue(unsigned int new_queue_entries) max_queue_entries = new_queue_entries; queue_buf_size = new_queue_buf_size; + spidev_clear_queue(); + LOG_DEBUG("Set queue entries to %u (buffers %u bytes)", max_queue_entries, queue_buf_size); return ERROR_OK; @@ -400,12 +413,7 @@ static int spidev_swd_execute_queue(unsigned int end_idle_bytes) } skip: - // Clear everything in the queue - queue_fill = 0; - queue_buf_fill = 0; - memset(queue_infos, 0, sizeof(queue_infos[0]) * max_queue_entries); - memset(queue_tx_buf, 0, queue_buf_size); - memset(queue_rx_buf, 0, queue_buf_size); + spidev_clear_queue(); int retval = queue_retval; queue_retval = ERROR_OK; From 73e9b7898f5518e0cfe7bc2f66d135736558a9fd Mon Sep 17 00:00:00 2001 From: Samuel Obuch Date: Tue, 11 Feb 2025 09:56:38 +0100 Subject: [PATCH 1079/1312] github/workflow: build jimtcl from sources JimTCL submodule was deprecated, this patch modifies the GitHub snapshot action to build from sources instead. Change-Id: Ie9ab20dbfd70506992d11a91489e82a9fa6e13ce Signed-off-by: Samuel Obuch Reviewed-on: https://review.openocd.org/c/openocd/+/8751 Reviewed-by: Marc Schink Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Erhan Kurubas --- .github/workflows/snapshot.yml | 15 ++++++++++++--- contrib/cross-build.sh | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index f5cf56459c..36b2f3bb3d 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -18,7 +18,7 @@ jobs: sudo apt-get update sudo apt-get install autotools-dev autoconf automake libtool pkg-config cmake texinfo texlive g++-mingw-w64-i686 - name: Checkout Code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - run: ./bootstrap - name: Prepare libusb1 env: @@ -66,6 +66,14 @@ jobs: cd libjaylink-${LIBJAYLINK_VER} ./autogen.sh echo "LIBJAYLINK_SRC=$PWD" >> $GITHUB_ENV + - name: Prepare jimtcl + env: + JIMTCL_VER: 0.83 + run: | + mkdir -p $DL_DIR && cd $DL_DIR + wget https://github.com/msteveb/jimtcl/archive/refs/tags/${JIMTCL_VER}.tar.gz + tar -xzf ${JIMTCL_VER}.tar.gz + echo "JIMTCL_SRC=$PWD/jimtcl-${JIMTCL_VER}" >> $GITHUB_ENV - name: Package OpenOCD for windows env: MAKE_JOBS: 2 @@ -75,6 +83,7 @@ jobs: LIBFTDI_CONFIG: -DSTATICLIBS=OFF -DEXAMPLES=OFF -DFTDI_EEPROM=OFF CAPSTONE_CONFIG: "CAPSTONE_BUILD_CORE_ONLY=yes CAPSTONE_STATIC=yes CAPSTONE_SHARED=no" LIBJAYLINK_CONFIG: --enable-shared --disable-static + JIMTCL_CONFIG: --with-ext=json --minimal --disable-ssl run: | # check if there is tag pointing at HEAD, otherwise take the HEAD SHA-1 as OPENOCD_TAG OPENOCD_TAG="`git tag --points-at HEAD`" @@ -102,11 +111,11 @@ jobs: echo "IS_PRE_RELEASE=$IS_PRE_RELEASE" >> $GITHUB_ENV echo "ARTIFACT_PATH=$PWD/$ARTIFACT" >> $GITHUB_ENV - name: Publish OpenOCD packaged for windows - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ${{ env.ARTIFACT_PATH }} - name: Delete 'latest' Release - uses: dev-drprasad/delete-tag-and-release@v0.2.1 + uses: dev-drprasad/delete-tag-and-release@v1.1 with: delete_release: true tag_name: ${{ env.RELEASE_NAME }} diff --git a/contrib/cross-build.sh b/contrib/cross-build.sh index bb8c8c47db..1784d79ad1 100755 --- a/contrib/cross-build.sh +++ b/contrib/cross-build.sh @@ -42,6 +42,7 @@ WORK_DIR=$PWD : ${LIBFTDI_SRC:=/path/to/libftdi} : ${CAPSTONE_SRC:=/path/to/capstone} : ${LIBJAYLINK_SRC:=/path/to/libjaylink} +: ${JIMTCL_SRC:=/path/to/jimtcl} OPENOCD_SRC=`readlink -m $OPENOCD_SRC` LIBUSB1_SRC=`readlink -m $LIBUSB1_SRC` @@ -49,6 +50,7 @@ HIDAPI_SRC=`readlink -m $HIDAPI_SRC` LIBFTDI_SRC=`readlink -m $LIBFTDI_SRC` CAPSTONE_SRC=`readlink -m $CAPSTONE_SRC` LIBJAYLINK_SRC=`readlink -m $LIBJAYLINK_SRC` +JIMTCL_SRC=`readlink -m $JIMTCL_SRC` HOST_TRIPLET=$1 BUILD_DIR=$WORK_DIR/$HOST_TRIPLET-build @@ -57,6 +59,7 @@ HIDAPI_BUILD_DIR=$BUILD_DIR/hidapi LIBFTDI_BUILD_DIR=$BUILD_DIR/libftdi CAPSTONE_BUILD_DIR=$BUILD_DIR/capstone LIBJAYLINK_BUILD_DIR=$BUILD_DIR/libjaylink +JIMTCL_BUILD_DIR=$BUILD_DIR/jimtcl OPENOCD_BUILD_DIR=$BUILD_DIR/openocd ## Root of host file tree @@ -172,6 +175,18 @@ if [ -d $LIBJAYLINK_SRC ] ; then make install DESTDIR=$SYSROOT fi +# jimtcl build & install into sysroot +if [ -d $JIMTCL_SRC ] ; then + mkdir -p $JIMTCL_BUILD_DIR + cd $JIMTCL_BUILD_DIR + $JIMTCL_SRC/configure --host=$HOST_TRIPLET --prefix=$PREFIX \ + $JIMTCL_CONFIG + make -j $MAKE_JOBS + # Running "make" does not create this file for static builds on Windows but "make install" still expects it + touch $JIMTCL_BUILD_DIR/build-jim-ext + make install DESTDIR=$SYSROOT +fi + # OpenOCD build & install into sysroot mkdir -p $OPENOCD_BUILD_DIR cd $OPENOCD_BUILD_DIR From 6e39af3b0e17ce0376db10bdca25ce60334448cd Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 12:13:30 +0100 Subject: [PATCH 1080/1312] rtt: drop useless typedefs There is no need to use extra typedef for the rtt functions. Declare the type of the functions in the struct. Change-Id: Idf2fee6e63ec3b3add38d042bbebe8d74613627c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8698 Tested-by: jenkins Reviewed-by: zapb --- src/rtt/rtt.h | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h index 49409074c4..d84fdb40b3 100644 --- a/src/rtt/rtt.h +++ b/src/rtt/rtt.h @@ -95,35 +95,27 @@ enum rtt_channel_type { RTT_CHANNEL_TYPE_DOWN }; -typedef int (*rtt_source_find_ctrl_block)(struct target *target, +/** RTT source. */ +struct rtt_source { + int (*find_cb)(struct target *target, target_addr_t *address, size_t size, const char *id, bool *found, void *user_data); -typedef int (*rtt_source_read_ctrl_block)(struct target *target, + int (*read_cb)(struct target *target, target_addr_t address, struct rtt_control *ctrl_block, void *user_data); -typedef int (*rtt_source_read_channel_info)(struct target *target, + int (*read_channel_info)(struct target *target, const struct rtt_control *ctrl, unsigned int channel, enum rtt_channel_type type, struct rtt_channel_info *info, void *user_data); -typedef int (*rtt_source_start)(struct target *target, + int (*start)(struct target *target, const struct rtt_control *ctrl, void *user_data); -typedef int (*rtt_source_stop)(struct target *target, void *user_data); -typedef int (*rtt_source_read)(struct target *target, + int (*stop)(struct target *target, void *user_data); + int (*read)(struct target *target, const struct rtt_control *ctrl, struct rtt_sink_list **sinks, size_t num_channels, void *user_data); -typedef int (*rtt_source_write)(struct target *target, + int (*write)(struct target *target, struct rtt_control *ctrl, unsigned int channel, const uint8_t *buffer, size_t *length, void *user_data); - -/** RTT source. */ -struct rtt_source { - rtt_source_find_ctrl_block find_cb; - rtt_source_read_ctrl_block read_cb; - rtt_source_read_channel_info read_channel_info; - rtt_source_start start; - rtt_source_stop stop; - rtt_source_read read; - rtt_source_write write; }; /** From 3e4512d62d1513a81905ff65f3d42477f0258f64 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 13:40:59 +0100 Subject: [PATCH 1081/1312] openocd: drop useless typedef There is no need to use typedef for the array of functions. Drop it. While there, move the declaration outside the function and use the array size to drop the error-prone sentinel to NULL. Change-Id: I424964a6ef82ed1a7b27e78fbd19aa9f985b52c7 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8699 Reviewed-by: zapb Tested-by: jenkins --- src/openocd.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/openocd.c b/src/openocd.c index 9fd709e323..3fbece3955 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -232,6 +232,23 @@ static int openocd_register_commands(struct command_context *cmd_ctx) struct command_context *global_cmd_ctx; +static int (* const command_registrants[])(struct command_context *cmd_ctx_value) = { + openocd_register_commands, + server_register_commands, + gdb_register_commands, + log_register_commands, + rtt_server_register_commands, + transport_register_commands, + adapter_register_commands, + target_register_commands, + flash_register_commands, + nand_register_commands, + pld_register_commands, + cti_register_commands, + dap_register_commands, + arm_tpiu_swo_register_commands, +}; + static struct command_context *setup_command_handler(Jim_Interp *interp) { log_init(); @@ -240,25 +257,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp) struct command_context *cmd_ctx = command_init(openocd_startup_tcl, interp); /* register subsystem commands */ - typedef int (*command_registrant_t)(struct command_context *cmd_ctx_value); - static const command_registrant_t command_registrants[] = { - &openocd_register_commands, - &server_register_commands, - &gdb_register_commands, - &log_register_commands, - &rtt_server_register_commands, - &transport_register_commands, - &adapter_register_commands, - &target_register_commands, - &flash_register_commands, - &nand_register_commands, - &pld_register_commands, - &cti_register_commands, - &dap_register_commands, - &arm_tpiu_swo_register_commands, - NULL - }; - for (unsigned int i = 0; command_registrants[i]; i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(command_registrants); i++) { int retval = (*command_registrants[i])(cmd_ctx); if (retval != ERROR_OK) { command_done(cmd_ctx); From 4140fa2a81b259fa99c76084fea78affb2511a08 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 13:55:18 +0100 Subject: [PATCH 1082/1312] drivers: rshim: drop useless typedef Use 'struct name' instead of typedef. Change-Id: Ifff56811f53a260c314c8f5473d368599e0912e6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8700 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/drivers/rshim.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index 21fc7fd378..b37fe8c453 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -60,14 +60,14 @@ #ifdef HAVE_SYS_IOCTL_H /* Message used to program rshim via ioctl(). */ -typedef struct { +struct rshim_ioctl_msg { uint32_t addr; uint64_t data; -} __attribute__((packed)) rshim_ioctl_msg; +} __attribute__((packed)); enum { - RSH_IOC_READ = _IOWR('R', 0, rshim_ioctl_msg), - RSH_IOC_WRITE = _IOWR('R', 1, rshim_ioctl_msg), + RSH_IOC_READ = _IOWR('R', 0, struct rshim_ioctl_msg), + RSH_IOC_WRITE = _IOWR('R', 1, struct rshim_ioctl_msg), }; #endif @@ -104,7 +104,7 @@ static int rshim_dev_read(int chan, int addr, uint64_t *value) #ifdef HAVE_SYS_IOCTL_H if (rc < 0 && errno == ENOSYS) { - rshim_ioctl_msg msg; + struct rshim_ioctl_msg msg; msg.addr = addr; msg.data = 0; @@ -126,7 +126,7 @@ static int rshim_dev_write(int chan, int addr, uint64_t value) #ifdef HAVE_SYS_IOCTL_H if (rc < 0 && errno == ENOSYS) { - rshim_ioctl_msg msg; + struct rshim_ioctl_msg msg; msg.addr = addr; msg.data = value; From e325b482b11d203423b44d44dd35b89e31ffb19d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:01:20 +0100 Subject: [PATCH 1083/1312] target: esp_algorithm: drop useless typedefs There is no need to use extra typedef for the functions in struct esp_algorithm_run_data. Declare the type of the functions in the struct. Split the comment lines to stay in the line limits. Change-Id: I0afa6242e57133f8bf1b13ba541abd6b067350b0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8701 Reviewed-by: Erhan Kurubas Tested-by: jenkins --- src/target/espressif/esp_algorithm.h | 125 +++++++++++++-------------- 1 file changed, 60 insertions(+), 65 deletions(-) diff --git a/src/target/espressif/esp_algorithm.h b/src/target/espressif/esp_algorithm.h index 11d2757776..185234f971 100644 --- a/src/target/espressif/esp_algorithm.h +++ b/src/target/espressif/esp_algorithm.h @@ -36,11 +36,13 @@ * Procedure of executing stub on target includes: * 1) User prepares struct esp_algorithm_run_data and calls one of algorithm_run_xxx() functions. * 2) Routine allocates all necessary stub code and data sections. - * 3) If a user specifies an initializer func esp_algorithm_usr_func_init_t it is called just before the stub starts. - * 4) If user specifies stub communication func esp_algorithm_usr_func_t (@see esp_flash_write/read in ESP flash driver) + * 3) If a user specifies an initializer func esp_algorithm_run_data::usr_func_init + * it is called just before the stub starts. + * 4) If user specifies stub communication func esp_algorithm_run_data::usr_func + * (@see esp_flash_write/read in ESP flash driver) * it is called just after the stub starts. When communication with stub is finished this function must return. * 5) OpenOCD waits for the stub to finish (hit exit breakpoint). - * 6) If the user specified arguments cleanup func esp_algorithm_usr_func_done_t, + * 6) If the user specified arguments cleanup func esp_algorithm_run_data::usr_func_done, * it is called just after the stub finishes. * * There are two options to run code on target under OpenOCD control: @@ -190,60 +192,6 @@ struct esp_algorithm_reg_args { struct esp_algorithm_run_data; -/** - * @brief Algorithm run function. - * - * @param target Pointer to target. - * @param run Pointer to algo run data. - * @param arg Function specific argument. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef int (*esp_algorithm_func_t)(struct target *target, struct esp_algorithm_run_data *run, void *arg); - -/** - * @brief Host part of algorithm. - * This function will be called while stub is running on target. - * It can be used for communication with stub. - * - * @param target Pointer to target. - * @param usr_arg Function specific argument. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef int (*esp_algorithm_usr_func_t)(struct target *target, void *usr_arg); - -/** - * @brief Algorithm's arguments setup function. - * This function will be called just before stub start. - * It must return when all operations with running stub are completed. - * It can be used to prepare stub memory parameters. - * - * @param target Pointer to target. - * @param run Pointer to algo run data. - * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef int (*esp_algorithm_usr_func_init_t)(struct target *target, - struct esp_algorithm_run_data *run, - void *usr_arg); - -/** - * @brief Algorithm's arguments cleanup function. - * This function will be called just after stub exit. - * It can be used to cleanup stub memory parameters. - * - * @param target Pointer to target. - * @param run Pointer to algo run data. - * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef void (*esp_algorithm_usr_func_done_t)(struct target *target, - struct esp_algorithm_run_data *run, - void *usr_arg); - struct esp_algorithm_hw { int (*algo_init)(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, va_list ap); int (*algo_cleanup)(struct target *target, struct esp_algorithm_run_data *run); @@ -283,14 +231,61 @@ struct esp_algorithm_run_data { }; /** Host side algorithm function argument. */ void *usr_func_arg; - /** Host side algorithm function. */ - esp_algorithm_usr_func_t usr_func; - /** Host side algorithm function setup routine. */ - esp_algorithm_usr_func_init_t usr_func_init; - /** Host side algorithm function cleanup routine. */ - esp_algorithm_usr_func_done_t usr_func_done; - /** Algorithm run function: see algorithm_run_xxx for example. */ - esp_algorithm_func_t algo_func; + + /** + * @brief Host part of algorithm. + * This function will be called while stub is running on target. + * It can be used for communication with stub. + * + * @param target Pointer to target. + * @param usr_arg Function specific argument. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + int (*usr_func)(struct target *target, void *usr_arg); + + /** + * @brief Algorithm's arguments setup function. + * This function will be called just before stub start. + * It must return when all operations with running stub are completed. + * It can be used to prepare stub memory parameters. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param usr_arg Function specific argument. The same as for usr_func. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + int (*usr_func_init)(struct target *target, + struct esp_algorithm_run_data *run, + void *usr_arg); + + /** + * @brief Algorithm's arguments cleanup function. + * This function will be called just after stub exit. + * It can be used to cleanup stub memory parameters. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param usr_arg Function specific argument. The same as for usr_func. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + void (*usr_func_done)(struct target *target, + struct esp_algorithm_run_data *run, + void *usr_arg); + + /** + * @brief Algorithm run function. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param arg Function specific argument. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + int (*algo_func)(struct target *target, struct esp_algorithm_run_data *run, void *arg); + /** HW specific API */ const struct esp_algorithm_hw *hw; }; From b023c4c6c51a90fb0f831c5725c44ee9061e80ab Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:09:49 +0100 Subject: [PATCH 1084/1312] nor: lpc2000: drop useless typedef lpc2000_variant No need to use a typedef for an enum. Drop it. Change-Id: Iec690ebf6704f346d010cad1e6c65496f7bcc218 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8702 Tested-by: jenkins Reviewed-by: zapb --- src/flash/nor/lpc2000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index f12eef7e4c..09d35f604a 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -272,7 +272,7 @@ #define LPC11XX_REG_SECTORS 24 -typedef enum { +enum lpc2000_variant { LPC2000_V1, LPC2000_V2, LPC1700, @@ -282,10 +282,10 @@ typedef enum { LPC1500, LPC54100, LPC_AUTO, -} lpc2000_variant; +}; struct lpc2000_flash_bank { - lpc2000_variant variant; + enum lpc2000_variant variant; uint32_t cclk; int cmd51_dst_boundary; int calc_checksum; From ff5fb8f6100fdd630e698133f860fb02515f5cf5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:12:38 +0100 Subject: [PATCH 1085/1312] target: etm: drop useless typedefs No need to use a typedef for an enum. Drop etmv1_pipestat_t and etmv1_branch_reason_t. Change-Id: I03ae4de3efe699d9635fc4f162649f6bedcef4c0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8703 Reviewed-by: zapb Tested-by: jenkins --- src/target/etm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/etm.h b/src/target/etm.h index be5f2c7d07..6c5b5e5953 100644 --- a/src/target/etm.h +++ b/src/target/etm.h @@ -175,7 +175,7 @@ struct etm_context { }; /* PIPESTAT values */ -typedef enum { +enum etmv1_pipestat { STAT_IE = 0x0, STAT_ID = 0x1, STAT_IN = 0x2, @@ -184,10 +184,10 @@ typedef enum { STAT_BD = 0x5, STAT_TR = 0x6, STAT_TD = 0x7 -} etmv1_pipestat_t; +}; /* branch reason values */ -typedef enum { +enum etmv1_branch_reason { BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */ BR_ENABLE = 0x1, /* Trace has been enabled */ BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */ @@ -196,7 +196,7 @@ typedef enum { BR_RSVD5 = 0x5, /* reserved */ BR_RSVD6 = 0x6, /* reserved */ BR_RSVD7 = 0x7, /* reserved */ -} etmv1_branch_reason_t; +}; struct reg_cache *etm_build_reg_cache(struct target *target, struct arm_jtag *jtag_info, struct etm_context *etm_ctx); From c50b54147170b70a794f39aa4850a61d3b52cb49 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:17:08 +0100 Subject: [PATCH 1086/1312] target: trace: drop useless typedef trace_status_t No need to use a typedef for an enum. Drop it. Change-Id: I31e0e3869c7277bcb14e05cfcac82c9655963ae6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8704 Tested-by: jenkins Reviewed-by: zapb --- src/target/etb.c | 4 ++-- src/target/etm.c | 2 +- src/target/etm.h | 4 ++-- src/target/etm_dummy.c | 2 +- src/target/trace.h | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/target/etb.c b/src/target/etb.c index 3b9004bb85..fb3112d70a 100644 --- a/src/target/etb.c +++ b/src/target/etb.c @@ -454,12 +454,12 @@ static int etb_init(struct etm_context *etm_ctx) return ERROR_OK; } -static trace_status_t etb_status(struct etm_context *etm_ctx) +static enum trace_status etb_status(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; struct reg *control = &etb->reg_cache->reg_list[ETB_CTRL]; struct reg *status = &etb->reg_cache->reg_list[ETB_STATUS]; - trace_status_t retval = 0; + enum trace_status retval = 0; int etb_timeout = 100; etb->etm_ctx = etm_ctx; diff --git a/src/target/etm.c b/src/target/etm.c index 53d5cb68ca..d9a3cdc5e5 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -1567,7 +1567,7 @@ COMMAND_HANDLER(handle_etm_status_command) struct target *target; struct arm *arm; struct etm_context *etm; - trace_status_t trace_status; + enum trace_status trace_status; target = get_current_target(CMD_CTX); arm = target_to_arm(target); diff --git a/src/target/etm.h b/src/target/etm.h index 6c5b5e5953..e18549dfe2 100644 --- a/src/target/etm.h +++ b/src/target/etm.h @@ -126,7 +126,7 @@ struct etm_capture_driver { const char *name; const struct command_registration *commands; int (*init)(struct etm_context *etm_ctx); - trace_status_t (*status)(struct etm_context *etm_ctx); + enum trace_status (*status)(struct etm_context *etm_ctx); int (*read_trace)(struct etm_context *etm_ctx); int (*start_capture)(struct etm_context *etm_ctx); int (*stop_capture)(struct etm_context *etm_ctx); @@ -153,7 +153,7 @@ struct etm_context { struct reg_cache *reg_cache; /* ETM register cache */ struct etm_capture_driver *capture_driver; /* driver used to access ETM data */ void *capture_driver_priv; /* capture driver private data */ - trace_status_t capture_status; /* current state of capture run */ + enum trace_status capture_status; /* current state of capture run */ struct etmv1_trace_data *trace_data; /* trace data */ uint32_t trace_depth; /* number of cycles to be analyzed, 0 if no data available */ uint32_t control; /* shadow of ETM_CTRL */ diff --git a/src/target/etm_dummy.c b/src/target/etm_dummy.c index 8deccf5f9d..2709b6e9d8 100644 --- a/src/target/etm_dummy.c +++ b/src/target/etm_dummy.c @@ -65,7 +65,7 @@ static int etm_dummy_init(struct etm_context *etm_ctx) return ERROR_OK; } -static trace_status_t etm_dummy_status(struct etm_context *etm_ctx) +static enum trace_status etm_dummy_status(struct etm_context *etm_ctx) { return TRACE_IDLE; } diff --git a/src/target/trace.h b/src/target/trace.h index e3d787eddf..dc3ab57124 100644 --- a/src/target/trace.h +++ b/src/target/trace.h @@ -33,13 +33,13 @@ struct trace { * to *hardware* tracing ... split such "real" tracing out from * the contrib/libdcc support. */ -typedef enum trace_status { +enum trace_status { TRACE_IDLE = 0x0, TRACE_RUNNING = 0x1, TRACE_TRIGGERED = 0x2, TRACE_COMPLETED = 0x4, TRACE_OVERFLOWED = 0x8, -} trace_status_t; +}; int trace_point(struct target *target, uint32_t number); int trace_register_commands(struct command_context *cmd_ctx); From 894a39eda30c1b0e8eff39b687333deb4b3b0891 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:20:35 +0100 Subject: [PATCH 1087/1312] target_request: drop useless typedef target_req_cmd_t No need to use a typedef for an enum. Drop it. Change-Id: Ib5a872b52a6f3d7379d2662e4ff84f32c2bd2ef8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8705 Reviewed-by: zapb Tested-by: jenkins --- src/target/target_request.c | 2 +- src/target/target_request.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/target_request.c b/src/target/target_request.c index bccae07b42..8d51dc3d60 100644 --- a/src/target/target_request.c +++ b/src/target/target_request.c @@ -107,7 +107,7 @@ static int target_hexmsg(struct target *target, int size, uint32_t length) */ int target_request(struct target *target, uint32_t request) { - target_req_cmd_t target_req_cmd = request & 0xff; + enum target_req_cmd target_req_cmd = request & 0xff; assert(target->type->target_request_data); diff --git a/src/target/target_request.h b/src/target/target_request.h index 62d5c74b1e..97edd9ede2 100644 --- a/src/target/target_request.h +++ b/src/target/target_request.h @@ -17,12 +17,12 @@ struct target; struct command_context; -typedef enum target_req_cmd { +enum target_req_cmd { TARGET_REQ_TRACEMSG, TARGET_REQ_DEBUGMSG, TARGET_REQ_DEBUGCHAR, /* TARGET_REQ_SEMIHOSTING, */ -} target_req_cmd_t; +}; struct debug_msg_receiver { struct command_context *cmd_ctx; From 8a5c3318315324574196ae3320c7abf326d4df88 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:22:17 +0100 Subject: [PATCH 1088/1312] jtag: remote_bitbang: drop useless typedef flush_bool_t No need to use a typedef for an enum. Drop it. Change-Id: I122784ddd7b81ccd86da258b08526685c3d70033 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8706 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/drivers/remote_bitbang.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 037c1f27f3..66f995d574 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -145,12 +145,12 @@ static int remote_bitbang_fill_buf(enum block_bool block) return ERROR_OK; } -typedef enum { +enum flush_bool { NO_FLUSH, FLUSH_SEND_BUF -} flush_bool_t; +}; -static int remote_bitbang_queue(int c, flush_bool_t flush) +static int remote_bitbang_queue(int c, enum flush_bool flush) { remote_bitbang_send_buf[remote_bitbang_send_buf_used++] = c; if (flush == FLUSH_SEND_BUF || From 54d07de86ea6abf1123cc2b032316f0c1bb88b3e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:25:15 +0100 Subject: [PATCH 1089/1312] jtag: bitbang: drop useless typedef bb_value_t No need to use a typedef for an enum. Drop it. Change-Id: I8800c95f97d2bafe27c699d7d451fb9b54286d99 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8707 Tested-by: jenkins --- src/jtag/drivers/am335xgpio.c | 2 +- src/jtag/drivers/at91rm9200.c | 4 ++-- src/jtag/drivers/bcm2835gpio.c | 2 +- src/jtag/drivers/bitbang.h | 8 ++++---- src/jtag/drivers/dummy.c | 2 +- src/jtag/drivers/ep93xx.c | 4 ++-- src/jtag/drivers/imx_gpio.c | 4 ++-- src/jtag/drivers/linuxgpiod.c | 2 +- src/jtag/drivers/parport.c | 2 +- src/jtag/drivers/remote_bitbang.c | 4 ++-- src/jtag/drivers/sysfsgpio.c | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index 05a73aa53c..cacf4e7c79 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -206,7 +206,7 @@ static void restore_gpio(enum adapter_gpio_config_index idx) } } -static bb_value_t am335xgpio_read(void) +static enum bb_value am335xgpio_read(void) { return get_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TDO]) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c index 57dd54c119..a77e29aa6e 100644 --- a/src/jtag/drivers/at91rm9200.c +++ b/src/jtag/drivers/at91rm9200.c @@ -98,7 +98,7 @@ static uint32_t *pio_base; /* low level command set */ -static bb_value_t at91rm9200_read(void); +static enum bb_value at91rm9200_read(void); static int at91rm9200_write(int tck, int tms, int tdi); static int at91rm9200_init(void); @@ -110,7 +110,7 @@ static const struct bitbang_interface at91rm9200_bitbang = { .blink = NULL, }; -static bb_value_t at91rm9200_read(void) +static enum bb_value at91rm9200_read(void) { return (pio_base[device->TDO_PIO + PIO_PDSR] & device->TDO_MASK) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 2c2061daec..095601fa61 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -182,7 +182,7 @@ static void initialize_gpio(enum adapter_gpio_config_index idx) bcm2835_gpio_synchronize(); } -static bb_value_t bcm2835gpio_read(void) +static enum bb_value bcm2835gpio_read(void) { unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num; uint32_t value = (GPIO_LEV >> shift) & 1; diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index d6fd95e279..6afa409e98 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -14,11 +14,11 @@ #include #include -typedef enum { +enum bb_value { BB_LOW, BB_HIGH, BB_ERROR -} bb_value_t; +}; /** Low level callbacks (for bitbang). * @@ -29,7 +29,7 @@ typedef enum { * increase throughput. */ struct bitbang_interface { /** Sample TDO and return the value. */ - bb_value_t (*read)(void); + enum bb_value (*read)(void); /** The number of TDO samples that can be buffered up before the caller has * to call read_sample. */ @@ -39,7 +39,7 @@ struct bitbang_interface { int (*sample)(void); /** Return the next unread value from the buffer. */ - bb_value_t (*read_sample)(void); + enum bb_value (*read_sample)(void); /** Set TCK, TMS, and TDI to the given values. */ int (*write)(int tck, int tms, int tdi); diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index 315e036974..bfd6e8c54d 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -22,7 +22,7 @@ static int clock_count; /* count clocks in any stable state, only stable states static uint32_t dummy_data; -static bb_value_t dummy_read(void) +static enum bb_value dummy_read(void) { int data = 1 & dummy_data; dummy_data = (dummy_data >> 1) | (1 << 31); diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c index ae35f4ac0c..ea9faf19b7 100644 --- a/src/jtag/drivers/ep93xx.c +++ b/src/jtag/drivers/ep93xx.c @@ -30,7 +30,7 @@ static volatile uint8_t *gpio_data_direction_register; /* low level command set */ -static bb_value_t ep93xx_read(void); +static enum bb_value ep93xx_read(void); static int ep93xx_write(int tck, int tms, int tdi); static int ep93xx_reset(int trst, int srst); @@ -61,7 +61,7 @@ static const struct bitbang_interface ep93xx_bitbang = { .blink = NULL, }; -static bb_value_t ep93xx_read(void) +static enum bb_value ep93xx_read(void) { return (*gpio_data_register & TDO_BIT) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c index 7aefbeb8aa..18dc2ddf67 100644 --- a/src/jtag/drivers/imx_gpio.c +++ b/src/jtag/drivers/imx_gpio.c @@ -72,7 +72,7 @@ static inline bool gpio_level(int g) return pio_base[g / 32].dr >> (g & 0x1F) & 1; } -static bb_value_t imx_gpio_read(void); +static enum bb_value imx_gpio_read(void); static int imx_gpio_write(int tck, int tms, int tdi); static int imx_gpio_swdio_read(void); @@ -118,7 +118,7 @@ static int speed_coeff = 50000; static int speed_offset = 100; static unsigned int jtag_delay; -static bb_value_t imx_gpio_read(void) +static enum bb_value imx_gpio_read(void) { return gpio_level(tdo_gpio) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 5ffbf4d2f2..eda7b1a80e 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -42,7 +42,7 @@ static bool is_gpio_config_valid(enum adapter_gpio_config_index idx) } /* Bitbang interface read of TDO */ -static bb_value_t linuxgpiod_read(void) +static enum bb_value linuxgpiod_read(void) { int retval; diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index f3478db51e..3b20fe2478 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -115,7 +115,7 @@ static unsigned long dataport; static unsigned long statusport; #endif -static bb_value_t parport_read(void) +static enum bb_value parport_read(void) { int data = 0; diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 66f995d574..bb608ba0a5 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -176,7 +176,7 @@ static int remote_bitbang_quit(void) return ERROR_OK; } -static bb_value_t char_to_int(int c) +static enum bb_value char_to_int(int c) { switch (c) { case '0': @@ -198,7 +198,7 @@ static int remote_bitbang_sample(void) return remote_bitbang_queue('R', NO_FLUSH); } -static bb_value_t remote_bitbang_read_sample(void) +static enum bb_value remote_bitbang_read_sample(void) { if (remote_bitbang_recv_buf_empty()) { if (remote_bitbang_fill_buf(BLOCK) != ERROR_OK) diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c index c47754bd19..ccd3974a42 100644 --- a/src/jtag/drivers/sysfsgpio.c +++ b/src/jtag/drivers/sysfsgpio.c @@ -255,7 +255,7 @@ static int sysfsgpio_swd_write(int swclk, int swdio) * The sysfs value will read back either '0' or '1'. The trick here is to call * lseek to bypass buffering in the sysfs kernel driver. */ -static bb_value_t sysfsgpio_read(void) +static enum bb_value sysfsgpio_read(void) { char buf[1]; From 0d1932520b535270d1b454d1aad28819d359e6a5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 15:26:50 +0100 Subject: [PATCH 1090/1312] jtag: openjtag: drop useless typedef openjtag_tap_state_t No need to use a typedef for an enum. Drop it. Change-Id: I31531b80eaf7f3d0ee6cd22844e60a05c6b748dc Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8708 Reviewed-by: zapb Tested-by: jenkins --- src/jtag/drivers/openjtag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 0ae885e871..a3fbd204eb 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -50,7 +50,7 @@ static const char * const openjtag_variant_names[] = { /* * OpenJTAG-OpenOCD state conversion */ -typedef enum openjtag_tap_state { +enum openjtag_tap_state { OPENJTAG_TAP_INVALID = -1, OPENJTAG_TAP_RESET = 0, OPENJTAG_TAP_IDLE = 1, @@ -68,7 +68,7 @@ typedef enum openjtag_tap_state { OPENJTAG_TAP_PAUSE_IR = 13, OPENJTAG_TAP_EXIT2_IR = 14, OPENJTAG_TAP_UPDATE_IR = 15, -} openjtag_tap_state_t; +}; /* OPENJTAG access library includes */ #include "libftdi_helper.h" From 4895a556fa6bafce14237b7e4c821d18fc55df02 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 17:05:29 +0100 Subject: [PATCH 1091/1312] jtag: drop useless typedef tap_state_t No need to use a typedef for an enum. Drop it. Change-Id: I9eb2dc4f926671c5bb44e61453d92880e3036848 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8709 Tested-by: jenkins Reviewed-by: zapb --- src/flash/nor/str9xpec.c | 2 +- src/jtag/commands.h | 10 +++--- src/jtag/core.c | 38 +++++++++++----------- src/jtag/drivers/amt_jtagaccel.c | 10 +++--- src/jtag/drivers/angie.c | 6 ++-- src/jtag/drivers/arm-jtag-ew.c | 12 +++---- src/jtag/drivers/bitbang.c | 6 ++-- src/jtag/drivers/bitq.c | 4 +-- src/jtag/drivers/buspirate.c | 12 +++---- src/jtag/drivers/cmsis_dap.c | 6 ++-- src/jtag/drivers/driver.c | 18 +++++----- src/jtag/drivers/dummy.c | 4 +-- src/jtag/drivers/ft232r.c | 6 ++-- src/jtag/drivers/ftdi.c | 8 ++--- src/jtag/drivers/gw16012.c | 6 ++-- src/jtag/drivers/jlink.c | 10 +++--- src/jtag/drivers/jtag_vpi.c | 4 +-- src/jtag/drivers/opendous.c | 12 +++---- src/jtag/drivers/openjtag.c | 2 +- src/jtag/drivers/osbdm.c | 8 ++--- src/jtag/drivers/rlink.c | 6 ++-- src/jtag/drivers/ulink.c | 6 ++-- src/jtag/drivers/usb_blaster/usb_blaster.c | 4 +-- src/jtag/drivers/usbprog.c | 6 ++-- src/jtag/drivers/vdebug.c | 10 +++--- src/jtag/drivers/vsllink.c | 12 +++---- src/jtag/drivers/xds110.c | 2 +- src/jtag/drivers/xlnx-pcie-xvc.c | 6 ++-- src/jtag/interface.c | 34 +++++++++---------- src/jtag/interface.h | 32 +++++++++--------- src/jtag/jtag.h | 28 ++++++++-------- src/jtag/minidriver.h | 12 +++---- src/jtag/tcl.c | 8 ++--- src/pld/lattice.c | 2 +- src/pld/lattice.h | 2 +- src/svf/svf.c | 24 +++++++------- src/svf/svf.h | 4 +-- src/target/arc_jtag.c | 6 ++-- src/target/arm11_dbgtap.c | 16 ++++----- src/target/arm11_dbgtap.h | 6 ++-- src/target/arm_jtag.c | 4 +-- src/target/arm_jtag.h | 8 ++--- src/target/dsp5680xx.c | 2 +- src/target/xscale.c | 8 ++--- src/target/xtensa/xtensa_debug_module.c | 2 +- src/xsvf/xsvf.c | 30 ++++++++--------- 46 files changed, 232 insertions(+), 232 deletions(-) diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index c39eb3aa84..eff7df5a11 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -68,7 +68,7 @@ static int str9xpec_erase_area(struct flash_bank *bank, unsigned int first, static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector); static int str9xpec_write_options(struct flash_bank *bank); -static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) +static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, enum tap_state end_state) { if (!tap) return ERROR_TARGET_INVALID; diff --git a/src/jtag/commands.h b/src/jtag/commands.h index 29fa8426ee..2923df1e6f 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -40,26 +40,26 @@ struct scan_command { /** pointer to an array of data scan fields */ struct scan_field *fields; /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct statemove_command { /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct pathmove_command { /** number of states in *path */ unsigned int num_states; /** states that have to be passed */ - tap_state_t *path; + enum tap_state *path; }; struct runtest_command { /** number of cycles to spend in Run-Test/Idle state */ unsigned int num_cycles; /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; @@ -78,7 +78,7 @@ struct reset_command { struct end_state_command { /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct sleep_command { diff --git a/src/jtag/core.c b/src/jtag/core.c index 769e07571f..89d53aecb9 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -48,8 +48,8 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, - tap_state_t state), - int in_num_fields, struct scan_field *in_fields, tap_state_t state); + enum tap_state state), + int in_num_fields, struct scan_field *in_fields, enum tap_state state); static int jtag_error_clear(void); @@ -87,7 +87,7 @@ static int jtag_srst = -1; static struct jtag_tap *__jtag_all_taps; static enum reset_types jtag_reset_config = RESET_NONE; -tap_state_t cmd_queue_cur_state = TAP_RESET; +enum tap_state cmd_queue_cur_state = TAP_RESET; static bool jtag_verify_capture_ir = true; static bool jtag_verify = true; @@ -350,7 +350,7 @@ static void jtag_checks(void) assert(jtag_trst == 0); } -static void jtag_prelude(tap_state_t state) +static void jtag_prelude(enum tap_state state) { jtag_checks(); @@ -360,7 +360,7 @@ static void jtag_prelude(tap_state_t state) } void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { jtag_prelude(state); @@ -371,13 +371,13 @@ void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field static void jtag_add_ir_scan_noverify_callback(struct jtag_tap *active, int dummy, const struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { jtag_add_ir_scan_noverify(active, in_fields, state); } /* If fields->in_value is filled out, then the captured IR value will be checked */ -void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state) +void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, enum tap_state state) { assert(state != TAP_RESET); @@ -396,7 +396,7 @@ void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap } void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t state) + enum tap_state state) { assert(out_bits); assert(state != TAP_RESET); @@ -426,8 +426,8 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, - tap_state_t state), - int in_num_fields, struct scan_field *in_fields, tap_state_t state) + enum tap_state state), + int in_num_fields, struct scan_field *in_fields, enum tap_state state) { jtag_add_scan(active, in_num_fields, in_fields, state); @@ -445,7 +445,7 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( void jtag_add_dr_scan_check(struct jtag_tap *active, int in_num_fields, struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { if (jtag_verify) jtag_add_scan_check(active, jtag_add_dr_scan, in_num_fields, in_fields, state); @@ -457,7 +457,7 @@ void jtag_add_dr_scan_check(struct jtag_tap *active, void jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { assert(state != TAP_RESET); @@ -469,7 +469,7 @@ void jtag_add_dr_scan(struct jtag_tap *active, } void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t state) + enum tap_state state) { assert(out_bits); assert(state != TAP_RESET); @@ -520,9 +520,9 @@ int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state stat return retval; } -void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path) +void jtag_add_pathmove(unsigned int num_states, const enum tap_state *path) { - tap_state_t cur_state = cmd_queue_cur_state; + enum tap_state cur_state = cmd_queue_cur_state; /* the last state has to be a stable state */ if (!tap_is_state_stable(path[num_states - 1])) { @@ -554,9 +554,9 @@ void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path) cmd_queue_cur_state = path[num_states - 1]; } -int jtag_add_statemove(tap_state_t goal_state) +int jtag_add_statemove(enum tap_state goal_state) { - tap_state_t cur_state = cmd_queue_cur_state; + enum tap_state cur_state = cmd_queue_cur_state; if (goal_state != cur_state) { LOG_DEBUG("cur_state=%s goal_state=%s", @@ -575,7 +575,7 @@ int jtag_add_statemove(tap_state_t goal_state) else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) { unsigned int tms_bits = tap_get_tms_path(cur_state, goal_state); unsigned int tms_count = tap_get_tms_path_len(cur_state, goal_state); - tap_state_t moves[8]; + enum tap_state moves[8]; assert(tms_count < ARRAY_SIZE(moves)); for (unsigned int i = 0; i < tms_count; i++, tms_bits >>= 1) { @@ -595,7 +595,7 @@ int jtag_add_statemove(tap_state_t goal_state) return ERROR_OK; } -void jtag_add_runtest(unsigned int num_cycles, tap_state_t state) +void jtag_add_runtest(unsigned int num_cycles, enum tap_state state) { jtag_prelude(state); jtag_set_error(interface_jtag_add_runtest(num_cycles, state)); diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index 489cb24713..80254ff074 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -146,7 +146,7 @@ static int amt_jtagaccel_speed(int speed) return ERROR_OK; } -static void amt_jtagaccel_end_state(tap_state_t state) +static void amt_jtagaccel_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -179,8 +179,8 @@ static void amt_jtagaccel_state_move(void) uint8_t aw_scan_tms_5; uint8_t tms_scan[2]; - tap_state_t cur_state = tap_get_state(); - tap_state_t end_state = tap_get_end_state(); + enum tap_state cur_state = tap_get_state(); + enum tap_state end_state = tap_get_end_state(); tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0]; tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1]; @@ -209,7 +209,7 @@ static void amt_jtagaccel_runtest(unsigned int num_cycles) uint8_t aw_scan_tms_5; uint8_t aw_scan_tms_1to4; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -237,7 +237,7 @@ static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffe { int bits_left = scan_size; int bit_count = 0; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); uint8_t aw_tdi_option; uint8_t dw_tdi_scan; uint8_t dr_tdo; diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 47628fef74..46a4c82e5b 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -219,7 +219,7 @@ static int angie_append_test_cmd(struct angie *device); static int angie_calculate_delay(enum angie_delay_type type, long f, int *delay); /* Interface between ANGIE and OpenOCD */ -static void angie_set_end_state(tap_state_t endstate); +static void angie_set_end_state(enum tap_state endstate); static int angie_queue_statemove(struct angie *device); static int angie_queue_scan(struct angie *device, struct jtag_command *cmd); @@ -1519,7 +1519,7 @@ static long angie_calculate_frequency(enum angie_delay_type type, int delay) * * @param endstate the state the end state follower should be set to. */ -static void angie_set_end_state(tap_state_t endstate) +static void angie_set_end_state(enum tap_state endstate) { if (tap_is_state_stable(endstate)) tap_set_end_state(endstate); @@ -1837,7 +1837,7 @@ static int angie_reset(int trst, int srst) static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd) { int ret, state_count; - tap_state_t *path; + enum tap_state *path; uint8_t tms_sequence; unsigned int num_states = cmd->cmd.pathmove->num_states; diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index aaed16db6e..45e03840ea 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -42,9 +42,9 @@ static uint8_t usb_in_buffer[ARMJTAGEW_IN_BUFFER_SIZE]; static uint8_t usb_out_buffer[ARMJTAGEW_OUT_BUFFER_SIZE]; /* Queue command functions */ -static void armjtagew_end_state(tap_state_t state); +static void armjtagew_end_state(enum tap_state state); static void armjtagew_state_move(void); -static void armjtagew_path_move(unsigned int num_states, tap_state_t *path); +static void armjtagew_path_move(unsigned int num_states, enum tap_state *path); static void armjtagew_runtest(unsigned int num_cycles); static void armjtagew_scan(bool ir_scan, enum scan_type type, @@ -253,7 +253,7 @@ static int armjtagew_quit(void) /************************************************************************** * Queue command implementations */ -static void armjtagew_end_state(tap_state_t state) +static void armjtagew_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -279,7 +279,7 @@ static void armjtagew_state_move(void) tap_set_state(tap_get_end_state()); } -static void armjtagew_path_move(unsigned int num_states, tap_state_t *path) +static void armjtagew_path_move(unsigned int num_states, enum tap_state *path) { for (unsigned int i = 0; i < num_states; i++) { /* @@ -305,7 +305,7 @@ static void armjtagew_path_move(unsigned int num_states, tap_state_t *path) static void armjtagew_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -329,7 +329,7 @@ static void armjtagew_scan(bool ir_scan, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; armjtagew_tap_ensure_space(1, scan_size + 8); diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 0a49feb003..c2e763ddb3 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -60,7 +60,7 @@ const struct bitbang_interface *bitbang_interface; #define CLOCK_IDLE() 0 /* The bitbang driver leaves the TCK 0 when in idle */ -static void bitbang_end_state(tap_state_t state) +static void bitbang_end_state(enum tap_state state) { assert(tap_is_state_stable(state)); tap_set_end_state(state); @@ -149,7 +149,7 @@ static int bitbang_path_move(struct pathmove_command *cmd) static int bitbang_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -195,7 +195,7 @@ static int bitbang_stableclocks(unsigned int num_cycles) static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, unsigned int scan_size) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); unsigned int bit_cnt; if (!((!ir_scan && diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c index ef870e6486..84acff8357 100644 --- a/src/jtag/drivers/bitq.c +++ b/src/jtag/drivers/bitq.c @@ -76,7 +76,7 @@ static void bitq_io(int tms, int tdi, int tdo_req) bitq_in_proc(); } -static void bitq_end_state(tap_state_t state) +static void bitq_end_state(enum tap_state state) { if (!tap_is_state_stable(state)) { LOG_ERROR("BUG: %i is not a valid end state", state); @@ -85,7 +85,7 @@ static void bitq_end_state(tap_state_t state) tap_set_end_state(state); } -static void bitq_state_move(tap_state_t new_state) +static void bitq_state_move(enum tap_state new_state) { int i = 0; uint8_t tms_scan; diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index 6f8df5adad..93f0ba3838 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -25,9 +25,9 @@ static int buspirate_init(void); static int buspirate_quit(void); static int buspirate_reset(int trst, int srst); -static void buspirate_end_state(tap_state_t state); +static void buspirate_end_state(enum tap_state state); static void buspirate_state_move(void); -static void buspirate_path_move(unsigned int num_states, tap_state_t *path); +static void buspirate_path_move(unsigned int num_states, enum tap_state *path); static void buspirate_runtest(unsigned int num_cycles); static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); @@ -554,7 +554,7 @@ struct adapter_driver buspirate_adapter_driver = { }; /*************** jtag execute commands **********************/ -static void buspirate_end_state(tap_state_t state) +static void buspirate_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -580,7 +580,7 @@ static void buspirate_state_move(void) tap_set_state(tap_get_end_state()); } -static void buspirate_path_move(unsigned int num_states, tap_state_t *path) +static void buspirate_path_move(unsigned int num_states, enum tap_state *path) { for (unsigned int i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), false) == path[i]) { @@ -604,7 +604,7 @@ static void buspirate_path_move(unsigned int num_states, tap_state_t *path) static void buspirate_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -628,7 +628,7 @@ static void buspirate_runtest(unsigned int num_cycles) static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; buspirate_tap_make_space(1, scan_size+8); /* is 8 correct ? (2 moves = 16) */ diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index e9fd93ad1b..c8a7cf8fcd 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -1502,7 +1502,7 @@ static int cmsis_dap_execute_tlr_reset(struct jtag_command *cmd) } /* Set new end state */ -static void cmsis_dap_end_state(tap_state_t state) +static void cmsis_dap_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -1831,7 +1831,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) tap_state_name(tap_get_end_state())); } -static void cmsis_dap_pathmove(int num_states, tap_state_t *path) +static void cmsis_dap_pathmove(int num_states, enum tap_state *path) { uint8_t tms0 = 0x00; uint8_t tms1 = 0xff; @@ -1873,7 +1873,7 @@ static void cmsis_dap_stableclocks(unsigned int num_cycles) static void cmsis_dap_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* Only do a state_move when we're not already in IDLE. */ if (tap_get_state() != TAP_IDLE) { diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index 58e59a559f..43101b8659 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -49,7 +49,7 @@ static void jtag_callback_queue_reset(void) * */ int interface_jtag_add_ir_scan(struct jtag_tap *active, - const struct scan_field *in_fields, tap_state_t state) + const struct scan_field *in_fields, enum tap_state state) { size_t num_taps = jtag_tap_count_enabled(); @@ -111,7 +111,7 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active, * */ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, - const struct scan_field *in_fields, tap_state_t state) + const struct scan_field *in_fields, enum tap_state state) { /* count devices in bypass */ @@ -184,7 +184,7 @@ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, } static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits, - uint8_t *in_bits, tap_state_t state, bool ir_scan) + uint8_t *in_bits, enum tap_state state, bool ir_scan) { struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command)); @@ -207,19 +207,19 @@ static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits, return ERROR_OK; } -int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) +int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, enum tap_state state) { return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false); } -int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) +int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, enum tap_state state) { return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true); } int interface_jtag_add_tlr(void) { - tap_state_t state = TAP_RESET; + enum tap_state state = TAP_RESET; /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -259,7 +259,7 @@ int interface_add_tms_seq(unsigned int num_bits, const uint8_t *seq, enum tap_st return ERROR_OK; } -int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path) +int interface_jtag_add_pathmove(unsigned int num_states, const enum tap_state *path) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -270,7 +270,7 @@ int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command)); cmd->cmd.pathmove->num_states = num_states; - cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states); + cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states); for (unsigned int i = 0; i < num_states; i++) cmd->cmd.pathmove->path[i] = path[i]; @@ -278,7 +278,7 @@ int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path return ERROR_OK; } -int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t state) +int interface_jtag_add_runtest(unsigned int num_cycles, enum tap_state state) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index bfd6e8c54d..79b29fbae7 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -14,7 +14,7 @@ #include "hello.h" /* my private tap controller state, which tracks state for calling code */ -static tap_state_t dummy_state = TAP_RESET; +static enum tap_state dummy_state = TAP_RESET; static int dummy_clock; /* edge detector */ @@ -34,7 +34,7 @@ static int dummy_write(int tck, int tms, int tdi) /* TAP standard: "state transitions occur on rising edge of clock" */ if (tck != dummy_clock) { if (tck) { - tap_state_t old_state = dummy_state; + enum tap_state old_state = dummy_state; dummy_state = tap_state_transition(old_state, tms); if (old_state != dummy_state) { diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index 6dc1304930..f4e5af4dd4 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -622,7 +622,7 @@ static const struct command_registration ft232r_command_handlers[] = { * Synchronous bitbang protocol implementation. */ -static void syncbb_end_state(tap_state_t state) +static void syncbb_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -705,7 +705,7 @@ static void syncbb_path_move(struct pathmove_command *cmd) static void syncbb_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -747,7 +747,7 @@ static void syncbb_stableclocks(unsigned int num_cycles) static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); int bit_cnt, bit0_index; if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) { diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 42ecda117b..ec0ae4c00b 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -238,9 +238,9 @@ static int ftdi_get_signal(const struct signal *s, uint16_t *value_out) * * @param goal_state is the destination state for the move. */ -static void move_to_state(tap_state_t goal_state) +static void move_to_state(enum tap_state goal_state) { - tap_state_t start_state = tap_get_state(); + enum tap_state start_state = tap_get_state(); /* goal_state is 1/2 of a tuple/pair of states which allow convenient lookup of the required TMS pattern to move to this state from the @@ -299,7 +299,7 @@ static int ftdi_khz(int khz, int *jtag_speed) return ERROR_OK; } -static void ftdi_end_state(tap_state_t state) +static void ftdi_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -370,7 +370,7 @@ static void ftdi_execute_tms(struct jtag_command *cmd) static void ftdi_execute_pathmove(struct jtag_command *cmd) { - tap_state_t *path = cmd->cmd.pathmove->path; + enum tap_state *path = cmd->cmd.pathmove->path; unsigned int num_states = cmd->cmd.pathmove->num_states; LOG_DEBUG_IO("pathmove: %u states, current: %s end: %s", num_states, diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index d0fe43fdb1..7200e757c7 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -133,7 +133,7 @@ static void gw16012_reset(int trst, int srst) gw16012_control(0x0b); } -static void gw16012_end_state(tap_state_t state) +static void gw16012_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -187,7 +187,7 @@ static void gw16012_path_move(struct pathmove_command *cmd) static void gw16012_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -209,7 +209,7 @@ static void gw16012_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int { int bits_left = scan_size; int bit_count = 0; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); uint8_t scan_out, scan_in; /* only if we're not already in the correct Shift state */ diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 74660744a7..4d15cf5e63 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -78,9 +78,9 @@ static struct device_config config; static struct device_config tmp_config; /* Queue command functions */ -static void jlink_end_state(tap_state_t state); +static void jlink_end_state(enum tap_state state); static void jlink_state_move(void); -static void jlink_path_move(unsigned int num_states, tap_state_t *path); +static void jlink_path_move(unsigned int num_states, enum tap_state *path); static void jlink_stableclocks(unsigned int num_cycles); static void jlink_runtest(unsigned int num_cycles); static void jlink_reset(int trst, int srst); @@ -875,7 +875,7 @@ static int jlink_quit(void) /***************************************************************************/ /* Queue command implementations */ -static void jlink_end_state(tap_state_t state) +static void jlink_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -899,7 +899,7 @@ static void jlink_state_move(void) tap_set_state(tap_get_end_state()); } -static void jlink_path_move(unsigned int num_states, tap_state_t *path) +static void jlink_path_move(unsigned int num_states, enum tap_state *path) { uint8_t tms = 0xff; @@ -930,7 +930,7 @@ static void jlink_stableclocks(unsigned int num_cycles) static void jlink_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* Only do a state_move when we're not already in IDLE. */ if (tap_get_state() != TAP_IDLE) { diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 079bb1d0a1..f6cb3de5d2 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -272,7 +272,7 @@ static int jtag_vpi_tms(struct tms_command *cmd) return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits); } -static int jtag_vpi_state_move(tap_state_t state) +static int jtag_vpi_state_move(enum tap_state state) { if (tap_get_state() == state) return ERROR_OK; @@ -440,7 +440,7 @@ static int jtag_vpi_scan(struct scan_command *cmd) return ERROR_OK; } -static int jtag_vpi_runtest(unsigned int num_cycles, tap_state_t state) +static int jtag_vpi_runtest(unsigned int num_cycles, enum tap_state state) { int retval; diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index e828d46d04..999afb3fc7 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -104,9 +104,9 @@ static int opendous_init(void); static int opendous_quit(void); /* Queue command functions */ -static void opendous_end_state(tap_state_t state); +static void opendous_end_state(enum tap_state state); static void opendous_state_move(void); -static void opendous_path_move(unsigned int num_states, tap_state_t *path); +static void opendous_path_move(unsigned int num_states, enum tap_state *path); static void opendous_runtest(unsigned int num_cycles); static void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); @@ -393,7 +393,7 @@ static int opendous_quit(void) /***************************************************************************/ /* Queue command implementations */ -void opendous_end_state(tap_state_t state) +void opendous_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -419,7 +419,7 @@ void opendous_state_move(void) tap_set_state(tap_get_end_state()); } -void opendous_path_move(unsigned int num_states, tap_state_t *path) +void opendous_path_move(unsigned int num_states, enum tap_state *path) { for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) @@ -440,7 +440,7 @@ void opendous_path_move(unsigned int num_states, tap_state_t *path) void opendous_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -460,7 +460,7 @@ void opendous_runtest(unsigned int num_cycles) void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; opendous_tap_ensure_space(1, scan_size + 8); diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index a3fbd204eb..14bcc171eb 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -748,7 +748,7 @@ static void openjtag_execute_scan(struct jtag_command *cmd) static void openjtag_execute_runtest(struct jtag_command *cmd) { - tap_state_t end_state = cmd->cmd.runtest->end_state; + enum tap_state end_state = cmd->cmd.runtest->end_state; tap_set_end_state(end_state); /* only do a state_move when we're not already in IDLE */ diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index c41a0e13c5..80f66d197e 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -380,7 +380,7 @@ static int osbdm_quit(void) static int osbdm_add_pathmove( struct queue *queue, - tap_state_t *path, + enum tap_state *path, unsigned int num_states) { assert(num_states <= 32); @@ -415,7 +415,7 @@ static int osbdm_add_pathmove( static int osbdm_add_statemove( struct queue *queue, - tap_state_t new_state, + enum tap_state new_state, int skip_first) { int len = 0; @@ -490,7 +490,7 @@ static int osbdm_add_scan( struct queue *queue, struct scan_field *fields, unsigned int num_fields, - tap_state_t end_state, + enum tap_state end_state, bool ir_scan) { /* Move to desired shift state */ @@ -537,7 +537,7 @@ static int osbdm_add_scan( static int osbdm_add_runtest( struct queue *queue, unsigned int num_cycles, - tap_state_t end_state) + enum tap_state end_state) { if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK) return ERROR_FAIL; diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index f4a4fcba94..6ea3729a5f 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -842,7 +842,7 @@ static int tap_state_queue_append(uint8_t tms) return 0; } -static void rlink_end_state(tap_state_t state) +static void rlink_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -898,7 +898,7 @@ static void rlink_path_move(struct pathmove_command *cmd) static void rlink_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in RTI */ if (tap_get_state() != TAP_IDLE) { @@ -1019,7 +1019,7 @@ static int rlink_scan(struct jtag_command *cmd, enum scan_type type, uint8_t *buffer, int scan_size) { bool ir_scan; - tap_state_t saved_end_state; + enum tap_state saved_end_state; int byte_bits; int extra_bits; int chunk_bits; diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 3a248e388f..0a13bf6d44 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -212,7 +212,7 @@ static int ulink_append_test_cmd(struct ulink *device); static int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay); /* Interface between OpenULINK and OpenOCD */ -static void ulink_set_end_state(tap_state_t endstate); +static void ulink_set_end_state(enum tap_state endstate); static int ulink_queue_statemove(struct ulink *device); static int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd); @@ -1393,7 +1393,7 @@ static long ulink_calculate_frequency(enum ulink_delay_type type, int delay) * * @param endstate the state the end state follower should be set to. */ -static void ulink_set_end_state(tap_state_t endstate) +static void ulink_set_end_state(enum tap_state endstate) { if (tap_is_state_stable(endstate)) tap_set_end_state(endstate); @@ -1702,7 +1702,7 @@ static int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd) static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd) { int ret, state_count; - tap_state_t *path; + enum tap_state *path; uint8_t tms_sequence; unsigned int num_states = cmd->cmd.pathmove->num_states; diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 496466ca3d..1782cc424e 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -494,7 +494,7 @@ static void ublast_path_move(struct pathmove_command *cmd) * Input the correct TMS sequence to the JTAG TAP so that we end up in the * target state. This assumes the current state (tap_get_state()) is correct. */ -static void ublast_state_move(tap_state_t state, int skip) +static void ublast_state_move(enum tap_state state, int skip) { uint8_t tms_scan; int tms_len; @@ -673,7 +673,7 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) ublast_idle_clock(); } -static void ublast_runtest(unsigned int num_cycles, tap_state_t state) +static void ublast_runtest(unsigned int num_cycles, enum tap_state state) { LOG_DEBUG_IO("%s(cycles=%u, end_state=%d)", __func__, num_cycles, state); diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index 6e3b3ba242..24407f0037 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -34,7 +34,7 @@ #define TCK_BIT 2 #define TMS_BIT 1 -static void usbprog_end_state(tap_state_t state); +static void usbprog_end_state(enum tap_state state); static void usbprog_state_move(void); static void usbprog_path_move(struct pathmove_command *cmd); static void usbprog_runtest(unsigned int num_cycles); @@ -168,7 +168,7 @@ static int usbprog_quit(void) } /*************** jtag execute commands **********************/ -static void usbprog_end_state(tap_state_t state) +static void usbprog_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -257,7 +257,7 @@ static void usbprog_runtest(unsigned int num_cycles) static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); if (ir_scan) usbprog_end_state(TAP_IRSHIFT); diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index 20819f70bd..fd1e6a7e7b 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -944,11 +944,11 @@ static int vdebug_jtag_path_move(struct pathmove_command *cmd, uint8_t f_flush) return vdebug_jtag_tms_seq(tms, cmd->num_states, f_flush); } -static int vdebug_jtag_tlr(tap_state_t state, uint8_t f_flush) +static int vdebug_jtag_tlr(enum tap_state state, uint8_t f_flush) { int rc = ERROR_OK; - tap_state_t cur = tap_get_state(); + enum tap_state cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); LOG_DEBUG_IO("tlr from %x to %x", cur, state); @@ -964,7 +964,7 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) { int rc = ERROR_OK; - tap_state_t cur = tap_get_state(); + enum tap_state cur = tap_get_state(); uint8_t state = cmd->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT; uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); @@ -992,9 +992,9 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) return rc; } -static int vdebug_jtag_runtest(unsigned int num_cycles, tap_state_t state, uint8_t f_flush) +static int vdebug_jtag_runtest(unsigned int num_cycles, enum tap_state state, uint8_t f_flush) { - tap_state_t cur = tap_get_state(); + enum tap_state cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); LOG_DEBUG_IO("idle len:%u state cur:%x end:%x", num_cycles, cur, state); diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index ca142177ec..c10ed13800 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -41,9 +41,9 @@ static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; /* Queue command functions */ -static void vsllink_end_state(tap_state_t state); +static void vsllink_end_state(enum tap_state state); static void vsllink_state_move(void); -static void vsllink_path_move(unsigned int num_states, tap_state_t *path); +static void vsllink_path_move(unsigned int num_states, enum tap_state *path); static void vsllink_tms(int num_bits, const uint8_t *bits); static void vsllink_runtest(unsigned int num_cycles); static void vsllink_stableclocks(unsigned int num_cycles, int tms); @@ -346,7 +346,7 @@ static int vsllink_init(void) /************************************************************************** * Queue command implementations */ -static void vsllink_end_state(tap_state_t state) +static void vsllink_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -371,7 +371,7 @@ static void vsllink_state_move(void) tap_set_state(tap_get_end_state()); } -static void vsllink_path_move(unsigned int num_states, tap_state_t *path) +static void vsllink_path_move(unsigned int num_states, enum tap_state *path) { for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) @@ -407,7 +407,7 @@ static void vsllink_stableclocks(unsigned int num_cycles, int tms) static void vsllink_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); if (tap_get_state() != TAP_IDLE) { /* enter IDLE state */ @@ -427,7 +427,7 @@ static void vsllink_runtest(unsigned int num_cycles) static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; saved_end_state = tap_get_end_state(); diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index 6e12b9a790..c84371001f 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -172,7 +172,7 @@ #define CMD_RUNTEST 3 #define CMD_STABLECLOCKS 4 -/* Array to convert from OpenOCD tap_state_t to XDS JTAG state */ +/* Array to convert from OpenOCD enum tap_state to XDS JTAG state */ static const uint32_t xds_jtag_state[] = { XDS_JTAG_STATE_EXIT2_DR, /* TAP_DREXIT2 = 0x0 */ XDS_JTAG_STATE_EXIT1_DR, /* TAP_DREXIT1 = 0x1 */ diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index d90a022cda..37c6777e4e 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -171,7 +171,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); - tap_state_t tmp_state = tap_get_end_state(); + enum tap_state tmp_state = tap_get_end_state(); if (tap_get_state() != TAP_IDLE) { tap_set_end_state(TAP_IDLE); @@ -201,7 +201,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) { unsigned int num_states = cmd->cmd.pathmove->num_states; - tap_state_t *path = cmd->cmd.pathmove->path; + enum tap_state *path = cmd->cmd.pathmove->path; int err = ERROR_OK; LOG_DEBUG("pathmove: %u states, end in %i", @@ -232,7 +232,7 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd) { enum scan_type type = jtag_scan_type(cmd->cmd.scan); - tap_state_t saved_end_state = cmd->cmd.scan->end_state; + enum tap_state saved_end_state = cmd->cmd.scan->end_state; bool ir_scan = cmd->cmd.scan->ir_scan; uint32_t tdi, tms, tdo; uint8_t *buf, *rd_ptr; diff --git a/src/jtag/interface.c b/src/jtag/interface.c index 87d704db97..92c88ca934 100644 --- a/src/jtag/interface.c +++ b/src/jtag/interface.c @@ -26,15 +26,15 @@ * @see tap_set_state() and tap_get_state() accessors. * Actual name is not important since accessors hide it. */ -static tap_state_t state_follower = TAP_RESET; +static enum tap_state state_follower = TAP_RESET; -void tap_set_state_impl(tap_state_t new_state) +void tap_set_state_impl(enum tap_state new_state) { /* this is the state we think the TAPs are in now, was cur_state */ state_follower = new_state; } -tap_state_t tap_get_state(void) +enum tap_state tap_get_state(void) { return state_follower; } @@ -43,9 +43,9 @@ tap_state_t tap_get_state(void) * @see tap_set_end_state() and tap_get_end_state() accessors. * Actual name is not important because accessors hide it. */ -static tap_state_t end_state_follower = TAP_RESET; +static enum tap_state end_state_follower = TAP_RESET; -void tap_set_end_state(tap_state_t new_end_state) +void tap_set_end_state(enum tap_state new_end_state) { /* this is the state we think the TAPs will be in at completion of the * current TAP operation, was end_state @@ -53,12 +53,12 @@ void tap_set_end_state(tap_state_t new_end_state) end_state_follower = new_end_state; } -tap_state_t tap_get_end_state(void) +enum tap_state tap_get_end_state(void) { return end_state_follower; } -int tap_move_ndx(tap_state_t astate) +int tap_move_ndx(enum tap_state astate) { /* given a stable state, return the index into the tms_seqs[] * array within tap_get_tms_path() @@ -187,17 +187,17 @@ typedef const struct tms_sequences tms_table[6][6]; static tms_table *tms_seqs = &short_tms_seqs; -int tap_get_tms_path(tap_state_t from, tap_state_t to) +int tap_get_tms_path(enum tap_state from, enum tap_state to) { return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits; } -int tap_get_tms_path_len(tap_state_t from, tap_state_t to) +int tap_get_tms_path_len(enum tap_state from, enum tap_state to) { return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count; } -bool tap_is_state_stable(tap_state_t astate) +bool tap_is_state_stable(enum tap_state astate) { bool is_stable; @@ -220,9 +220,9 @@ bool tap_is_state_stable(tap_state_t astate) return is_stable; } -tap_state_t tap_state_transition(tap_state_t cur_state, bool tms) +enum tap_state tap_state_transition(enum tap_state cur_state, bool tms) { - tap_state_t new_state; + enum tap_state new_state; /* A switch is used because it is symbol dependent and not value dependent * like an array. Also it can check for out of range conditions. @@ -341,7 +341,7 @@ static const struct name_mapping { { TAP_IDLE, "IDLE", }, }; -const char *tap_state_name(tap_state_t state) +const char *tap_state_name(enum tap_state state) { unsigned int i; @@ -352,7 +352,7 @@ const char *tap_state_name(tap_state_t state) return "???"; } -tap_state_t tap_state_by_name(const char *name) +enum tap_state tap_state_by_name(const char *name) { unsigned int i; @@ -371,8 +371,8 @@ tap_state_t tap_state_by_name(const char *name) LOG_DEBUG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \ tap_state_name(a), tap_state_name(b), astr, bstr) -tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, - unsigned int tap_bits, tap_state_t next_state) +enum tap_state jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, + unsigned int tap_bits, enum tap_state next_state) { const uint8_t *tms_buffer; const uint8_t *tdi_buffer; @@ -384,7 +384,7 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, char tms_str[33]; char tdi_str[33]; - tap_state_t last_state; + enum tap_state last_state; /* set startstate (and possibly last, if tap_bits == 0) */ last_state = next_state; diff --git a/src/jtag/interface.h b/src/jtag/interface.h index f69326492a..b2d7123fd4 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -28,7 +28,7 @@ /** implementation of wrapper function tap_set_state() */ -void tap_set_state_impl(tap_state_t new_state); +void tap_set_state_impl(enum tap_state new_state); /** * This function sets the state of a "state follower" which tracks the @@ -55,9 +55,9 @@ void tap_set_state_impl(tap_state_t new_state); /** * This function gets the state of the "state follower" which tracks the * state of the TAPs connected to the cable. @see tap_set_state @return - * tap_state_t The state the TAPs are in now. + * enum tap_state The state the TAPs are in now. */ -tap_state_t tap_get_state(void); +enum tap_state tap_get_state(void); /** * This function sets the state of an "end state follower" which tracks @@ -70,13 +70,13 @@ tap_state_t tap_get_state(void); * @param new_end_state The state the TAPs should enter at completion of * a pending TAP operation. */ -void tap_set_end_state(tap_state_t new_end_state); +void tap_set_end_state(enum tap_state new_end_state); /** * For more information, @see tap_set_end_state - * @return tap_state_t - The state the TAPs should be in at completion of the current TAP operation. + * @return enum tap_state - The state the TAPs should be in at completion of the current TAP operation. */ -tap_state_t tap_get_end_state(void); +enum tap_state tap_get_end_state(void); /** * This function provides a "bit sequence" indicating what has to be @@ -91,7 +91,7 @@ tap_state_t tap_get_end_state(void); * @return int The required TMS bit sequence, with the first bit in the * sequence at bit 0. */ -int tap_get_tms_path(tap_state_t from, tap_state_t to); +int tap_get_tms_path(enum tap_state from, enum tap_state to); /** * Function int tap_get_tms_path_len @@ -109,7 +109,7 @@ int tap_get_tms_path(tap_state_t from, tap_state_t to); * @param to is the resultant or final state * @return int - the total number of bits in a transition. */ -int tap_get_tms_path_len(tap_state_t from, tap_state_t to); +int tap_get_tms_path_len(enum tap_state from, enum tap_state to); /** @@ -125,30 +125,30 @@ int tap_get_tms_path_len(tap_state_t from, tap_state_t to); * and terminate. * @return int - the array (or sequence) index as described above */ -int tap_move_ndx(tap_state_t astate); +int tap_move_ndx(enum tap_state astate); /** * Function tap_is_state_stable * returns true if the \a astate is stable. */ -bool tap_is_state_stable(tap_state_t astate); +bool tap_is_state_stable(enum tap_state astate); /** * Function tap_state_transition * takes a current TAP state and returns the next state according to the tms value. * @param current_state is the state of a TAP currently. * @param tms is either zero or non-zero, just like a real TMS line in a jtag interface. - * @return tap_state_t - the next state a TAP would enter. + * @return enum tap_state - the next state a TAP would enter. */ -tap_state_t tap_state_transition(tap_state_t current_state, bool tms); +enum tap_state tap_state_transition(enum tap_state current_state, bool tms); /** Allow switching between old and new TMS tables. @see tap_get_tms_path */ void tap_use_new_tms_table(bool use_new); /** @returns True if new TMS table is active; false otherwise. */ bool tap_uses_new_tms_table(void); -tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, - unsigned int tap_len, tap_state_t start_tap_state); +enum tap_state jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, + unsigned int tap_len, enum tap_state start_tap_state); /** * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers. @@ -158,8 +158,8 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, * @param start_tap_state must specify the current TAP state. * @returns the final TAP state; pass as @a start_tap_state in following call. */ -static inline tap_state_t jtag_debug_state_machine(const void *tms_buf, - const void *tdi_buf, unsigned int tap_len, tap_state_t start_tap_state) +static inline enum tap_state jtag_debug_state_machine(const void *tms_buf, + const void *tdi_buf, unsigned int tap_len, enum tap_state start_tap_state) { if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) return jtag_debug_state_machine_(tms_buf, tdi_buf, tap_len, start_tap_state); diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 86526a09a1..47efdff37c 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -34,7 +34,7 @@ * Fix those drivers to map as appropriate ... then pick some * sane set of numbers here (where 0/uninitialized == INVALID). */ -typedef enum tap_state { +enum tap_state { TAP_INVALID = -1, /* Proper ARM recommended numbers */ @@ -54,7 +54,7 @@ typedef enum tap_state { TAP_IRUPDATE = 0xd, TAP_IRCAPTURE = 0xe, TAP_RESET = 0x0f, -} tap_state_t; +}; /** * Defines arguments for reset functions @@ -68,13 +68,13 @@ typedef enum tap_state { * Function tap_state_name * Returns a string suitable for display representing the JTAG tap_state */ -const char *tap_state_name(tap_state_t state); +const char *tap_state_name(enum tap_state state); /** Provides user-friendly name lookup of TAP states. */ -tap_state_t tap_state_by_name(const char *name); +enum tap_state tap_state_by_name(const char *name); /** The current TAP state of the pending JTAG command queue. */ -extern tap_state_t cmd_queue_cur_state; +extern enum tap_state cmd_queue_cur_state; /** * This structure defines a single scan field in the scan. It provides @@ -295,20 +295,20 @@ int jtag_init_inner(struct command_context *cmd_ctx); * */ void jtag_add_ir_scan(struct jtag_tap *tap, - struct scan_field *fields, tap_state_t endstate); + struct scan_field *fields, enum tap_state endstate); /** * The same as jtag_add_ir_scan except no verification is performed out * the output values. */ void jtag_add_ir_scan_noverify(struct jtag_tap *tap, - const struct scan_field *fields, tap_state_t state); + const struct scan_field *fields, enum tap_state state); /** * Scan out the bits in ir scan mode. * * If in_bits == NULL, discard incoming bits. */ void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t endstate); + enum tap_state endstate); /** * Generate a DR SCAN using the fields passed to the function. @@ -317,17 +317,17 @@ void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_b * 1-bit field. The bypass status of TAPs is set by jtag_add_ir_scan(). */ void jtag_add_dr_scan(struct jtag_tap *tap, int num_fields, - const struct scan_field *fields, tap_state_t endstate); + const struct scan_field *fields, enum tap_state endstate); /** A version of jtag_add_dr_scan() that uses the check_value/mask fields */ void jtag_add_dr_scan_check(struct jtag_tap *tap, int num_fields, - struct scan_field *fields, tap_state_t endstate); + struct scan_field *fields, enum tap_state endstate); /** * Scan out the bits in ir scan mode. * * If in_bits == NULL, discard incoming bits. */ void jtag_add_plain_dr_scan(int num_bits, - const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate); + const uint8_t *out_bits, uint8_t *in_bits, enum tap_state endstate); /** * Defines the type of data passed to the jtag_callback_t interface. @@ -435,7 +435,7 @@ void jtag_add_tlr(void); * - ERROR_JTAG_TRANSITION_INVALID -- The path includes invalid * state transitions. */ -void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path); +void jtag_add_pathmove(unsigned int num_states, const enum tap_state *path); /** * jtag_add_statemove() moves from the current state to @a goal_state. @@ -446,7 +446,7 @@ void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path); * Moves from the current state to the goal \a state. * Both states must be stable. */ -int jtag_add_statemove(tap_state_t goal_state); +int jtag_add_statemove(enum tap_state goal_state); /** * Goes to TAP_IDLE (if we're not already there), cycle @@ -458,7 +458,7 @@ int jtag_add_statemove(tap_state_t goal_state); * via TAP_IDLE. * @param endstate The final state. */ -void jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate); +void jtag_add_runtest(unsigned int num_cycles, enum tap_state endstate); /** * A reset of the TAP state machine can be requested. diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h index 1b1094dd5b..4b61bf1250 100644 --- a/src/jtag/minidriver.h +++ b/src/jtag/minidriver.h @@ -38,21 +38,21 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_plain_ir_scan( int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields, const struct scan_field *fields, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_plain_dr_scan( int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_tlr(void); -int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path); -int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate); +int interface_jtag_add_pathmove(unsigned int num_states, const enum tap_state *path); +int interface_jtag_add_runtest(unsigned int num_cycles, enum tap_state endstate); int interface_add_tms_seq(unsigned int num_bits, const uint8_t *bits, enum tap_state state); diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 790aedfc46..8b0bc7affb 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -61,7 +61,7 @@ struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) return t; } -static bool scan_is_safe(tap_state_t state) +static bool scan_is_safe(enum tap_state state) { switch (state) { case TAP_RESET: @@ -126,7 +126,7 @@ COMMAND_HANDLER(handle_jtag_command_drscan) return ERROR_FAIL; } - tap_state_t endstate = TAP_IDLE; + enum tap_state endstate = TAP_IDLE; if (CMD_ARGC > 3 && !strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2])) { const char *state_name = CMD_ARGV[CMD_ARGC - 1]; endstate = tap_state_by_name(state_name); @@ -176,7 +176,7 @@ COMMAND_HANDLER(handle_jtag_command_drscan) COMMAND_HANDLER(handle_jtag_command_pathmove) { - tap_state_t states[8]; + enum tap_state states[8]; if (CMD_ARGC < 1 || CMD_ARGC > ARRAY_SIZE(states)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -919,7 +919,7 @@ COMMAND_HANDLER(handle_irscan_command) int i; struct scan_field *fields; struct jtag_tap *tap = NULL; - tap_state_t endstate; + enum tap_state endstate; if ((CMD_ARGC < 2) || (CMD_ARGC % 2)) return ERROR_COMMAND_SYNTAX_ERROR; diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 2997cdc39f..93ef3565c9 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -59,7 +59,7 @@ static const struct lattice_devices_elem lattice_devices[] = { {0x010f4043, 362, LATTICE_CERTUS /* LFCPNX-100 */}, }; -int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate) +int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, enum tap_state endstate) { struct scan_field field; field.num_bits = tap->ir_length; diff --git a/src/pld/lattice.h b/src/pld/lattice.h index 9a76a4ec37..c215989669 100644 --- a/src/pld/lattice.h +++ b/src/pld/lattice.h @@ -20,7 +20,7 @@ struct lattice_pld_device { enum lattice_family_e family; }; -int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate); +int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, enum tap_state endstate); int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_val, uint32_t out_val, bool do_idle); int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t *in_val, diff --git a/src/svf/svf.c b/src/svf/svf.c index 9dd2463c0a..ce994686f1 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -75,10 +75,10 @@ static const char *svf_trst_mode_name[4] = { }; struct svf_statemove { - tap_state_t from; - tap_state_t to; + enum tap_state from; + enum tap_state to; uint32_t num_of_moves; - tap_state_t paths[8]; + enum tap_state paths[8]; }; /* @@ -155,10 +155,10 @@ struct svf_xxr_para { struct svf_para { float frequency; - tap_state_t ir_end_state; - tap_state_t dr_end_state; - tap_state_t runtest_run_state; - tap_state_t runtest_end_state; + enum tap_state ir_end_state; + enum tap_state dr_end_state; + enum tap_state runtest_run_state; + enum tap_state runtest_end_state; enum trst_mode trst_mode; struct svf_xxr_para hir_para; @@ -313,9 +313,9 @@ static void svf_free_xxd_para(struct svf_xxr_para *para) } } -int svf_add_statemove(tap_state_t state_to) +int svf_add_statemove(enum tap_state state_to) { - tap_state_t state_from = cmd_queue_cur_state; + enum tap_state state_from = cmd_queue_cur_state; unsigned int index_var; /* when resetting, be paranoid and ignore current state */ @@ -816,7 +816,7 @@ static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_ar return ERROR_OK; } -bool svf_tap_state_is_stable(tap_state_t state) +bool svf_tap_state_is_stable(enum tap_state state) { return (state == TAP_RESET) || (state == TAP_IDLE) || (state == TAP_DRPAUSE) || (state == TAP_IRPAUSE); @@ -995,7 +995,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str) uint8_t **pbuffer_tmp; struct scan_field field; /* for STATE */ - tap_state_t *path = NULL, state; + enum tap_state *path = NULL, state; /* flag padding commands skipped due to -tap command */ int padding_command_skipped = 0; @@ -1498,7 +1498,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str) } if (num_of_argu > 2) { /* STATE pathstate1 ... stable_state */ - path = malloc((num_of_argu - 1) * sizeof(tap_state_t)); + path = malloc((num_of_argu - 1) * sizeof(enum tap_state)); if (!path) { LOG_ERROR("not enough memory"); return ERROR_FAIL; diff --git a/src/svf/svf.h b/src/svf/svf.h index 74f7d9ca9b..77a0e0dcf1 100644 --- a/src/svf/svf.h +++ b/src/svf/svf.h @@ -23,7 +23,7 @@ int svf_register_commands(struct command_context *cmd_ctx); * SVF specification for single-argument STATE commands (and also used * for various other state transitions). */ -int svf_add_statemove(tap_state_t goal_state); +int svf_add_statemove(enum tap_state goal_state); /** * svf_tap_state_is_stable() returns true for stable non-SHIFT states @@ -31,6 +31,6 @@ int svf_add_statemove(tap_state_t goal_state); * @param state The TAP state in question * @return true iff the state is stable and not a SHIFT state. */ -bool svf_tap_state_is_stable(tap_state_t state); +bool svf_tap_state_is_stable(enum tap_state state); #endif /* OPENOCD_SVF_SVF_H */ diff --git a/src/target/arc_jtag.c b/src/target/arc_jtag.c index a186709c61..c2bc5aa8fd 100644 --- a/src/target/arc_jtag.c +++ b/src/target/arc_jtag.c @@ -66,7 +66,7 @@ static void arc_jtag_enque_write_ir(struct arc_jtag *jtag_info, uint32_t * @param end_state End state after reading. */ static void arc_jtag_enque_read_dr(struct arc_jtag *jtag_info, uint8_t *data, - tap_state_t end_state) + enum tap_state end_state) { assert(jtag_info); @@ -88,7 +88,7 @@ static void arc_jtag_enque_read_dr(struct arc_jtag *jtag_info, uint8_t *data, * @param end_state End state after writing. */ static void arc_jtag_enque_write_dr(struct arc_jtag *jtag_info, uint32_t data, - tap_state_t end_state) + enum tap_state end_state) { uint8_t out_value[sizeof(uint32_t)] = {0}; @@ -116,7 +116,7 @@ static void arc_jtag_enque_write_dr(struct arc_jtag *jtag_info, uint32_t data, * @param end_state End state after writing. */ static void arc_jtag_enque_set_transaction(struct arc_jtag *jtag_info, - uint32_t new_trans, tap_state_t end_state) + uint32_t new_trans, enum tap_state end_state) { uint8_t out_value[sizeof(uint32_t)] = {0}; diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index 36325911ad..4c7211365b 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -31,13 +31,13 @@ behavior of the FTDI driver IIRC was to go via RTI. Conversely there may be other places in this code where the ARM11 code relies on the driver to hit through RTI when coming from Update-?R. */ -static const tap_state_t arm11_move_pi_to_si_via_ci[] = { +static const enum tap_state arm11_move_pi_to_si_via_ci[] = { TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT }; /* REVISIT no error handling here! */ static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields, - tap_state_t state) + enum tap_state state) { if (cmd_queue_cur_state == TAP_IRPAUSE) jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci), @@ -46,13 +46,13 @@ static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields jtag_add_ir_scan(tap, fields, state); } -static const tap_state_t arm11_move_pd_to_sd_via_cd[] = { +static const enum tap_state arm11_move_pd_to_sd_via_cd[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; /* REVISIT no error handling here! */ void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields, - tap_state_t state) + enum tap_state state) { if (cmd_queue_cur_state == TAP_DRPAUSE) jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd), @@ -121,7 +121,7 @@ static const char *arm11_ir_to_string(uint8_t ir) * * \remarks This adds to the JTAG command queue but does \em not execute it. */ -void arm11_add_ir(struct arm11_common *arm11, uint8_t instr, tap_state_t state) +void arm11_add_ir(struct arm11_common *arm11, uint8_t instr, enum tap_state state) { struct jtag_tap *tap = arm11->arm.target->tap; @@ -181,7 +181,7 @@ static void arm11_in_handler_scan_n(uint8_t *in_value) */ int arm11_add_debug_scan_n(struct arm11_common *arm11, - uint8_t chain, tap_state_t state) + uint8_t chain, enum tap_state state) { /* Don't needlessly switch the scan chain. * NOTE: the ITRSEL instruction fakes SCREG changing; @@ -240,7 +240,7 @@ int arm11_add_debug_scan_n(struct arm11_common *arm11, * to ensure that the rDTR is ready before that Run-Test/Idle state. */ static void arm11_add_debug_inst(struct arm11_common *arm11, - uint32_t inst, uint8_t *flag, tap_state_t state) + uint32_t inst, uint8_t *flag, enum tap_state state) { JTAG_DEBUG("INST <= 0x%08" PRIx32, inst); @@ -542,7 +542,7 @@ int arm11_run_instr_data_to_core(struct arm11_common *arm11, * https://lists.berlios.de/pipermail/openocd-development/2009-July/009698.html * https://lists.berlios.de/pipermail/openocd-development/2009-August/009865.html */ -static const tap_state_t arm11_move_drpause_idle_drpause_with_delay[] = { +static const enum tap_state arm11_move_drpause_idle_drpause_with_delay[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; diff --git a/src/target/arm11_dbgtap.h b/src/target/arm11_dbgtap.h index eeb174a8ba..74dda6e893 100644 --- a/src/target/arm11_dbgtap.h +++ b/src/target/arm11_dbgtap.h @@ -17,9 +17,9 @@ void arm11_setup_field(struct arm11_common *arm11, int num_bits, void *in_data, void *out_data, struct scan_field *field); void arm11_add_ir(struct arm11_common *arm11, - uint8_t instr, tap_state_t state); + uint8_t instr, enum tap_state state); int arm11_add_debug_scan_n(struct arm11_common *arm11, - uint8_t chain, tap_state_t state); + uint8_t chain, enum tap_state state); int arm11_read_dscr(struct arm11_common *arm11); int arm11_write_dscr(struct arm11_common *arm11, uint32_t dscr); @@ -40,7 +40,7 @@ int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t data); void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields, - tap_state_t state); + enum tap_state state); /** * Used with arm11_sc7_run to make a list of read/write commands for diff --git a/src/target/arm_jtag.c b/src/target/arm_jtag.c index c1ec4735ac..e553ec8b87 100644 --- a/src/target/arm_jtag.c +++ b/src/target/arm_jtag.c @@ -19,7 +19,7 @@ #endif int arm_jtag_set_instr_inner(struct jtag_tap *tap, - uint32_t new_instr, void *no_verify_capture, tap_state_t end_state) + uint32_t new_instr, void *no_verify_capture, enum tap_state end_state) { struct scan_field field; uint8_t t[4] = { 0 }; @@ -41,7 +41,7 @@ int arm_jtag_set_instr_inner(struct jtag_tap *tap, return ERROR_OK; } -int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state) +int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, enum tap_state end_state) { int retval = ERROR_OK; diff --git a/src/target/arm_jtag.h b/src/target/arm_jtag.h index 11b7c3efd7..5356bcf277 100644 --- a/src/target/arm_jtag.h +++ b/src/target/arm_jtag.h @@ -26,10 +26,10 @@ struct arm_jtag { int arm_jtag_set_instr_inner(struct jtag_tap *tap, uint32_t new_instr, void *no_verify_capture, - tap_state_t end_state); + enum tap_state end_state); static inline int arm_jtag_set_instr(struct jtag_tap *tap, - uint32_t new_instr, void *no_verify_capture, tap_state_t end_state) + uint32_t new_instr, void *no_verify_capture, enum tap_state end_state) { /* inline most common code path */ if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (new_instr & (BIT(tap->ir_length) - 1))) @@ -39,8 +39,8 @@ static inline int arm_jtag_set_instr(struct jtag_tap *tap, } -int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state); -static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state) +int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, enum tap_state end_state); +static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, enum tap_state end_state) { /* inline most common code path */ int retval = ERROR_OK; diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index 8b3b1c49b6..b370aafa46 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -44,7 +44,7 @@ static int reset_jtag(void) { int retval; - tap_state_t states[2]; + enum tap_state states[2]; const char *cp = "RESET"; diff --git a/src/target/xscale.c b/src/target/xscale.c index 155abaef1a..83afd5de23 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -137,7 +137,7 @@ static int xscale_verify_pointer(struct command_invocation *cmd, return ERROR_OK; } -static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) +static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, enum tap_state end_state) { assert(tap); @@ -232,7 +232,7 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words struct xscale_common *xscale = target_to_xscale(target); int retval = ERROR_OK; - tap_state_t path[3]; + enum tap_state path[3]; struct scan_field fields[3]; uint8_t *field0 = malloc(num_words * 1); uint8_t field0_check_value = 0x2; @@ -330,8 +330,8 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words static int xscale_read_tx(struct target *target, int consume) { struct xscale_common *xscale = target_to_xscale(target); - tap_state_t path[3]; - tap_state_t noconsume_path[6]; + enum tap_state path[3]; + enum tap_state noconsume_path[6]; int retval; struct timeval timeout, now; struct scan_field fields[3]; diff --git a/src/target/xtensa/xtensa_debug_module.c b/src/target/xtensa/xtensa_debug_module.c index 8045779b81..943f199c1f 100644 --- a/src/target/xtensa/xtensa_debug_module.c +++ b/src/target/xtensa/xtensa_debug_module.c @@ -60,7 +60,7 @@ static void xtensa_dm_add_dr_scan(struct xtensa_debug_module *dm, int len, const uint8_t *src, uint8_t *dest, - tap_state_t endstate) + enum tap_state endstate) { struct scan_field field; diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index 88275043ed..617c2f423e 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -111,10 +111,10 @@ TDO (1); static int xsvf_fd; -/* map xsvf tap state to an openocd "tap_state_t" */ -static tap_state_t xsvf_to_tap(int xsvf_state) +/* map xsvf tap state to an openocd "enum tap_state" */ +static enum tap_state xsvf_to_tap(int xsvf_state) { - tap_state_t ret; + enum tap_state ret; switch (xsvf_state) { case XSV_RESET: @@ -196,16 +196,16 @@ COMMAND_HANDLER(handle_xsvf_command) int xruntest = 0; /* number of TCK cycles OR *microseconds */ int xrepeat = 0; /* number of retries */ - tap_state_t xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial + enum tap_state xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial *xendir to be TAP_IDLE */ - tap_state_t xenddr = TAP_IDLE; + enum tap_state xenddr = TAP_IDLE; uint8_t opcode; uint8_t uc = 0; long file_offset = 0; int loop_count = 0; - tap_state_t loop_state = TAP_IDLE; + enum tap_state loop_state = TAP_IDLE; int loop_clocks = 0; int loop_usecs = 0; @@ -216,7 +216,7 @@ COMMAND_HANDLER(handle_xsvf_command) int verbose = 1; bool collecting_path = false; - tap_state_t path[XSTATE_MAX_PATH]; + enum tap_state path[XSTATE_MAX_PATH]; unsigned int pathlen = 0; /* a flag telling whether to clock TCK during waits, @@ -272,7 +272,7 @@ COMMAND_HANDLER(handle_xsvf_command) * or terminate a path. */ if (collecting_path) { - tap_state_t mystate; + enum tap_state mystate; switch (opcode) { case XCOMMENT: @@ -455,7 +455,7 @@ COMMAND_HANDLER(handle_xsvf_command) * will be skipped entirely if xrepeat is set to zero. */ - static tap_state_t exception_path[] = { + static enum tap_state exception_path[] = { TAP_DREXIT2, TAP_DRSHIFT, TAP_DREXIT1, @@ -563,7 +563,7 @@ COMMAND_HANDLER(handle_xsvf_command) case XSTATE: { - tap_state_t mystate; + enum tap_state mystate; if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; @@ -654,7 +654,7 @@ COMMAND_HANDLER(handle_xsvf_command) uint8_t short_buf[2]; uint8_t *ir_buf; int bitcount; - tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir; + enum tap_state my_end_state = xruntest ? TAP_IDLE : xendir; if (opcode == XSIR) { /* one byte bitcount */ @@ -744,8 +744,8 @@ COMMAND_HANDLER(handle_xsvf_command) uint8_t end; uint8_t delay_buf[4]; - tap_state_t wait_state; - tap_state_t end_state; + enum tap_state wait_state; + enum tap_state end_state; int delay; if (read(xsvf_fd, &wait_local, 1) < 0 @@ -788,8 +788,8 @@ COMMAND_HANDLER(handle_xsvf_command) uint8_t usecs_buf[4]; uint8_t wait_local; uint8_t end; - tap_state_t wait_state; - tap_state_t end_state; + enum tap_state wait_state; + enum tap_state end_state; int clock_count; int usecs; From 9ccd6265dd56c75cc8d58359d33bf6d65a7524ab Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 10 Jan 2025 17:11:24 +0100 Subject: [PATCH 1092/1312] checkpatch: enable check for new typedefs We should strictly check for every new typedef. Let checkpatch detect them and let developer use Checkpatch-ignore: NEW_TYPEDEFS if it's really needed to add a new typedef. With this change chackpatch will not complain for typedef on function's type but only on enum, struct, variable's type. Change-Id: I644a753e97de877d892af3a0219716f022fb1c59 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8710 Reviewed-by: zapb Tested-by: jenkins --- .checkpatch.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/.checkpatch.conf b/.checkpatch.conf index 8cb9a3729a..f432503e1a 100644 --- a/.checkpatch.conf +++ b/.checkpatch.conf @@ -17,7 +17,6 @@ --ignore LINE_SPACING --ignore LOGICAL_CONTINUATIONS --ignore MACRO_WITH_FLOW_CONTROL ---ignore NEW_TYPEDEFS --ignore PARENTHESIS_ALIGNMENT --ignore PREFER_DEFINED_ATTRIBUTE_MACRO --ignore PREFER_FALLTHROUGH From 9bb0a4558bc84b8be63aa937d4b7b9283614f132 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 9 Dec 2024 16:11:03 -0500 Subject: [PATCH 1093/1312] target/arc: add RTT commands Since RTT is architecture agnostic, add support for using it on the ARC architecture as well. Change-Id: Icd0dec105177a1a224bfb1a63f0be5f03561b166 Signed-off-by: Chris Friedt Reviewed-on: https://review.openocd.org/c/openocd/+/8720 Reviewed-by: zapb Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arc.h | 1 + src/target/arc_cmd.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/target/arc.h b/src/target/arc.h index a351802ac6..4255840d1f 100644 --- a/src/target/arc.h +++ b/src/target/arc.h @@ -22,6 +22,7 @@ #include "target_request.h" #include "target_type.h" #include "helper/bits.h" +#include "rtt/rtt.h" #include "arc_jtag.h" #include "arc_cmd.h" diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c index e7760b0378..bf8a8aa28b 100644 --- a/src/target/arc_cmd.c +++ b/src/target/arc_cmd.c @@ -906,5 +906,8 @@ const struct command_registration arc_monitor_command_handlers[] = { .usage = "", .chain = arc_core_command_handlers, }, + { + .chain = rtt_target_command_handlers, + }, COMMAND_REGISTRATION_DONE }; From 44e782d55bf1ce0d924c082281082496cdc2495e Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 16 Jan 2025 22:33:48 -0500 Subject: [PATCH 1094/1312] target/arc: allow reading memory while target runs There is no reason that ARC can't support reading from memory over JTAG while the target is executing, and this is in fact required for RTT support. Remove this check from arc_mem_read and arc_mem_write Change-Id: I2accfb4b99bf77c5473d133623e0eb0632cb45f6 Signed-off-by: Daniel DeGrasse Reviewed-on: https://review.openocd.org/c/openocd/+/8721 Tested-by: jenkins Reviewed-by: Evgeniy Didin Reviewed-by: Antonio Borneo --- src/target/arc_mem.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/target/arc_mem.c b/src/target/arc_mem.c index 3daed1cbbf..5132aca3d9 100644 --- a/src/target/arc_mem.c +++ b/src/target/arc_mem.c @@ -161,11 +161,6 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size, LOG_TARGET_DEBUG(target, "address: 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: %" PRIu32, address, size, count); - if (target->state != TARGET_HALTED) { - LOG_TARGET_ERROR(target, "not halted"); - return ERROR_TARGET_NOT_HALTED; - } - /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || !(count) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -246,11 +241,6 @@ int arc_mem_read(struct target *target, target_addr_t address, uint32_t size, LOG_TARGET_DEBUG(target, "Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 ", count=%" PRIu32, address, size, count); - if (target->state != TARGET_HALTED) { - LOG_TARGET_WARNING(target, "target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - /* Sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || !(count) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; From a71f2b70894a8118730d912edf27fe488580bd4c Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 25 Jan 2025 17:26:16 +0100 Subject: [PATCH 1095/1312] README: report dependency from libjim The support for jimtcl submodule is deprecated. Report libjim as a dependency for building OpenOCD. Change-Id: Iaaeb03dc810451c0d72add281016c81b8cbf7059 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8722 Reviewed-by: zapb Tested-by: jenkins --- README | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README b/README index 950c71f707..fba758cfef 100644 --- a/README +++ b/README @@ -209,9 +209,7 @@ You'll also need: - make - libtool - pkg-config >= 0.23 or pkgconf - -OpenOCD uses jimtcl library; build from git can retrieve jimtcl as git -submodule. +- libjim >= 0.79 Additionally, for building from git: From 4deb76fc9d48aff71b1f2875eecc4b6964c0a0c7 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 25 Jan 2025 22:06:22 +0100 Subject: [PATCH 1096/1312] options.c: option --help should yield exit code 0 --help is supported and there is no reason to signal failure Change-Id: I59fda5336df47ec0b8172541a5fbfe60014bba7e Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8723 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/options.c b/src/helper/options.c index 50977a6106..735b8af5f6 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -334,7 +334,7 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) LOG_OUTPUT(" | -d\tset debug level to \n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file \n"); LOG_OUTPUT("--command | -c\trun \n"); - exit(-1); + exit(0); } if (version_flag) { From 5e4ad24ba610e81ee6e9358154ef176e15c36fe7 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 25 Jan 2025 21:04:05 +0100 Subject: [PATCH 1097/1312] configure.ac: show vdebug in the config summary Also enable this adapter by default (auto). Change-Id: Id011168b93c4cdc602ab78eabfb9a64ca8d8a7df Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8601 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 4b10aabd5d..fda0b2a360 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,8 @@ m4_define([SERIAL_PORT_ADAPTERS], m4_define([LINUXSPIDEV_ADAPTER], [[[linuxspidev], [Linux spidev driver], [LINUXSPIDEV]]]) +m4_define([VDEBUG_ADAPTER], + [[[vdebug], [Cadence Virtual Debug Interface], [VDEBUG]]]) # The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter # because there is an M4 macro called 'adapter'. @@ -302,6 +304,7 @@ AC_ARG_ADAPTERS([ LINUXSPIDEV_ADAPTER, SERIAL_PORT_ADAPTERS, DUMMY_ADAPTER, + VDEBUG_ADAPTER, PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) @@ -324,10 +327,6 @@ AC_ARG_ENABLE([jtag_vpi], AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]), [build_jtag_vpi=$enableval], [build_jtag_vpi=no]) -AC_ARG_ENABLE([vdebug], - AS_HELP_STRING([--enable-vdebug], [Enable building support for Cadence Virtual Debug Interface]), - [build_vdebug=$enableval], [build_vdebug=no]) - AC_ARG_ENABLE([jtag_dpi], AS_HELP_STRING([--enable-jtag_dpi], [Enable building support for JTAG DPI]), [build_jtag_dpi=$enableval], [build_jtag_dpi=no]) @@ -581,12 +580,6 @@ AS_IF([test "x$build_jtag_vpi" = "xyes"], [ AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.]) ]) -AS_IF([test "x$build_vdebug" = "xyes"], [ - AC_DEFINE([BUILD_VDEBUG], [1], [1 if you want Cadence vdebug interface.]) -], [ - AC_DEFINE([BUILD_VDEBUG], [0], [0 if you don't want Cadence vdebug interface.]) -]) - AS_IF([test "x$build_jtag_dpi" = "xyes"], [ AC_DEFINE([BUILD_JTAG_DPI], [1], [1 if you want JTAG DPI.]) ], [ @@ -738,6 +731,7 @@ PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], [internal error: validation should happen beforehand]) PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev]) +PROCESS_ADAPTERS([VDEBUG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -786,7 +780,6 @@ AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"]) AM_CONDITIONAL([AM335XGPIO], [test "x$build_am335xgpio" = "xyes"]) AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes"]) -AM_CONDITIONAL([VDEBUG], [test "x$build_vdebug" = "xyes"]) AM_CONDITIONAL([JTAG_DPI], [test "x$build_jtag_dpi" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"]) @@ -892,6 +885,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, LIBGPIOD_ADAPTERS, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, LINUXSPIDEV_ADAPTER, + VDEBUG_ADAPTER, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], From dcf02f46ff8355eb3f889aaa9d660f73dacede4f Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 25 Jan 2025 23:04:50 +0100 Subject: [PATCH 1098/1312] Makefile.am: DISTCHECK_CONFIGURE_FLAGS -> AM_DISTCHECK_CONFIGURE_FLAGS The Automake manual states: "The user can still extend or override the flags provided there by defining the DISTCHECK_CONFIGURE_FLAGS variable". Overriding variable DISTCHECK_CONFIGURE_FLAGS in Makefile.am makes it impossible for the user to do that. I discovered this when trying to pass --enable-internal-jimtcl to distcheck. Change-Id: Ibe5b1f23ccf3fbaa21c48b574a1b3f3e9f6fb916 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8724 Reviewed-by: Antonio Borneo Tested-by: jenkins --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 155a2b3bb7..271a2c1654 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = gnu 1.6 .DELETE_ON_ERROR: # make sure we pass the correct jimtcl flags to distcheck -DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim +AM_DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim # do not run Jim Tcl tests (esp. during distcheck) check-recursive: SUBDIRS := From 71f92c94468f370be80ce60dd76d5d924ddba69a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 28 Jan 2025 20:43:33 +0100 Subject: [PATCH 1099/1312] target/cortex_m: call adapter_deassert_reset() only if srst is configured Deasserting is useless if reset was not asserted except the very corner case: changed reset_config during reset processing. Change-Id: I1d1ea142980d67293daa348a2869b68ffd78d0eb Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8734 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/cortex_m.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 2cea203a29..9314d6675f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1849,10 +1849,12 @@ static int cortex_m_deassert_reset(struct target *target) target_state_name(target), target_was_examined(target) ? "" : " not"); + enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* deassert reset lines */ - adapter_deassert_reset(); + if (jtag_reset_config & RESET_HAS_SRST) + adapter_deassert_reset(); - enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_HAS_SRST) && !(jtag_reset_config & RESET_SRST_NO_GATING) && From ed4e58410446343a485625ee2722144cc23d55a6 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 3 Feb 2025 21:45:07 +0100 Subject: [PATCH 1100/1312] jtag/core: fix segfault when adapter driver has no reset method xlnx-pcie-xvc and linuxspidev adapter drivers does not implement the reset method. Although it is likely both adapters will implement the method in the near future, avoid segfault and return an error instead. Change-Id: If8ddf165dbc563cf6d64b2094968151075778ba7 Signed-off-by: Tomas Vanek Fixes: commit 8850eb8f2c51 ("swd: get rid of jtag queue to assert/deassert srst") Reviewed-on: https://review.openocd.org/c/openocd/+/8735 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/jtag/core.c b/src/jtag/core.c index 89d53aecb9..030c173be6 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -631,6 +631,13 @@ static int adapter_system_reset(int req_srst) /* Maybe change SRST signal state */ if (jtag_srst != req_srst) { + if (!adapter_driver->reset) { + if (req_srst) + LOG_ERROR("Adapter driver does not implement SRST handling"); + + return ERROR_NOT_IMPLEMENTED; + } + retval = adapter_driver->reset(0, req_srst); if (retval != ERROR_OK) { LOG_ERROR("SRST error"); From 1f3f635693a1ddc85f362dc324cb49c3e7b75f27 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 6 Feb 2025 11:48:30 +0100 Subject: [PATCH 1101/1312] build: drop space after 'angie' folder name The makefile consider the two white spaces between the end of the folder name and the '#' character for the beginning of the comment as part of the folder name. This cause 'make install' to create a folder named 'angie ' that is not welcome on all the OS. Drop the comment and the space after the folder name. Reported-by: Liviu Ionescu Change-Id: Iadd6803431edb83d0d84f4e4dc6d36b454f912ac Signed-off-by: Antonio Borneo Fixes: 0ed03df6e95b ("amend angie build definitions to fix make dist") Reviewed-on: https://review.openocd.org/c/openocd/+/8740 Reviewed-by: Liviu Ionescu Tested-by: jenkins Reviewed-by: Adrien Charruel --- src/jtag/drivers/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index ec233b2470..b0dd8e3ad1 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -125,7 +125,7 @@ dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex endif if ANGIE - angiedir = $(pkgdatadir)/angie # This is only for dist_angie_DATA. + angiedir = $(pkgdatadir)/angie DRIVERFILES += %D%/angie.c DRIVERFILES += %D%/angie/include/msgtypes.h EXTRA_DIST += %D%/angie/README From 583506730d00cd88d2b8741993fa604c43a71658 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Wed, 12 Feb 2025 20:54:00 +0300 Subject: [PATCH 1102/1312] target/adi_v5_swd: drop unused `swd_driver` in `swd_queue_dp_write()` `struct swd_driver swd` is only used in `swd_queue_dp_write()` in an assertion triggerring `-Wunused-variable` when compiled with `DNDEBUG`. Drop it. Change-Id: Id3283b9e2c36a74cda9fc4afc16da02ac4d62b69 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8754 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/adi_v5_swd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index dda1b0674a..e50f8f1371 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -502,9 +502,6 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { - const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - assert(swd); - int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; From 0d7d178ed4fe2e99de804412fde9bb11c872f10a Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Wed, 12 Feb 2025 21:12:30 +0300 Subject: [PATCH 1103/1312] flash/nor/rsl10: drop unused `rsl10_info` in `rsl10_protect_check()` `struct rsl10_info *chip` is only used in `rsl10_protect_check()` in an assertion triggerring `-Wunused-variable` when compiled with `DNDEBUG`. Drop it. Change-Id: Ib302aea742131479f04f32e8fe8a88a3230ae203 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8755 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/rsl10.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/flash/nor/rsl10.c b/src/flash/nor/rsl10.c index c286e9ac88..c33099787a 100644 --- a/src/flash/nor/rsl10.c +++ b/src/flash/nor/rsl10.c @@ -155,11 +155,6 @@ static int rsl10_get_probed_chip_if_halted(struct flash_bank *bank, struct rsl10 static int rsl10_protect_check(struct flash_bank *bank) { - struct rsl10_bank *nbank = bank->driver_priv; - struct rsl10_info *chip = nbank->chip; - - assert(chip); - uint32_t status; int retval = target_read_u32(bank->target, RSL10_FLASH_REG_IF_STATUS, &status); From f63b41bbe4ce33449ec18106620f57ba69ce7549 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 15 Feb 2025 08:11:02 +0100 Subject: [PATCH 1104/1312] drivers/linuxspidev: fix compilation on Linux older than 3.15 Although the commit [1] which introduced SPI_IOC_WR_MODE32 is 10 years old, some hardware may enforce old Linux because the vendor didn't bother with system updates. Change-Id: I76d0b38c8646b1be329418860916b9f01b90990d Link: [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/include/uapi/linux/spi/spidev.h?h=linux-3.15.y&id=dc64d39b54c1e9db97a6fb1ca52598c981728157 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8759 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/linuxspidev.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c index 6a149a977b..18abdc7db3 100644 --- a/src/jtag/drivers/linuxspidev.c +++ b/src/jtag/drivers/linuxspidev.c @@ -302,8 +302,20 @@ static int spidev_init(void) return ERROR_JTAG_INIT_FAILED; } + int ret; // Set SPI mode. - int ret = ioctl(spi_fd, SPI_IOC_WR_MODE32, &spi_mode); +#ifdef SPI_IOC_WR_MODE32 + ret = ioctl(spi_fd, SPI_IOC_WR_MODE32, &spi_mode); +#else + // Linux pre 3.15 does not support MODE32, use 8-bit ioctl + if (spi_mode & ~0xff) { + LOG_ERROR("SPI mode 0x%" PRIx32 ", system permits 8 bits only", spi_mode); + return ERROR_JTAG_INIT_FAILED; + } + + uint8_t mode = (uint8_t)spi_mode; + ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode); +#endif if (ret == -1) { LOG_ERROR("Failed to set SPI mode 0x%" PRIx32, spi_mode); return ERROR_JTAG_INIT_FAILED; From 297844cf46c7de5faa9de1c4a9f223b505dc3e9c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 10 Oct 2024 17:07:20 +0200 Subject: [PATCH 1105/1312] target: Use 'bool' data type in target_{step,resume} While at it, adapt data types of related functions and fix some coding style issues. Change-Id: I74db9258fc17b1ee8aa446f35ae722ea7c2f67e6 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8524 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/server/gdb_server.c | 22 ++++++++-------- src/target/aarch64.c | 26 +++++++++--------- src/target/arc.c | 26 +++++++++--------- src/target/arm11.c | 21 ++++++++------- src/target/arm7_9_common.c | 13 ++++----- src/target/arm7_9_common.h | 8 +++--- src/target/arm_semihosting.c | 4 +-- src/target/armv4_5.c | 2 +- src/target/armv7m.c | 2 +- src/target/avr32_ap7k.c | 10 +++---- src/target/avrt.c | 15 ++++++----- src/target/cortex_a.c | 29 ++++++++++---------- src/target/cortex_m.c | 23 ++++++++-------- src/target/dsp563xx.c | 24 ++++++++--------- src/target/dsp5680xx.c | 10 +++---- src/target/esirisc.c | 15 ++++++----- src/target/espressif/esp32.c | 3 ++- src/target/espressif/esp32_apptrace.c | 6 ++--- src/target/espressif/esp32s2.c | 5 ++-- src/target/espressif/esp32s3.c | 3 ++- src/target/espressif/esp_xtensa.c | 2 +- src/target/espressif/esp_xtensa_smp.c | 19 +++++++------- src/target/espressif/esp_xtensa_smp.h | 10 +++---- src/target/feroceon.c | 2 +- src/target/hla_target.c | 13 ++++----- src/target/lakemont.c | 10 +++---- src/target/lakemont.h | 8 +++--- src/target/ls1_sap.c | 8 +++--- src/target/mem_ap.c | 9 ++++--- src/target/mips32.c | 2 +- src/target/mips_m4k.c | 32 +++++++++++----------- src/target/mips_mips64.c | 14 +++++----- src/target/openrisc/or1k.c | 19 +++++++------- src/target/quark_d20xx.c | 2 +- src/target/riscv/riscv-011.c | 11 ++++---- src/target/riscv/riscv.c | 38 +++++++++++++-------------- src/target/riscv/riscv.h | 4 +-- src/target/stm8.c | 16 +++++------ src/target/target.c | 21 ++++++++------- src/target/target.h | 6 ++--- src/target/target_type.h | 8 +++--- src/target/xscale.c | 24 ++++++++--------- src/target/xtensa/xtensa.c | 25 ++++++++++-------- src/target/xtensa/xtensa.h | 18 +++++++------ 44 files changed, 303 insertions(+), 285 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index c572f392a9..1866de0b56 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -909,7 +909,7 @@ static void gdb_fileio_reply(struct target *target, struct connection *connectio /* encounter unknown syscall, continue */ gdb_connection->frontend_state = TARGET_RUNNING; - target_resume(target, 1, 0x0, 0, 0); + target_resume(target, true, 0x0, false, false); return; } @@ -919,7 +919,7 @@ static void gdb_fileio_reply(struct target *target, struct connection *connectio if (program_exited) { /* Use target_resume() to let target run its own exit syscall handler. */ gdb_connection->frontend_state = TARGET_RUNNING; - target_resume(target, 1, 0x0, 0, 0); + target_resume(target, true, 0x0, false, false); } else { gdb_connection->frontend_state = TARGET_HALTED; rtos_update_threads(target); @@ -1704,7 +1704,7 @@ static int gdb_step_continue_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); - int current = 0; + bool current = false; uint64_t address = 0x0; int retval = ERROR_OK; @@ -1713,17 +1713,17 @@ static int gdb_step_continue_packet(struct connection *connection, if (packet_size > 1) address = strtoull(packet + 1, NULL, 16); else - current = 1; + current = true; gdb_running_type = packet[0]; if (packet[0] == 'c') { LOG_DEBUG("continue"); /* resume at current address, don't handle breakpoints, not debugging */ - retval = target_resume(target, current, address, 0, 0); + retval = target_resume(target, current, address, false, false); } else if (packet[0] == 's') { LOG_DEBUG("step"); /* step at current or address, don't handle breakpoints */ - retval = target_step(target, current, address, 0); + retval = target_step(target, current, address, false); } return retval; } @@ -3003,7 +3003,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p gdb_running_type = 'c'; LOG_TARGET_DEBUG(target, "target continue"); gdb_connection->output_flag = GDB_OUTPUT_ALL; - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval == ERROR_TARGET_NOT_HALTED) LOG_TARGET_INFO(target, "target was not halted when resume was requested"); @@ -3031,7 +3031,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p bool fake_step = false; struct target *ct = target; - int current_pc = 1; + bool current_pc = true; int64_t thread_id; parse++; if (parse[0] == ':') { @@ -3129,7 +3129,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p return true; } - retval = target_step(ct, current_pc, 0, 0); + retval = target_step(ct, current_pc, 0, false); if (retval == ERROR_TARGET_NOT_HALTED) LOG_TARGET_INFO(ct, "target was not halted when step was requested"); @@ -3457,9 +3457,9 @@ static int gdb_fileio_response_packet(struct connection *connection, /* After File-I/O ends, keep continue or step */ if (gdb_running_type == 'c') - retval = target_resume(target, 1, 0x0, 0, 0); + retval = target_resume(target, true, 0x0, false, false); else if (gdb_running_type == 's') - retval = target_step(target, 1, 0x0, 0); + retval = target_step(target, true, 0x0, false); else retval = ERROR_FAIL; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 3cc8130054..609965ba55 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -589,8 +589,8 @@ static int aarch64_halt(struct target *target) return aarch64_halt_one(target, HALT_SYNC); } -static int aarch64_restore_one(struct target *target, int current, - uint64_t *address, int handle_breakpoints, int debug_execution) +static int aarch64_restore_one(struct target *target, bool current, + uint64_t *address, bool handle_breakpoints, bool debug_execution) { struct armv8_common *armv8 = target_to_armv8(target); struct arm *arm = &armv8->arm; @@ -602,7 +602,7 @@ static int aarch64_restore_one(struct target *target, int current, if (!debug_execution) target_free_all_working_areas(target); - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ resume_pc = buf_get_u64(arm->pc->value, 0, 64); if (!current) resume_pc = *address; @@ -753,7 +753,8 @@ static int aarch64_restart_one(struct target *target, enum restart_mode mode) /* * prepare all but the current target for restart */ -static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoints, struct target **p_first) +static int aarch64_prep_restart_smp(struct target *target, + bool handle_breakpoints, struct target **p_first) { int retval = ERROR_OK; struct target_list *head; @@ -772,7 +773,8 @@ static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoint continue; /* resume at current address, not in step mode */ - retval = aarch64_restore_one(curr, 1, &address, handle_breakpoints, 0); + retval = aarch64_restore_one(curr, true, &address, handle_breakpoints, + false); if (retval == ERROR_OK) retval = aarch64_prepare_restart_one(curr); if (retval != ERROR_OK) { @@ -799,7 +801,7 @@ static int aarch64_step_restart_smp(struct target *target) LOG_DEBUG("%s", target_name(target)); - retval = aarch64_prep_restart_smp(target, 0, &first); + retval = aarch64_prep_restart_smp(target, false, &first); if (retval != ERROR_OK) return retval; @@ -864,8 +866,8 @@ static int aarch64_step_restart_smp(struct target *target) return retval; } -static int aarch64_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int aarch64_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { int retval = 0; uint64_t addr = address; @@ -1113,8 +1115,8 @@ static int aarch64_post_debug_entry(struct target *target) /* * single-step a target */ -static int aarch64_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int aarch64_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct armv8_common *armv8 = target_to_armv8(target); struct aarch64_common *aarch64 = target_to_aarch64(target); @@ -1147,7 +1149,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres if (retval != ERROR_OK) return retval; - if (target->smp && (current == 1)) { + if (target->smp && current) { /* * isolate current target so that it doesn't get resumed * together with the others @@ -1164,7 +1166,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } /* all other targets running, restore and restart the current target */ - retval = aarch64_restore_one(target, current, &address, 0, 0); + retval = aarch64_restore_one(target, current, &address, false, false); if (retval == ERROR_OK) retval = aarch64_restart_one(target, RESTART_LAZY); diff --git a/src/target/arc.c b/src/target/arc.c index 0c111d553b..8757cafedc 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -1100,7 +1100,7 @@ static int arc_assert_reset(struct target *target) /* Resume the target and continue from the current * PC register value. */ LOG_TARGET_DEBUG(target, "Starting CPU execution after reset"); - CHECK_RETVAL(target_resume(target, 1, 0, 0, 0)); + CHECK_RETVAL(target_resume(target, true, 0, false, false)); } target->state = TARGET_RESET; @@ -1246,7 +1246,7 @@ static int arc_restore_context(struct target *target) return retval; } -static int arc_enable_interrupts(struct target *target, int enable) +static int arc_enable_interrupts(struct target *target, bool enable) { uint32_t value; @@ -1269,8 +1269,8 @@ static int arc_enable_interrupts(struct target *target, int enable) return ERROR_OK; } -static int arc_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int arc_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { struct arc_common *arc = target_to_arc(target); uint32_t resume_pc = 0; @@ -1297,7 +1297,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_enable_watchpoints(target)); } - /* current = 1: continue on current PC, otherwise continue at
*/ + /* current = true: continue on current PC, otherwise continue at
*/ if (!current) { target_buffer_set_u32(target, pc->value, address); pc->dirty = true; @@ -2030,7 +2030,7 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat /* Helper function which switches core to single_step mode by * doing aux r/w operations. */ -static int arc_config_step(struct target *target, int enable_step) +static int arc_config_step(struct target *target, bool enable_step) { uint32_t value; @@ -2071,10 +2071,10 @@ static int arc_single_step_core(struct target *target) CHECK_RETVAL(arc_debug_entry(target)); /* disable interrupts while stepping */ - CHECK_RETVAL(arc_enable_interrupts(target, 0)); + CHECK_RETVAL(arc_enable_interrupts(target, false)); /* configure single step mode */ - CHECK_RETVAL(arc_config_step(target, 1)); + CHECK_RETVAL(arc_config_step(target, true)); /* exit debug mode */ CHECK_RETVAL(arc_exit_debug(target)); @@ -2082,8 +2082,8 @@ static int arc_single_step_core(struct target *target) return ERROR_OK; } -static int arc_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int arc_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { /* get pointers to arch-specific information */ struct arc_common *arc = target_to_arc(target); @@ -2095,7 +2095,7 @@ static int arc_step(struct target *target, int current, target_addr_t address, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(pc->value, 0, 32, address); pc->dirty = true; @@ -2120,10 +2120,10 @@ static int arc_step(struct target *target, int current, target_addr_t address, CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); /* disable interrupts while stepping */ - CHECK_RETVAL(arc_enable_interrupts(target, 0)); + CHECK_RETVAL(arc_enable_interrupts(target, false)); /* do a single step */ - CHECK_RETVAL(arc_config_step(target, 1)); + CHECK_RETVAL(arc_config_step(target, true)); /* make sure we done our step */ alive_sleep(1); diff --git a/src/target/arm11.c b/src/target/arm11.c index c583a2ebd7..756b36b959 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -30,8 +30,8 @@ #endif -static int arm11_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints); +static int arm11_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints); /** Check and if necessary take control of the system @@ -401,7 +401,8 @@ static int arm11_halt(struct target *target) return ERROR_OK; } -static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address) +static uint32_t arm11_nextpc(struct arm11_common *arm11, bool current, + uint32_t address) { void *value = arm11->arm.pc->value; @@ -435,8 +436,8 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t a return address; } -static int arm11_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int arm11_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { /* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */ /* current, address, handle_breakpoints, debug_execution); */ @@ -469,7 +470,7 @@ static int arm11_resume(struct target *target, int current, for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->address == address) { LOG_DEBUG("must step over %08" TARGET_PRIxADDR "", bp->address); - arm11_step(target, 1, 0, 0); + arm11_step(target, true, 0, false); break; } } @@ -543,8 +544,8 @@ static int arm11_resume(struct target *target, int current, return ERROR_OK; } -static int arm11_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int arm11_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -569,13 +570,13 @@ static int arm11_step(struct target *target, int current, /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { - address = arm11_nextpc(arm11, 0, address + 4); + address = arm11_nextpc(arm11, false, address + 4); LOG_DEBUG("Skipping BKPT %08" TARGET_PRIxADDR, address); } /* skip over Wait for interrupt / Standby * mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { - address = arm11_nextpc(arm11, 0, address + 4); + address = arm11_nextpc(arm11, false, address + 4); LOG_DEBUG("Skipping WFI %08" TARGET_PRIxADDR, address); } /* ignore B to self */ diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index ad814e0541..5550fb1e24 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1697,10 +1697,10 @@ static void arm7_9_enable_breakpoints(struct target *target) } int arm7_9_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; @@ -1717,7 +1717,7 @@ int arm7_9_resume(struct target *target, if (!debug_execution) target_free_all_working_areas(target); - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); @@ -1900,7 +1900,8 @@ void arm7_9_disable_eice_step(struct target *target) embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]); } -int arm7_9_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +int arm7_9_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; @@ -1912,7 +1913,7 @@ int arm7_9_step(struct target *target, int current, target_addr_t address, int h return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 92d0fd51a2..c4a5b08d21 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -145,10 +145,10 @@ int arm7_9_early_halt(struct target *target); int arm7_9_soft_reset_halt(struct target *target); int arm7_9_halt(struct target *target); -int arm7_9_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); -int arm7_9_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints); +int arm7_9_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); +int arm7_9_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); int arm7_9_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm7_9_write_memory(struct target *target, target_addr_t address, diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index b557589407..a7c47bf417 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -50,7 +50,7 @@ static int arm_semihosting_resume(struct target *target, int *retval) if (is_armv8(target_to_armv8(target))) { struct armv8_common *armv8 = target_to_armv8(target); if (armv8->last_run_control_op == ARMV8_RUNCONTROL_RESUME) { - *retval = target_resume(target, 1, 0, 0, 0); + *retval = target_resume(target, true, 0, false, false); if (*retval != ERROR_OK) { LOG_ERROR("Failed to resume target"); return 0; @@ -58,7 +58,7 @@ static int arm_semihosting_resume(struct target *target, int *retval) } else if (armv8->last_run_control_op == ARMV8_RUNCONTROL_STEP) target->debug_reason = DBG_REASON_SINGLESTEP; } else { - *retval = target_resume(target, 1, 0, 0, 0); + *retval = target_resume(target, true, 0, false, false); if (*retval != ERROR_OK) { LOG_ERROR("Failed to resume target"); return 0; diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index a258c7fd45..597dc8990c 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1514,7 +1514,7 @@ int armv4_5_run_algorithm_inner(struct target *target, } } - retval = target_resume(target, 0, entry_point, 1, 1); + retval = target_resume(target, false, entry_point, true, true); if (retval != ERROR_OK) return retval; retval = run_it(target, exit_point, timeout_ms, arch_info); diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 440ca49d16..dc2d84fe15 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -642,7 +642,7 @@ int armv7m_start_algorithm(struct target *target, /* save previous core mode */ armv7m_algorithm_info->core_mode = core_mode; - retval = target_resume(target, 0, entry_point, 1, 1); + retval = target_resume(target, false, entry_point, true, true); return retval; } diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index bbbf236592..1b051dc014 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -300,8 +300,8 @@ static int avr32_ap7k_deassert_reset(struct target *target) return ERROR_OK; } -static int avr32_ap7k_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int avr32_ap7k_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct breakpoint *breakpoint = NULL; @@ -321,7 +321,7 @@ static int avr32_ap7k_resume(struct target *target, int current, */ } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { #if 0 if (retval != ERROR_OK) @@ -382,8 +382,8 @@ static int avr32_ap7k_resume(struct target *target, int current, return ERROR_OK; } -static int avr32_ap7k_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int avr32_ap7k_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_ERROR("%s: implement me", __func__); diff --git a/src/target/avrt.c b/src/target/avrt.c index 8886a46778..3afe320157 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -22,10 +22,10 @@ static int avr_init_target(struct command_context *cmd_ctx, struct target *targe static int avr_arch_state(struct target *target); static int avr_poll(struct target *target); static int avr_halt(struct target *target); -static int avr_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); -static int avr_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints); +static int avr_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); +static int avr_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); static int avr_assert_reset(struct target *target); static int avr_deassert_reset(struct target *target); @@ -105,14 +105,15 @@ static int avr_halt(struct target *target) return ERROR_OK; } -static int avr_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int avr_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int avr_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +static int avr_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index bfe6980518..b32fec270e 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -817,8 +817,8 @@ static int cortex_a_halt(struct target *target) return ERROR_OK; } -static int cortex_a_internal_restore(struct target *target, int current, - target_addr_t *address, int handle_breakpoints, int debug_execution) +static int cortex_a_internal_restore(struct target *target, bool current, + target_addr_t *address, bool handle_breakpoints, bool debug_execution) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; @@ -849,7 +849,7 @@ static int cortex_a_internal_restore(struct target *target, int current, } #endif - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ resume_pc = buf_get_u32(arm->pc->value, 0, 32); if (!current) resume_pc = *address; @@ -965,7 +965,7 @@ static int cortex_a_internal_restart(struct target *target) return ERROR_OK; } -static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) +static int cortex_a_restore_smp(struct target *target, bool handle_breakpoints) { int retval = 0; struct target_list *head; @@ -976,16 +976,16 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) { /* resume current address , not in step mode */ - retval += cortex_a_internal_restore(curr, 1, &address, - handle_breakpoints, 0); + retval += cortex_a_internal_restore(curr, true, &address, + handle_breakpoints, false); retval += cortex_a_internal_restart(curr); } } return retval; } -static int cortex_a_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int cortex_a_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { int retval = 0; /* dummy resume for smp toggle in order to reduce gdb impact */ @@ -997,7 +997,8 @@ static int cortex_a_resume(struct target *target, int current, target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return 0; } - cortex_a_internal_restore(target, current, &address, handle_breakpoints, debug_execution); + cortex_a_internal_restore(target, current, &address, handle_breakpoints, + debug_execution); if (target->smp) { target->gdb_service->core[0] = -1; retval = cortex_a_restore_smp(target, handle_breakpoints); @@ -1168,8 +1169,8 @@ static int cortex_a_set_dscr_bits(struct target *target, return retval; } -static int cortex_a_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int cortex_a_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); @@ -1184,7 +1185,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ r = arm->pc; if (!current) buf_set_u32(r->value, 0, 32, address); @@ -1195,7 +1196,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre * But since Cortex-A uses breakpoint for single step, * we MUST handle breakpoints. */ - handle_breakpoints = 1; + handle_breakpoints = true; if (handle_breakpoints) { breakpoint = breakpoint_find(target, address); if (breakpoint) @@ -1222,7 +1223,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre target->debug_reason = DBG_REASON_SINGLESTEP; - retval = cortex_a_resume(target, 1, address, 0, 0); + retval = cortex_a_resume(target, true, address, false, false); if (retval != ERROR_OK) return retval; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 9314d6675f..e17f23c1d3 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1359,7 +1359,7 @@ static int cortex_m_restore_one(struct target *target, bool current, r->valid = true; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ r = armv7m->arm.pc; if (!current) { buf_set_u32(r->value, 0, 32, *address); @@ -1444,7 +1444,7 @@ static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints) continue; int retval = cortex_m_restore_one(curr, true, &address, - handle_breakpoints, false); + handle_breakpoints, false); if (retval != ERROR_OK) return retval; @@ -1457,22 +1457,23 @@ static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints) return ERROR_OK; } -static int cortex_m_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int cortex_m_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { - int retval = cortex_m_restore_one(target, !!current, &address, !!handle_breakpoints, !!debug_execution); + int retval = cortex_m_restore_one(target, current, &address, + handle_breakpoints, debug_execution); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "context restore failed, aborting resume"); return retval; } if (target->smp && !debug_execution) { - retval = cortex_m_restore_smp(target, !!handle_breakpoints); + retval = cortex_m_restore_smp(target, handle_breakpoints); if (retval != ERROR_OK) LOG_TARGET_WARNING(target, "resume of a SMP target failed, trying to resume current one"); } - cortex_m_restart_one(target, !!debug_execution); + cortex_m_restart_one(target, debug_execution); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "resume failed"); return retval; @@ -1485,8 +1486,8 @@ static int cortex_m_resume(struct target *target, int current, } /* int irqstepcount = 0; */ -static int cortex_m_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int cortex_m_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; @@ -1506,7 +1507,7 @@ static int cortex_m_step(struct target *target, int current, if (target->smp && target->gdb_service) target->gdb_service->target = target; - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(pc->value, 0, 32, address); pc->dirty = true; @@ -2316,7 +2317,7 @@ int cortex_m_profiling(struct target *target, uint32_t *samples, /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "Error while resuming target"); diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 953888de3d..9b6f4756c9 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -1115,10 +1115,10 @@ static int dsp563xx_halt(struct target *target) } static int dsp563xx_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); @@ -1132,7 +1132,7 @@ static int dsp563xx_resume(struct target *target, if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) { dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC); address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC]; - current = 0; + current = false; } LOG_DEBUG("%s %08X %08" TARGET_PRIXADDR, __func__, current, address); @@ -1172,9 +1172,9 @@ static int dsp563xx_resume(struct target *target, } static int dsp563xx_step_ex(struct target *target, - int current, + bool current, uint32_t address, - int handle_breakpoints, + bool handle_breakpoints, int steps) { int err; @@ -1196,7 +1196,7 @@ static int dsp563xx_step_ex(struct target *target, if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) { dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC); address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC]; - current = 0; + current = false; } LOG_DEBUG("%s %08X %08" PRIX32, __func__, current, address); @@ -1288,9 +1288,9 @@ static int dsp563xx_step_ex(struct target *target, } static int dsp563xx_step(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints) + bool handle_breakpoints) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); @@ -1359,7 +1359,7 @@ static int dsp563xx_deassert_reset(struct target *target) * reset vector and need 2 cycles to fill * the cache (fetch,decode,execute) */ - err = dsp563xx_step_ex(target, 1, 0, 1, 1); + err = dsp563xx_step_ex(target, true, 0, true, 1); if (err != ERROR_OK) return err; } @@ -1419,7 +1419,7 @@ static int dsp563xx_run_algorithm(struct target *target, } /* exec */ - retval = target_resume(target, 0, entry_point, 1, 1); + retval = target_resume(target, false, entry_point, true, true); if (retval != ERROR_OK) return retval; @@ -1972,7 +1972,7 @@ static int dsp563xx_add_custom_watchpoint(struct target *target, uint32_t addres if (err == ERROR_OK && was_running) { /* Resume from current PC */ - err = dsp563xx_resume(target, 1, 0x0, 0, 0); + err = dsp563xx_resume(target, true, 0x0, false, false); } return err; diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index b370aafa46..3f9a6742c4 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -993,8 +993,8 @@ static int dsp5680xx_poll(struct target *target) return ERROR_OK; } -static int dsp5680xx_resume(struct target *target, int current, - target_addr_t address, int hb, int d) +static int dsp5680xx_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { if (target->state == TARGET_RUNNING) { LOG_USER("Target already running."); @@ -2048,7 +2048,7 @@ int dsp5680xx_f_wr(struct target *t, const uint8_t *b, uint32_t a, uint32_t coun retval = core_tx_upper_data(target, tmp, &drscan_data); err_check_propagate(retval); - retval = dsp5680xx_resume(target, 0, ram_addr, 0, 0); + retval = dsp5680xx_resume(target, false, ram_addr, false, false); err_check_propagate(retval); int counter = FLUSH_COUNT_FLASH; @@ -2234,8 +2234,8 @@ int dsp5680xx_f_lock(struct target *target) return retval; } -static int dsp5680xx_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int dsp5680xx_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP, "Not implemented yet."); diff --git a/src/target/esirisc.c b/src/target/esirisc.c index fc2d20105a..da40928da9 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -846,8 +846,9 @@ static int esirisc_enable_step(struct target *target) return ERROR_OK; } -static int esirisc_resume_or_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution, bool step) +static int esirisc_resume_or_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution, + bool step) { struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; @@ -917,8 +918,8 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add return ERROR_OK; } -static int esirisc_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int esirisc_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { LOG_TARGET_DEBUG(target, "-"); @@ -926,13 +927,13 @@ static int esirisc_resume(struct target *target, int current, target_addr_t addr handle_breakpoints, debug_execution, false); } -static int esirisc_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int esirisc_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_TARGET_DEBUG(target, "-"); return esirisc_resume_or_step(target, current, address, - handle_breakpoints, 0, true); + handle_breakpoints, false, true); } static int esirisc_debug_step(struct target *target) diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 324aa3993b..4deb5e0709 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -175,7 +175,8 @@ static int esp32_soc_reset(struct target *target) LOG_DEBUG("Resuming the target"); xtensa = target_to_xtensa(target); xtensa->suppress_dsr_errors = true; - res = xtensa_resume(target, 0, ESP32_RTC_SLOW_MEM_BASE + 4, 0, 0); + res = xtensa_resume(target, false, ESP32_RTC_SLOW_MEM_BASE + 4, false, + false); xtensa->suppress_dsr_errors = false; if (res != ERROR_OK) { LOG_ERROR("Failed to run stub (%d)!", res); diff --git a/src/target/espressif/esp32_apptrace.c b/src/target/espressif/esp32_apptrace.c index 125f366329..3202fd3d64 100644 --- a/src/target/espressif/esp32_apptrace.c +++ b/src/target/espressif/esp32_apptrace.c @@ -708,7 +708,7 @@ int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx, } while (stat) { /* allow this CPU to leave ERI write critical section */ - res = target_resume(ctx->cpus[k], 1, 0, 1, 0); + res = target_resume(ctx->cpus[k], true, 0, true, false); if (res != ERROR_OK) { LOG_ERROR("Failed to resume target (%d)!", res); breakpoint_remove(ctx->cpus[k], bp_addr); @@ -796,7 +796,7 @@ static int esp32_apptrace_connect_targets(struct esp32_apptrace_cmd_ctx *ctx, /* in SMP mode we need to call target_resume for one core only */ continue; } - res = target_resume(ctx->cpus[k], 1, 0, 1, 0); + res = target_resume(ctx->cpus[k], true, 0, true, false); if (res != ERROR_OK) { command_print(ctx->cmd, "Failed to resume target (%d)!", res); return res; @@ -1352,7 +1352,7 @@ static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx) /* in SMP mode we need to call target_resume for one core only */ continue; } - res = target_resume(ctx->cpus[k], 1, 0, 1, 0); + res = target_resume(ctx->cpus[k], true, 0, true, false); if (res != ERROR_OK) { LOG_ERROR("sysview: Failed to resume target '%s' (%d)!", target_name(ctx->cpus[k]), res); return res; diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index 2abde479ea..4f3914f66a 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -370,7 +370,8 @@ static int esp32s2_on_halt(struct target *target) return ret; } -static int esp32s2_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +static int esp32s2_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { int ret = xtensa_step(target, current, address, handle_breakpoints); if (ret == ERROR_OK) { @@ -397,7 +398,7 @@ static int esp32s2_poll(struct target *target) if (ret == ERROR_OK && esp_xtensa->semihost.need_resume) { esp_xtensa->semihost.need_resume = false; /* Resume xtensa_resume will handle BREAK instruction. */ - ret = target_resume(target, 1, 0, 1, 0); + ret = target_resume(target, true, 0, true, false); if (ret != ERROR_OK) { LOG_ERROR("Failed to resume target"); return ret; diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 2afb4b009e..7507c11c24 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -175,7 +175,8 @@ static int esp32s3_soc_reset(struct target *target) LOG_DEBUG("Resuming the target"); xtensa = target_to_xtensa(target); xtensa->suppress_dsr_errors = true; - res = xtensa_resume(target, 0, ESP32_S3_RTC_SLOW_MEM_BASE + 4, 0, 0); + res = xtensa_resume(target, false, ESP32_S3_RTC_SLOW_MEM_BASE + 4, false, + false); xtensa->suppress_dsr_errors = false; if (res != ERROR_OK) { LOG_ERROR("Failed to run stub (%d)!", res); diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index 9b57f345e4..4cadcb3301 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -213,7 +213,7 @@ int esp_xtensa_profiling(struct target *target, uint32_t *samples, /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "Error while resuming target"); diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c index c49146d787..b9e2156440 100644 --- a/src/target/espressif/esp_xtensa_smp.c +++ b/src/target/espressif/esp_xtensa_smp.c @@ -218,7 +218,7 @@ int esp_xtensa_smp_poll(struct target *target) !esp_xtensa_smp->other_core_does_resume) { esp_xtensa->semihost.need_resume = false; /* Resume xtensa_resume will handle BREAK instruction. */ - ret = target_resume(target, 1, 0, 1, 0); + ret = target_resume(target, true, 0, true, false); if (ret != ERROR_OK) { LOG_ERROR("Failed to resume target"); return ret; @@ -229,7 +229,7 @@ int esp_xtensa_smp_poll(struct target *target) /* check whether any core polled by esp_xtensa_smp_update_halt_gdb() requested resume */ if (target->smp && other_core_resume_req) { /* Resume xtensa_resume will handle BREAK instruction. */ - ret = target_resume(target, 1, 0, 1, 0); + ret = target_resume(target, true, 0, true, false); if (ret != ERROR_OK) { LOG_ERROR("Failed to resume target"); return ret; @@ -334,8 +334,7 @@ static inline int esp_xtensa_smp_smpbreak_restore(struct target *target, uint32_ } static int esp_xtensa_smp_resume_cores(struct target *target, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, bool debug_execution) { struct target_list *head; struct target *curr; @@ -348,7 +347,7 @@ static int esp_xtensa_smp_resume_cores(struct target *target, if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) { /* resume current address, not in SMP mode */ curr->smp = 0; - int res = esp_xtensa_smp_resume(curr, 1, 0, handle_breakpoints, debug_execution); + int res = esp_xtensa_smp_resume(curr, true, 0, handle_breakpoints, debug_execution); curr->smp = 1; if (res != ERROR_OK) return res; @@ -358,10 +357,10 @@ static int esp_xtensa_smp_resume_cores(struct target *target, } int esp_xtensa_smp_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { int res; uint32_t smp_break; @@ -420,9 +419,9 @@ int esp_xtensa_smp_resume(struct target *target, } int esp_xtensa_smp_step(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints) + bool handle_breakpoints) { int res; uint32_t smp_break = 0; diff --git a/src/target/espressif/esp_xtensa_smp.h b/src/target/espressif/esp_xtensa_smp.h index 39afd8af10..ec074c11ce 100644 --- a/src/target/espressif/esp_xtensa_smp.h +++ b/src/target/espressif/esp_xtensa_smp.h @@ -27,14 +27,14 @@ struct esp_xtensa_smp_common { int esp_xtensa_smp_poll(struct target *target); int esp_xtensa_smp_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution); + bool handle_breakpoints, + bool debug_execution); int esp_xtensa_smp_step(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints); + bool handle_breakpoints); int esp_xtensa_smp_assert_reset(struct target *target); int esp_xtensa_smp_deassert_reset(struct target *target); int esp_xtensa_smp_soft_reset_halt(struct target *target); diff --git a/src/target/feroceon.c b/src/target/feroceon.c index 1e7eb0961f..840ca1b62b 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -526,7 +526,7 @@ static int feroceon_bulk_write_memory(struct target *target, arm->core_state = ARM_STATE_ARM; embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0); - arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1); + arm7_9_resume(target, false, arm7_9->dcc_working_area->address, true, true); /* send data over */ x = 0; diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 6b0d2e95e8..ef05df2027 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -406,7 +406,8 @@ static int hl_deassert_reset(struct target *target) target->SAVED_DCRDR = 0; /* clear both DCC busy bits on initial resume */ - return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0); + return target->reset_halt ? ERROR_OK : target_resume(target, true, 0, false, + false); } static int adapter_halt(struct target *target) @@ -434,9 +435,9 @@ static int adapter_halt(struct target *target) return ERROR_OK; } -static int adapter_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution) +static int adapter_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { int res; struct hl_interface *adapter = target_to_adapter(target); @@ -525,8 +526,8 @@ static int adapter_resume(struct target *target, int current, return ERROR_OK; } -static int adapter_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int adapter_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { int res; struct hl_interface *adapter = target_to_adapter(target); diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 0340d0d0b1..39a50c7a69 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -988,8 +988,8 @@ int lakemont_halt(struct target *t) } } -int lakemont_resume(struct target *t, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +int lakemont_resume(struct target *t, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { struct breakpoint *bp = NULL; struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -1004,7 +1004,7 @@ int lakemont_resume(struct target *t, int current, target_addr_t address, bp = breakpoint_find(t, eip); if (bp /*&& bp->type == BKPT_SOFT*/) { /* the step will step over the breakpoint */ - if (lakemont_step(t, 0, 0, 1) != ERROR_OK) { + if (lakemont_step(t, false, 0, true) != ERROR_OK) { LOG_ERROR("%s stepping over a software breakpoint at 0x%08" PRIx32 " " "failed to resume the target", __func__, eip); return ERROR_FAIL; @@ -1029,8 +1029,8 @@ int lakemont_resume(struct target *t, int current, target_addr_t address, return ERROR_OK; } -int lakemont_step(struct target *t, int current, - target_addr_t address, int handle_breakpoints) +int lakemont_step(struct target *t, bool current, target_addr_t address, + bool handle_breakpoints) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); diff --git a/src/target/lakemont.h b/src/target/lakemont.h index ca6557fcde..4c84f74aee 100644 --- a/src/target/lakemont.h +++ b/src/target/lakemont.h @@ -84,10 +84,10 @@ int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32); int lakemont_poll(struct target *t); int lakemont_arch_state(struct target *t); int lakemont_halt(struct target *t); -int lakemont_resume(struct target *t, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); -int lakemont_step(struct target *t, int current, - target_addr_t address, int handle_breakpoints); +int lakemont_resume(struct target *t, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); +int lakemont_step(struct target *t, bool current, + target_addr_t address, bool handle_breakpoints); int lakemont_reset_assert(struct target *t); int lakemont_reset_deassert(struct target *t); int lakemont_update_after_probemode_entry(struct target *t); diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c index 9bd00c0e5f..692f4cc9e4 100644 --- a/src/target/ls1_sap.c +++ b/src/target/ls1_sap.c @@ -55,15 +55,15 @@ static int ls1_sap_halt(struct target *target) return ERROR_OK; } -static int ls1_sap_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int ls1_sap_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int ls1_sap_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int ls1_sap_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 5b2bbb1ae0..fdc52c3071 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -102,8 +102,9 @@ static int mem_ap_halt(struct target *target) return ERROR_OK; } -static int mem_ap_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int mem_ap_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_RUNNING; @@ -111,8 +112,8 @@ static int mem_ap_resume(struct target *target, int current, target_addr_t addre return ERROR_OK; } -static int mem_ap_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int mem_ap_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_HALTED; diff --git a/src/target/mips32.c b/src/target/mips32.c index fcb7042cb1..4527c5fa88 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -588,7 +588,7 @@ static int mips32_run_and_wait(struct target *target, target_addr_t entry_point, int retval; /* This code relies on the target specific resume() and poll()->debug_entry() * sequence to write register values to the processor and the read them back */ - retval = target_resume(target, 0, entry_point, 0, 1); + retval = target_resume(target, false, entry_point, false, true); if (retval != ERROR_OK) return retval; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 1543de355e..dc74501086 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -30,9 +30,9 @@ static int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint); static int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); -static int mips_m4k_internal_restore(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution); +static int mips_m4k_internal_restore(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution); static int mips_m4k_halt(struct target *target); static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); @@ -398,7 +398,8 @@ static int mips_m4k_single_step_core(struct target *target) return ERROR_OK; } -static int mips_m4k_restore_smp(struct target *target, uint32_t address, int handle_breakpoints) +static int mips_m4k_restore_smp(struct target *target, uint32_t address, + bool handle_breakpoints) { int retval = ERROR_OK; struct target_list *head; @@ -408,8 +409,8 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han struct target *curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING)) { /* resume current address , not in step mode */ - ret = mips_m4k_internal_restore(curr, 1, address, - handle_breakpoints, 0); + ret = mips_m4k_internal_restore(curr, true, address, + handle_breakpoints, false); if (ret != ERROR_OK) { LOG_TARGET_ERROR(curr, "failed to resume at address: 0x%" PRIx32, @@ -421,8 +422,9 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han return retval; } -static int mips_m4k_internal_restore(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int mips_m4k_internal_restore(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; @@ -440,7 +442,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, mips_m4k_enable_watchpoints(target); } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address); @@ -448,7 +450,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true; } - if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */ + if (mips32->isa_imp > 1 && debug_execution) /* if more than one isa supported */ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1, mips32->isa_mode); if (!current) @@ -494,8 +496,8 @@ static int mips_m4k_internal_restore(struct target *target, int current, return ERROR_OK; } -static int mips_m4k_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int mips_m4k_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { int retval = ERROR_OK; @@ -521,8 +523,8 @@ static int mips_m4k_resume(struct target *target, int current, return retval; } -static int mips_m4k_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int mips_m4k_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); @@ -534,7 +536,7 @@ static int mips_m4k_step(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address); diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c index 9921e93807..85e3779375 100644 --- a/src/target/mips_mips64.c +++ b/src/target/mips_mips64.c @@ -592,9 +592,9 @@ static int mips_mips64_unset_breakpoint(struct target *target, return ERROR_OK; } -static int mips_mips64_resume(struct target *target, int current, - uint64_t address, int handle_breakpoints, - int debug_execution) +static int mips_mips64_resume(struct target *target, bool current, + uint64_t address, bool handle_breakpoints, + bool debug_execution) { struct mips64_common *mips64 = target->arch_info; struct mips_ejtag *ejtag_info = &mips64->ejtag_info; @@ -622,7 +622,7 @@ static int mips_mips64_resume(struct target *target, int current, } pc = &mips64->core_cache->reg_list[MIPS64_PC]; - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u64(pc->value, 0, 64, address); pc->dirty = true; @@ -696,8 +696,8 @@ static int mips_mips64_resume(struct target *target, int current, return ERROR_OK; } -static int mips_mips64_step(struct target *target, int current, - uint64_t address, int handle_breakpoints) +static int mips_mips64_step(struct target *target, bool current, + uint64_t address, bool handle_breakpoints) { struct mips64_common *mips64 = target->arch_info; struct mips_ejtag *ejtag_info = &mips64->ejtag_info; @@ -713,7 +713,7 @@ static int mips_mips64_step(struct target *target, int current, if (mips64->mips64mode32) address = mips64_extend_sign(address); - /* current = 1: continue on current pc, otherwise continue at + /* current = true: continue on current pc, otherwise continue at *
*/ if (!current) { buf_set_u64(pc->value, 0, 64, address); diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index efc076c999..4b9d3bca68 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -775,9 +775,9 @@ static bool is_any_soft_breakpoint(struct target *target) return false; } -static int or1k_resume_or_step(struct target *target, int current, - uint32_t address, int handle_breakpoints, - int debug_execution, int step) +static int or1k_resume_or_step(struct target *target, bool current, + uint32_t address, bool handle_breakpoints, bool debug_execution, + int step) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); @@ -885,9 +885,8 @@ static int or1k_resume_or_step(struct target *target, int current, return ERROR_OK; } -static int or1k_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution) +static int or1k_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { return or1k_resume_or_step(target, current, address, handle_breakpoints, @@ -895,12 +894,12 @@ static int or1k_resume(struct target *target, int current, NO_SINGLE_STEP); } -static int or1k_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int or1k_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { return or1k_resume_or_step(target, current, address, handle_breakpoints, - 0, + false, SINGLE_STEP); } @@ -1216,7 +1215,7 @@ static int or1k_profiling(struct target *target, uint32_t *samples, /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { LOG_ERROR("Error while resuming target"); diff --git a/src/target/quark_d20xx.c b/src/target/quark_d20xx.c index d63a42a6c0..90cf6670ec 100644 --- a/src/target/quark_d20xx.c +++ b/src/target/quark_d20xx.c @@ -65,7 +65,7 @@ static int quark_d20xx_reset_deassert(struct target *t) } /* resume target if reset mode is run */ if (!t->reset_halt) { - retval = lakemont_resume(t, 1, 0, 0, 0); + retval = lakemont_resume(t, true, 0, false, false); if (retval != ERROR_OK) { LOG_ERROR("%s could not resume target", __func__); return retval; diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 302ace8698..f4a7d0e5ca 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -1192,7 +1192,7 @@ static int full_step(struct target *target, bool announce) return ERROR_OK; } -static int resume(struct target *target, int debug_execution, bool step) +static int resume(struct target *target, bool debug_execution, bool step) { if (debug_execution) { LOG_ERROR("TODO: debug_execution is true"); @@ -1439,8 +1439,8 @@ static int strict_step(struct target *target, bool announce) return ERROR_OK; } -static int step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); @@ -1929,8 +1929,9 @@ static int riscv011_poll(struct target *target) return poll_target(target, true); } -static int riscv011_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int riscv011_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { RISCV_INFO(r); jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 99f40a7393..6a8577f5cb 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1096,16 +1096,15 @@ static int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_w return ERROR_FAIL; } - -static int oldriscv_step(struct target *target, int current, uint32_t address, - int handle_breakpoints) +static int oldriscv_step(struct target *target, bool current, uint32_t address, + bool handle_breakpoints) { struct target_type *tt = get_target_type(target); return tt->step(target, current, address, handle_breakpoints); } -static int old_or_new_riscv_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int old_or_new_riscv_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { RISCV_INFO(r); LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints); @@ -1115,7 +1114,6 @@ static int old_or_new_riscv_step(struct target *target, int current, return riscv_openocd_step(target, current, address, handle_breakpoints); } - static int riscv_examine(struct target *target) { LOG_DEBUG("riscv_examine()"); @@ -1395,8 +1393,8 @@ static int enable_triggers(struct target *target, riscv_reg_t *state) /** * Get everything ready to resume. */ -static int resume_prep(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int resume_prep(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { RISCV_INFO(r); LOG_DEBUG("[%d]", target->coreid); @@ -1434,8 +1432,8 @@ static int resume_prep(struct target *target, int current, * Resume all the harts that have been prepped, as close to instantaneous as * possible. */ -static int resume_go(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int resume_go(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { RISCV_INFO(r); int result; @@ -1465,10 +1463,10 @@ static int resume_finish(struct target *target) */ static int riscv_resume( struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution, + bool handle_breakpoints, + bool debug_execution, bool single_hart) { LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints); @@ -1515,8 +1513,8 @@ static int riscv_resume( return result; } -static int riscv_target_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int riscv_target_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { return riscv_resume(target, current, address, handle_breakpoints, debug_execution, false); @@ -1904,7 +1902,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, /* Run algorithm */ LOG_DEBUG("resume at 0x%" TARGET_PRIxADDR, entry_point); - if (riscv_resume(target, 0, entry_point, 0, 0, true) != ERROR_OK) + if (riscv_resume(target, false, entry_point, false, false, true) != ERROR_OK) return ERROR_FAIL; int64_t start = timeval_ms(); @@ -2245,7 +2243,7 @@ int riscv_openocd_poll(struct target *target) riscv_halt(target); } else if (should_resume) { LOG_DEBUG("resume all"); - riscv_resume(target, true, 0, 0, 0, false); + riscv_resume(target, true, 0, false, false, false); } /* Sample memory if any target is running. */ @@ -2287,7 +2285,7 @@ int riscv_openocd_poll(struct target *target) target_call_event_callbacks(target, TARGET_EVENT_HALTED); break; case SEMIHOSTING_HANDLED: - if (riscv_resume(target, true, 0, 0, 0, false) != ERROR_OK) + if (riscv_resume(target, true, 0, false, false, false) != ERROR_OK) return ERROR_FAIL; break; case SEMIHOSTING_ERROR: @@ -2300,8 +2298,8 @@ int riscv_openocd_poll(struct target *target) return ERROR_OK; } -int riscv_openocd_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +int riscv_openocd_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("stepping rtos hart"); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 6cb2709de8..f06b5f516d 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -294,9 +294,9 @@ int riscv_halt(struct target *target); int riscv_openocd_step( struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints + bool handle_breakpoints ); int riscv_openocd_assert_reset(struct target *target); diff --git a/src/target/stm8.c b/src/target/stm8.c index fb5c81f061..76482e8789 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -980,9 +980,9 @@ static int stm8_single_step_core(struct target *target) return ERROR_OK; } -static int stm8_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution) +static int stm8_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { struct stm8_common *stm8 = target_to_stm8(target); struct breakpoint *breakpoint = NULL; @@ -1004,7 +1004,7 @@ static int stm8_resume(struct target *target, int current, stm8_set_hwbreak(target, comparator_list); } - /* current = 1: continue on current pc, + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(stm8->core_cache->reg_list[STM8_PC].value, @@ -1290,8 +1290,8 @@ static int stm8_arch_state(struct target *target) return ERROR_OK; } -static int stm8_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int stm8_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("%x " TARGET_ADDR_FMT " %x", current, address, handle_breakpoints); @@ -1305,7 +1305,7 @@ static int stm8_step(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(stm8->core_cache->reg_list[STM8_PC].value, 0, 32, address); stm8->core_cache->reg_list[STM8_PC].dirty = true; @@ -1789,7 +1789,7 @@ static int stm8_run_and_wait(struct target *target, uint32_t entry_point, /* This code relies on the target specific resume() and poll()->debug_entry() sequence to write register values to the processor and the read them back */ - retval = target_resume(target, 0, entry_point, 0, 1); + retval = target_resume(target, false, entry_point, false, true); if (retval != ERROR_OK) return retval; diff --git a/src/target/target.c b/src/target/target.c index 8deab8f34d..9c5a33d3d2 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -553,8 +553,8 @@ int target_halt(struct target *target) * hand the infrastructure for running such helpers might use this * procedure but rely on hardware breakpoint to detect termination.) */ -int target_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +int target_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { int retval; @@ -579,7 +579,8 @@ int target_resume(struct target *target, int current, target_addr_t address, * in the correct order. */ bool save_poll_mask = jtag_poll_mask(); - retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); + retval = target->type->resume(target, current, address, handle_breakpoints, + debug_execution); jtag_poll_unmask(save_poll_mask); if (retval != ERROR_OK) @@ -1408,7 +1409,7 @@ bool target_supports_gdb_connection(const struct target *target) } int target_step(struct target *target, - int current, target_addr_t address, int handle_breakpoints) + bool current, target_addr_t address, bool handle_breakpoints) { int retval; @@ -2309,7 +2310,7 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t t = buf_get_u32(reg->value, 0, 32); samples[sample_count++] = t; /* current pc, addr = 0, do not handle breakpoints, not debugging */ - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); target_poll(target); alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */ } else if (target->state == TARGET_RUNNING) { @@ -3303,7 +3304,7 @@ COMMAND_HANDLER(handle_reset_command) COMMAND_HANDLER(handle_resume_command) { - int current = 1; + bool current = true; if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -3315,10 +3316,10 @@ COMMAND_HANDLER(handle_resume_command) target_addr_t addr = 0; if (CMD_ARGC == 1) { COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - current = 0; + current = false; } - return target_resume(target, current, addr, 1, 0); + return target_resume(target, current, addr, true, false); } COMMAND_HANDLER(handle_step_command) @@ -3340,7 +3341,7 @@ COMMAND_HANDLER(handle_step_command) struct target *target = get_current_target(CMD_CTX); - return target_step(target, current_pc, addr, 1); + return target_step(target, current_pc, addr, true); } void target_handle_md_output(struct command_invocation *cmd, @@ -4379,7 +4380,7 @@ COMMAND_HANDLER(handle_profile_command) } else if (target->state == TARGET_HALTED && !halted_before_profiling) { /* The target was running before we started and is halted now. Resume * it, for consistency. */ - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { free(samples); return retval; diff --git a/src/target/target.h b/src/target/target.h index abd0b58255..47f02ec266 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -386,8 +386,8 @@ int target_unregister_trace_callback( * yet it is possible to detect error conditions. */ int target_poll(struct target *target); -int target_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); +int target_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); int target_halt(struct target *target); int target_call_event_callbacks(struct target *target, enum target_event event); int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode); @@ -536,7 +536,7 @@ bool target_supports_gdb_connection(const struct target *target); * This routine is a wrapper for target->type->step. */ int target_step(struct target *target, - int current, target_addr_t address, int handle_breakpoints); + bool current, target_addr_t address, bool handle_breakpoints); /** * Run an algorithm on the @a target given. * diff --git a/src/target/target_type.h b/src/target/target_type.h index f35a59c5fe..ce98cbad27 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -42,10 +42,10 @@ struct target_type { /* halt will log a warning, but return ERROR_OK if the target is already halted. */ int (*halt)(struct target *target); /* See target.c target_resume() for documentation. */ - int (*resume)(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); - int (*step)(struct target *target, int current, target_addr_t address, - int handle_breakpoints); + int (*resume)(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); + int (*step)(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); /* target reset control. assert reset can be invoked when OpenOCD and * the target is out of sync. * diff --git a/src/target/xscale.c b/src/target/xscale.c index 83afd5de23..5cc790a311 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -47,8 +47,8 @@ */ /* forward declarations */ -static int xscale_resume(struct target *, int current, - target_addr_t address, int handle_breakpoints, int debug_execution); +static int xscale_resume(struct target *, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution); static int xscale_debug_entry(struct target *); static int xscale_restore_banked(struct target *); static int xscale_get_reg(struct reg *reg); @@ -997,7 +997,7 @@ static int xscale_debug_entry(struct target *target) * can only happen in fill mode. */ if (xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL) { if (--xscale->trace.fill_counter > 0) - xscale_resume(target, 1, 0x0, 1, 0); + xscale_resume(target, true, 0x0, true, false); } else /* entered debug for other reason; reset counter */ xscale->trace.fill_counter = 0; } @@ -1106,8 +1106,8 @@ static void xscale_free_trace_data(struct xscale_common *xscale) xscale->trace.data = NULL; } -static int xscale_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int xscale_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; @@ -1130,7 +1130,7 @@ static int xscale_resume(struct target *target, int current, if (retval != ERROR_OK) return retval; - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); @@ -1277,8 +1277,8 @@ static int xscale_resume(struct target *target, int current, return ERROR_OK; } -static int xscale_step_inner(struct target *target, int current, - uint32_t address, int handle_breakpoints) +static int xscale_step_inner(struct target *target, bool current, + uint32_t address, bool handle_breakpoints) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; @@ -1372,8 +1372,8 @@ static int xscale_step_inner(struct target *target, int current, return ERROR_OK; } -static int xscale_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int xscale_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { struct arm *arm = target_to_arm(target); struct breakpoint *breakpoint = NULL; @@ -1386,7 +1386,7 @@ static int xscale_step(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ + /* current = true: continue on current pc, otherwise continue at
*/ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); @@ -1598,7 +1598,7 @@ static int xscale_deassert_reset(struct target *target) target->state = TARGET_HALTED; /* resume the target */ - xscale_resume(target, 1, 0x0, 1, 0); + xscale_resume(target, true, 0x0, true, false); } } diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 3b888fe5f0..3a877edfa6 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -1591,10 +1591,10 @@ int xtensa_halt(struct target *target) } int xtensa_prepare_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { struct xtensa *xtensa = target_to_xtensa(target); uint32_t bpena = 0; @@ -1671,13 +1671,14 @@ int xtensa_do_resume(struct target *target) } int xtensa_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { LOG_TARGET_DEBUG(target, "start"); - int res = xtensa_prepare_resume(target, current, address, handle_breakpoints, debug_execution); + int res = xtensa_prepare_resume(target, current, address, + handle_breakpoints, debug_execution); if (res != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to prepare for resume!"); return res; @@ -1719,7 +1720,8 @@ static bool xtensa_pc_in_winexc(struct target *target, target_addr_t pc) return false; } -int xtensa_do_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +int xtensa_do_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct xtensa *xtensa = target_to_xtensa(target); int res; @@ -1844,7 +1846,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in /* Now that ICOUNT (LX) or DCR.StepRequest (NX) is set, * we can resume as if we were going to run */ - res = xtensa_prepare_resume(target, current, address, 0, 0); + res = xtensa_prepare_resume(target, current, address, false, false); if (res != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to prepare resume for single step"); return res; @@ -1941,7 +1943,8 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in return res; } -int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +int xtensa_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { int retval = xtensa_do_step(target, current, address, handle_breakpoints); if (retval != ERROR_OK) @@ -2806,7 +2809,7 @@ int xtensa_start_algorithm(struct target *target, } } - return xtensa_resume(target, 0, entry_point, 1, 1); + return xtensa_resume(target, false, entry_point, true, true); } /** Waits for an algorithm in the target. */ diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 419277675c..a920f77cdf 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -378,18 +378,20 @@ int xtensa_poll(struct target *target); void xtensa_on_poll(struct target *target); int xtensa_halt(struct target *target); int xtensa_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution); + bool handle_breakpoints, + bool debug_execution); int xtensa_prepare_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution); + bool handle_breakpoints, + bool debug_execution); int xtensa_do_resume(struct target *target); -int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); -int xtensa_do_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); +int xtensa_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); +int xtensa_do_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); int xtensa_mmu_is_enabled(struct target *target, int *enabled); int xtensa_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int xtensa_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer); From 9470853d476b431ead7218a3124717ffb4b10e50 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 19 Feb 2025 22:30:45 +0100 Subject: [PATCH 1106/1312] jep106: update to revision JEP106BL Feb 2025 Update to latest available document. Change-Id: Ic7f31bf74c25aaebc5a2ecc7d5a0e516321bf862 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8766 Tested-by: jenkins --- src/helper/jep106.inc | 49 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 53d0355c18..8bbaf4ca5c 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -2,18 +2,18 @@ /* * The manufacturer's standard identification code list appears in JEP106. - * Copyright (c) 2024 JEDEC. All rights reserved. + * Copyright (c) 2025 JEDEC. All rights reserved. * * JEP106 is regularly updated. For the current manufacturer's standard * identification code list, please visit the JEDEC website at www.jedec.org . */ -/* This file is aligned to revision JEP106BK September 2024. */ +/* This file is aligned to revision JEP106BL February 2025. */ [0][0x01 - 1] = "AMD", [0][0x02 - 1] = "AMI", [0][0x03 - 1] = "Fairchild", -[0][0x04 - 1] = "Fujitsu", +[0][0x04 - 1] = "RAMXEED Limited", [0][0x05 - 1] = "GTE", [0][0x06 - 1] = "Harris", [0][0x07 - 1] = "Hitachi", @@ -1373,7 +1373,7 @@ [10][0x65 - 1] = "Esperanto Technologies", [10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd", [10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology", -[10][0x68 - 1] = "Shanghai Rui Xuan Information Tech", +[10][0x68 - 1] = "Shanghai Ruixuan Information Tech", [10][0x69 - 1] = "Fraunhofer IIS", [10][0x6a - 1] = "Kandou Bus SA", [10][0x6b - 1] = "Acer", @@ -1745,7 +1745,7 @@ [13][0x5f - 1] = "Guangdong OPPO Mobile Telecommunication", [13][0x60 - 1] = "Akeana", [13][0x61 - 1] = "Lyczar", -[13][0x62 - 1] = "Shenzhen Qiji Technology Co Ltd", +[13][0x62 - 1] = "QJTEK", [13][0x63 - 1] = "Shenzhen Shangzhaoyuan Technology", [13][0x64 - 1] = "Han Stor", [13][0x65 - 1] = "China Micro Semicon Co., Ltd.", @@ -1893,7 +1893,7 @@ [14][0x75 - 1] = "HOGE Technology Co Ltd", [14][0x76 - 1] = "United Micro Technology (Shenzhen) Co", [14][0x77 - 1] = "Fabric of Truth Inc", -[14][0x78 - 1] = "Epitech", +[14][0x78 - 1] = "Elpitech", [14][0x79 - 1] = "Elitestek", [14][0x7a - 1] = "Cornelis Networks Inc", [14][0x7b - 1] = "WingSemi Technologies Co Ltd", @@ -1916,7 +1916,7 @@ [15][0x0e - 1] = "Shenzhen Ranshuo Technology Co Limited", [15][0x0f - 1] = "ScaleFlux", [15][0x10 - 1] = "XC Memory", -[15][0x11 - 1] = "Guangzhou Beimu Technology Co., Ltd", +[15][0x11 - 1] = "Guangzhou Beimu Technology Co Ltd", [15][0x12 - 1] = "Rays Semiconductor Nanjing Co Ltd", [15][0x13 - 1] = "Milli-Centi Intelligence Technology Jiangsu", [15][0x14 - 1] = "Zilia Technologies", @@ -1925,7 +1925,7 @@ [15][0x17 - 1] = "Nanjing Houmo Technology Co Ltd", [15][0x18 - 1] = "Suzhou Yige Technology Co Ltd", [15][0x19 - 1] = "Shenzhen Techwinsemi Technology Co Ltd", -[15][0x1a - 1] = "Pure Array Technology (Shanghai) Co. Ltd", +[15][0x1a - 1] = "Pure Array Technology (Shanghai) Co Ltd", [15][0x1b - 1] = "Shenzhen Techwinsemi Technology Udstore", [15][0x1c - 1] = "RISE MODE", [15][0x1d - 1] = "NEWREESTAR", @@ -2016,4 +2016,37 @@ [15][0x72 - 1] = "KEYSOM", [15][0x73 - 1] = "Shenzhen YYF Info Tech Co Ltd", [15][0x74 - 1] = "Sharetronics Data Technology Co Ltd", +[15][0x75 - 1] = "AptCore Limited", +[15][0x76 - 1] = "Uchampion Semiconductor Co Ltd", +[15][0x77 - 1] = "YCT Semiconductor", +[15][0x78 - 1] = "FADU Inc", +[15][0x79 - 1] = "Hefei CLT Microelectronics Co LTD", +[15][0x7a - 1] = "Smart Technologies (BD) Ltd", +[15][0x7b - 1] = "Zhangdian District Qunyuan Computer Firm", +[15][0x7c - 1] = "Silicon Xpandas Electronics Co Ltd", +[15][0x7d - 1] = "PC Components Y Multimedia S", +[15][0x7e - 1] = "Shenzhen Tanlr Technology Group Co Ltd", +[16][0x01 - 1] = "Shenzhen JIEQING Technology Co Ltd", +[16][0x02 - 1] = "Orionix", +[16][0x03 - 1] = "JoulWatt Technology Co Ltd", +[16][0x04 - 1] = "Tenstorrent", +[16][0x05 - 1] = "Unis Flash Memory Technology (Chengdu)", +[16][0x06 - 1] = "Huatu Stars", +[16][0x07 - 1] = "Ardor Gaming", +[16][0x08 - 1] = "QuanZhou KunFang Semiconductor Co Ltd", +[16][0x09 - 1] = "EIAI PLANET", +[16][0x0a - 1] = "Ningbo Lingkai Semiconductor Technology Inc", +[16][0x0b - 1] = "Shenzhen Hancun Technology Co Ltd", +[16][0x0c - 1] = "Hongkong Manyi Technology Co Limited", +[16][0x0d - 1] = "Shenzhen Storgon Technology Co Ltd", +[16][0x0e - 1] = "YUNTU Microelectronics", +[16][0x0f - 1] = "Essencore", +[16][0x10 - 1] = "Shenzhen Xingyun Lianchuang Computer Tech", +[16][0x11 - 1] = "ShenZhen Aoscar Digital Tech Co Ltd", +[16][0x12 - 1] = "XOC Technologies Inc", +[16][0x13 - 1] = "BOS Semiconductors", +[16][0x14 - 1] = "Eliyan Corp", +[16][0x15 - 1] = "Hangzhou Lishu Technology Co Ltd", +[16][0x16 - 1] = "Tier IV Inc", +[16][0x17 - 1] = "Wuhan Xuanluzhe Network Technology Co", /* EOF */ From 91c11ea469c7613d2b474149c48457dcc082ebed Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 12 Jun 2024 13:34:48 +0200 Subject: [PATCH 1107/1312] rtos: Use lower case filenames Change-Id: I309c7a649e33f516e28037fef2dc6e574d48c000 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8334 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/rtos/Makefile.am | 10 +++++----- src/rtos/{eCos.c => ecos.c} | 0 src/rtos/{embKernel.c => embkernel.c} | 0 src/rtos/{FreeRTOS.c => freertos.c} | 0 src/rtos/{ThreadX.c => threadx.c} | 0 src/rtos/{uCOS-III.c => ucos_iii.c} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename src/rtos/{eCos.c => ecos.c} (100%) rename src/rtos/{embKernel.c => embkernel.c} (100%) rename src/rtos/{FreeRTOS.c => freertos.c} (100%) rename src/rtos/{ThreadX.c => threadx.c} (100%) rename src/rtos/{uCOS-III.c => ucos_iii.c} (100%) diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index 0796910de8..5267fea248 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -11,15 +11,15 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/rtos_ucos_iii_stackings.c \ %D%/rtos_riot_stackings.c \ %D%/rtos_nuttx_stackings.c \ - %D%/FreeRTOS.c \ - %D%/ThreadX.c \ - %D%/eCos.c \ + %D%/freertos.c \ + %D%/threadx.c \ + %D%/ecos.c \ %D%/linux.c \ %D%/chibios.c \ %D%/chromium-ec.c \ - %D%/embKernel.c \ + %D%/embkernel.c \ %D%/mqx.c \ - %D%/uCOS-III.c \ + %D%/ucos_iii.c \ %D%/nuttx.c \ %D%/rtkernel.c \ %D%/hwthread.c \ diff --git a/src/rtos/eCos.c b/src/rtos/ecos.c similarity index 100% rename from src/rtos/eCos.c rename to src/rtos/ecos.c diff --git a/src/rtos/embKernel.c b/src/rtos/embkernel.c similarity index 100% rename from src/rtos/embKernel.c rename to src/rtos/embkernel.c diff --git a/src/rtos/FreeRTOS.c b/src/rtos/freertos.c similarity index 100% rename from src/rtos/FreeRTOS.c rename to src/rtos/freertos.c diff --git a/src/rtos/ThreadX.c b/src/rtos/threadx.c similarity index 100% rename from src/rtos/ThreadX.c rename to src/rtos/threadx.c diff --git a/src/rtos/uCOS-III.c b/src/rtos/ucos_iii.c similarity index 100% rename from src/rtos/uCOS-III.c rename to src/rtos/ucos_iii.c From e1425845ea32713924cbfdfc9a328c6eb774f11f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 26 Feb 2025 23:25:03 +0100 Subject: [PATCH 1108/1312] target: algorithm: change reg_name to const in init_reg_param() The function init_reg_param() initializes a struct where the pointer reg_name is assigned to a 'const char *'. Change the prototype of init_reg_param() to make also the reg_name parameter as 'const char *'. Change-Id: Ib999eaa5786ad24aa2a361070162c6f362784758 Reported-by: Marek Kraus Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8797 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Marek Kraus --- src/target/algorithm.c | 3 ++- src/target/algorithm.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/target/algorithm.c b/src/target/algorithm.c index 64abffc7b6..dee1f364b4 100644 --- a/src/target/algorithm.c +++ b/src/target/algorithm.c @@ -26,7 +26,8 @@ void destroy_mem_param(struct mem_param *param) param->value = NULL; } -void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction) +void init_reg_param(struct reg_param *param, const char *reg_name, + uint32_t size, enum param_direction direction) { param->reg_name = reg_name; param->size = size; diff --git a/src/target/algorithm.h b/src/target/algorithm.h index 25f1a66ab5..45b3fd97a5 100644 --- a/src/target/algorithm.h +++ b/src/target/algorithm.h @@ -35,8 +35,8 @@ void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction dir); void destroy_mem_param(struct mem_param *param); -void init_reg_param(struct reg_param *param, - char *reg_name, uint32_t size, enum param_direction dir); +void init_reg_param(struct reg_param *param, const char *reg_name, + uint32_t size, enum param_direction dir); void destroy_reg_param(struct reg_param *param); #endif /* OPENOCD_TARGET_ALGORITHM_H */ From c986b4dbf2ff81753adcd0235954cfd577831672 Mon Sep 17 00:00:00 2001 From: Marek Kraus Date: Sat, 23 Nov 2024 15:54:26 +0100 Subject: [PATCH 1109/1312] tcl/target: add Bouffalo Lab BL602 and BL702L chip series support BL602, BL702 and BL702L series of chips are sharing same architecture, so they all need same software reset mechanism as well. Only difference (in terms of configuration needed for JTAG) are TAP ID, workarea address and size. This is addressed by creating bl602_common.cfg tcl file, which contains all those common stuff between the chips. The script is prefixed by bl602, as this was first *publicly* available chip from Bouffalo with this architecture. This patch also improves reset mechanism. Previous reset mechanism did not worked properly when slower JTAG adapter was used (it attached too late). New reset mechanism uses various methods to keep CPU in BootROM, until the JTAG adapter does not attach again after reset. Additionally, we trigger SW Reset by directly using DMI commands to write to register with system bus method, to avoid getting error about unsuccessful write. The new method works on both FT232H (8MHz JTAG clock) and unnamed CMSIS-DAP dongle (1.5MHz JTAG clock). Change-Id: I5be3694927793fd3f64c9ed4ee6ded2db0d25cae Signed-off-by: Marek Kraus Reviewed-on: https://review.openocd.org/c/openocd/+/8593 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/bl602.cfg | 34 +++++++++ tcl/target/bl602_common.cfg | 143 ++++++++++++++++++++++++++++++++++++ tcl/target/bl702.cfg | 59 +++------------ tcl/target/bl702l.cfg | 47 ++++++++++++ 4 files changed, 234 insertions(+), 49 deletions(-) create mode 100644 tcl/target/bl602.cfg create mode 100644 tcl/target/bl602_common.cfg create mode 100644 tcl/target/bl702l.cfg diff --git a/tcl/target/bl602.cfg b/tcl/target/bl602.cfg new file mode 100644 index 0000000000..d110d3e3bd --- /dev/null +++ b/tcl/target/bl602.cfg @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Bouffalo Labs BL602 and BL604 target +# +# https://en.bouffalolab.com/product/?type=detail&id=1 +# +# Default JTAG pins: (if not changed by eFuse configuration) +# TDO - GPIO11 +# TMS - GPIO12 +# TCK - GPIO14 +# TDI - GPIO17 +# + +if { [info exists CHIPNAME] } { + set BL602_CHIPNAME $CHIPNAME +} else { + set BL602_CHIPNAME bl602 +} + +set CPUTAPID 0x20000c05 + +# For work-area we use DTCM instead of ITCM, due ITCM is used as buffer for L1 cache and XIP +set WORKAREAADDR 0x42014000 +set WORKAREASIZE 0xC000 + +source [find target/bl602_common.cfg] + +# JTAG reset is broken. Read comment of bl602_sw_reset_hbn_wait function for more information +$_TARGETNAME configure -event reset-assert { + halt + + bl602_sw_reset_hbn_wait +} diff --git a/tcl/target/bl602_common.cfg b/tcl/target/bl602_common.cfg new file mode 100644 index 0000000000..cf4bc3947c --- /dev/null +++ b/tcl/target/bl602_common.cfg @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Script for Bouffalo chips with similar architecture used in BL602 +# based on SiFive E21 core + +source [find mem_helper.tcl] + +transport select jtag + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + error "you must specify a tap id" +} + +if { [info exists BL602_CHIPNAME] } { + set _CHIPNAME $BL602_CHIPNAME +} else { + error "you must specify a chip name" +} + +if { [info exists WORKAREAADDR] } { + set _WORKAREAADDR $WORKAREAADDR +} else { + error "you must specify a work area address" +} + +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + error "you must specify a work area size" +} + +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME + +riscv set_mem_access sysbus +riscv set_enable_virt2phys off + +$_TARGETNAME configure -work-area-phys $_WORKAREAADDR -work-area-size $_WORKAREASIZE -work-area-backup 1 + +# Internal RC ticks on 32 MHz, so this speed should be safe to use. +adapter speed 8000 + +# Useful functions + +set dmcontrol 0x10 +set dmcontrol_dmactive [expr {1 << 0}] +set dmcontrol_ndmreset [expr {1 << 1}] +set dmcontrol_resumereq [expr {1 << 30}] +set dmcontrol_haltreq [expr {1 << 31}] + +proc bl602_restore_clock_defaults { } { + # Switch clock to internal RC32M + # In HBN_GLB, set ROOT_CLK_SEL = 0 + mmw 0x4000f030 0x0 0x00000003 + # Wait for clock switch + sleep 10 + + # GLB_REG_BCLK_DIS_FALSE + mww 0x40000ffc 0x0 + + # HCLK is RC32M, so BCLK/HCLK doesn't need divider + # In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0 + mmw 0x40000000 0x0 0x00FFFF00 + # Wait for clock to stabilize + sleep 10 +} + +# By spec, ndmreset should reset whole chip. This implementation resets only few parts of the chip. +# CTRL_PWRON_RESET register in GLB core triggers full "power-on like" reset, so we use it instead +# for full software reset. +proc bl602_sw_reset { } { + # In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET + mmw 0x40000018 0x0 0x00000007 + + # This Software reset method resets everything, so CPU as well. + # It does that in not much good way, resulting in Debug Module being reset as well. + # This also means, that right after CPU and Debug Module are turned on, we need to + # enable Debug Module and halt CPU if needed. Additionally, we trigger this SW reset + # through system bus access directly with DMI commands, to avoid errors printed by + # OpenOCD about unsuccessful register write. + + # In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1 + riscv dmi_write 0x39 0x40000018 + riscv dmi_write 0x3c 0x7 + + # We need to wait for chip to finish reset and execute BootROM + sleep 1 + + # JTAG Debug Transport Module is reset as well, so we need to get into RUN/IDLE state + runtest 10 + + # We need to enable Debug Module and halt the CPU, so we can reset Program Counter + # and to do additional clean-ups. If reset was called without halt, resume is handled + # by reset-deassert-post event handler. + + # In Debug Module Control (dmcontrol), set dmactive to 1 and then haltreq to 1 + riscv dmi_write $::dmcontrol $::dmcontrol_dmactive + riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_haltreq} ] + + # Set Program Counter to start of BootROM + set_reg {pc 0x21000000} +} + +# On BL602 and BL702, the only way to force chip stay in BootROM (until JTAG attaches) +# is by putting infinity loop into HBN RAM (which is not reset by sw reset), and then +# configure HBN registers, which will cause BootROM to jump into our code early in BootROM. +proc bl602_sw_reset_hbn_wait {} { + # Restore clocks to defaults + bl602_restore_clock_defaults + + # In HBN RAM, write infinity loop instruction + # beq zero, zero, 0 + mww 0x40010000 0x00000063 + # In HNB, set HBN_RSV0 (Status Flag) to "EHBN" (as uint32_t) + mww 0x4000f100 0x4e424845 + # In HBN, set HBN_RSV1 (WakeUp Address) to HBN RAM address + mww 0x4000f104 0x40010000 + + # Perform software reset + bl602_sw_reset + + # Clear HBN RAM, HBN_RSV0 and HBN_RSV1 + mww 0x40010000 0x00000000 + mww 0x4000f100 0x00000000 + mww 0x4000f104 0x00000000 + + # This early jump method locks up BootROM through Trust Zone Controller. + # That means any read of BootROM returns 0xDEADBEEF. + # Only way to reset it, is through JTAG Reset, thus toggling ndmreset in dmcontrol. + riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_ndmreset} ] + riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive} ] +} + +$_TARGETNAME configure -event reset-deassert-post { + # Resume the processor if reset was triggered without halt request + if {$halt == 0} { + riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_resumereq} ] + } +} diff --git a/tcl/target/bl702.cfg b/tcl/target/bl702.cfg index 5046cd189a..8caf06ebe1 100644 --- a/tcl/target/bl702.cfg +++ b/tcl/target/bl702.cfg @@ -12,62 +12,23 @@ # TDO - GPIO9 # -source [find mem_helper.tcl] - -transport select jtag - if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME + set BL602_CHIPNAME $CHIPNAME } else { - set _CHIPNAME bl702 + set BL602_CHIPNAME bl702 } -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000e05 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME - -riscv set_mem_access sysbus +set CPUTAPID 0x20000e05 -$_TARGETNAME configure -work-area-phys 0x22020000 -work-area-size 0x10000 -work-area-backup 1 +# For work-area we use DTCM instead of ITCM, due ITCM is used as buffer for L1 cache and XIP +set WORKAREAADDR 0x22014000 +set WORKAREASIZE 0xC000 -# Internal RC ticks on 32 MHz, so this speed should be safe to use. -adapter speed 4000 +source [find target/bl602_common.cfg] -# Debug Module's ndmreset resets only Trust Zone Controller, so we need to do SW reset instead. -# CTRL_PWRON_RESET triggers full "power-on like" reset. -# This means that pinmux configuration to access JTAG is reset as well, and configured back early -# in BootROM. -$_TARGETNAME configure -event reset-assert-pre { +# JTAG reset is broken. Read comment of bl602_sw_reset_hbn_wait function for more information +$_TARGETNAME configure -event reset-assert { halt - # Switch clock to internal RC32M - # In HBN_GLB, set ROOT_CLK_SEL = 0 - mmw 0x4000f030 0x0 0x00000003 - # Wait for clock switch - sleep 10 - - # GLB_REG_BCLK_DIS_FALSE - mww 0x40000ffc 0x0 - - # HCLK is RC32M, so BCLK/HCLK doesn't need divider - # In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0 - mmw 0x40000000 0x0 0x00FFFF00 - # Wait for clock to stabilize - sleep 10 - - # Do reset - # In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET - mmw 0x40000018 0x0 0x00000007 - - # Since this full software reset resets GPIO pinmux as well, we will lose access - # to JTAG right away after writing to register. This chip doesn't support abstract - # memory access, so when this is done by progbuf or sysbus, OpenOCD will fail to read - # if write was successful or not, and will print error about that. Since receiving of - # this error is expected, we will turn off log printing for a moment, - set lvl [lindex [debug_level] 1] - debug_level -1 - # In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1 - catch {mmw 0x40000018 0x7 0x0} - debug_level $lvl + bl602_sw_reset_hbn_wait } diff --git a/tcl/target/bl702l.cfg b/tcl/target/bl702l.cfg new file mode 100644 index 0000000000..467dd8ce6b --- /dev/null +++ b/tcl/target/bl702l.cfg @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Bouffalo Labs BL702L and BL704L target +# +# https://en.bouffalolab.com/product/?type=detail&id=26 +# +# Default JTAG pins: (if not changed by eFuse configuration) +# TMS - GPIO0 +# TDI - GPIO1 +# TCK - GPIO2 +# TDO - GPIO7 +# + +if { [info exists CHIPNAME] } { + set BL602_CHIPNAME $CHIPNAME +} else { + set BL602_CHIPNAME bl702l +} + +set CPUTAPID 0x20000e05 + +# For work-area we use beginning of OCRAM, since BL702L have only ITCM, which can be taken +# by L1 cache and XIP during runtime. +set WORKAREAADDR 0x42020000 +set WORKAREASIZE 0x10000 + +source [find target/bl602_common.cfg] + +# JTAG reset is broken. Read comment of bl602_sw_reset function for more information +# On BL702L, we are forcing boot into ISP mode, so chip stays in BootROM until JTAG re-attach +$_TARGETNAME configure -event reset-assert { + halt + + # Restore clocks to defaults + bl602_restore_clock_defaults + + # In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4) + # and HBN_USER_BOOT_SEL to 1 (ISP) + mww 0x4000f108 0x44000000 + + # Perform software reset + bl602_sw_reset + + # Reset HBN_RSV2 so BootROM will not force ISP mode again + mww 0x4000f108 0x00000000 +} From accbeaed99bc6014d060259d6b0b0e080c0f44b4 Mon Sep 17 00:00:00 2001 From: Jim Paris Date: Fri, 21 Feb 2025 12:33:45 -0500 Subject: [PATCH 1110/1312] gdb_server: fix invalid free `gdb_service_free` calls `free(gdb_port_next)`, so this needs to be an allocated string. Otherwise we trip up detectors like Android's tagged pointers. Change-Id: Ib08ea55a38af4e15c4fbae95f10db0e3684ae1af Signed-off-by: Jim Paris Reviewed-on: https://review.openocd.org/c/openocd/+/8768 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/server/gdb_server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 1866de0b56..71b7c7764a 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3898,7 +3898,8 @@ static int gdb_target_add_one(struct target *target) } } } else if (strcmp(gdb_port_next, "pipe") == 0) { - gdb_port_next = "disabled"; + free(gdb_port_next); + gdb_port_next = strdup("disabled"); } } return retval; From d126cdb9239990dac88023d42fe5056401190e5e Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 17 Feb 2025 12:15:09 +0100 Subject: [PATCH 1111/1312] drivers/cmsis_dap: fix misleading error selecting not compiled backend If one of CMSIS-DAP backends was not compiled (due to missing library or configure --disable-cmsis-dap) and Tcl config explicitly selected it, a misleading message "invalid backend argument to cmsis-dap backend " was printed. Create dummy backends in struct cmsis_dap_backend to replace a not built backend. Check for NULL open backend method to distinguish the backend is dummy. Rework 'cmsis-dap backend' command to honour dummy backend. While on it print more helpful error messages. Change-Id: I8f12aeaaecf19302032870bc232e5135c1d935e7 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8760 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/cmsis_dap.c | 68 +++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index c8a7cf8fcd..be9ebaed58 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -39,14 +39,22 @@ #include "cmsis_dap.h" #include "libusb_helper.h" -static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { -#if BUILD_CMSIS_DAP_USB == 1 - &cmsis_dap_usb_backend, +/* Create a dummy backend for 'backend' command if real one does not build */ +#if BUILD_CMSIS_DAP_USB == 0 +const struct cmsis_dap_backend cmsis_dap_usb_backend = { + .name = "usb_bulk", +}; #endif -#if BUILD_CMSIS_DAP_HID == 1 - &cmsis_dap_hid_backend, +#if BUILD_CMSIS_DAP_HID == 0 +const struct cmsis_dap_backend cmsis_dap_hid_backend = { + .name = "hid" +}; #endif + +static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { + &cmsis_dap_usb_backend, + &cmsis_dap_hid_backend, }; /* USB Config */ @@ -261,26 +269,32 @@ static int cmsis_dap_open(void) return ERROR_FAIL; } + int retval = ERROR_FAIL; if (cmsis_dap_backend >= 0) { /* Use forced backend */ backend = cmsis_dap_backends[cmsis_dap_backend]; - if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) != ERROR_OK) - backend = NULL; + if (backend->open) + retval = backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()); + else + LOG_ERROR("Requested CMSIS-DAP backend is disabled by configure"); + } else { /* Try all backends */ for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { backend = cmsis_dap_backends[i]; - if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) == ERROR_OK) + if (!backend->open) + continue; + + retval = backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()); + if (retval == ERROR_OK) break; - else - backend = NULL; } } - if (!backend) { + if (retval != ERROR_OK) { LOG_ERROR("unable to find a matching CMSIS-DAP device"); free(dap); - return ERROR_FAIL; + return retval; } dap->backend = backend; @@ -293,7 +307,8 @@ static int cmsis_dap_open(void) static void cmsis_dap_close(struct cmsis_dap *dap) { if (dap->backend) { - dap->backend->close(dap); + if (dap->backend->close) + dap->backend->close(dap); dap->backend = NULL; } @@ -2192,22 +2207,27 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) COMMAND_HANDLER(cmsis_dap_handle_backend_command) { - if (CMD_ARGC == 1) { - if (strcmp(CMD_ARGV[0], "auto") == 0) { - cmsis_dap_backend = -1; /* autoselect */ - } else { - for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { - if (strcasecmp(cmsis_dap_backends[i]->name, CMD_ARGV[0]) == 0) { + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[0], "auto") == 0) { + cmsis_dap_backend = -1; /* autoselect */ + } else { + for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { + if (strcasecmp(cmsis_dap_backends[i]->name, CMD_ARGV[0]) == 0) { + if (cmsis_dap_backends[i]->open) { cmsis_dap_backend = i; return ERROR_OK; } - } - command_print(CMD, "invalid backend argument to cmsis-dap backend "); - return ERROR_COMMAND_ARGUMENT_INVALID; + command_print(CMD, "Requested cmsis-dap backend %s is disabled by configure", + cmsis_dap_backends[i]->name); + return ERROR_NOT_IMPLEMENTED; + } } - } else { - return ERROR_COMMAND_SYNTAX_ERROR; + + command_print(CMD, "invalid argument %s to cmsis-dap backend", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } return ERROR_OK; From a168c634126e9e6bb95c6e68b2db5afbb099abf7 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 18 Feb 2025 08:13:07 +0100 Subject: [PATCH 1112/1312] configure: better differentiate CMSIS-DAP versions and keep them together in the configuration summary. Change-Id: I5937393590ac72f1d499457e67763686a79cadee Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8765 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index fda0b2a360..e31e056cc7 100644 --- a/configure.ac +++ b/configure.ac @@ -136,16 +136,19 @@ m4_define([USB1_ADAPTERS], [[ft232r], [Bitbang mode of FT232R based devices], [FT232R]], [[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]], [[xds110], [TI XDS110 Debug Probe], [XDS110]], - [[cmsis_dap_v2], [CMSIS-DAP v2 Compliant Debugger], [CMSIS_DAP_USB]], [[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]], [[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]], [[armjtagew], [Olimex ARM-JTAG-EW Programmer], [ARMJTAGEW]], [[rlink], [Raisonance RLink JTAG Programmer], [RLINK]], [[usbprog], [USBProg JTAG Programmer], [USBPROG]], - [[esp_usb_jtag], [Espressif JTAG Programmer], [ESP_USB_JTAG]]]) + [[esp_usb_jtag], [Espressif JTAG Programmer], [ESP_USB_JTAG]], + [[cmsis_dap_v2], [CMSIS-DAP v2 compliant dongle (USB bulk)], [CMSIS_DAP_USB]]]) + +# Please keep cmsis_dap_v2 the last in USB1_ADAPTERS +# and cmsis_dap the first in HIDAPI_ADAPTERS m4_define([HIDAPI_ADAPTERS], - [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP_HID]], + [[[cmsis_dap], [CMSIS-DAP v1 compliant dongle (HID)], [CMSIS_DAP_HID]], [[nulink], [Nu-Link Programmer], [HLADAPTER_NULINK]]]) m4_define([HIDAPI_USB1_ADAPTERS], @@ -878,7 +881,7 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ echo echo echo OpenOCD configuration summary -echo -------------------------------------------------- +echo --------------------------------------------------- m4_foreach([adapter], [USB1_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, @@ -889,7 +892,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], - [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) + [s=m4_format(["%-41s"], ADAPTER_DESC([adapter])) AS_CASE([$ADAPTER_VAR([adapter])], [auto], [ echo "$s"yes '(auto)' From 7837f508a5cca2c82ec46f076d115853a4eaac38 Mon Sep 17 00:00:00 2001 From: Parshintsev Anatoly Date: Fri, 8 Nov 2024 07:12:46 +0300 Subject: [PATCH 1113/1312] target: fix wrap-around detection for read_memory/write_memory while at it change the order of checks for requested region sizes to get rid of potential overflow during multiplication. Change-Id: I97dac68e7024591cfd7abb70c8c62dff791298fe Signed-off-by: Parshintsev Anatoly Reviewed-on: https://review.openocd.org/c/openocd/+/8572 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Antonio Borneo --- src/target/target.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 9c5a33d3d2..0e41f0d10f 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4447,15 +4447,17 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_COMMAND_ARGUMENT_INVALID; } - const unsigned int width = width_bits / 8; - - if ((addr + (count * width)) < addr) { - command_print(CMD, "read_memory: addr + count wraps to zero"); + if (count > 65536) { + command_print(CMD, "read_memory: too large read request, exceeds 64K elements"); return ERROR_COMMAND_ARGUMENT_INVALID; } - if (count > 65536) { - command_print(CMD, "read_memory: too large read request, exceeds 64K elements"); + const unsigned int width = width_bits / 8; + /* -1 is needed to handle cases when (addr + count * width) results in zero + * due to overflow. + */ + if ((addr + count * width - 1) < addr) { + command_print(CMD, "read_memory: memory region wraps over address zero"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -4584,15 +4586,19 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, return JIM_ERR; } - const unsigned int width = width_bits / 8; - - if ((addr + (count * width)) < addr) { - Jim_SetResultString(interp, "write_memory: addr + len wraps to zero", -1); + if (count > 65536) { + Jim_SetResultString(interp, + "write_memory: too large memory write request, exceeds 64K elements", -1); return JIM_ERR; } - if (count > 65536) { - Jim_SetResultString(interp, "write_memory: too large memory write request, exceeds 64K elements", -1); + const unsigned int width = width_bits / 8; + /* -1 is needed to handle cases when (addr + count * width) results in zero + * due to overflow. + */ + if ((addr + count * width - 1) < addr) { + Jim_SetResultFormatted(interp, + "write_memory: memory region wraps over address zero"); return JIM_ERR; } From 953ad9e11658534ea4ca682c7f112db3059be1cc Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 13 Feb 2025 22:37:40 +0000 Subject: [PATCH 1114/1312] rtt: Raise error if control block was not found Since RTT is not started if the control block was not found, an error must be raised instead of just informing the user. Change-Id: I2873e72f142ca572da97ee1fe91f6f1301307555 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8757 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtt/rtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c index 42c3ee3ad4..15b9a373a5 100644 --- a/src/rtt/rtt.c +++ b/src/rtt/rtt.c @@ -140,8 +140,8 @@ int rtt_start(void) addr); rtt.ctrl.address = addr; } else { - LOG_INFO("rtt: No control block found"); - return ERROR_OK; + LOG_ERROR("rtt: No control block found"); + return ERROR_FAIL; } } From 7ec11e52387390ea1fab510f10fc6cd0ed200ef5 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 14 Feb 2025 19:29:08 +0300 Subject: [PATCH 1115/1312] rtos/rtos: handle OOM in `rtos_thread_packet()` Return an error in case `calloc()` fails. Change-Id: Ibb21a62991be83be8b219887953ccf27156f8af5 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8763 Tested-by: jenkins Reviewed-by: zapb --- src/rtos/rtos.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index f218f63694..2c563d522b 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -362,6 +362,10 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa str_size += strlen(detail->extra_info_str); char *tmp_str = calloc(str_size + 9, sizeof(char)); + if (!tmp_str) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } char *tmp_str_ptr = tmp_str; if (detail->thread_name_str) From b6b5edf13b5d3500c94a5afc7adda132768cd568 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 14 Feb 2025 19:30:55 +0300 Subject: [PATCH 1116/1312] rtos/linux: handle OOM in `linux_gdb_thread_packet()` Return an error in case `calloc()` fails. Change-Id: Id1b758a1edbae3d71d625d1992579b99720d77d6 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8762 Tested-by: jenkins Reviewed-by: zapb --- src/rtos/linux.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 5467988f3e..91d9a39f24 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -1040,6 +1040,10 @@ static int linux_gdb_thread_packet(struct target *target, return ERROR_TARGET_FAILURE; char *out_str = calloc(MAX_THREADS * 17 + 10, 1); + if (!out_str) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } char *tmp_str = out_str; tmp_str += sprintf(tmp_str, "m"); struct threads *temp = linux_os->thread_list; From 8a6f89ca170ce69835f03805aa60106801da61a8 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 28 Sep 2023 03:37:03 -0500 Subject: [PATCH 1117/1312] flash/nor: Add basic support for TI's MSPM0L/G family Add basic flashing support for Texas Instruments MSPM0L, C and G family of Cortex-M0 based micro-controllers. This initial basic flashing support allows for controlling protection, erase, write and read of non-main flash region. This has been tested with: * Valgrind (3.22.0): valgrind --leak-check=full --show-leak-kinds=all \ --track-origins=yes --verbose * Ubuntu clang version 20.0.0 (++20241014053649+ed77df56f272-1~exp1~20241014053827.1987) Valgrind-clean, no new Clang analyzer or sparse warnings have been introduced. Change-Id: I29b8055ea6da9c38c5b7b91bea1ec7581c5bc8ff Co-developed-by: Henry Nguyen Signed-off-by: Henry Nguyen Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8384 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: zapb Reviewed-by: Antonio Borneo --- doc/openocd.texi | 50 ++ src/flash/nor/Makefile.am | 1 + src/flash/nor/driver.h | 1 + src/flash/nor/drivers.c | 1 + src/flash/nor/mspm0.c | 1131 +++++++++++++++++++++++++++++++++++++ 5 files changed, 1184 insertions(+) create mode 100644 src/flash/nor/mspm0.c diff --git a/doc/openocd.texi b/doc/openocd.texi index 2ec49a4c08..68c7a825bd 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7401,6 +7401,56 @@ msp432 bsl lock @end deffn @end deffn +@deffn {Flash Driver} {mspm0} + +All Arm Cortex-M0+ MSPM0 microcontroller versions from Texas Instruments +include internal flash. The mspm0 flash driver automatically recognizes the +specific version's flash parameters and autoconfigures itself. The main +program flash starts at address 0x0. Non-main flash starts at 0x41c00000. +If present on the device, the optional region called "Data" starts at +0x41d00000. + +@b{Warning}: + +@itemize @bullet +@item @b{Reset while MCU operation:} When erasing all of MAIN memory, if the +MCU is still executing from MAIN memory do not reset the device as it could +cause a double hard-fault due to the missing interrupt vector table at the +start of memory. To recover from such scenario reset or power-cycle the MCU. + +@item @b{No explicit protection support:} MSPM0 flash controller auto-protect +themselves after every flash operation. As a result of this, OpenOCD does not +explicitly provide any protection function and automatically un-protects +required sections as flash operations are requested. +@end itemize + +@b{Examples}: + +@itemize @bullet + +@item @b{Flash bank description:} +@example +flash bank $_FLASHNAME mspm0 0 0 0 0 $_TARGETNAME +@end example + +@item @b{To erase and program the MAIN region:} +@example +halt +flash erase_sector 0 0 last +flash write_image MAIN.bin 0x0 +@end example + +@item @b{To erase and program the NONMAIN region:} +@example +halt +flash erase_sector 1 0 last +flash write_image NONMAIN.bin 0x41C00000 +@end example + +@end itemize + +@end deffn + @deffn {Flash Driver} {niietcm4} This drivers handles the integrated NOR flash on NIIET Cortex-M4 based controllers. Flash size and sector layout are auto-configured by the driver. diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 8296877610..147807fbaa 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -45,6 +45,7 @@ NOR_DRIVERS = \ %D%/max32xxx.c \ %D%/mdr.c \ %D%/msp432.c \ + %D%/mspm0.c \ %D%/mrvlqspi.c \ %D%/niietcm4.c \ %D%/non_cfi.c \ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 852a55a112..794566f121 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -274,6 +274,7 @@ extern const struct flash_driver max32xxx_flash; extern const struct flash_driver mdr_flash; extern const struct flash_driver mrvlqspi_flash; extern const struct flash_driver msp432_flash; +extern const struct flash_driver mspm0_flash; extern const struct flash_driver niietcm4_flash; extern const struct flash_driver npcx_flash; extern const struct flash_driver nrf51_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index ce97b81504..67d86243b7 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -51,6 +51,7 @@ static const struct flash_driver * const flash_drivers[] = { &mdr_flash, &mrvlqspi_flash, &msp432_flash, + &mspm0_flash, &niietcm4_flash, &npcx_flash, &nrf5_flash, diff --git a/src/flash/nor/mspm0.c b/src/flash/nor/mspm0.c new file mode 100644 index 0000000000..4731c89ccf --- /dev/null +++ b/src/flash/nor/mspm0.c @@ -0,0 +1,1131 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/*************************************************************************** + * Copyright (C) 2023-2025 Texas Instruments Incorporated - https://www.ti.com/ + * + * NOR flash driver for MSPM0L and MSPM0G class of uC from Texas Instruments. + * + * See: + * https://www.ti.com/microcontrollers-mcus-processors/arm-based-microcontrollers/arm-cortex-m0-mcus/overview.html + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include +#include + +/* MSPM0 Region memory map */ +#define MSPM0_FLASH_BASE_NONMAIN 0x41C00000 +#define MSPM0_FLASH_END_NONMAIN 0x41C00400 +#define MSPM0_FLASH_BASE_MAIN 0x0 +#define MSPM0_FLASH_BASE_DATA 0x41D00000 + +/* MSPM0 FACTORYREGION registers */ +#define MSPM0_FACTORYREGION 0x41C40000 +#define MSPM0_TRACEID (MSPM0_FACTORYREGION + 0x000) +#define MSPM0_DID (MSPM0_FACTORYREGION + 0x004) +#define MSPM0_USERID (MSPM0_FACTORYREGION + 0x008) +#define MSPM0_SRAMFLASH (MSPM0_FACTORYREGION + 0x018) + +/* MSPM0 FCTL registers */ +#define FLASH_CONTROL_BASE 0x400CD000 +#define FCTL_REG_DESC (FLASH_CONTROL_BASE + 0x10FC) +#define FCTL_REG_CMDEXEC (FLASH_CONTROL_BASE + 0x1100) +#define FCTL_REG_CMDTYPE (FLASH_CONTROL_BASE + 0x1104) +#define FCTL_REG_CMDADDR (FLASH_CONTROL_BASE + 0x1120) +#define FCTL_REG_CMDBYTEN (FLASH_CONTROL_BASE + 0x1124) +#define FCTL_REG_CMDDATA0 (FLASH_CONTROL_BASE + 0x1130) +#define FCTL_REG_CMDWEPROTA (FLASH_CONTROL_BASE + 0x11D0) +#define FCTL_REG_CMDWEPROTB (FLASH_CONTROL_BASE + 0x11D4) +#define FCTL_REG_CMDWEPROTNM (FLASH_CONTROL_BASE + 0x1210) +#define FCTL_REG_STATCMD (FLASH_CONTROL_BASE + 0x13D0) + +/* FCTL_STATCMD[CMDDONE] Bits */ +#define FCTL_STATCMD_CMDDONE_MASK 0x00000001 +#define FCTL_STATCMD_CMDDONE_STATDONE 0x00000001 + +/* FCTL_STATCMD[CMDPASS] Bits */ +#define FCTL_STATCMD_CMDPASS_MASK 0x00000002 +#define FCTL_STATCMD_CMDPASS_STATPASS 0x00000002 + +/* + * FCTL_CMDEXEC Bits + * FCTL_CMDEXEC[VAL] Bits + */ +#define FCTL_CMDEXEC_VAL_EXECUTE 0x00000001 + +/* FCTL_CMDTYPE[COMMAND] Bits */ +#define FCTL_CMDTYPE_COMMAND_PROGRAM 0x00000001 +#define FCTL_CMDTYPE_COMMAND_ERASE 0x00000002 + +/* FCTL_CMDTYPE[SIZE] Bits */ +#define FCTL_CMDTYPE_SIZE_ONEWORD 0x00000000 +#define FCTL_CMDTYPE_SIZE_SECTOR 0x00000040 + +/* FCTL_FEATURE_VER_B minimum */ +#define FCTL_FEATURE_VER_B 0xA + +#define MSPM0_MAX_PROTREGS 3 + +#define MSPM0_FLASH_TIMEOUT_MS 8000 +#define ERR_STRING_MAX 255 + +/* SYSCTL BASE */ +#define SYSCTL_BASE 0x400AF000 +#define SYSCTL_SECCFG_SECSTATUS (SYSCTL_BASE + 0x00003048) + +/* TI manufacturer ID */ +#define TI_MANUFACTURER_ID 0x17 + +/* Defines for probe status */ +#define MSPM0_NO_ID_FOUND 0 +#define MSPM0_DEV_ID_FOUND 1 +#define MSPM0_DEV_PART_ID_FOUND 2 + +struct mspm0_flash_bank { + /* chip id register */ + uint32_t did; + /* Device Unique ID register */ + uint32_t traceid; + unsigned char version; + + const char *name; + + /* Decoded flash information */ + unsigned int data_flash_size_kb; + unsigned int main_flash_size_kb; + unsigned int main_flash_num_banks; + unsigned int sector_size; + /* Decoded SRAM information */ + unsigned int sram_size_kb; + + /* Flash word size: 64 bit = 8, 128bit = 16 bytes */ + unsigned char flash_word_size_bytes; + + /* Protection register stuff */ + unsigned int protect_reg_base; + unsigned int protect_reg_count; + + /* Flashctl version: A - CMDWEPROTA/B, B- CMDWEPROTB */ + unsigned char flash_version; +}; + +struct mspm0_part_info { + const char *part_name; + unsigned short part; + unsigned char variant; +}; + +struct mspm0_family_info { + const char *family_name; + unsigned short part_num; + unsigned char part_count; + const struct mspm0_part_info *part_info; +}; + +/* https://www.ti.com/lit/ds/symlink/mspm0l1346.pdf Table 8-13 and so on */ +static const struct mspm0_part_info mspm0l_parts[] = { + { "MSPM0L1105TDGS20R", 0x51DB, 0x16 }, + { "MSPM0L1105TDGS28R", 0x51DB, 0x83 }, + { "MSPM0L1105TDYYR", 0x51DB, 0x54 }, + { "MSPM0L1105TRGER", 0x51DB, 0x86 }, + { "MSPM0L1105TRHBR", 0x51DB, 0x68 }, + { "MSPM0L1106TDGS20R", 0x5552, 0x4B }, + { "MSPM0L1106TDGS28R", 0x5552, 0x98 }, + { "MSPM0L1106TDYYR", 0x5552, 0x9D }, + { "MSPM0L1106TRGER", 0x5552, 0x90 }, + { "MSPM0L1106TRHBR", 0x5552, 0x53 }, + { "MSPM0L1303SRGER", 0xef0, 0x17 }, + { "MSPM0L1303TRGER", 0xef0, 0xe2 }, + { "MSPM0L1304QDGS20R", 0xd717, 0x91 }, + { "MSPM0L1304QDGS28R", 0xd717, 0xb6 }, + { "MSPM0L1304QDYYR", 0xd717, 0xa0 }, + { "MSPM0L1304QRHBR", 0xd717, 0xa9 }, + { "MSPM0L1304SDGS20R", 0xd717, 0xfa }, + { "MSPM0L1304SDGS28R", 0xd717, 0x73 }, + { "MSPM0L1304SDYYR", 0xd717, 0xb7 }, + { "MSPM0L1304SRGER", 0xd717, 0x26 }, + { "MSPM0L1304SRHBR", 0xd717, 0xe4 }, + { "MSPM0L1304TDGS20R", 0xd717, 0x33 }, + { "MSPM0L1304TDGS28R", 0xd717, 0xa8 }, + { "MSPM0L1304TDYYR", 0xd717, 0xf9 }, + { "MSPM0L1304TRGER", 0xd717, 0xb7 }, + { "MSPM0L1304TRHBR", 0xd717, 0x5a }, + { "MSPM0L1305QDGS20R", 0x4d03, 0xb7 }, + { "MSPM0L1305QDGS28R", 0x4d03, 0x74 }, + { "MSPM0L1305QDYYR", 0x4d03, 0xec }, + { "MSPM0L1305QRHBR", 0x4d03, 0x78 }, + { "MSPM0L1305SDGS20R", 0x4d03, 0xc7 }, + { "MSPM0L1305SDGS28R", 0x4d03, 0x64 }, + { "MSPM0L1305SDYYR", 0x4d03, 0x91 }, + { "MSPM0L1305SRGER", 0x4d03, 0x73 }, + { "MSPM0L1305SRHBR", 0x4d03, 0x2d }, + { "MSPM0L1305TDGS20R", 0x4d03, 0xa0 }, + { "MSPM0L1305TDGS28R", 0x4d03, 0xfb }, + { "MSPM0L1305TDYYR", 0x4d03, 0xde }, + { "MSPM0L1305TRGER", 0x4d03, 0xea }, + { "MSPM0L1305TRHBR", 0x4d03, 0x85 }, + { "MSPM0L1306QDGS20R", 0xbb70, 0x59 }, + { "MSPM0L1306QDGS28R", 0xbb70, 0xf7 }, + { "MSPM0L1306QDYYR", 0xbb70, 0x9f }, + { "MSPM0L1306QRHBR", 0xbb70, 0xc2 }, + { "MSPM0L1306SDGS20R", 0xbb70, 0xf4 }, + { "MSPM0L1306SDGS28R", 0xbb70, 0x5 }, + { "MSPM0L1306SDYYR", 0xbb70, 0xe }, + { "MSPM0L1306SRGER", 0xbb70, 0x7f }, + { "MSPM0L1306SRHBR", 0xbb70, 0x3c }, + { "MSPM0L1306TDGS20R", 0xbb70, 0xa }, + { "MSPM0L1306TDGS28R", 0xbb70, 0x63 }, + { "MSPM0L1306TDYYR", 0xbb70, 0x35 }, + { "MSPM0L1306TRGER", 0xbb70, 0xaa }, + { "MSPM0L1306TRHBR", 0xbb70, 0x52 }, + { "MSPM0L1343TDGS20R", 0xb231, 0x2e }, + { "MSPM0L1344TDGS20R", 0x40b0, 0xd0 }, + { "MSPM0L1345TDGS28R", 0x98b4, 0x74 }, + { "MSPM0L1346TDGS28R", 0xf2b5, 0xef }, +}; + +/* https://www.ti.com/lit/ds/symlink/mspm0g3506.pdf Table 8-20 */ +static const struct mspm0_part_info mspm0g_parts[] = { + { "MSPM0G1105TPTR", 0x8934, 0xD }, + { "MSPM0G1105TRGZR", 0x8934, 0xFE }, + { "MSPM0G1106TPMR", 0x477B, 0xD4 }, + { "MSPM0G1106TPTR", 0x477B, 0x71 }, + { "MSPM0G1106TRGZR", 0x477B, 0xBB }, + { "MSPM0G1106TRHBR", 0x477B, 0x0 }, + { "MSPM0G1107TDGS28R", 0x807B, 0x82 }, + { "MSPM0G1107TPMR", 0x807B, 0xB3 }, + { "MSPM0G1107TPTR", 0x807B, 0x32 }, + { "MSPM0G1107TRGER", 0x807B, 0x79 }, + { "MSPM0G1107TRGZR", 0x807B, 0x20 }, + { "MSPM0G1107TRHBR", 0x807B, 0xBC }, + { "MSPM0G1505SDGS28R", 0x13C4, 0x73 }, + { "MSPM0G1505SPMR", 0x13C4, 0x53 }, + { "MSPM0G1505SPTR", 0x13C4, 0x3E }, + { "MSPM0G1505SRGER", 0x13C4, 0x47 }, + { "MSPM0G1505SRGZR", 0x13C4, 0x34 }, + { "MSPM0G1505SRHBR", 0x13C4, 0x30 }, + { "MSPM0G1506SDGS28R", 0x5AE0, 0x3A }, + { "MSPM0G1506SPMR", 0x5AE0, 0xF6 }, + { "MSPM0G1506SRGER", 0x5AE0, 0x67 }, + { "MSPM0G1506SRGZR", 0x5AE0, 0x75 }, + { "MSPM0G1506SRHBR", 0x5AE0, 0x57 }, + { "MSPM0G1507SDGS28R", 0x2655, 0x6D }, + { "MSPM0G1507SPMR", 0x2655, 0x97 }, + { "MSPM0G1507SRGER", 0x2655, 0x83 }, + { "MSPM0G1507SRGZR", 0x2655, 0xD3 }, + { "MSPM0G1507SRHBR", 0x2655, 0x4D }, + { "MSPM0G3105SDGS20R", 0x4749, 0x21 }, + { "MSPM0G3105SDGS28R", 0x4749, 0xDD }, + { "MSPM0G3105SRHBR", 0x4749, 0xBE }, + { "MSPM0G3106SDGS20R", 0x54C7, 0xD2 }, + { "MSPM0G3106SDGS28R", 0x54C7, 0xB9 }, + { "MSPM0G3106SRHBR", 0x54C7, 0x67 }, + { "MSPM0G3107SDGS20R", 0xAB39, 0x5C }, + { "MSPM0G3107SDGS28R", 0xAB39, 0xCC }, + { "MSPM0G3107SRHBR", 0xAB39, 0xB7 }, + { "MSPM0G3505SDGS28R", 0xc504, 0x8e }, + { "MSPM0G3505SPMR", 0xc504, 0x1d }, + { "MSPM0G3505SPTR", 0xc504, 0x93 }, + { "MSPM0G3505SRGZR", 0xc504, 0xc7 }, + { "MSPM0G3505SRHBR", 0xc504, 0xe7 }, + { "MSPM0G3505TDGS28R", 0xc504, 0xdf }, + { "MSPM0G3506SDGS28R", 0x151f, 0x8 }, + { "MSPM0G3506SPMR", 0x151f, 0xd4 }, + { "MSPM0G3506SPTR", 0x151f, 0x39 }, + { "MSPM0G3506SRGZR", 0x151f, 0xfe }, + { "MSPM0G3506SRHBR", 0x151f, 0xb5 }, + { "MSPM0G3507SDGS28R", 0xae2d, 0xca }, + { "MSPM0G3507SPMR", 0xae2d, 0xc7 }, + { "MSPM0G3507SPTR", 0xae2d, 0x3f }, + { "MSPM0G3507SRGZR", 0xae2d, 0xf7 }, + { "MSPM0G3507SRHBR", 0xae2d, 0x4c }, + { "M0G3107QPMRQ1", 0x4e2f, 0x51 }, + { "M0G3107QPTRQ1", 0x4e2f, 0xc7}, + { "M0G3107QRGZRQ1", 0x4e2f, 0x8a }, + { "M0G3107QRHBRQ1", 0x4e2f, 0x9a}, + { "M0G3107QDGS28RQ1", 0x4e2f, 0xd5}, + { "M0G3107QDGS28RQ1", 0x4e2f, 0x67}, + { "M0G3107QDGS20RQ1", 0x4e2f, 0xfd}, + { "M0G3106QPMRQ1", 0x54C7, 0x08}, + { "M0G3105QDGS32RQ1", 0x1349, 0x08}, + { "M0G3106QPTRQ1", 0x54C7, 0x3F}, + { "M0G3105QDGS28RQ1", 0x1349, 0x1B}, + { "M0G3106QRGZRQ1", 0x94AD, 0xE6}, + { "M0G3105QDGS20RQ1", 0x1349, 0xFB}, + { "M0G3106QRHBRQ1", 0x94AD, 0x20}, + { "M0G3106QDGS32RQ1", 0x94AD, 0x8D}, + { "M0G3106QDGS28RQ1", 0x94AD, 0x03}, + { "M0G3106QDGS20RQ1", 0x94AD, 0x6F}, + { "M0G3105QPMRQ1", 0x1349, 0xD0}, + { "M0G3105QPTRQ1", 0x1349, 0xEF}, + { "M0G3105QRGZRQ1", 0x1349, 0x70}, + { "M0G3105QRHBRQ1", 0x1349, 0x01}, +}; + +/* https://www.ti.com/lit/gpn/mspm0c1104 Table 8-12 and so on */ +static const struct mspm0_part_info mspm0c_parts[] = { + { "MSPS003F4SPW20R", 0x57b3, 0x70}, + { "MSPM0C1104SDGS20R", 0x57b3, 0x71}, + { "MSPM0C1104SRUKR", 0x57b3, 0x73}, + { "MSPM0C1104SDYYR", 0x57b3, 0x75}, + { "MSPM0C1104SDDFR", 0x57b3, 0x77}, + { "MSPM0C1104SDSGR", 0x57b3, 0x79}, +}; + +/* https://www.ti.com/lit/gpn/MSPM0L2228 Table 8-16 and so on */ +static const struct mspm0_part_info mspm0lx22x_parts[] = { + { "MSPM0L1227SRGER", 0x7C32, 0xF1}, + { "MSPM0L1227SPTR", 0x7C32, 0xC9}, + { "MSPM0L1227SPMR", 0x7C32, 0x1C}, + { "MSPM0L1227SPNAR", 0x7C32, 0x91}, + { "MSPM0L1227SPNR", 0x7C32, 0x39}, + { "MSPM0L1228SRGER", 0x33F7, 0x13}, + { "MSPM0L1228SRHBR", 0x33F7, 0x3A}, + { "MSPM0L1228SRGZR", 0x33F7, 0xBC}, + { "MSPM0L1228SPTR", 0x33F7, 0xF8}, + { "MSPM0L1228SPMR", 0x33F7, 0xCE}, + { "MSPM0L1228SPNAR", 0x33F7, 0x59}, + { "MSPM0L1228SPNR", 0x33F7, 0x7}, + { "MSPM0L2227SRGZR", 0x5E8F, 0x90}, + { "MSPM0L2227SPTR", 0x5E8F, 0xA}, + { "MSPM0L2227SPMR", 0x5E8F, 0x6D}, + { "MSPM0L2227SPNAR", 0x5E8F, 0x24}, + { "MSPM0L2227SPNR", 0x5E8F, 0x68}, + { "MSPM0L2228SRGZR", 0x2C38, 0xB8}, + { "MSPM0L2228SPTR", 0x2C38, 0x25}, + { "MSPM0L2228SPMR", 0x2C38, 0x6E}, + { "MSPM0L2228SPNAR", 0x2C38, 0x63}, + { "MSPM0L2228SPNR", 0x2C38, 0x3C}, +}; + +static const struct mspm0_family_info mspm0_finf[] = { + { "MSPM0L", 0xbb82, ARRAY_SIZE(mspm0l_parts), mspm0l_parts }, + { "MSPM0Lx22x", 0xbb9f, ARRAY_SIZE(mspm0lx22x_parts), mspm0lx22x_parts }, + { "MSPM0G", 0xbb88, ARRAY_SIZE(mspm0g_parts), mspm0g_parts }, + { "MSPM0C", 0xbba1, ARRAY_SIZE(mspm0c_parts), mspm0c_parts }, +}; + +/* + * OpenOCD command interface + */ + +/* + * flash_bank mspm0 0 0 + */ +FLASH_BANK_COMMAND_HANDLER(mspm0_flash_bank_command) +{ + struct mspm0_flash_bank *mspm0_info; + + switch (bank->base) { + case MSPM0_FLASH_BASE_NONMAIN: + case MSPM0_FLASH_BASE_MAIN: + case MSPM0_FLASH_BASE_DATA: + break; + default: + LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); + return ERROR_FAIL; + } + + mspm0_info = calloc(1, sizeof(struct mspm0_flash_bank)); + if (!mspm0_info) { + LOG_ERROR("%s: Out of memory for mspm0_info!", __func__); + return ERROR_FAIL; + } + + bank->driver_priv = mspm0_info; + + mspm0_info->sector_size = 0x400; + + return ERROR_OK; +} + +/* + * Chip identification and status + */ +static int get_mspm0_info(struct flash_bank *bank, struct command_invocation *cmd) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + command_print_sameline(cmd, + "\nTI MSPM0 information: Chip is " + "%s rev %d Device Unique ID: 0x%" PRIu32 "\n", + mspm0_info->name, mspm0_info->version, + mspm0_info->traceid); + command_print_sameline(cmd, + "main flash: %uKiB in %u bank(s), sram: %uKiB, data flash: %uKiB", + mspm0_info->main_flash_size_kb, + mspm0_info->main_flash_num_banks, mspm0_info->sram_size_kb, + mspm0_info->data_flash_size_kb); + + return ERROR_OK; +} + +/* Extract a bitfield helper */ +static unsigned int mspm0_extract_val(unsigned int var, unsigned char hi, unsigned char lo) +{ + return (var & GENMASK(hi, lo)) >> lo; +} + +static int mspm0_read_part_info(struct flash_bank *bank) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + struct target *target = bank->target; + const struct mspm0_family_info *minfo = NULL; + + /* Read and parse chip identification and flash version register */ + uint32_t did; + int retval = target_read_u32(target, MSPM0_DID, &did); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read device ID"); + return retval; + } + retval = target_read_u32(target, MSPM0_TRACEID, &mspm0_info->traceid); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read trace ID"); + return retval; + } + uint32_t userid; + retval = target_read_u32(target, MSPM0_USERID, &userid); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read user ID"); + return retval; + } + uint32_t flashram; + retval = target_read_u32(target, MSPM0_SRAMFLASH, &flashram); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read sramflash register"); + return retval; + } + uint32_t flashdesc; + retval = target_read_u32(target, FCTL_REG_DESC, &flashdesc); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read flashctl description register"); + return retval; + } + + unsigned char version = mspm0_extract_val(did, 31, 28); + unsigned short pnum = mspm0_extract_val(did, 27, 12); + unsigned char variant = mspm0_extract_val(userid, 23, 16); + unsigned short part = mspm0_extract_val(userid, 15, 0); + unsigned short manufacturer = mspm0_extract_val(did, 11, 1); + + /* + * Valid DIE and manufacturer ID? + * Check the ALWAYS_1 bit to be 1 and manufacturer to be 0x17. All MSPM0 + * devices within the Device ID field of the factory constants will + * always read 0x17 as it is TI's JEDEC bank and company code. If 1 + * and 0x17 is not read from their respective registers then it truly + * is not a MSPM0 device so we will return an error instead of + * going any further. + */ + if (!(did & BIT(0)) || !(manufacturer & TI_MANUFACTURER_ID)) { + LOG_WARNING("Unknown Device ID[0x%" PRIx32 "], cannot identify target", + did); + LOG_DEBUG("did 0x%" PRIx32 ", traceid 0x%" PRIx32 ", userid 0x%" PRIx32 + ", flashram 0x%" PRIx32 "", did, mspm0_info->traceid, userid, + flashram); + return ERROR_FLASH_OPERATION_FAILED; + } + + /* Initialize master index selector and probe status*/ + unsigned char minfo_idx = 0xff; + unsigned char probe_status = MSPM0_NO_ID_FOUND; + + /* Check if we at least know the family of devices */ + for (unsigned int i = 0; i < ARRAY_SIZE(mspm0_finf); i++) { + if (mspm0_finf[i].part_num == pnum) { + minfo_idx = i; + minfo = &mspm0_finf[i]; + probe_status = MSPM0_DEV_ID_FOUND; + break; + } + } + + /* Initialize part index selector*/ + unsigned char pinfo_idx = 0xff; + + /* + * If we can identify the part number then we will attempt to identify + * the specific chip. Otherwise, if we do not know the part number then + * it would be useless to identify the specific chip. + */ + if (probe_status == MSPM0_DEV_ID_FOUND) { + /* Can we specifically identify the chip */ + for (unsigned int i = 0; i < minfo->part_count; i++) { + if (minfo->part_info[i].part == part + && minfo->part_info[i].variant == variant) { + pinfo_idx = i; + probe_status = MSPM0_DEV_PART_ID_FOUND; + break; + } + } + } + + /* + * We will check the status of our probe within this switch-case statement + * using these three scenarios. + * + * 1) Device, part, and variant ID is unknown. + * 2) Device ID is known but the part/variant ID is unknown. + * 3) Device ID and part/variant ID is known + * + * For scenario 1, we allow the user to continue because if the + * manufacturer matches TI's JEDEC value and ALWAYS_1 from the device ID + * field is correct then the assumption the user is using an MSPM0 device + * can be made. + */ + switch (probe_status) { + case MSPM0_NO_ID_FOUND: + mspm0_info->name = "mspm0x"; + LOG_INFO("Unidentified PART[0x%x]/variant[0x%x" + "], unknown DeviceID[0x%x" + "]. Attempting to proceed as %s.", part, variant, pnum, + mspm0_info->name); + break; + case MSPM0_DEV_ID_FOUND: + mspm0_info->name = mspm0_finf[minfo_idx].family_name; + LOG_INFO("Unidentified PART[0x%x]/variant[0x%x" + "], known DeviceID[0x%x" + "]. Attempting to proceed as %s.", part, variant, pnum, + mspm0_info->name); + break; + case MSPM0_DEV_PART_ID_FOUND: + default: + mspm0_info->name = mspm0_finf[minfo_idx].part_info[pinfo_idx].part_name; + LOG_DEBUG("Part: %s detected", mspm0_info->name); + break; + } + + mspm0_info->did = did; + mspm0_info->version = version; + mspm0_info->data_flash_size_kb = mspm0_extract_val(flashram, 31, 26); + mspm0_info->main_flash_size_kb = mspm0_extract_val(flashram, 11, 0); + mspm0_info->main_flash_num_banks = mspm0_extract_val(flashram, 13, 12) + 1; + mspm0_info->sram_size_kb = mspm0_extract_val(flashram, 25, 16); + mspm0_info->flash_version = mspm0_extract_val(flashdesc, 15, 12); + + /* + * Hardcode flash_word_size unless we find some other pattern + * See section 7.7 (Foot note mentions the flash word size). + * almost all values seem to be 8 bytes, but if there are variance, + * then we should update mspm0_part_info structure with this info. + */ + mspm0_info->flash_word_size_bytes = 8; + + LOG_DEBUG("Detected: main flash: %uKb in %u banks, sram: %uKb, data flash: %uKb", + mspm0_info->main_flash_size_kb, mspm0_info->main_flash_num_banks, + mspm0_info->sram_size_kb, mspm0_info->data_flash_size_kb); + + return ERROR_OK; +} + +/* + * Decode error values + */ +static const struct { + const unsigned char bit_offset; + const char *fail_string; +} mspm0_fctl_fail_decode_strings[] = { + { 2, "CMDINPROGRESS" }, + { 4, "FAILWEPROT" }, + { 5, "FAILVERIFY" }, + { 6, "FAILILLADDR" }, + { 7, "FAILMODE" }, + { 12, "FAILMISC" }, +}; + +static const char *mspm0_fctl_translate_ret_err(unsigned int return_code) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(mspm0_fctl_fail_decode_strings); i++) { + if (return_code & BIT(mspm0_fctl_fail_decode_strings[i].bit_offset)) + return mspm0_fctl_fail_decode_strings[i].fail_string; + } + + /* If unknown error notify the user*/ + return "FAILUNKNOWN"; +} + +static int mspm0_fctl_get_sector_reg(struct flash_bank *bank, unsigned int addr, + unsigned int *reg, unsigned int *sector_mask) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + struct target *target = bank->target; + int ret = ERROR_OK; + unsigned int sector_num = (addr >> 10); + unsigned int sector_in_bank = sector_num; + unsigned int phys_sector_num = sector_num; + uint32_t sysctl_sec_status; + unsigned int exec_upper_bank; + + /* + * If the device has dual banks we will need to check if it is configured + * to execute from the upper bank. In the scenario that we are executing + * from upper bank then we will need to protect it using CMDWEPROTA rather + * than CMDWEPROTB. We also need to take into account what sector + * we're using when going between banks. + */ + if (mspm0_info->main_flash_num_banks > 1 && + bank->base == MSPM0_FLASH_BASE_MAIN) { + ret = target_read_u32(target, SYSCTL_SECCFG_SECSTATUS, &sysctl_sec_status); + if (ret != ERROR_OK) + return ret; + exec_upper_bank = mspm0_extract_val(sysctl_sec_status, 12, 12); + if (exec_upper_bank) { + if (sector_num > (mspm0_info->main_flash_size_kb / 2)) { + phys_sector_num = + sector_num - (mspm0_info->main_flash_size_kb / 2); + } else { + phys_sector_num = + sector_num + (mspm0_info->main_flash_size_kb / 2); + } + } + sector_in_bank = + sector_num % (mspm0_info->main_flash_size_kb / + mspm0_info->main_flash_num_banks); + } + + /* + * NOTE: MSPM0 devices of version A will use CMDWEPROTA and CMDWEPROTB + * for MAIN flash. CMDWEPROTC is included in the TRM/DATASHEET but for + * all practical purposes, it is considered reserved. If the flash + * version on the device is version B, then we will only use + * CMDWEPROTB for MAIN and DATA flash if the device has it. + */ + switch (bank->base) { + case MSPM0_FLASH_BASE_MAIN: + case MSPM0_FLASH_BASE_DATA: + if (mspm0_info->flash_version < FCTL_FEATURE_VER_B) { + /* Use CMDWEPROTA */ + if (phys_sector_num < 32) { + *sector_mask = BIT(phys_sector_num); + *reg = FCTL_REG_CMDWEPROTA; + } + + /* Use CMDWEPROTB */ + if (phys_sector_num >= 32 && sector_in_bank < 256) { + /* Dual bank system */ + if (mspm0_info->main_flash_num_banks > 1) + *sector_mask = BIT(sector_in_bank / 8); + else /* Single bank system */ + *sector_mask = BIT((sector_in_bank - 32) / 8); + *reg = FCTL_REG_CMDWEPROTB; + } + } else { + *sector_mask = BIT((sector_in_bank / 8) % 32); + *reg = FCTL_REG_CMDWEPROTB; + } + break; + case MSPM0_FLASH_BASE_NONMAIN: + *sector_mask = BIT(sector_num % 32); + *reg = FCTL_REG_CMDWEPROTNM; + break; + default: + /* + * Not expected to reach here due to check in mspm0_address_check() + * but adding it as another layer of safety. + */ + ret = ERROR_FLASH_DST_OUT_OF_BANK; + break; + } + + if (ret != ERROR_OK) + LOG_ERROR("Unable to map sector protect reg for address 0x%08x", addr); + + return ret; +} + +static int mspm0_address_check(struct flash_bank *bank, unsigned int addr) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + unsigned int flash_main_size = mspm0_info->main_flash_size_kb * 1024; + unsigned int flash_data_size = mspm0_info->data_flash_size_kb * 1024; + int ret = ERROR_FLASH_SECTOR_INVALID; + + /* + * Before unprotecting any memory lets make sure that the address and + * bank given is a known bank and whether or not the address falls under + * the proper bank. + */ + switch (bank->base) { + case MSPM0_FLASH_BASE_MAIN: + if (addr <= (MSPM0_FLASH_BASE_MAIN + flash_main_size)) + ret = ERROR_OK; + break; + case MSPM0_FLASH_BASE_NONMAIN: + if (addr >= MSPM0_FLASH_BASE_NONMAIN && addr <= MSPM0_FLASH_END_NONMAIN) + ret = ERROR_OK; + break; + case MSPM0_FLASH_BASE_DATA: + if (addr >= MSPM0_FLASH_BASE_DATA && + addr <= (MSPM0_FLASH_BASE_DATA + flash_data_size)) + ret = ERROR_OK; + break; + default: + ret = ERROR_FLASH_DST_OUT_OF_BANK; + break; + } + + return ret; +} + +static int mspm0_fctl_unprotect_sector(struct flash_bank *bank, unsigned int addr) +{ + struct target *target = bank->target; + unsigned int reg = 0x0; + uint32_t sector_mask = 0x0; + int ret; + + ret = mspm0_address_check(bank, addr); + switch (ret) { + case ERROR_FLASH_SECTOR_INVALID: + LOG_ERROR("Unable to map sector protect reg for address 0x%08x", addr); + break; + case ERROR_FLASH_DST_OUT_OF_BANK: + LOG_ERROR("Unable to determine which bank to use 0x%08x", addr); + break; + default: + mspm0_fctl_get_sector_reg(bank, addr, ®, §or_mask); + ret = target_write_u32(target, reg, ~sector_mask); + break; + } + + return ret; +} + +static int mspm0_fctl_cfg_command(struct flash_bank *bank, + uint32_t addr, + uint32_t cmd, + uint32_t byte_en) +{ + struct target *target = bank->target; + + /* + * Configure the flash operation within the CMDTYPE register, byte_en + * bits if needed, and then set the address where the flash operation + * will execute. + */ + int retval = target_write_u32(target, FCTL_REG_CMDTYPE, cmd); + if (retval != ERROR_OK) + return retval; + if (byte_en != 0) { + retval = target_write_u32(target, FCTL_REG_CMDBYTEN, byte_en); + if (retval != ERROR_OK) + return retval; + } + + return target_write_u32(target, FCTL_REG_CMDADDR, addr); +} + +static int mspm0_fctl_wait_cmd_ok(struct flash_bank *bank) +{ + struct target *target = bank->target; + uint32_t return_code = 0; + int64_t start_ms; + int64_t elapsed_ms; + + start_ms = timeval_ms(); + while ((return_code & FCTL_STATCMD_CMDDONE_MASK) != FCTL_STATCMD_CMDDONE_STATDONE) { + int retval = target_read_u32(target, FCTL_REG_STATCMD, &return_code); + if (retval != ERROR_OK) + return retval; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > MSPM0_FLASH_TIMEOUT_MS) + break; + } + + if ((return_code & FCTL_STATCMD_CMDPASS_MASK) != FCTL_STATCMD_CMDPASS_STATPASS) { + LOG_ERROR("Flash command failed: %s", mspm0_fctl_translate_ret_err(return_code)); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int mspm0_fctl_sector_erase(struct flash_bank *bank, uint32_t addr) +{ + struct target *target = bank->target; + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated. + * + * This means that as we start erasing sector by sector, the protection + * registers are reset and need to be unprotected *again* for the next + * erase operation. Unfortunately, this means that we cannot do a unitary + * unprotect operation independent of flash erase operation + */ + int retval = mspm0_fctl_unprotect_sector(bank, addr); + if (retval != ERROR_OK) { + LOG_ERROR("Unprotecting sector of memory at address 0x%08" PRIx32 + " failed", addr); + return retval; + } + + /* Actual erase operation */ + retval = mspm0_fctl_cfg_command(bank, addr, + (FCTL_CMDTYPE_COMMAND_ERASE | FCTL_CMDTYPE_SIZE_SECTOR), 0); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, FCTL_REG_CMDEXEC, FCTL_CMDEXEC_VAL_EXECUTE); + if (retval != ERROR_OK) + return retval; + + return mspm0_fctl_wait_cmd_ok(bank); +} + +static int mspm0_protect_check(struct flash_bank *bank) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated. + * + * This means that when any flash operation is performed at a block level, + * the block is locked back again. This prevents usage where we can set a + * protection level once at the flash level and then do erase / write + * operation without touching the protection register (since it is + * reset by hardware automatically). In effect, we cannot use the hardware + * defined protection scheme in openOCD. + * + * To deal with this protection scheme, the CMDWEPROTx register that + * correlates to the sector is modified at the time of operation and as far + * openOCD is concerned, the flash operates as completely un-protected + * flash. + */ + for (unsigned int i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_protected = 0; + + return ERROR_OK; +} + +static int mspm0_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + struct target *target = bank->target; + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + int retval = ERROR_OK; + uint32_t protect_reg_cache[MSPM0_MAX_PROTREGS]; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Please halt target for erasing flash"); + return ERROR_TARGET_NOT_HALTED; + } + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + /* Pick a copy of the current protection config for later restoration */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_read_u32(target, + mspm0_info->protect_reg_base + (i * 4), + &protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed saving flashctl protection status"); + return retval; + } + } + + switch (bank->base) { + case MSPM0_FLASH_BASE_MAIN: + for (unsigned int csa = first; csa <= last; csa++) { + unsigned int addr = csa * mspm0_info->sector_size; + retval = mspm0_fctl_sector_erase(bank, addr); + if (retval != ERROR_OK) + LOG_ERROR("Sector erase on MAIN failed at address 0x%08x " + "(sector: %u)", addr, csa); + } + break; + case MSPM0_FLASH_BASE_NONMAIN: + retval = mspm0_fctl_sector_erase(bank, MSPM0_FLASH_BASE_NONMAIN); + if (retval != ERROR_OK) + LOG_ERROR("Sector erase on NONMAIN failed"); + break; + case MSPM0_FLASH_BASE_DATA: + for (unsigned int csa = first; csa <= last; csa++) { + unsigned int addr = (MSPM0_FLASH_BASE_DATA + + (csa * mspm0_info->sector_size)); + retval = mspm0_fctl_sector_erase(bank, addr); + if (retval != ERROR_OK) + LOG_ERROR("Sector erase on DATA bank failed at address 0x%08x " + "(sector: %u)", addr, csa); + } + break; + default: + LOG_ERROR("Invalid memory region access"); + retval = ERROR_FLASH_BANK_INVALID; + break; + } + + /* If there were any issues in our checks, return the error */ + if (retval != ERROR_OK) + return retval; + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated + * Let us just Dump the protection registers back to the system. + * That way we retain the protection status as requested by the user + */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_write_u32(target, mspm0_info->protect_reg_base + (i * 4), + protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed re-applying protection status of flashctl"); + return retval; + } + } + + return retval; +} + +static int mspm0_write(struct flash_bank *bank, const unsigned char *buffer, + unsigned int offset, unsigned int count) +{ + struct target *target = bank->target; + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + uint32_t protect_reg_cache[MSPM0_MAX_PROTREGS]; + int retval; + + /* + * XXX: TRM Says: + * The number of program operations applied to a given word line must be + * monitored to ensure that the maximum word line program limit before + * erase is not violated. + * + * There is no reasonable way we can maintain that state in OpenOCD. So, + * Let the manufacturing path figure this out. + */ + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Please halt target for programming flash"); + return ERROR_TARGET_NOT_HALTED; + } + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + /* + * Pick a copy of the current protection config for later restoration + * We need to restore these regs after every write, so instead of trying + * to figure things out on the fly, we just context save and restore + */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_read_u32(target, + mspm0_info->protect_reg_base + (i * 4), + &protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed saving flashctl protection status"); + return retval; + } + } + + /* Add proper memory offset for bank being written to */ + unsigned int addr = bank->base + offset; + + while (count) { + unsigned int num_bytes_to_write; + uint32_t bytes_en; + + /* + * If count is not 64 bit aligned, we will do byte wise op to keep things simple + * Usually this might mean we need to additional write ops towards + * trailing edge, but that is a tiny penalty for image downloads. + * NOTE: we are going to assume the device does not support multi-word + * programming - there does not seem to be discoverability! + */ + if (count < mspm0_info->flash_word_size_bytes) + num_bytes_to_write = count; + else + num_bytes_to_write = mspm0_info->flash_word_size_bytes; + + /* Data bytes to write */ + bytes_en = (1 << num_bytes_to_write) - 1; + /* ECC chunks to write */ + switch (mspm0_info->flash_word_size_bytes) { + case 8: + bytes_en |= BIT(8); + break; + case 16: + bytes_en |= BIT(16); + bytes_en |= (num_bytes_to_write > 8) ? BIT(17) : 0; + break; + default: + LOG_ERROR("Invalid flash_word_size_bytes %d", + mspm0_info->flash_word_size_bytes); + return ERROR_FAIL; + } + + retval = mspm0_fctl_cfg_command(bank, addr, + (FCTL_CMDTYPE_COMMAND_PROGRAM | FCTL_CMDTYPE_SIZE_ONEWORD), + bytes_en); + if (retval != ERROR_OK) + return retval; + + retval = mspm0_fctl_unprotect_sector(bank, addr); + if (retval != ERROR_OK) + return retval; + + retval = target_write_buffer(target, FCTL_REG_CMDDATA0, num_bytes_to_write, buffer); + if (retval != ERROR_OK) + return retval; + + addr += num_bytes_to_write; + buffer += num_bytes_to_write; + count -= num_bytes_to_write; + + retval = target_write_u32(target, FCTL_REG_CMDEXEC, FCTL_CMDEXEC_VAL_EXECUTE); + if (retval != ERROR_OK) + return retval; + + retval = mspm0_fctl_wait_cmd_ok(bank); + if (retval != ERROR_OK) + return retval; + } + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated + * Let us just Dump the protection registers back to the system. + * That way we retain the protection status as requested by the user + */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_write_u32(target, + mspm0_info->protect_reg_base + (i * 4), + protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed re-applying protection status of flashctl"); + return retval; + } + } + + return ERROR_OK; +} + +static int mspm0_probe(struct flash_bank *bank) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + + /* + * If this is a mspm0 chip, it has flash; probe() is just + * to figure out how much is present. Only do it once. + */ + if (mspm0_info->did != 0) + return ERROR_OK; + + /* + * mspm0_read_part_info() already handled error checking and + * reporting. Note that it doesn't write, so we don't care about + * whether the target is halted or not. + */ + int retval = mspm0_read_part_info(bank); + if (retval != ERROR_OK) + return retval; + + if (bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + + bank->write_start_alignment = 4; + bank->write_end_alignment = 4; + + switch (bank->base) { + case MSPM0_FLASH_BASE_NONMAIN: + bank->size = 1024; + bank->num_sectors = 0x1; + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTNM; + mspm0_info->protect_reg_count = 1; + break; + case MSPM0_FLASH_BASE_MAIN: + bank->size = (mspm0_info->main_flash_size_kb * 1024); + bank->num_sectors = bank->size / mspm0_info->sector_size; + /* + * If the feature version bit read from the FCTL_REG_DESC is + * greater than or equal to 0xA then it means that the device + * will exclusively use CMDWEPROTB ONLY for MAIN memory protection + */ + if (mspm0_info->flash_version >= FCTL_FEATURE_VER_B) { + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTB; + mspm0_info->protect_reg_count = 1; + } else { + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTA; + mspm0_info->protect_reg_count = 3; + } + break; + case MSPM0_FLASH_BASE_DATA: + if (!mspm0_info->data_flash_size_kb) { + LOG_INFO("Data region NOT available!"); + bank->size = 0x0; + bank->num_sectors = 0x0; + return ERROR_OK; + } + /* + * Any MSPM0 device containing data bank will have a flashctl + * feature version of 0xA or higher. Since data bank is treated + * like MAIN memory, it will also exclusively use CMDWEPROTB for + * protection. + */ + bank->size = (mspm0_info->data_flash_size_kb * 1024); + bank->num_sectors = bank->size / mspm0_info->sector_size; + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTB; + mspm0_info->protect_reg_count = 1; + break; + default: + LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, + bank->base); + return ERROR_FAIL; + } + + bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); + if (!bank->sectors) { + LOG_ERROR("Out of memory for sectors!"); + return ERROR_FAIL; + } + for (unsigned int i = 0; i < bank->num_sectors; i++) { + bank->sectors[i].offset = i * mspm0_info->sector_size; + bank->sectors[i].size = mspm0_info->sector_size; + bank->sectors[i].is_erased = -1; + } + + return ERROR_OK; +} + +const struct flash_driver mspm0_flash = { + .name = "mspm0", + .flash_bank_command = mspm0_flash_bank_command, + .erase = mspm0_erase, + .protect = NULL, + .write = mspm0_write, + .read = default_flash_read, + .probe = mspm0_probe, + .auto_probe = mspm0_probe, + .erase_check = default_flash_blank_check, + .protect_check = mspm0_protect_check, + .info = get_mspm0_info, + .free_driver_priv = default_flash_free_driver_priv, +}; From c81cb4aa2d2b85a513f58d2ddbc492f606473c77 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 28 Sep 2023 03:37:03 -0500 Subject: [PATCH 1118/1312] tcl/target: Add support for TI MSPM0 Add basic support for Texas Instruments MSPM0L, C and G family of Cortex-M0 based micro-controllers. Change-Id: If2b5b1eca001f74d501ede67ec621c7497548a85 Co-developed-by: Henry Nguyen Signed-off-by: Henry Nguyen Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8385 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: zapb --- doc/openocd.texi | 20 ++++ tcl/target/ti_mspm0.cfg | 199 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 tcl/target/ti_mspm0.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 68c7a825bd..386528a9d6 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7438,6 +7438,7 @@ flash bank $_FLASHNAME mspm0 0 0 0 0 $_TARGETNAME halt flash erase_sector 0 0 last flash write_image MAIN.bin 0x0 +mspm0_board_reset @end example @item @b{To erase and program the NONMAIN region:} @@ -7445,10 +7446,29 @@ flash write_image MAIN.bin 0x0 halt flash erase_sector 1 0 last flash write_image NONMAIN.bin 0x41C00000 +mspm0_board_reset @end example @end itemize +@deffn {TCL proc} {mspm0_board_reset} +Performs an nRST toggle on the device. +@end deffn + +@deffn {TCL proc} {mspm0_mass_erase} +Sends the mass erase command to the SEC-AP mailbox and then performs +an nRST toggle. Once the command has been fully processed by the ROM, +all MAIN memory will be erased. NOTE: This command is not supported +on MSPM0C* family of devices. +@end deffn + +@deffn {TCL proc} {mspm0_factory_reset} +Sends the factory reset command to the SEC-AP mailbox and then performs +an nRST toggle. Once the command has been fully processed by the ROM, +all MAIN memory will be erased and NONMAIN will be reset to its default +values. +@end deffn + @end deffn @deffn {Flash Driver} {niietcm4} diff --git a/tcl/target/ti_mspm0.cfg b/tcl/target/ti_mspm0.cfg new file mode 100644 index 0000000000..4e9b89c1f5 --- /dev/null +++ b/tcl/target/ti_mspm0.cfg @@ -0,0 +1,199 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023-2025 Texas Instruments Incorporated - https://www.ti.com/ +# +# Texas Instruments MSPM0L/G - ARM Cortex-M0 @ 32MHz +# https://www.ti.com/microcontrollers-mcus-processors/arm-based-microcontrollers/arm-cortex-m0-mcus/overview.html +# + +source [find bitsbytes.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + # Meant to work with MSPM0L and MSPM0G class of devices. + set _CHIPNAME mspm0x +} + +if { [info exists CPUTAPID] } { + set _DAP_TAPID $CPUTAPID +} else { + set _DAP_TAPID 0x4ba00477 +} + +if { [info exists DAP_SWD_ID] } { + set _DAP_SWD_ID $DAP_SWD_ID +} else { + set _DAP_SWD_ID 0x2ba01477 +} + +source [find target/swj-dp.tcl] + +# MSPM0 only supports swd, so set it here and save a line for custom boards +transport select swd + +set _DAP_ID $_DAP_SWD_ID + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_ID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap + +if { [info exists WORKAREABASE] } { + set _WORKAREABASE $WORKAREABASE +} else { + set _WORKAREABASE 0x20000000 +} +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + # Smallest SRAM size is 1K SRAM. + set _WORKAREASIZE 0x400 +} + +# +# MSPM0 Debug SubSystem Mailbox (DSSM) Communication helpers +# + +proc _mspm0_wait_for_dssm_response {command} { + # Wait for SECAP::RCR rx_valid to be set + set timeout 1000 + while { [expr { [$::_CHIPNAME.dap apreg 2 0xc] & 0x1}] != 0x1 } { + sleep 1 + set timeout [expr {$timeout - 1}] + if { $timeout == 0 } { + set rcr [$::_CHIPNAME.dap apreg 2 0xc] + return -code error [format "MSPM0 SECAP RCR=0x%08x timeout rx_valid" $rcr] + } + } + + # Read SECAP::RXD to clear the RX_VALID bit + set rxd [$::_CHIPNAME.dap apreg 2 0x8] + # Read SECAP::RCR + set rcr [$::_CHIPNAME.dap apreg 2 0xc] + + # Check if we got successful response. This is denoted as: + # 8 LSBits of $command should matchup with SECAP::RCR + # and + # SECAP::RXD should be 0x10003 + if { ([expr { $command & 0xff}] == $rcr) && ($rxd == 0x10003) } { + return 0 + } + + # Provide some debug log for users to report back if CMD fails. + return -code error [format "MSPM0 SECAP CMD FAIL! RXD: 0x%08X RCR: 0x%08X" $rxd $rcr] +} + +proc _mspm0_dssm_command {command} { + # SECAP::TCR = command + $::_CHIPNAME.dap apreg 2 0x4 $command + # SECAP::TDR = 0x0 + $::_CHIPNAME.dap apreg 2 0x0 0x0 + # Read SECAP::RCR and RXD to clear up any prev pending reads + set rxd [$::_CHIPNAME.dap apreg 2 0x8] + set rcr [$::_CHIPNAME.dap apreg 2 0xc] + # Make sure everything is synced + sleep 1000 + # Trigger nRST + mspm0_board_reset + + # Wait for ROM to do it's magic and respond back + set res [_mspm0_wait_for_dssm_response $command] + if { $res } { + return $res + } + # Paranoid.. make sure ROM does what it is meant to do + # RX valid should have been cleared after the operation is + # complete + sleep 1000 + + # Trigger nRST to get back to sane system + mspm0_board_reset + sleep 1000 + + return 0 +} + +# NOTE: Password authentication scheme is NOT supported atm. +# mspm0_factory_reset: Factory reset the board +proc mspm0_factory_reset {} { + set res [_mspm0_dssm_command 0x020a] + if { $res } { + echo "Factory Reset failed!" + } else { + echo "Factory reset success! Halting processor" + # We need to halt the processor else the WDT fires! + halt + } + return $res +} + +add_help_text mspm0_factory_reset "Force Factory reset to recover 'bricked' board" + +# NOTE: Password authentication scheme is NOT supported atm. +# mspm0_mass_erase: Mass erase flash +proc mspm0_mass_erase {} { + set res [_mspm0_dssm_command 0x020c] + if { $res } { + echo "Mass Erase failed!" + } else { + echo "Mass Erase success! Halting Processor" + # We need to halt the processor else the WDT fires! + halt + } + return $res +} + +add_help_text mspm0_mass_erase "Mass erase flash" + +# mspm0_start_bootloader: Ask explicitly for bootloader startup +proc mspm0_start_bootloader {} { + set res [_mspm0_dssm_command 0x0108] + if { $res } { + echo "Start BL failed!" + } + return $res +} + +add_help_text mspm0_start_bootloader "Ask explicitly for bootloader startup" + +# MSPM0 requires board level NRST reset to be toggled for +# Factory reset operations to function. +# However this cannot be the default configuration as this +# prevents reset init reset halt to function properly +# since the Debug Subsystem (debugss) logic or coresight +# seems impacted by nRST. +# This can be overridden in board file as required. +# +# mspm0_board_reset: Board level reset +proc mspm0_board_reset {} { + set user_reset_config [reset_config] + reset_config srst_only + set errno [catch {reset}] + eval reset_config $user_reset_config + if {$errno} {error} +} + +add_help_text mspm0_board_reset "Request a board level reset" + +# If the flash is empty or the device is already in low-power state, then +# debug access is not available. to handle this, explicitly control power ap +# to provide access. Refer to Technical Reference Manual for further info. +proc _mspm0_enable_low_power_mode { } { + # PWR_AP::DPREC <= FRCACT(3)=1, RST_CTL(14:16)=1, IHIB_SLP(20)=1 + $::_CHIPNAME.dap apreg 4 0x00 0x104008 + # PWR_AP::SPREC <= SYSRST=1 + $::_CHIPNAME.dap apreg 4 0xF0 0x01 + # PWR_AP::DPREC <= FRCACT(3)=1, IHIB_SLP(20)=1 + $::_CHIPNAME.dap apreg 4 0x00 0x100008 +} + +$_TARGETNAME configure -event examine-start { _mspm0_enable_low_power_mode } +$_TARGETNAME configure -work-area-phys $_WORKAREABASE -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME.main mspm0 0 0 0 0 $_TARGETNAME +flash bank $_FLASHNAME.nonmain mspm0 0x41c00000 0 0 0 $_TARGETNAME +flash bank $_FLASHNAME.data mspm0 0x41d00000 0 0 0 $_TARGETNAME + +cortex_m reset_config sysresetreq From b7ad702bc884e6c37002b41afcac1dfdb6b030ee Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 28 Sep 2023 03:37:03 -0500 Subject: [PATCH 1119/1312] tcl/board: Add MSPM0 Launchpad support Add basic connection details for TI's MSPM0 Launchpad series of evaluation kits: https://www.ti.com/tool/LP-MSPM0L1306 https://www.ti.com/tool/LP-MSPM0C1104 https://www.ti.com/tool/LP-MSPM0G3507 Change-Id: I33499f2d5fef846185ff6c330f9bfd0251117eb6 Co-developed-by: Henry Nguyen Signed-off-by: Henry Nguyen Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8386 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/ti_mspm0_launchpad.cfg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tcl/board/ti_mspm0_launchpad.cfg diff --git a/tcl/board/ti_mspm0_launchpad.cfg b/tcl/board/ti_mspm0_launchpad.cfg new file mode 100644 index 0000000000..132fdc2a30 --- /dev/null +++ b/tcl/board/ti_mspm0_launchpad.cfg @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023-2025 Texas Instruments Incorporated - https://www.ti.com/ +# +# TI MSPM0L1306 LaunchPad Evaluation Kit +# https://www.ti.com/tool/LP-MSPM0L1306 +# TI MSPM0C1104 LaunchPad Evaluation Kit +# https://www.ti.com/tool/LP-MSPM0C1104 +# TI MSPM0G3507 LaunchPad Evaluation Kit +# https://www.ti.com/tool/LP-MSPM0G3507 +# + +source [find interface/xds110.cfg] +adapter speed 10000 +source [find target/ti_mspm0.cfg] From b2016dc44319ec6a872efbb656d32999f6732382 Mon Sep 17 00:00:00 2001 From: Daniel Goehring Date: Wed, 5 Mar 2025 17:48:01 -0500 Subject: [PATCH 1120/1312] target/target: fix RTOS thread awareness support This prior patch replaces "LOG_xxx()" with "LOG_TARGET_xxx()" to indicate which target the message belongs to. commit 7f2db80ebc16 ("rtos/hwthread: Use LOG_TARGET_xxx()") To support this change for hardware thread awareness, the target command name needs to be established before calling the "target_configure()" routine. Change-Id: I0dc70c23b84e983a2ee694fb5b9d01758f5c84a3 Signed-off-by: Daniel Goehring Reviewed-on: https://review.openocd.org/c/openocd/+/8800 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 0e41f0d10f..ce468cc90a 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5829,6 +5829,16 @@ static int target_create(struct jim_getopt_info *goi) target->gdb_port_override = NULL; target->gdb_max_connections = 1; + cp = Jim_GetString(new_cmd, NULL); + target->cmd_name = strdup(cp); + if (!target->cmd_name) { + LOG_ERROR("Out of memory"); + free(target->trace_info); + free(target->type); + free(target); + return JIM_ERR; + } + /* Do the rest as "configure" options */ goi->is_configure = true; e = target_configure(goi, target); @@ -5865,19 +5875,6 @@ static int target_create(struct jim_getopt_info *goi) target->endianness = TARGET_LITTLE_ENDIAN; } - cp = Jim_GetString(new_cmd, NULL); - target->cmd_name = strdup(cp); - if (!target->cmd_name) { - LOG_ERROR("Out of memory"); - rtos_destroy(target); - free(target->gdb_port_override); - free(target->trace_info); - free(target->type); - free(target->private_config); - free(target); - return JIM_ERR; - } - if (target->type->target_create) { e = (*(target->type->target_create))(target, goi->interp); if (e != ERROR_OK) { From f5dd564a7b089f7918dd0a93d04fd62ae1a79de5 Mon Sep 17 00:00:00 2001 From: Daniel Goehring Date: Thu, 6 Mar 2025 10:55:20 -0500 Subject: [PATCH 1121/1312] target/armv8: fix 128-bit register writes Assert checking was recently added to the "buf_get_u64()" procedure for the buffer size argument. For 128-bit register writes, instead of calling "buf_get_u64()" with a 128-bit argument which fails the assert check, use two 64-bit calls. Change-Id: I32ddbdb7bbe68c43f3b0a27738537391a227b08c Signed-off-by: Daniel Goehring Reviewed-on: https://review.openocd.org/c/openocd/+/8801 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv8.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 50a9f46883..40390731e8 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1686,12 +1686,12 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) struct arm_reg *armv8_reg = reg->arch_info; struct target *target = armv8_reg->target; struct arm *arm = target_to_arm(target); - uint64_t value = buf_get_u64(buf, 0, reg->size); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; if (reg->size <= 64) { + uint64_t value = buf_get_u64(buf, 0, reg->size); if (reg == arm->cpsr) armv8_set_cpsr(arm, (uint32_t)value); else { @@ -1699,6 +1699,7 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) reg->valid = true; } } else if (reg->size <= 128) { + uint64_t value = buf_get_u64(buf, 0, 64); uint64_t hvalue = buf_get_u64(buf + 8, 0, reg->size - 64); buf_set_u64(reg->value, 0, 64, value); From 5300242a3edad9924ed75119320e0fccc5afd614 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 3 Mar 2025 06:47:28 -0600 Subject: [PATCH 1122/1312] tcl/target/ti_k3: Add AM62L SoC Add support for the TI K3 family AM62L SoC. For further details, see https://www.ti.com/lit/pdf/sprujb4 Change-Id: I31e4e89507a1cd70a8c8c3242dd0a9dd7d0f2a06 Co-developed-by: Bryan Brattlof Signed-off-by: Bryan Brattlof Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8798 Tested-by: jenkins Reviewed-by: Bryan Brattlof Reviewed-by: Antonio Borneo --- tcl/target/ti_k3.cfg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 2ae0f75b80..b033ca9783 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -14,6 +14,8 @@ # Has 4 ARMV8 Cores and 2 R5 Cores # * AM62P: https://www.ti.com/lit/pdf/spruj83 # Has 4 ARMV8 Cores and 2 R5 Cores +# * AM62L: https://www.ti.com/lit/pdf/sprujb4 +# Has 2 ARMv8 Cores only # * AM642: https://www.ti.com/lit/pdf/spruim2 # Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3 # * AM654x: https://www.ti.com/lit/pdf/spruid7 @@ -233,6 +235,18 @@ switch $_soc { set R5_CTIBASE {0x9d418000 0x9d518000 0x9d818000} } } + am62l { + set _K3_DAP_TAPID 0x0bba702f + + # AM62Lx has 1 cluster of 2 A53 cores. + set _armv8_cpu_name a53 + set _armv8_cores 2 + set ARMV8_DBGBASE {0x90010000 0x90110000} + set ARMV8_CTIBASE {0x90020000 0x90120000} + + # Has no supporting microcontrollers + set _r5_cores 0 + } j721e { set _K3_DAP_TAPID 0x0bb6402f # J721E has 1 cluster of 2 A72 cores. From a8555b0b6d3e3c3150786550686292b1e69ec985 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 3 Mar 2025 06:57:23 -0600 Subject: [PATCH 1123/1312] tcl/board: Add TI am62levm config Add basic connection details with AM62l SK/EVM For further details, see: https://www.ti.com/tool/TMDS62LEVM Change-Id: Ic957a904dfe01951396f9767479884f2a121b181 Co-developed-by: Bryan Brattlof Signed-off-by: Bryan Brattlof Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8799 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/ti_am62levm.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/board/ti_am62levm.cfg diff --git a/tcl/board/ti_am62levm.cfg b/tcl/board/ti_am62levm.cfg new file mode 100644 index 0000000000..6debdd49f4 --- /dev/null +++ b/tcl/board/ti_am62levm.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/ +# +# Texas Instruments AM62L EVM: +# Links: https://www.ti.com/tool/TMDS62LEVM +# + +# the AM62L3 EVM/SK has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am62l +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 From a2c3c791ad86b12f7a689697166c46cb60db3c8b Mon Sep 17 00:00:00 2001 From: Shivasharan Nagalikar Date: Wed, 19 Feb 2025 13:53:03 +0530 Subject: [PATCH 1124/1312] tcl/target/ti_k3: Add support for system reset using powerAP TI K3 Debug systems have a Power Access Port (Power-AP) which allows for functionality such as reset via debugger that using the SPREC register. SoCs/Boards that do not have support for SRST or TRST can make use of this to force a system reset via debug access. Change-Id: Ic5f9cc7f7fba77b353b0c0b42d8afc02502251a0 Signed-off-by: Shivasharan Nagalikar Reviewed-on: https://review.openocd.org/c/openocd/+/8769 Reviewed-by: Nishanth Menon Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/ti_k3.cfg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index b033ca9783..dbf8962cbf 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -79,6 +79,12 @@ set _gp_mcu_ap_unlock_offsets {0xf0 0x60} # Generic mem-ap port number set _mem_ap_num 2 +# Generic AP_SEL PWR Register number +set _power_ap_num 3 + +# Generic SPREC RESET BANK and Field number +set _powerap_sprec_reset 0xf0 + # Set configuration overrides for each SOC switch $_soc { am263 { @@ -96,6 +102,8 @@ switch $_soc { set R5_DBGBASE {0x90030000 0x90032000 0x90050000 0x90052000} set R5_CTIBASE {0x90038000 0x90039000 0x90058000 0x90059000} set _r5_ap_num 5 + + set _power_ap_num 7 } am273 { set _K3_DAP_TAPID 0x1bb6a02f @@ -513,3 +521,10 @@ if { 0 == [string compare [adapter name] dmem ] } { # AXI AP access port for SoC address map target create $_CHIPNAME.axi_ap mem_ap -dap $_CHIPNAME.dap -ap-num $_mem_ap_num } + +# Reset system using (Debug Reset) SPREC Register,SYSTEMRESET bit field via apreg +proc dbg_sys_reset {} { + $::_CHIPNAME.dap apreg $::_power_ap_num $::_powerap_sprec_reset 0x1 +} + +add_help_text dbg_sys_reset "Debugger initiated system reset attempt via Power-AP" From 9e5ffed7d6f045f86a35beab461018bab2c1da0c Mon Sep 17 00:00:00 2001 From: Shivasharan Nagalikar Date: Wed, 19 Feb 2025 13:57:35 +0530 Subject: [PATCH 1125/1312] tcl/target/ti_k3: Add support for AM263P AM263P[1] adds additional features to AM263 SoC. [2] provides a detailed list of differences, however, the key difference from processor usage perspective is the increased SRAM and Remote L2(RL2) Cache for improved performance of R5F. To differentiate the DIE ID is different, however rest of the processor description remain compatible to AM263, hence reuse the definition. [1] https://www.ti.com/product/AM263P4 [2] https://www.ti.com/lit/pdf/spradb3 Change-Id: If47935caf1f995d7e606547e0d6545c39544678a Signed-off-by: Shivasharan Nagalikar Reviewed-on: https://review.openocd.org/c/openocd/+/8770 Reviewed-by: Nishanth Menon Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/ti_k3.cfg | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index dbf8962cbf..2feffb92e5 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -6,6 +6,8 @@ # Has 4 R5 Cores, M4F and an M3 # * AM263: https://www.ti.com/lit/pdf/spruj17 # Has 4 R5 Cores and an M3 +# * AM263P: https://www.ti.com/lit/pdf/spruj55 +# Has 4 R5 Cores and an M4F # * AM273: https://www.ti.com/lit/pdf/spruiu0 # Has 2 R5 Cores and an M3 # * AM625: https://www.ti.com/lit/pdf/spruiv7a @@ -87,6 +89,7 @@ set _powerap_sprec_reset 0xf0 # Set configuration overrides for each SOC switch $_soc { + am263p - am263 { set _K3_DAP_TAPID 0x2bb7d02f @@ -104,6 +107,10 @@ switch $_soc { set _r5_ap_num 5 set _power_ap_num 7 + + if { "$_soc" == "am263p" } { + set _K3_DAP_TAPID 0x1bb9502f + } } am273 { set _K3_DAP_TAPID 0x1bb6a02f From c00228468cc039437bae5e41df3df4aa793e6a52 Mon Sep 17 00:00:00 2001 From: Shivasharan Nagalikar Date: Fri, 21 Feb 2025 16:31:03 +0530 Subject: [PATCH 1126/1312] tcl/board: Add TI AM263P launchpad config Add basic connection details with AM263P Launchpad For further details, see: https://www.ti.com/tool/LP-AM263P Change-Id: I7232a0b9337583eab499bc72929bd059624b4ff1 Signed-off-by: Shivasharan Nagalikar Reviewed-on: https://review.openocd.org/c/openocd/+/8771 Reviewed-by: Antonio Borneo Reviewed-by: Nishanth Menon Tested-by: jenkins --- tcl/board/ti_am263p_launchpad.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/board/ti_am263p_launchpad.cfg diff --git a/tcl/board/ti_am263p_launchpad.cfg b/tcl/board/ti_am263p_launchpad.cfg new file mode 100644 index 0000000000..96e06fab6b --- /dev/null +++ b/tcl/board/ti_am263p_launchpad.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/ +# +# Texas Instruments AM263P Launchpad +# https://www.ti.com/tool/LP-AM263P +# + +# AM263P Launchpad has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am263p +} + +source [find target/ti_k3.cfg] + +adapter speed 250 From da7e369266b7b5e1fea4e2baa072dac8ce15217b Mon Sep 17 00:00:00 2001 From: Shivasharan Nagalikar Date: Wed, 19 Feb 2025 13:58:43 +0530 Subject: [PATCH 1127/1312] tcl/target/ti_k3: Add support for AM261 AM261[1] is a optimized cutdown of AM263P SoC. The key difference is the reduced number of R5F cores which is now dropped down to 2, and the DIE ID is different from AM263p, but all other definitions are compatible, so reuse the definition. [1] https://www.ti.com/product/AM2612 Change-Id: Ib6ca0b59d0b8991df6e4ab349d371187438cb393 Signed-off-by: Shivasharan Nagalikar Reviewed-on: https://review.openocd.org/c/openocd/+/8792 Reviewed-by: Antonio Borneo Reviewed-by: Nishanth Menon Tested-by: jenkins --- tcl/target/ti_k3.cfg | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 2feffb92e5..0dee74e5ee 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -4,6 +4,8 @@ # Texas Instruments K3 devices: # * AM243: https://www.ti.com/lit/pdf/spruim2 # Has 4 R5 Cores, M4F and an M3 +# * AM261: https://www.ti.com/lit/pdf/sprujb6 +# Has 2 R5 Cores and an M4F # * AM263: https://www.ti.com/lit/pdf/spruj17 # Has 4 R5 Cores and an M3 # * AM263P: https://www.ti.com/lit/pdf/spruj55 @@ -89,6 +91,7 @@ set _powerap_sprec_reset 0xf0 # Set configuration overrides for each SOC switch $_soc { + am261 - am263p - am263 { set _K3_DAP_TAPID 0x2bb7d02f @@ -111,6 +114,10 @@ switch $_soc { if { "$_soc" == "am263p" } { set _K3_DAP_TAPID 0x1bb9502f } + if { "$_soc" == "am261" } { + set _K3_DAP_TAPID 0x1bba602f + set _r5_cores 2 + } } am273 { set _K3_DAP_TAPID 0x1bb6a02f From 80b1c9aff8ad450839859e4a29559f6bdc481891 Mon Sep 17 00:00:00 2001 From: Shivasharan Nagalikar Date: Fri, 21 Feb 2025 16:33:37 +0530 Subject: [PATCH 1128/1312] tcl/board: Add TI AM261 launchpad config Add basic connection details with AM261 Launchpad. For further details, see https://www.ti.com/tool/LP-AM261 Signed-off-by: Shivasharan Nagalikar Change-Id: Ibf1270a8e470cc6ab5846dc3da64e451a8a769fd Reviewed-on: https://review.openocd.org/c/openocd/+/8793 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Nishanth Menon --- tcl/board/ti_am261_launchpad.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/board/ti_am261_launchpad.cfg diff --git a/tcl/board/ti_am261_launchpad.cfg b/tcl/board/ti_am261_launchpad.cfg new file mode 100644 index 0000000000..c6c4609ed1 --- /dev/null +++ b/tcl/board/ti_am261_launchpad.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/ +# +# Texas Instruments AM261 Launchpad +# https://www.ti.com/tool/LP-AM261 +# + +# AM263 Launchpad has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am261 +} + +source [find target/ti_k3.cfg] + +adapter speed 250 From d892a4d763c283ca775213d4148b76d5b0fde520 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 4 Dec 2024 08:26:04 +0100 Subject: [PATCH 1129/1312] target/arm_adiv5: print DAP name if not found If a DAP is not found, include its name in the error message. Change-Id: Icffc52894a1c5573f938b1f3e3b53441167f085e Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8636 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_adi_v5.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 0c7633beab..df897b80ed 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -2367,7 +2367,9 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, return e; dap = dap_instance_by_jim_obj(goi->interp, o_t); if (!dap) { - Jim_SetResultString(goi->interp, "DAP name invalid!", -1); + const char *dap_name = Jim_GetString(o_t, NULL); + Jim_SetResultFormatted(goi->interp, "DAP '%s' not found", + dap_name); return JIM_ERR; } if (*dap_p && *dap_p != dap) { From 16c6497a89600ab8e8b354e2fc2c0ceb9ae74330 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 14 Feb 2025 19:31:38 +0300 Subject: [PATCH 1130/1312] rtos/linux: fix name overwrite in `linux_thread_extra_info()` commit 908ee4dc9641bd3df2eb00264575501867da539d ("build: remove clang unused variable assignment warnings") introduced an error: ``` - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", name); + sprintf(tmp_str_ptr, "%s", name); sprintf(tmp_str_ptr, "%s", temp->name); ``` This results in `name` being overwritten by `temp->name`. Fix this, adding OOM handling along the way. Change-Id: Id41f73247c3f7e6194d7c92187ad3163a9ea6c89 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8761 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtos/linux.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 91d9a39f24..5efdc9f609 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -1120,23 +1120,13 @@ static int linux_thread_extra_info(struct target *target, while (temp) { if (temp->threadid == threadid) { - char *pid = " PID: "; - char *pid_current = "*PID: "; - char *name = "Name: "; - int str_size = strlen(pid) + strlen(name); - char *tmp_str = calloc(1, str_size + 50); - char *tmp_str_ptr = tmp_str; - - /* discriminate current task */ - if (temp->status == 3) - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", - pid_current); - else - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid); - - tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid); - sprintf(tmp_str_ptr, "%s", name); - sprintf(tmp_str_ptr, "%s", temp->name); + char *tmp_str = alloc_printf("%cPID: %" PRIu32 ", Name: %s", + temp->status == 3 ? '*' : ' ', + temp->pid, temp->name); + if (!tmp_str) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, strlen(tmp_str), strlen(tmp_str) * 2 + 1); From fdd0c2b1d370e48186329cf7b81b42fa60b0e4bc Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 16 Feb 2025 19:59:27 +0100 Subject: [PATCH 1131/1312] configure.ac: show the JTAG DPI and VPI adapters in the config summary Also enable these adapters by default (auto). Change-Id: Icbbcd470eaf1d1bfb33900885776c1dbd0cccb5f Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8758 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/configure.ac b/configure.ac index e31e056cc7..75c8e5d8a7 100644 --- a/configure.ac +++ b/configure.ac @@ -178,6 +178,12 @@ m4_define([LINUXSPIDEV_ADAPTER], m4_define([VDEBUG_ADAPTER], [[[vdebug], [Cadence Virtual Debug Interface], [VDEBUG]]]) +m4_define([JTAG_DPI_ADAPTER], + [[[jtag_dpi], [JTAG DPI Adapter], [JTAG_DPI]]]) + +m4_define([JTAG_VPI_ADAPTER], + [[[jtag_vpi], [JTAG VPI Adapter], [JTAG_VPI]]]) + # The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter # because there is an M4 macro called 'adapter'. m4_define([DUMMY_ADAPTER], @@ -308,6 +314,8 @@ AC_ARG_ADAPTERS([ SERIAL_PORT_ADAPTERS, DUMMY_ADAPTER, VDEBUG_ADAPTER, + JTAG_DPI_ADAPTER, + JTAG_VPI_ADAPTER, PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) @@ -326,14 +334,6 @@ AC_ARG_ENABLE([parport_giveio], [Enable use of giveio for parport (for CygWin only)]), [parport_use_giveio=$enableval], [parport_use_giveio=]) -AC_ARG_ENABLE([jtag_vpi], - AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]), - [build_jtag_vpi=$enableval], [build_jtag_vpi=no]) - -AC_ARG_ENABLE([jtag_dpi], - AS_HELP_STRING([--enable-jtag_dpi], [Enable building support for JTAG DPI]), - [build_jtag_dpi=$enableval], [build_jtag_dpi=no]) - AC_ARG_ENABLE([amtjtagaccel], AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) @@ -577,19 +577,6 @@ AS_IF([test "x$parport_use_giveio" = "xyes"], [ AC_DEFINE([PARPORT_USE_GIVEIO], [0], [0 if you don't want parport to use giveio.]) ]) -AS_IF([test "x$build_jtag_vpi" = "xyes"], [ - AC_DEFINE([BUILD_JTAG_VPI], [1], [1 if you want JTAG VPI.]) -], [ - AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.]) -]) - -AS_IF([test "x$build_jtag_dpi" = "xyes"], [ - AC_DEFINE([BUILD_JTAG_DPI], [1], [1 if you want JTAG DPI.]) -], [ - AC_DEFINE([BUILD_JTAG_DPI], [0], [0 if you don't want JTAG DPI.]) -]) - - AS_IF([test "x$build_amtjtagaccel" = "xyes"], [ AC_DEFINE([BUILD_AMTJTAGACCEL], [1], [1 if you want the Amontec JTAG-Accelerator driver.]) ], [ @@ -735,6 +722,8 @@ PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], [internal error: validation should happen beforehand]) PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev]) PROCESS_ADAPTERS([VDEBUG_ADAPTER], [true], [unused]) +PROCESS_ADAPTERS([JTAG_DPI_ADAPTER], [true], [unused]) +PROCESS_ADAPTERS([JTAG_VPI_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -782,8 +771,6 @@ AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"]) AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"]) AM_CONDITIONAL([AM335XGPIO], [test "x$build_am335xgpio" = "xyes"]) AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) -AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes"]) -AM_CONDITIONAL([JTAG_DPI], [test "x$build_jtag_dpi" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"]) AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) @@ -889,6 +876,8 @@ m4_foreach([adapter], [USB1_ADAPTERS, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, LINUXSPIDEV_ADAPTER, VDEBUG_ADAPTER, + JTAG_DPI_ADAPTER, + JTAG_VPI_ADAPTER, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], From a2d4b9b718552a4bbb88e0f210444b4f5047bc0c Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 3 Nov 2024 12:24:20 +0100 Subject: [PATCH 1132/1312] bcm2835gpio.c: change adapter init order Make also sure that the struct bitbang_interface with callbacks that we pass to the bitbang driver is const. Change-Id: I954014f062d6d9185db45f5fbd2ad0b0955aab82 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8536 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/bcm2835gpio.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 095601fa61..e8689aa037 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -427,7 +427,7 @@ static int bcm2835gpio_blink(bool on) return ERROR_OK; } -static struct bitbang_interface bcm2835gpio_bitbang = { +static const struct bitbang_interface bcm2835gpio_bitbang_swd_write_generic = { .read = bcm2835gpio_read, .write = bcm2835gpio_write, .swdio_read = bcm2835_swdio_read, @@ -436,11 +436,19 @@ static struct bitbang_interface bcm2835gpio_bitbang = { .blink = bcm2835gpio_blink, }; +static const struct bitbang_interface bcm2835gpio_bitbang_swd_write_fast = { + .read = bcm2835gpio_read, + .write = bcm2835gpio_write, + .swdio_read = bcm2835_swdio_read, + .swdio_drive = bcm2835_swdio_drive, + .swd_write = bcm2835gpio_swd_write_fast, + .blink = bcm2835gpio_blink, +}; + static int bcm2835gpio_init(void) { LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver"); - bitbang_interface = &bcm2835gpio_bitbang; adapter_gpio_config = adapter_gpio_get_config(); if (transport_is_jtag() && !bcm2835gpio_jtag_mode_possible()) { @@ -509,6 +517,8 @@ LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]); initialize_gpio(ADAPTER_GPIO_IDX_TRST); } + const struct bitbang_interface *bcm2835gpio_bitbang = &bcm2835gpio_bitbang_swd_write_generic; + if (transport_is_swd()) { /* swdio and its buffer should be initialized in the order that prevents * two outputs from being connected together. This will occur if the @@ -529,16 +539,18 @@ LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]); if (adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL && adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) { LOG_DEBUG("BCM2835 GPIO using fast mode for SWD write"); - bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_fast; + bcm2835gpio_bitbang = &bcm2835gpio_bitbang_swd_write_fast; } else { LOG_DEBUG("BCM2835 GPIO using generic mode for SWD write"); - bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_generic; + assert(bcm2835gpio_bitbang == &bcm2835gpio_bitbang_swd_write_generic); } } initialize_gpio(ADAPTER_GPIO_IDX_SRST); initialize_gpio(ADAPTER_GPIO_IDX_LED); + bitbang_interface = bcm2835gpio_bitbang; + return ERROR_OK; } From e12ceddd5ee4d946107e3764d05ce2810befb293 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 14 Feb 2025 19:20:58 +0300 Subject: [PATCH 1133/1312] helper/log: mark `fmt` argument of `alloc_vprintf()` as format string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building on Ubuntu 22.04 with `-fsanitize=undefined` (GCC 12.3.0) results in an error: Checkpatch-ignore: COMMIT_LOG_LONG_LINE ``` In file included from /usr/include/stdio.h:894, from /src/helper/system.h:23, from /src/helper/replacements.h:18, from /src/helper/log.c:20: In function ‘vsnprintf’, inlined from ‘alloc_vprintf’ at /src/helper/log.c:347:8: /usr/include/x86_64-linux-gnu/bits/stdio2.h:85:10: error: null format string [-Werror=format-truncation=] 85 | return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 86 | __glibc_objsize (__s), __fmt, __ap); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors ``` The error mentiones the call site `src/helper/log.c:347`. There `vsnprintf()` is called passing `fmt` as format string. To mitigate this, mark the format string with the corresponding attribute in `alloc_vprintf()` Change-Id: I91011490715998ef5a931c19c3c9d74a1a304e5d Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8764 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/helper/log.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helper/log.h b/src/helper/log.h index e2bb131ed3..ac24f8e833 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -85,7 +85,8 @@ struct log_callback { int log_add_callback(log_callback_fn fn, void *priv); int log_remove_callback(log_callback_fn fn, void *priv); -char *alloc_vprintf(const char *fmt, va_list ap); +char *alloc_vprintf(const char *fmt, va_list ap) + __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 0))); char *alloc_printf(const char *fmt, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2))); From e4a51b3235167ea2fccf399d55dc3fe87364dbb8 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 23 Dec 2024 20:59:28 +0100 Subject: [PATCH 1134/1312] doc: drop mention of not implemented SPI transport The commit 93f2afa45f4c ("initial "transport" framework") adds a dedicated chapter in the documentation about a possible SPI transport for flashing. This transport has never been part of OpenOCD and should not be listed in the documentation. Drop the chapter. Change-Id: I9b406754399abda4dc7c2f8cf09dd47730a7e1d9 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8670 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/openocd.texi | 7 ------- 1 file changed, 7 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 386528a9d6..140d0f8c77 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3816,13 +3816,6 @@ Not all adapters and adapter drivers support SWD multi-drop. Only the following adapter drivers are SWD multi-drop capable: cmsis_dap (use an adapter with CMSIS-DAP version 2.0), ftdi, all bitbang based. -@subsection SPI Transport -@cindex SPI -@cindex Serial Peripheral Interface -The Serial Peripheral Interface (SPI) is a general purpose transport -which uses four wire signaling. Some processors use it as part of a -solution for flash programming. - @anchor{swimtransport} @subsection SWIM Transport @cindex SWIM From 6beb6280af985e79094501af5cb66d1a33019544 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 22 Dec 2024 17:13:59 +0100 Subject: [PATCH 1135/1312] adapter: drop command 'adapter transports' The commit 93f2afa45f4c ("initial "transport" framework") that added the transport framework in 2010 was overly optimistic on the possibility to dynamically add, at runtime, a new adapter and to specify with the command 'adapter transports' the list of the transports supported by the new adapter. Such feature has never become part of OpenOCD, and the command above has never become useful nor ever been used. Drop the command 'adapter transports' and its documentation. Drop the helper 'transport_list_parse', now unused. Change-Id: Ie3d71c74d068fba802839b116bb9bc9af77cc83d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8671 Reviewed-by: Tomas Vanek Tested-by: jenkins --- doc/openocd.texi | 6 ----- src/jtag/adapter.c | 26 --------------------- src/transport/transport.c | 48 --------------------------------------- src/transport/transport.h | 2 -- 4 files changed, 82 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 140d0f8c77..9ff524b749 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2415,12 +2415,6 @@ target. List the debug adapter drivers that have been built into the running copy of OpenOCD. @end deffn -@deffn {Config Command} {adapter transports} transport_name+ -Specifies the transports supported by this debug adapter. -The adapter driver builds-in similar knowledge; use this only -when external configuration (such as jumpering) changes what -the hardware can support. -@end deffn @anchor{adapter gpio} @deffn {Config Command} {adapter gpio [ @ diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 04942f753b..db3d3b0fe8 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -392,25 +392,6 @@ COMMAND_HANDLER(handle_adapter_name) return ERROR_OK; } -COMMAND_HANDLER(adapter_transports_command) -{ - char **transports; - int retval; - - retval = CALL_COMMAND_HANDLER(transport_list_parse, &transports); - if (retval != ERROR_OK) - return retval; - - retval = allow_transports(CMD_CTX, (const char **)transports); - - if (retval != ERROR_OK) { - for (unsigned int i = 0; transports[i]; i++) - free(transports[i]); - free(transports); - } - return retval; -} - COMMAND_HANDLER(handle_adapter_list_command) { if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0) @@ -1137,13 +1118,6 @@ static const struct command_registration adapter_command_handlers[] = { .usage = "", .chain = adapter_srst_command_handlers, }, - { - .name = "transports", - .handler = adapter_transports_command, - .mode = COMMAND_CONFIG, - .help = "Declare transports the adapter supports.", - .usage = "transport ...", - }, { .name = "usb", .mode = COMMAND_ANY, diff --git a/src/transport/transport.c b/src/transport/transport.c index c7293e7fda..0af1360369 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -166,54 +166,6 @@ struct transport *get_current_transport(void) * Infrastructure for Tcl interface to transports. */ -/** - * Makes and stores a copy of a set of transports passed as - * parameters to a command. - * - * @param vector where the resulting copy is stored, as an argv-style - * NULL-terminated vector. - */ -COMMAND_HELPER(transport_list_parse, char ***vector) -{ - char **argv; - unsigned int n = CMD_ARGC; - unsigned int j = 0; - - *vector = NULL; - - if (n < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - /* our return vector must be NULL terminated */ - argv = calloc(n + 1, sizeof(char *)); - if (!argv) - return ERROR_FAIL; - - for (unsigned int i = 0; i < n; i++) { - struct transport *t; - - for (t = transport_list; t; t = t->next) { - if (strcmp(t->name, CMD_ARGV[i]) != 0) - continue; - argv[j++] = strdup(CMD_ARGV[i]); - break; - } - if (!t) { - LOG_ERROR("no such transport '%s'", CMD_ARGV[i]); - goto fail; - } - } - - *vector = argv; - return ERROR_OK; - -fail: - for (unsigned int i = 0; i < n; i++) - free(argv[i]); - free(argv); - return ERROR_FAIL; -} - COMMAND_HANDLER(handle_transport_init) { LOG_DEBUG("%s", __func__); diff --git a/src/transport/transport.h b/src/transport/transport.h index 00d8b07e11..2e3dcc61aa 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -77,8 +77,6 @@ struct transport *get_current_transport(void); int transport_register_commands(struct command_context *ctx); -COMMAND_HELPER(transport_list_parse, char ***vector); - int allow_transports(struct command_context *ctx, const char * const *vector); bool transport_is_jtag(void); From 427528069806b20c05c78f935529bd62308351a9 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 1 Dec 2024 00:01:00 +0100 Subject: [PATCH 1136/1312] adapter: simplify command 'adapter list' The code of command 'adapter list' is called by command 'adapter driver' to list the available drivers in case of error. This dual possible entry points require a conditional check on the number of command line arguments, reducing the code readability. Split the command in a simpler code for the command 'adapter list' that only checks the command line, and move in a common helper the code that list the drivers. While there, fix the output and the comments to report 'adapter driver' instead of 'debug adapters'; we are not parsing the HW to know which adapter is present. Change-Id: I17538e86dc4a31a9589d404e49dcc65a29393390 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8672 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/adapter.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index db3d3b0fe8..2fcbd609e8 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -392,12 +392,8 @@ COMMAND_HANDLER(handle_adapter_name) return ERROR_OK; } -COMMAND_HANDLER(handle_adapter_list_command) +COMMAND_HANDLER(dump_adapter_driver_list) { - if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0) - return ERROR_COMMAND_SYNTAX_ERROR; - - command_print(CMD, "The following debug adapters are available:"); for (unsigned int i = 0; adapter_drivers[i]; i++) { const char *name = adapter_drivers[i]->name; command_print(CMD, "%u: %s", i + 1, name); @@ -406,6 +402,14 @@ COMMAND_HANDLER(handle_adapter_list_command) return ERROR_OK; } +COMMAND_HANDLER(handle_adapter_list_command) +{ + if (CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + + return CALL_COMMAND_HANDLER(dump_adapter_driver_list); +} + COMMAND_HANDLER(handle_adapter_driver_command) { int retval; @@ -440,7 +444,8 @@ COMMAND_HANDLER(handle_adapter_driver_command) */ LOG_ERROR("The specified debug interface was not found (%s)", CMD_ARGV[0]); - CALL_COMMAND_HANDLER(handle_adapter_list_command); + command_print(CMD, "The following adapter drivers are available:"); + CALL_COMMAND_HANDLER(dump_adapter_driver_list); return ERROR_JTAG_INVALID_INTERFACE; } From bb4c7e323393c74be1cba3836a32f0aa4a9b0dc7 Mon Sep 17 00:00:00 2001 From: Adrien Grassein Date: Thu, 18 Jan 2024 12:04:02 +0100 Subject: [PATCH 1137/1312] tcl/ngultra: Use newly created armv8r target ngultra cores are cortex-r52, so use armv8r target now its created. Change-Id: If2d22593ab1e200ac15e7b883c70937acf1d2a59 Signed-off-by: Adrien Grassein Signed-off-by: Adrien Charruel Reviewed-on: https://review.openocd.org/c/openocd/+/8658 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/ngultra.cfg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tcl/target/ngultra.cfg b/tcl/target/ngultra.cfg index 956fdbb5ca..9f9814fd75 100644 --- a/tcl/target/ngultra.cfg +++ b/tcl/target/ngultra.cfg @@ -36,12 +36,11 @@ dap create $_CHIPNAME.coresight.dap -chain-position $_CHIPNAME.coresight.cpu for { set _core 0 } { $_core < $_cores } { incr _core } { cti create cti.$_core -dap $_CHIPNAME.coresight.dap -ap-num 0 \ -baseaddr [lindex $CTIBASE $_core] -# Cores are armv8-r but works with aarch64 (since armv8-r not directly supported by openocd yet). if { $_core == 0} { - target create core.$_core aarch64 -dap $_CHIPNAME.coresight.dap \ + target create core.$_core armv8r -dap $_CHIPNAME.coresight.dap \ -ap-num 0 -dbgbase [lindex $DBGBASE $_core] -cti cti.$_core } else { - target create core.$_core aarch64 -dap $_CHIPNAME.coresight.dap \ + target create core.$_core armv8r -dap $_CHIPNAME.coresight.dap \ -ap-num 0 -dbgbase [lindex $DBGBASE $_core] -cti cti.$_core -defer-examine } } From 72ff2e2d9f869cd19951ce101e5ac61209ec434d Mon Sep 17 00:00:00 2001 From: Adrien Grassein Date: Thu, 18 Jan 2024 15:12:12 +0100 Subject: [PATCH 1138/1312] target/armv8: regularly send keep_alive packet. Flushing all d-cache may be a long operation. We need to send keep_alive regularly to keep the connection alive. If not done a warning is emitted. Change-Id: I52c3ee9a9f9b8a1dc0b8d5439e8b71212f56165a Signed-off-by: Adrien Grassein Signed-off-by: Adrien Charruel Reviewed-on: https://review.openocd.org/c/openocd/+/8659 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv8_cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index 66d4e00801..74d063b0e8 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -61,6 +61,7 @@ static int armv8_cache_d_inner_flush_level(struct armv8_common *armv8, struct ar goto done; c_way -= 1; } while (c_way >= 0); + keep_alive(); c_index -= 1; } while (c_index >= 0); From 6d139422cb22ab3fc78f903038a7288acde4e4d4 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 23 Nov 2024 18:15:40 +0100 Subject: [PATCH 1139/1312] helper: command: return correct error on command 'echo' In case of incorrect syntax, return ERROR_COMMAND_SYNTAX_ERROR so the command framework will print the usage string. Change-Id: I348debc77f470551d54fa77b4da780a48ff539c0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8802 Tested-by: jenkins --- src/helper/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/command.c b/src/helper/command.c index d90d34141b..38fb4f83b7 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -673,7 +673,7 @@ COMMAND_HANDLER(handle_echo) } if (CMD_ARGC != 1) - return ERROR_FAIL; + return ERROR_COMMAND_SYNTAX_ERROR; LOG_USER("%s", CMD_ARGV[0]); return ERROR_OK; From 864e1341ada378db6a553b2f13ef7741ffcede51 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 23 Nov 2024 18:35:51 +0100 Subject: [PATCH 1140/1312] target: read_memory: drop command name from error messages The error message should not report the command name as it should be already clear from the context. Change-Id: I219e31be808bf6ff1924ce60f3025fb48ed7b125 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8803 Tested-by: jenkins --- src/target/target.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index ce468cc90a..cfb9cf3f3d 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4448,7 +4448,7 @@ COMMAND_HANDLER(handle_target_read_memory) } if (count > 65536) { - command_print(CMD, "read_memory: too large read request, exceeds 64K elements"); + command_print(CMD, "too large read request, exceeds 64K elements"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -4457,7 +4457,7 @@ COMMAND_HANDLER(handle_target_read_memory) * due to overflow. */ if ((addr + count * width - 1) < addr) { - command_print(CMD, "read_memory: memory region wraps over address zero"); + command_print(CMD, "memory region wraps over address zero"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -4484,13 +4484,13 @@ COMMAND_HANDLER(handle_target_read_memory) retval = target_read_memory(target, addr, width, chunk_len, buffer); if (retval != ERROR_OK) { - LOG_DEBUG("read_memory: read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + LOG_DEBUG("read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", addr, width_bits, chunk_len); /* * FIXME: we append the errmsg to the list of value already read. * Add a way to flush and replace old output, but LOG_DEBUG() it */ - command_print(CMD, "read_memory: failed to read memory"); + command_print(CMD, "failed to read memory"); free(buffer); return retval; } From f55ec6d4492251a453eb441dfd427b5f4ca4e452 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 14:21:42 +0100 Subject: [PATCH 1141/1312] target: rewrite command 'write_memory' as COMMAND_HANDLER While there: - drop the command name from the error messages; - check the returned value from Jim_GetWide() to detect incorrect numeric values. Change-Id: I399402ac11b6d459f1771e59e44210aef3e2a637 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8582 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov --- src/target/target.c | 90 +++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 52 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index cfb9cf3f3d..2f736f0e8e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4526,50 +4526,36 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_OK; } -static int target_jim_write_memory(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) +COMMAND_HANDLER(handle_target_write_memory) { /* - * argv[1] = memory address - * argv[2] = desired element width in bits - * argv[3] = list of data to write - * argv[4] = optional "phys" + * CMD_ARGV[0] = memory address + * CMD_ARGV[1] = desired element width in bits + * CMD_ARGV[2] = list of data to write + * CMD_ARGV[3] = optional "phys" */ - if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 1, argv, "address width data ['phys']"); - return JIM_ERR; - } + if (CMD_ARGC < 3 || CMD_ARGC > 4) + return ERROR_COMMAND_SYNTAX_ERROR; /* Arg 1: Memory address. */ - int e; - jim_wide wide_addr; - e = Jim_GetWide(interp, argv[1], &wide_addr); - - if (e != JIM_OK) - return e; - - target_addr_t addr = (target_addr_t)wide_addr; + target_addr_t addr; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr); /* Arg 2: Bit width of one element. */ - long l; - e = Jim_GetLong(interp, argv[2], &l); - - if (e != JIM_OK) - return e; + unsigned int width_bits; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits); - const unsigned int width_bits = l; - size_t count = Jim_ListLength(interp, argv[3]); + /* Arg 3: Elements to write. */ + size_t count = Jim_ListLength(CMD_CTX->interp, CMD_JIMTCL_ARGV[2]); /* Arg 4: Optional 'phys'. */ bool is_phys = false; - if (argc > 4) { - const char *phys = Jim_GetString(argv[4], NULL); - - if (strcmp(phys, "phys")) { - Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys); - return JIM_ERR; + if (CMD_ARGC == 4) { + if (strcmp(CMD_ARGV[3], "phys")) { + command_print(CMD, "invalid argument '%s', must be 'phys'", CMD_ARGV[3]); + return ERROR_COMMAND_ARGUMENT_INVALID; } is_phys = true; @@ -4582,14 +4568,13 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, case 64: break; default: - Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1); - return JIM_ERR; + command_print(CMD, "invalid width, must be 8, 16, 32 or 64"); + return ERROR_COMMAND_ARGUMENT_INVALID; } if (count > 65536) { - Jim_SetResultString(interp, - "write_memory: too large memory write request, exceeds 64K elements", -1); - return JIM_ERR; + command_print(CMD, "too large memory write request, exceeds 64K elements"); + return ERROR_COMMAND_ARGUMENT_INVALID; } const unsigned int width = width_bits / 8; @@ -4597,21 +4582,18 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, * due to overflow. */ if ((addr + count * width - 1) < addr) { - Jim_SetResultFormatted(interp, - "write_memory: memory region wraps over address zero"); - return JIM_ERR; + command_print(CMD, "memory region wraps over address zero"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); const size_t buffersize = 4096; uint8_t *buffer = malloc(buffersize); if (!buffer) { LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; + return ERROR_FAIL; } size_t j = 0; @@ -4621,9 +4603,13 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, const size_t chunk_len = MIN(count, max_chunk_len); for (size_t i = 0; i < chunk_len; i++, j++) { - Jim_Obj *tmp = Jim_ListGetIndex(interp, argv[3], j); + Jim_Obj *tmp = Jim_ListGetIndex(CMD_CTX->interp, CMD_JIMTCL_ARGV[2], j); jim_wide element_wide; - Jim_GetWide(interp, tmp, &element_wide); + int jimretval = Jim_GetWide(CMD_CTX->interp, tmp, &element_wide); + if (jimretval != JIM_OK) { + command_print(CMD, "invalid value \"%s\"", Jim_GetString(tmp, NULL)); + return ERROR_COMMAND_ARGUMENT_INVALID; + } const uint64_t v = element_wide; @@ -4653,11 +4639,11 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, retval = target_write_memory(target, addr, width, chunk_len, buffer); if (retval != ERROR_OK) { - LOG_ERROR("write_memory: write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + LOG_DEBUG("write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", addr, width_bits, chunk_len); - Jim_SetResultString(interp, "write_memory: failed to write memory", -1); - e = JIM_ERR; - break; + command_print(CMD, "failed to write memory"); + free(buffer); + return retval; } addr += chunk_len * width; @@ -4665,7 +4651,7 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, free(buffer); - return e; + return ERROR_OK; } /* FIX? should we propagate errors here rather than printing them @@ -5612,7 +5598,7 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "write_memory", .mode = COMMAND_EXEC, - .jim_handler = target_jim_write_memory, + .handler = handle_target_write_memory, .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, @@ -6747,7 +6733,7 @@ static const struct command_registration target_exec_command_handlers[] = { { .name = "write_memory", .mode = COMMAND_EXEC, - .jim_handler = target_jim_write_memory, + .handler = handle_target_write_memory, .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, From 50c1a156aeb7a96f2f8bacc8bfcfc93f1bbabb04 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 16:50:14 +0100 Subject: [PATCH 1142/1312] command: factorize jim_command_mode() During 'help' dump, to determine the mode (e.g. COMMAND_CONFIG) of a command, the current code executes the OpenOCD TCL command "command mode", while it could directly call the implementation of the TCL command above. Factorize jim_command_mode() and call the inner implementation instead of executing "command mode". Change-Id: Id8c33d0ed1373b5744dcc3ac354c3e0a88576f75 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8585 Reviewed-by: Evgeniy Naydanov Tested-by: jenkins --- src/helper/command.c | 78 ++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 38fb4f83b7..3d4379d06c 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -41,6 +41,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a static int help_add_command(struct command_context *cmd_ctx, const char *cmd_name, const char *help_text, const char *usage_text); static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name); +static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_name); /* set of functions to wrap jimtcl internal data */ static inline bool jimcmd_is_proc(Jim_Cmd *cmd) @@ -779,24 +780,7 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c, if (is_match && show_help) { char *msg; - /* TODO: factorize jim_command_mode() to avoid running jim command here */ - char *request = alloc_printf("command mode %s", c->cmd_name); - if (!request) { - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } - int retval = Jim_Eval(CMD_CTX->interp, request); - free(request); - enum command_mode mode = COMMAND_UNKNOWN; - if (retval != JIM_ERR) { - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL); - if (!strcmp(result, "any")) - mode = COMMAND_ANY; - else if (!strcmp(result, "config")) - mode = COMMAND_CONFIG; - else if (!strcmp(result, "exec")) - mode = COMMAND_EXEC; - } + enum command_mode mode = get_command_mode(CMD_CTX->interp, c->cmd_name); /* Normal commands are runtime-only; highlight exceptions */ if (mode != COMMAND_EXEC) { @@ -809,6 +793,7 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c, case COMMAND_ANY: stage_msg = " (command valid any time)"; break; + case COMMAND_UNKNOWN: default: stage_msg = " (?mode error?)"; break; @@ -817,11 +802,13 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c, } else msg = alloc_printf("%s", c->help ? c->help : ""); - if (msg) { - command_help_show_wrap(msg, n + 3, n + 3); - free(msg); - } else - return -ENOMEM; + if (!msg) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + command_help_show_wrap(msg, n + 3, n + 3); + free(msg); } return ERROR_OK; @@ -936,35 +923,41 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a return retval; } +static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_name) +{ + if (!cmd_name) + return COMMAND_UNKNOWN; + + Jim_Obj *s = Jim_NewStringObj(interp, cmd_name, -1); + Jim_IncrRefCount(s); + Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE); + Jim_DecrRefCount(interp, s); + + if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_oocd_command(cmd))) + return COMMAND_UNKNOWN; + + /* tcl proc */ + if (jimcmd_is_proc(cmd)) + return COMMAND_ANY; + + struct command *c = jimcmd_privdata(cmd); + return c->mode; +} + static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command_context *cmd_ctx = current_command_context(interp); - enum command_mode mode; + enum command_mode mode = cmd_ctx->mode; if (argc > 1) { char *full_name = alloc_concatenate_strings(argc - 1, argv + 1); if (!full_name) return JIM_ERR; - Jim_Obj *s = Jim_NewStringObj(interp, full_name, -1); - Jim_IncrRefCount(s); - Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE); - Jim_DecrRefCount(interp, s); - free(full_name); - if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_oocd_command(cmd))) { - Jim_SetResultString(interp, "unknown", -1); - return JIM_OK; - } - if (jimcmd_is_proc(cmd)) { - /* tcl proc */ - mode = COMMAND_ANY; - } else { - struct command *c = jimcmd_privdata(cmd); + mode = get_command_mode(interp, full_name); - mode = c->mode; - } - } else - mode = cmd_ctx->mode; + free(full_name); + } const char *mode_str; switch (mode) { @@ -977,6 +970,7 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) case COMMAND_EXEC: mode_str = "exec"; break; + case COMMAND_UNKNOWN: default: mode_str = "unknown"; break; From 98e34fd1f17207ce30fd5c80ab9aefb28fbdc688 Mon Sep 17 00:00:00 2001 From: HAOUES Ahmed Date: Wed, 12 Mar 2025 14:37:46 +0100 Subject: [PATCH 1143/1312] flash/stm32l4x: support STM32U5F/U5Gx devices STM32U5F/U5Gx devices are similar to STM32U59/U5Ax devices while at there update STM32U5xx revisions Change-Id: I4f1c302cc91739a89cf4869401e9f5015dbc72b9 Signed-off-by: HAOUES Ahmed Reviewed-on: https://review.openocd.org/c/openocd/+/8616 Reviewed-by: Antonio Borneo Reviewed-by: Tarek BOCHKATI Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/stm32l4x.c | 23 ++++++++++++++++++++--- src/flash/nor/stm32l4x.h | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 3062fca72a..fa57db8bbf 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -370,11 +370,15 @@ static const struct stm32l4_rev stm32u53_u54xx_revs[] = { static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, - { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, + { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, { 0x3007, "U" }, }; static const struct stm32l4_rev stm32u59_u5axx_revs[] = { - { 0x3001, "X" }, + { 0x3001, "X" }, { 0x3002, "W" }, +}; + +static const struct stm32l4_rev stm32u5f_u5gxx_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, }; static const struct stm32l4_rev stm32wba5x_revs[] = { @@ -674,6 +678,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x0BFA0000, .otp_size = 512, }, + { + .id = DEVID_STM32U5F_U5GXX, + .revs = stm32u5f_u5gxx_revs, + .num_revs = ARRAY_SIZE(stm32u5f_u5gxx_revs), + .device_str = "STM32U5F/U5Gxx", + .max_flash_size_kb = 4096, + .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0BFA07A0, + .otp_base = 0x0BFA0000, + .otp_size = 512, + }, { .id = DEVID_STM32WBA5X, .revs = stm32wba5x_revs, @@ -2095,6 +2111,7 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32U53_U54XX: case DEVID_STM32U57_U58XX: case DEVID_STM32U59_U5AXX: + case DEVID_STM32U5F_U5GXX: /* according to RM0456 Rev 4, Chapter 7.3.1 and 7.9.13 * U53x/U54x have 512K max flash size: * 512K variants are always in DUAL BANK mode @@ -2102,7 +2119,7 @@ static int stm32l4_probe(struct flash_bank *bank) * U57x/U58x have 2M max flash size: * 2M variants are always in DUAL BANK mode * 1M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set - * U59x/U5Ax have 4M max flash size: + * U59x/U5Ax/U5Fx/U5Gx have 4M max flash size: * 4M variants are always in DUAL BANK mode * 2M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set * Note: flash banks are always contiguous diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index f152c9f30a..3199d4f6dc 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -103,6 +103,7 @@ #define DEVID_STM32L4R_L4SXX 0x470 #define DEVID_STM32L4P_L4QXX 0x471 #define DEVID_STM32L55_L56XX 0x472 +#define DEVID_STM32U5F_U5GXX 0x476 #define DEVID_STM32G49_G4AXX 0x479 #define DEVID_STM32U59_U5AXX 0x481 #define DEVID_STM32U57_U58XX 0x482 From 5773ff9d82a06e7e270dd71fc3d4352815384292 Mon Sep 17 00:00:00 2001 From: Adrien Grassein Date: Thu, 18 Jan 2024 11:58:38 +0100 Subject: [PATCH 1144/1312] target/armv8: Handle instruction cache invalidate Some armv8 target have separate i-cache and d-cache. The actual code only handles the flush of the d-cache. Change-Id: I61a223b43c71646bbbed8fa63825360c67700988 Signed-off-by: Adrien Grassein Signed-off-by: Adrien Charruel Reviewed-on: https://review.openocd.org/c/openocd/+/8655 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv8.h | 1 + src/target/armv8_cache.c | 62 ++++++++++++++++++++++++++++++++++++++ src/target/armv8_opcodes.c | 2 ++ src/target/armv8_opcodes.h | 3 ++ 4 files changed, 68 insertions(+) diff --git a/src/target/armv8.h b/src/target/armv8.h index 49ab3e5cb7..dba12f9666 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -162,6 +162,7 @@ struct armv8_cache_common { /* l2 external unified cache if some */ void *l2_cache; int (*flush_all_data_cache)(struct target *target); + int (*invalidate_all_instruction_cache)(struct target *target); int (*display_cache_info)(struct command_invocation *cmd, struct armv8_cache_common *armv8_cache); }; diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index 74d063b0e8..1c251beb99 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -141,6 +141,36 @@ int armv8_cache_d_inner_flush_virt(struct armv8_common *armv8, target_addr_t va, return retval; } +static int armv8_cache_i_inner_clean_inval_all(struct armv8_common *armv8) +{ + struct arm_dpm *dpm = armv8->arm.dpm; + int retval; + + retval = armv8_i_cache_sanity_check(armv8); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("flushing cache"); + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_ICIALLU)); + if (retval != ERROR_OK) + goto done; + + dpm->finish(dpm); + LOG_DEBUG("flushing cache done"); + return retval; + +done: + LOG_ERROR("i-cache invalidate failed"); + dpm->finish(dpm); + + return retval; +} + int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, size_t size) { struct arm_dpm *dpm = armv8->arm.dpm; @@ -253,6 +283,32 @@ static int armv8_flush_all_data(struct target *target) return retval; } +static int armv8_flush_all_instruction(struct target *target) +{ + int retval = ERROR_FAIL; + /* check that armv8_cache is correctly identify */ + struct armv8_common *armv8 = target_to_armv8(target); + if (armv8->armv8_mmu.armv8_cache.info == -1) { + LOG_ERROR("trying to flush un-identified cache"); + return retval; + } + + if (target->smp) { + /* look if all the other target have been flushed in order to flush icache */ + struct target_list *head; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; + if (curr->state == TARGET_HALTED) { + LOG_TARGET_INFO(curr, "Wait flushing instruction l1."); + retval = armv8_cache_i_inner_clean_inval_all(target_to_armv8(curr)); + } + } + } else { + retval = armv8_cache_i_inner_clean_inval_all(armv8); + } + return retval; +} + static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg) { struct armv8_common *armv8 = dpm->arm->arch_info; @@ -412,6 +468,12 @@ int armv8_identify_cache(struct armv8_common *armv8) armv8->armv8_mmu.armv8_cache.flush_all_data_cache = armv8_flush_all_data; } + if (!armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache) { + armv8->armv8_mmu.armv8_cache.display_cache_info = + armv8_handle_inner_cache_info_command; + armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache = + armv8_flush_all_instruction; + } done: armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 2635b3ec5f..0f6c8108e8 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -41,6 +41,7 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP(1, 0), [ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP(1, 0), [ARMV8_OPC_STRD_IP] = ARMV8_STRD_IP(1, 0), + [ARMV8_OPC_ICIALLU] = ARMV8_SYS(SYSTEM_ICIALLU, 0x1F), }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { @@ -68,6 +69,7 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_STRB_IP] = ARMV8_STRB_IP_T3(1, 0), [ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP_T3(1, 0), [ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP_T3(1, 0), + [ARMV8_OPC_ICIALLU] = ARMV4_5_MCR(15, 0, 0, 7, 5, 0), }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 9200dac723..9f18e94d29 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -72,6 +72,8 @@ #define SYSTEM_DCCISW 0x43F2 #define SYSTEM_DCCSW 0x43D2 #define SYSTEM_ICIVAU 0x5BA9 +/* Attention, SYSTEM_ICIALLU requires rt=0x1f */ +#define SYSTEM_ICIALLU 0x03A8 #define SYSTEM_DCCVAU 0x5BD9 #define SYSTEM_DCCIVAC 0x5BF1 @@ -207,6 +209,7 @@ enum armv8_opcode { ARMV8_OPC_LDRH_IP, ARMV8_OPC_LDRW_IP, ARMV8_OPC_LDRD_IP, + ARMV8_OPC_ICIALLU, ARMV8_OPC_NUM, }; From a86fdfc73548a2b317ed8e61a618ebff2ee4f5e2 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 16 Mar 2025 11:50:04 +0100 Subject: [PATCH 1145/1312] target: drop last instances of 'target->cmd_name' The helper function 'target_name()' or, better, the log functions 'LOG_TARGET_xxx(target, ...)' should be used in place of taking the target name directly from 'target->cmd_name'. Replace the remaining instances in the code. While there: - address some indentation, - drop trailing punctuation in log message, - replace one LOG WARNING with LOG_TARGET_WARNING. Change-Id: Ie6cf4c174ffe91b975c983e4697c735766267041 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8806 Tested-by: jenkins Reviewed-by: zapb --- src/target/armv7a.c | 16 ++++++++-------- src/target/cortex_a.c | 11 +++++------ src/target/espressif/esp32_apptrace.c | 2 +- src/target/espressif/esp_xtensa_apptrace.c | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/target/armv7a.c b/src/target/armv7a.c index e22d309a07..c14155e013 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -101,14 +101,14 @@ static int armv7a_read_midr(struct target *target) armv7a->arch = (midr >> 16) & 0xf; armv7a->variant = (midr >> 20) & 0xf; armv7a->implementor = (midr >> 24) & 0xff; - LOG_DEBUG("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 - ", variant %" PRIx32 ", implementor %" PRIx32, - target->cmd_name, - armv7a->rev, - armv7a->partnum, - armv7a->arch, - armv7a->variant, - armv7a->implementor); + LOG_TARGET_DEBUG(target, + "rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 + ", variant %" PRIx32 ", implementor %" PRIx32, + armv7a->rev, + armv7a->partnum, + armv7a->arch, + armv7a->variant, + armv7a->implementor); done: dpm->finish(dpm); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index b32fec270e..9c60645586 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2923,14 +2923,12 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_ap->memaccess_tck = 80; if (!target->dbgbase_set) { - LOG_DEBUG("%s's dbgbase is not set, trying to detect using the ROM table", - target->cmd_name); + LOG_TARGET_DEBUG(target, "dbgbase is not set, trying to detect using the ROM table"); /* Lookup Processor DAP */ retval = dap_lookup_cs_component(armv7a->debug_ap, ARM_CS_C9_DEVTYPE_CORE_DEBUG, &armv7a->debug_base, target->coreid); if (retval != ERROR_OK) { - LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.", - target->cmd_name); + LOG_TARGET_ERROR(target, "Can't detect dbgbase from the ROM table; you need to specify it explicitly"); return retval; } LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT, @@ -2939,8 +2937,9 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_base = target->dbgbase; if ((armv7a->debug_base & (1UL<<31)) == 0) - LOG_WARNING("Debug base address for target %s has bit 31 set to 0. Access to debug registers will likely fail!\n" - "Please fix the target configuration.", target_name(target)); + LOG_TARGET_WARNING(target, + "Debug base address has bit 31 set to 0. Access to debug registers will likely fail!\n" + "Please fix the target configuration"); retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DIDR, &didr); diff --git a/src/target/espressif/esp32_apptrace.c b/src/target/espressif/esp32_apptrace.c index 3202fd3d64..307096019a 100644 --- a/src/target/espressif/esp32_apptrace.c +++ b/src/target/espressif/esp32_apptrace.c @@ -649,7 +649,7 @@ static int esp32_apptrace_wait4halt(struct esp32_apptrace_cmd_ctx *ctx, struct t if (res != ERROR_OK) return res; if (target->state == TARGET_HALTED) { - LOG_USER("%s: HALTED", target->cmd_name); + LOG_TARGET_USER(target, "HALTED"); break; } alive_sleep(500); diff --git a/src/target/espressif/esp_xtensa_apptrace.c b/src/target/espressif/esp_xtensa_apptrace.c index 5741ab0308..313f6ce778 100644 --- a/src/target/espressif/esp_xtensa_apptrace.c +++ b/src/target/espressif/esp_xtensa_apptrace.c @@ -277,7 +277,7 @@ static int esp_xtensa_swdbg_activate(struct target *target, int enab) xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod); int res = xtensa_dm_queue_execute(&xtensa->dbg_mod); if (res != ERROR_OK) { - LOG_ERROR("%s: writing DCR failed!", target->cmd_name); + LOG_TARGET_ERROR(target, "writing DCR failed"); return res; } From a9fa3392670659dfd558d8733911ffce9538e2d2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Aug 2024 01:29:12 +0200 Subject: [PATCH 1146/1312] tcl/target: Add Renesas R-Car Gen4 R8A779G0 V4H and R8A779H0 V4M targets Add support for Renesas R-Car Gen4 R8A779G0 V4H and R8A779H0 V4M SoCs. Those contain 4x CA76 and 3x CR52 cores. Change-Id: I4a701f0fec4dd574fc099a221d464ccc55db6252 Signed-off-by: Marek Vasut Reviewed-on: https://review.openocd.org/c/openocd/+/8807 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/renesas_rcar_gen3.cfg | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/tcl/target/renesas_rcar_gen3.cfg b/tcl/target/renesas_rcar_gen3.cfg index 73b3003a94..f6bc5e4c8f 100644 --- a/tcl/target/renesas_rcar_gen3.cfg +++ b/tcl/target/renesas_rcar_gen3.cfg @@ -90,6 +90,18 @@ switch $_soc { set _num_cr52 1 set _boot_core CA76 } + V4H { + set _CHIPNAME r8a779g0 + set _num_ca76 4 + set _num_cr52 3 + set _boot_core CR52 + } + V4M { + set _CHIPNAME r8a779h0 + set _num_ca76 4 + set _num_cr52 3 + set _boot_core CR52 + } default { error "'$_soc' is invalid!" } @@ -126,8 +138,8 @@ set CA57_DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000} set CA57_CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000} set CA53_DBGBASE {0x80C10000 0x80D10000 0x80E10000 0x80F10000} set CA53_CTIBASE {0x80C20000 0x80D20000 0x80E20000 0x80F20000} -set CR52_DBGBASE 0x80c10000 -set CR52_CTIBASE 0x80c20000 +set CR52_DBGBASE {0x80C10000 0x80D10000 0x80E10000} +set CR52_CTIBASE {0x80C20000 0x80D20000 0x80E20000} set CR7_DBGBASE 0x80910000 set CR7_CTIBASE 0x80918000 @@ -159,24 +171,27 @@ proc setup_a5x {core_name dbgbase ctibase num boot} { proc setup_crx {core_name dbgbase ctibase num boot} { global _CHIPNAME global _DAPNAME + global smp_targets global _targets for { set _core 0 } { $_core < $num } { incr _core } { - set _TARGETNAME $_CHIPNAME.$core_name + set _TARGETNAME $_CHIPNAME.$core_name.$_core set _CTINAME $_TARGETNAME.cti - cti create $_CTINAME -dap $_DAPNAME -ap-num 1 -baseaddr $ctibase + cti create $_CTINAME -dap $_DAPNAME -ap-num 1 -baseaddr [lindex $ctibase $_core] if { $core_name == "r52" } { set _command "target create $_TARGETNAME armv8r -dap $_DAPNAME \ - -ap-num 1 -dbgbase $dbgbase -cti $_CTINAME" + -ap-num 1 -dbgbase [lindex $dbgbase $_core] -cti $_CTINAME" } else { set _command "target create $_TARGETNAME cortex_r4 -dap $_DAPNAME \ - -ap-num 1 -dbgbase $dbgbase" + -ap-num 1 -dbgbase [lindex $dbgbase $_core]" } - if { $boot == 1 } { + if { $_core == 0 && $boot == 1 } { set _targets "$_TARGETNAME" } else { set _command "$_command -defer-examine" } + set smp_targets "$smp_targets $_TARGETNAME" eval $_command + $_TARGETNAME configure -event examine-end { halt } } } From f885a8d76c96ec94e2f7a4c4fadd57dfe384a8ac Mon Sep 17 00:00:00 2001 From: Adrien Grassein Date: Thu, 18 Jan 2024 11:54:15 +0100 Subject: [PATCH 1147/1312] target/aarch64: Cleanup on exit Restore target configuration on exit so that OpenOCD get correct values when restarting. Change-Id: I8cbba1fdae1d3c4a580197b7a97691443780ed06 Signed-off-by: Adrien Grassein Signed-off-by: Adrien Charruel Reviewed-on: https://review.openocd.org/c/openocd/+/8654 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/aarch64.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 609965ba55..ce7808e3ac 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2857,6 +2857,14 @@ static void aarch64_deinit_target(struct target *target) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct arm_dpm *dpm = &armv8->dpm; + uint64_t address; + + if (target->state == TARGET_HALTED) { + // Restore the previous state of the target (gp registers, MMU, caches, etc) + int retval = aarch64_restore_one(target, true, &address, false, false); + if (retval != ERROR_OK) + LOG_TARGET_ERROR(target, "Failed to restore target state"); + } if (armv8->debug_ap) dap_put_ap(armv8->debug_ap); From fe3aa0a4bc185828cb318715b055dc64518bd9eb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 15:04:09 +0100 Subject: [PATCH 1148/1312] target: rewrite command 'get_reg' as COMMAND_HANDLER Print one register per line. Repeated registers will be printed each time. While there, fix the 'usage' string. Change-Id: I4eb21696705bdf15cd2cb7a4a9caa41f9ffdbf64 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8583 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov --- src/target/target.c | 81 +++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 2f736f0e8e..7baeeddd08 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4701,63 +4701,46 @@ void target_handle_event(struct target *target, enum target_event e) } } -static int target_jim_get_reg(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) +COMMAND_HANDLER(handle_target_get_reg) { - bool force = false; + if (CMD_ARGC < 1 || CMD_ARGC > 2) + return ERROR_COMMAND_SYNTAX_ERROR; - if (argc == 3) { - const char *option = Jim_GetString(argv[1], NULL); + bool force = false; + Jim_Obj *next_argv = CMD_JIMTCL_ARGV[0]; - if (!strcmp(option, "-force")) { - argc--; - argv++; - force = true; - } else { - Jim_SetResultFormatted(interp, "invalid option '%s'", option); - return JIM_ERR; + if (CMD_ARGC == 2) { + if (strcmp(CMD_ARGV[0], "-force")) { + command_print(CMD, "invalid argument '%s', must be '-force'", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } - } - if (argc != 2) { - Jim_WrongNumArgs(interp, 1, argv, "[-force] list"); - return JIM_ERR; + force = true; + next_argv = CMD_JIMTCL_ARGV[1]; } - const int length = Jim_ListLength(interp, argv[1]); + const int length = Jim_ListLength(CMD_CTX->interp, next_argv); - Jim_Obj *result_dict = Jim_NewDictObj(interp, NULL, 0); - - if (!result_dict) - return JIM_ERR; - - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - const struct target *target = get_current_target(cmd_ctx); + const struct target *target = get_current_target(CMD_CTX); for (int i = 0; i < length; i++) { - Jim_Obj *elem = Jim_ListGetIndex(interp, argv[1], i); - - if (!elem) - return JIM_ERR; + Jim_Obj *elem = Jim_ListGetIndex(CMD_CTX->interp, next_argv, i); const char *reg_name = Jim_String(elem); - struct reg *reg = register_get_by_name(target->reg_cache, reg_name, - false); + struct reg *reg = register_get_by_name(target->reg_cache, reg_name, false); if (!reg || !reg->exist) { - Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name); - return JIM_ERR; + command_print(CMD, "unknown register '%s'", reg_name); + return ERROR_COMMAND_ARGUMENT_INVALID; } if (force || !reg->valid) { int retval = reg->type->get(reg); if (retval != ERROR_OK) { - Jim_SetResultFormatted(interp, "failed to read register '%s'", - reg_name); - return JIM_ERR; + command_print(CMD, "failed to read register '%s'", reg_name); + return retval; } } @@ -4765,27 +4748,15 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc, if (!reg_value) { LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; + return ERROR_FAIL; } - char *tmp = alloc_printf("0x%s", reg_value); + command_print(CMD, "%s 0x%s", reg_name, reg_value); free(reg_value); - - if (!tmp) { - LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; - } - - Jim_DictAddElement(interp, result_dict, elem, - Jim_NewStringObj(interp, tmp, -1)); - - free(tmp); } - Jim_SetResult(interp, result_dict); - - return JIM_OK; + return ERROR_OK; } COMMAND_HANDLER(handle_set_reg_command) @@ -5577,9 +5548,9 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "get_reg", .mode = COMMAND_EXEC, - .jim_handler = target_jim_get_reg, + .handler = handle_target_get_reg, .help = "Get register values from the target", - .usage = "list", + .usage = "[-force] list", }, { .name = "set_reg", @@ -6712,9 +6683,9 @@ static const struct command_registration target_exec_command_handlers[] = { { .name = "get_reg", .mode = COMMAND_EXEC, - .jim_handler = target_jim_get_reg, + .handler = handle_target_get_reg, .help = "Get register values from the target", - .usage = "list", + .usage = "[-force] list", }, { .name = "set_reg", From 169d463a3d3c91f62c980aba287b5e110b310ad0 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 11 Feb 2025 17:59:00 +0100 Subject: [PATCH 1149/1312] tcl/target/nordic/nrf54l: minor corrections Add SWD multidrop setting. Fix the name of AP #1 to AUX-AP Set AUX-AP CSW Prot bit[0] to make RISC-V debug accessible on AUX-AP. Change-Id: I496e07acfe90dd858e4403176a8330d8c1a0b560 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8752 Tested-by: jenkins Reviewed-by: zapb --- tcl/target/nordic/nrf54l.cfg | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tcl/target/nordic/nrf54l.cfg b/tcl/target/nordic/nrf54l.cfg index 70ead1365c..3e14055f14 100644 --- a/tcl/target/nordic/nrf54l.cfg +++ b/tcl/target/nordic/nrf54l.cfg @@ -27,18 +27,35 @@ if { [info exists CPUTAPID] } { set _CPUTAPID 0x6ba02477 } +# Multidrop instance ID should be configurable by FW in TAD TINSTANCE register. +# Writes to the register are ignored due to a silicon erratum. +if { [info exists SWD_INSTANCE_ID] } { + set _SWD_INSTANCE_ID $SWD_INSTANCE_ID +} else { + set _SWD_INSTANCE_ID 0 +} + transport select swd swd newdap $_CHIPNAME cpu -expected-id $_CPUTAPID -dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if { [info exists SWD_MULTIDROP] } { + dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu -dp-id 0x001c0289 -instance-id $_SWD_INSTANCE_ID +} else { + dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +} set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap -ap-num 0 $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -# Create target for the control access port (CTRL-AP). -target create $_CHIPNAME.ctrl mem_ap -dap $_CHIPNAME.dap -ap-num 1 +# Create target for the AUX access port (AUX-AP). +target create $_CHIPNAME.aux mem_ap -dap $_CHIPNAME.dap -ap-num 1 + +# AUX-AP is accessible only if CSW Prot[0] bit (Data Access) is set +$_CHIPNAME.dap apsel 1 +$_CHIPNAME.dap apcsw 0x01000000 0x01000000 adapter speed 1000 From 04124c77f48b9748b88b4ccf77a36665855ee73e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 29 Mar 2025 22:51:59 +0100 Subject: [PATCH 1150/1312] target: fix memory leak in handle_target_write_memory() Commit f55ec6d44922 ("target: rewrite command 'write_memory' as COMMAND_HANDLER") adds a new return statement without freeing the allocated buffer. Add the needed free(). Fixes: f55ec6d44922 ("target: rewrite command 'write_memory' as COMMAND_HANDLER") Change-Id: I676d658118b32f4d7cc71eda3436bb52f1966cd8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8822 Tested-by: jenkins --- src/target/target.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/target.c b/src/target/target.c index 7baeeddd08..3b62e0db09 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4608,6 +4608,7 @@ COMMAND_HANDLER(handle_target_write_memory) int jimretval = Jim_GetWide(CMD_CTX->interp, tmp, &element_wide); if (jimretval != JIM_OK) { command_print(CMD, "invalid value \"%s\"", Jim_GetString(tmp, NULL)); + free(buffer); return ERROR_COMMAND_ARGUMENT_INVALID; } From c023534e7b6f61dddf91fc6ca4644d4071bb73dc Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 23 Mar 2025 12:09:28 +0100 Subject: [PATCH 1151/1312] target: use list for target events To simplify removing an event when it's set to an empty string, switch event list from hardcoded simply linked list to helper's double linked list. While there, move the declaration of struct target_event_action in 'target.c' as it is not anymore visible outside. Change-Id: I799754c80055dc6d22db55aca483757e833714ff Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8813 Tested-by: jenkins --- src/target/target.c | 41 +++++++++++++++++++++++++---------------- src/target/target.h | 9 +-------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 3b62e0db09..53850bf288 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -31,6 +31,7 @@ #endif #include +#include #include #include #include @@ -52,6 +53,13 @@ /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 +struct target_event_action { + enum target_event event; + Jim_Interp *interp; + Jim_Obj *body; + struct list_head list; +}; + static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, target_addr_t address, @@ -2194,12 +2202,11 @@ static void target_destroy(struct target *target) jtag_unregister_event_callback(jtag_enable_callback, target); - struct target_event_action *teap = target->event_action; - while (teap) { - struct target_event_action *next = teap->next; + struct target_event_action *teap, *temp; + list_for_each_entry_safe(teap, temp, &target->events_action, list) { + list_del(&teap->list); Jim_DecrRefCount(teap->interp, teap->body); free(teap); - teap = next; } target_free_all_working_areas(target); @@ -4663,7 +4670,7 @@ void target_handle_event(struct target *target, enum target_event e) struct target_event_action *teap; int retval; - for (teap = target->event_action; teap; teap = teap->next) { + list_for_each_entry(teap, &target->events_action, list) { if (teap->event == e) { LOG_DEBUG("target: %s (%s) event: %d (%s) action: %s", target_name(target), @@ -4826,7 +4833,7 @@ bool target_has_event_action(const struct target *target, enum target_event even { struct target_event_action *teap; - for (teap = target->event_action; teap; teap = teap->next) { + list_for_each_entry(teap, &target->events_action, list) { if (teap->event == event) return true; } @@ -4946,13 +4953,14 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) { struct target_event_action *teap; - teap = target->event_action; /* replace existing? */ - while (teap) { + list_for_each_entry(teap, &target->events_action, list) if (teap->event == (enum target_event)n->value) break; - teap = teap->next; - } + + /* not found! */ + if (&teap->list == &target->events_action) + teap = NULL; if (goi->is_configure) { /* START_DEPRECATED_TPIU */ @@ -4986,8 +4994,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) if (!replace) { /* add to head of event list */ - teap->next = target->event_action; - target->event_action = teap; + list_add(&teap->list, &target->events_action); } Jim_SetEmptyResult(goi->interp); } else { @@ -5402,19 +5409,19 @@ COMMAND_HANDLER(handle_target_wait_state) COMMAND_HANDLER(handle_target_event_list) { struct target *target = get_current_target(CMD_CTX); - struct target_event_action *teap = target->event_action; + struct target_event_action *teap; command_print(CMD, "Event actions for target %s\n", target_name(target)); command_print(CMD, "%-25s | Body", "Event"); command_print(CMD, "------------------------- | " "----------------------------------------"); - while (teap) { + + list_for_each_entry(teap, &target->events_action, list) command_print(CMD, "%-25s | %s", target_event_name(teap->event), Jim_GetString(teap->body, NULL)); - teap = teap->next; - } + command_print(CMD, "***END***"); return ERROR_OK; } @@ -5767,6 +5774,8 @@ static int target_create(struct jim_getopt_info *goi) target->halt_issued = false; + INIT_LIST_HEAD(&target->events_action); + /* initialize trace information */ target->trace_info = calloc(1, sizeof(struct trace)); if (!target->trace_info) { diff --git a/src/target/target.h b/src/target/target.h index 47f02ec266..b698f250ce 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -139,7 +139,7 @@ struct target { */ bool running_alg; - struct target_event_action *event_action; + struct list_head events_action; bool reset_halt; /* attempt resetting the CPU into the halted mode? */ target_addr_t working_area; /* working area (initialised RAM). Evaluated @@ -295,13 +295,6 @@ enum target_event { TARGET_EVENT_SEMIHOSTING_USER_CMD_0X107 = 0x107, }; -struct target_event_action { - enum target_event event; - Jim_Interp *interp; - Jim_Obj *body; - struct target_event_action *next; -}; - bool target_has_event_action(const struct target *target, enum target_event event); struct target_event_callback { From 160f7b3e5d9aa78dbbb6eff63681621aed712ab6 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 23 Mar 2025 15:27:37 +0100 Subject: [PATCH 1152/1312] target: remove events that are set to empty string Current code allows replacing the body of an existing event, but it doesn't provides a way to remove it. Replacing the event with an empty string makes the event still present and visible through $target_name eventlist The presence of empty events makes more complex checking for the event not set or set to empty. Remove the event when set to empty string. While there, add 'Jim_Length' to the list of allowed CamelCase symbols, avoiding the associated checkpatch error. Change-Id: I1ec2e1a71d298a0eba0b6863902645bcc6c4cb09 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8814 Tested-by: jenkins --- src/target/target.c | 12 +++++++++++- tools/scripts/camelcase.txt | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/target/target.c b/src/target/target.c index 53850bf288..8c5c8e5e30 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4968,6 +4968,17 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); /* END_DEPRECATED_TPIU */ + jim_getopt_obj(goi, &o); + if (Jim_Length(o) == 0) { + /* empty action, drop existing one */ + if (teap) { + list_del(&teap->list); + Jim_DecrRefCount(teap->interp, teap->body); + free(teap); + } + break; + } + bool replace = true; if (!teap) { /* create new */ @@ -4976,7 +4987,6 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) } teap->event = n->value; teap->interp = goi->interp; - jim_getopt_obj(goi, &o); if (teap->body) Jim_DecrRefCount(teap->interp, teap->body); teap->body = Jim_DuplicateObj(goi->interp, o); diff --git a/tools/scripts/camelcase.txt b/tools/scripts/camelcase.txt index b787902006..6c6c28daa5 100644 --- a/tools/scripts/camelcase.txt +++ b/tools/scripts/camelcase.txt @@ -122,6 +122,7 @@ Jim_GetWide Jim_IncrRefCount Jim_InitStaticExtensions Jim_Interp +Jim_Length Jim_ListAppendElement Jim_ListGetIndex Jim_ListLength From 9eb2426411aa0c1c13f5fc59801ac3cb3319f476 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 23 Mar 2025 22:04:20 +0100 Subject: [PATCH 1153/1312] configure.ac: show the Remote Bitbang driver in the config summary Also enable this driver by default (auto). Change-Id: I112d6c8c0796d0dc464651feb1f7f81fa8b93910 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8817 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 75c8e5d8a7..b63c70e1f9 100644 --- a/configure.ac +++ b/configure.ac @@ -164,6 +164,9 @@ m4_define([LIBFTDI_USB1_ADAPTERS], m4_define([LIBGPIOD_ADAPTERS], [[[linuxgpiod], [Linux GPIO bitbang through libgpiod], [LINUXGPIOD]]]) +m4_define([REMOTE_BITBANG_ADAPTER], + [[[remote_bitbang], [Remote Bitbang driver], [REMOTE_BITBANG]]]) + m4_define([LIBJAYLINK_ADAPTERS], [[[jlink], [SEGGER J-Link Programmer], [JLINK]]]) @@ -310,6 +313,7 @@ AC_ARG_ADAPTERS([ LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + REMOTE_BITBANG_ADAPTER, LINUXSPIDEV_ADAPTER, SERIAL_PORT_ADAPTERS, DUMMY_ADAPTER, @@ -413,10 +417,6 @@ AC_ARG_ENABLE([internal-libjaylink], [Enable building internal libjaylink]), [use_internal_libjaylink=$enableval], [use_internal_libjaylink=no]) -AC_ARG_ENABLE([remote-bitbang], - AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang driver]), - [build_remote_bitbang=$enableval], [build_remote_bitbang=no]) - AS_CASE(["${host_cpu}"], [i?86|x86*], [], [ @@ -611,13 +611,6 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ ]) ]) -AS_IF([test "x$build_remote_bitbang" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang driver.]) -], [ - AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang driver.]) -]) - AS_IF([test "x$build_sysfsgpio" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_SYSFSGPIO], [1], [1 if you want the SysfsGPIO driver.]) @@ -716,6 +709,7 @@ PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libu PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x]) PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpiod]) +PROCESS_ADAPTERS([REMOTE_BITBANG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], @@ -730,6 +724,10 @@ AS_IF([test "x$enable_linuxgpiod" != "xno"], [ build_bitbang=yes ]) +AS_IF([test "x$enable_remote_bitbang" != "xno"], [ + build_bitbang=yes +]) + AS_IF([test "x$enable_stlink" != "xno" -o "x$enable_ti_icdi" != "xno" -o "x$enable_nulink" != "xno"], [ AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.]) AM_CONDITIONAL([HLADAPTER], [true]) @@ -774,7 +772,6 @@ AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"]) AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) -AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"]) AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) @@ -873,6 +870,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + REMOTE_BITBANG_ADAPTER, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, LINUXSPIDEV_ADAPTER, VDEBUG_ADAPTER, From e45d66fd9a2f43ddc106957ca141f8734dc757a5 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 22 Mar 2025 23:35:23 +0100 Subject: [PATCH 1154/1312] configure.ac: show the rshim adapter in the config summary Also enable this adapter by default (auto). Change-Id: Ic302041ecb9e88ca58b03f9675fa92fb3d558821 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8811 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index b63c70e1f9..84ca03bf07 100644 --- a/configure.ac +++ b/configure.ac @@ -187,6 +187,9 @@ m4_define([JTAG_DPI_ADAPTER], m4_define([JTAG_VPI_ADAPTER], [[[jtag_vpi], [JTAG VPI Adapter], [JTAG_VPI]]]) +m4_define([RSHIM_ADAPTER], + [[[rshim], [BlueField SoC via rshim], [RSHIM]]]) + # The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter # because there is an M4 macro called 'adapter'. m4_define([DUMMY_ADAPTER], @@ -285,10 +288,6 @@ AS_IF([test "x$debug_malloc" = "xyes" -a "x$have_glibc" = "xyes"], [ AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging]) ]) -AC_ARG_ENABLE([rshim], - AS_HELP_STRING([--enable-rshim], [Enable building the rshim driver]), - [build_rshim=$enableval], [build_rshim=no]) - AC_ARG_ENABLE([dmem], AS_HELP_STRING([--enable-dmem], [Enable building the dmem driver]), [build_dmem=$enableval], [build_dmem=no]) @@ -320,6 +319,7 @@ AC_ARG_ADAPTERS([ VDEBUG_ADAPTER, JTAG_DPI_ADAPTER, JTAG_VPI_ADAPTER, + RSHIM_ADAPTER, PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) @@ -383,19 +383,24 @@ AC_ARG_ENABLE([sysfsgpio], AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) +can_build_rshim=no + AS_CASE([$host_os], [linux*], [ is_linux=yes + can_build_rshim=yes ], [ AS_IF([test "x$build_sysfsgpio" = "xyes"], [ AC_MSG_ERROR([sysfsgpio is only available on linux]) ]) - AS_CASE([$host_os], [freebsd*], [], + AS_CASE([$host_os], [freebsd*], [ + can_build_rshim=yes + ], [ - AS_IF([test "x$build_rshim" = "xyes"], [ - AC_MSG_ERROR([build_rshim is only available on linux or freebsd]) + AS_IF([test "x$enable_rshim" = "xyes"], [ + AC_MSG_ERROR([rshim is only available on linux or freebsd]) ]) ]) @@ -514,12 +519,6 @@ AS_IF([test "x$build_parport" = "xyes"], [ AC_DEFINE([BUILD_PARPORT], [0], [0 if you don't want parport.]) ]) -AS_IF([test "x$build_rshim" = "xyes"], [ - AC_DEFINE([BUILD_RSHIM], [1], [1 if you want to debug BlueField SoC via rshim.]) -], [ - AC_DEFINE([BUILD_RSHIM], [0], [0 if you don't want to debug BlueField SoC via rshim.]) -]) - AS_IF([test "x$build_dmem" = "xyes"], [ AC_DEFINE([BUILD_DMEM], [1], [1 if you want to debug via Direct Mem.]) ], [ @@ -718,6 +717,8 @@ PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev]) PROCESS_ADAPTERS([VDEBUG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([JTAG_DPI_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([JTAG_VPI_ADAPTER], [true], [unused]) +PROCESS_ADAPTERS([RSHIM_ADAPTER], ["x$can_build_rshim" = "xyes"], + [internal error: validation should happen beforehand]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -783,7 +784,6 @@ AM_CONDITIONAL([USE_LIBFTDI], [test "x$use_libftdi" = "xyes"]) AM_CONDITIONAL([USE_LIBGPIOD], [test "x$use_libgpiod" = "xyes"]) AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"]) AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"]) -AM_CONDITIONAL([RSHIM], [test "x$build_rshim" = "xyes"]) AM_CONDITIONAL([DMEM], [test "x$build_dmem" = "xyes"]) AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"]) @@ -876,6 +876,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, VDEBUG_ADAPTER, JTAG_DPI_ADAPTER, JTAG_VPI_ADAPTER, + RSHIM_ADAPTER, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], From 6834f022b96fb1c7f5829166578e01a0ac223cb0 Mon Sep 17 00:00:00 2001 From: Sofiane HAMAM Date: Fri, 28 Mar 2025 12:31:17 +0100 Subject: [PATCH 1155/1312] Makefile.am: Use SOURCE_DATE_EPOCH environment variable This package defines PKGBLDDATE as build timestamp which makes it non reproducible. Use SOURCE_DATE_EPOCH if it is found, otherwise use build timestamp. Following best practices, see : https://reproducible-builds.org/docs/source-date-epoch/ The patch is BSD compatible too. Change-Id: I26c1a00f2e8059ae31fe72a794b5962af5a84f44 Co-developed-by: Yoann Congal Signed-off-by: Yoann Congal Signed-off-by: Sofiane HAMAM Reviewed-on: https://review.openocd.org/c/openocd/+/8619 Reviewed-by: Antonio Borneo Reviewed-by: Paul Fertser Tested-by: jenkins --- src/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4d1c1a2509..4dbe93feea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,7 +34,10 @@ if RELEASE else %C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" %C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" -%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\" +%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`DATE_FMT=+%F-%R; \ + SOURCE_DATE_EPOCH="$${SOURCE_DATE_EPOCH:-$$(date +%s)}"; \ + date -u -d "@$$SOURCE_DATE_EPOCH" "$$DATE_FMT" 2>/dev/null || \ + date -u -r "$$SOURCE_DATE_EPOCH" "$$DATE_FMT" 2>/dev/null || date -u "$$DATE_FMT"`\" endif # add default CPPFLAGS From 339763ed2d9a00ac1f2418403bd29c324d1c7e6e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 17:06:17 +0100 Subject: [PATCH 1156/1312] command: rewrite command 'command mode' as COMMAND_HANDLER Another step to drop jim_handler. Change-Id: I85cb567386a5aceb36aa273f8b66cbfd4a637c3f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8586 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov --- src/helper/command.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 3d4379d06c..923b091a8a 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -843,22 +843,19 @@ COMMAND_HANDLER(handle_help_command) return retval; } -static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv) +static char *alloc_concatenate_strings(int argc, const char **argv) { - char *prev, *all; - int i; - assert(argc >= 1); - all = strdup(Jim_GetString(argv[0], NULL)); + char *all = strdup(argv[0]); if (!all) { LOG_ERROR("Out of memory"); return NULL; } - for (i = 1; i < argc; ++i) { - prev = all; - all = alloc_printf("%s %s", all, Jim_GetString(argv[i], NULL)); + for (int i = 1; i < argc; ++i) { + char *prev = all; + all = alloc_printf("%s %s", all, argv[i]); free(prev); if (!all) { LOG_ERROR("Out of memory"); @@ -944,17 +941,16 @@ static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_na return c->mode; } -static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +COMMAND_HANDLER(handle_command_mode) { - struct command_context *cmd_ctx = current_command_context(interp); - enum command_mode mode = cmd_ctx->mode; + enum command_mode mode = CMD_CTX->mode; - if (argc > 1) { - char *full_name = alloc_concatenate_strings(argc - 1, argv + 1); + if (CMD_ARGC) { + char *full_name = alloc_concatenate_strings(CMD_ARGC, CMD_ARGV); if (!full_name) - return JIM_ERR; + return ERROR_FAIL; - mode = get_command_mode(interp, full_name); + mode = get_command_mode(CMD_CTX->interp, full_name); free(full_name); } @@ -975,8 +971,8 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) mode_str = "unknown"; break; } - Jim_SetResultString(interp, mode_str, -1); - return JIM_OK; + command_print(CMD, "%s", mode_str); + return ERROR_OK; } int help_del_all_commands(struct command_context *cmd_ctx) @@ -1115,7 +1111,7 @@ static const struct command_registration command_subcommand_handlers[] = { { .name = "mode", .mode = COMMAND_ANY, - .jim_handler = jim_command_mode, + .handler = handle_command_mode, .usage = "[command_name ...]", .help = "Returns the command modes allowed by a command: " "'any', 'config', or 'exec'. If no command is " From 16c5c1b353b06602d81a8a81f5243154a6c366cc Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 17:34:57 +0100 Subject: [PATCH 1157/1312] command: rewrite command 'capture' as COMMAND_HANDLER While there, use Jim_EvalObj() to execute the subcommand, so any error will correctly report the TCL file and the line number that have originated the error, instead of the silly: > capture {bogus command} command.c:703: Error: invalid command name "bogus" at file "command.c", line 703 Change-Id: Ic75a6146d6cedf49e808d98501fa1a7d4235b58a Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8587 Tested-by: jenkins --- src/helper/command.c | 113 +++++++++++++------------------------------ 1 file changed, 34 insertions(+), 79 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 923b091a8a..218f0581ef 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -31,8 +31,7 @@ #define __THIS__FILE__ "command.c" struct log_capture_state { - Jim_Interp *interp; - Jim_Obj *output; + char *output; }; static int unregister_command(struct command_context *context, @@ -59,73 +58,6 @@ void *jimcmd_privdata(Jim_Cmd *cmd) return cmd->isproc ? NULL : cmd->u.native.privData; } -static void tcl_output(void *privData, const char *file, unsigned int line, - const char *function, const char *string) -{ - struct log_capture_state *state = privData; - Jim_AppendString(state->interp, state->output, string, strlen(string)); -} - -static struct log_capture_state *command_log_capture_start(Jim_Interp *interp) -{ - /* capture log output and return it. A garbage collect can - * happen, so we need a reference count to this object */ - Jim_Obj *jim_output = Jim_NewStringObj(interp, "", 0); - if (!jim_output) - return NULL; - - Jim_IncrRefCount(jim_output); - - struct log_capture_state *state = malloc(sizeof(*state)); - if (!state) { - LOG_ERROR("Out of memory"); - Jim_DecrRefCount(interp, jim_output); - return NULL; - } - - state->interp = interp; - state->output = jim_output; - - log_add_callback(tcl_output, state); - - return state; -} - -/* Classic openocd commands provide progress output which we - * will capture and return as a Tcl return value. - * - * However, if a non-openocd command has been invoked, then it - * makes sense to return the tcl return value from that command. - * - * The tcl return value is empty for openocd commands that provide - * progress output. - * - * For other commands, we prepend the logs to the tcl return value. - */ -static void command_log_capture_finish(struct log_capture_state *state) -{ - if (!state) - return; - - log_remove_callback(tcl_output, state); - - int loglen; - const char *log_result = Jim_GetString(state->output, &loglen); - int reslen; - const char *cmd_result = Jim_GetString(Jim_GetResult(state->interp), &reslen); - - // Just in case the log doesn't end with a newline, we add it - if (loglen != 0 && reslen != 0 && log_result[loglen - 1] != '\n') - Jim_AppendString(state->interp, state->output, "\n", 1); - - Jim_AppendString(state->interp, state->output, cmd_result, reslen); - - Jim_SetResult(state->interp, state->output); - Jim_DecrRefCount(state->interp, state->output); - - free(state); -} - static int command_retval_set(Jim_Interp *interp, int retval) { int *return_retval = Jim_GetAssocData(interp, "retval"); @@ -680,15 +612,28 @@ COMMAND_HANDLER(handle_echo) return ERROR_OK; } -/* Return both the progress output (LOG_INFO and higher) +static void tcl_output(void *privData, const char *file, unsigned int line, + const char *function, const char *string) +{ + struct log_capture_state *state = privData; + char *old = state->output; + + state->output = alloc_printf("%s%s", old ? old : "", string); + free(old); + if (!state->output) + LOG_ERROR("Out of memory"); +} + +/* + * Return both the progress output (LOG_INFO and higher) * and the tcl return value of a command. */ -static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +COMMAND_HANDLER(handle_command_capture) { - if (argc != 2) - return JIM_ERR; + struct log_capture_state state = {NULL}; - struct log_capture_state *state = command_log_capture_start(interp); + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; /* disable polling during capture. This avoids capturing output * from polling. @@ -698,14 +643,24 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) */ bool save_poll_mask = jtag_poll_mask(); - const char *str = Jim_GetString(argv[1], NULL); - int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); + log_add_callback(tcl_output, &state); + + int jimretval = Jim_EvalObj(CMD_CTX->interp, CMD_JIMTCL_ARGV[0]); + const char *cmd_result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL); + + log_remove_callback(tcl_output, &state); jtag_poll_unmask(save_poll_mask); - command_log_capture_finish(state); + if (state.output && *state.output) + command_print(CMD, "%s", state.output); + + if (cmd_result && *cmd_result) + command_print(CMD, "%s", cmd_result); + + free(state.output); - return retcode; + return (jimretval == JIM_OK) ? ERROR_OK : ERROR_FAIL; } struct help_entry { @@ -1133,7 +1088,7 @@ static const struct command_registration command_builtin_handlers[] = { { .name = "capture", .mode = COMMAND_ANY, - .jim_handler = jim_capture, + .handler = handle_command_capture, .help = "Capture progress output and return as tcl return value. If the " "progress output was empty, return tcl return value.", .usage = "command", From cfed1f78db635b504e4d11da537e614adfd57d3f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 5 Apr 2025 17:04:43 +0200 Subject: [PATCH 1158/1312] list: silent scan-build false positive With commit c023534e7b6f ("target: use list for target events") scan build incorrectly states that list_add() would be called with the field 'next' of the parameter 'head' (thus 'head->next') set to NULL. Then, list_add() would call linux_list_add() with the parameter 'next' set to NULL that will cause a NULL dereference. While this can really happen with broken code, it's not the case with the code from the change above. Add assert() in linux_list_add() to silent scan build on this false positive and to detect future incorrect use of the list. Change-Id: Iec7f3d70237312b646ac58f76ecaab2fa25eab41 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8824 Tested-by: jenkins --- src/helper/list.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helper/list.h b/src/helper/list.h index ba07f15568..89b8468ec4 100644 --- a/src/helper/list.h +++ b/src/helper/list.h @@ -35,6 +35,7 @@ /* begin OpenOCD changes */ +#include #include struct list_head { @@ -109,6 +110,9 @@ static inline void linux_list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { + assert(next); + assert(prev); + next->prev = new; new->next = next; new->prev = prev; From a1ecf0a03d9812c285618ed995ea818eba020be3 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Apr 2025 01:20:44 +0200 Subject: [PATCH 1159/1312] target: don't free working areas during 'configure -chain-position' Since commit ef1cfb23947b ("Duane Ellis: "target as an [tcl] object" feature.") merged in 2008, the commands: $target_name configure -chain-position ... target create ... -chain-position ... cause the allocated working area to be freed. There is no reason for this, it is probably caused by an incorrect copy/paste from the author. Drop the call to target_free_all_working_areas(). Change-Id: I61a9303afe7fee6953669218330635c0b965b20d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8825 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/target/target.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target/target.c b/src/target/target.c index 8c5c8e5e30..36ad0eec83 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5128,7 +5128,6 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) return JIM_ERR; } - target_free_all_working_areas(target); e = jim_getopt_obj(goi, &o_t); if (e != JIM_OK) return e; From 4a616ca4d83919fea03bf084ff326f584de558d7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 18:40:47 +0100 Subject: [PATCH 1160/1312] target: rewrite command 'invoke-event' as COMMAND_HANDLER The command shares with command 'target create' the struct jim_nvp nvp_target_event[] - Convert the 'struct jim_nvp' in 'struct nvp'. - Create an alias 'struct jim_nvp' to decouple the commands 'invoke-event' and 'target create', abusing the fact that the actual layout of the two struct's type is the same. This alias will be dropped in a following change. - Rewrite the command 'invoke-event' and the helper function target_event_name(). Change-Id: I537732fe4c08042cc02bcd0f72142254d7968fa6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8826 Tested-by: jenkins --- src/target/target.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 36ad0eec83..3f16caaffe 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -162,7 +162,7 @@ static const char *target_strerror_safe(int err) return n->name; } -static const struct jim_nvp nvp_target_event[] = { +static const struct nvp nvp_target_event[] = { { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" }, { .value = TARGET_EVENT_HALTED, .name = "halted" }, @@ -214,6 +214,8 @@ static const struct jim_nvp nvp_target_event[] = { { .name = NULL, .value = -1 } }; +static const struct jim_nvp *jim_nvp_target_event = (const struct jim_nvp *)nvp_target_event; + static const struct nvp nvp_target_state[] = { { .name = "unknown", .value = TARGET_UNKNOWN }, { .name = "running", .value = TARGET_RUNNING }, @@ -283,7 +285,7 @@ const char *target_state_name(const struct target *t) const char *target_event_name(enum target_event event) { const char *cp; - cp = jim_nvp_value2name_simple(nvp_target_event, event)->name; + cp = nvp_value2name(nvp_target_event, event)->name; if (!cp) { LOG_ERROR("Invalid target event: %d", (int)(event)); cp = "(*BUG*unknown*BUG*)"; @@ -4932,9 +4934,9 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) return JIM_ERR; } - e = jim_getopt_nvp(goi, nvp_target_event, &n); + e = jim_getopt_nvp(goi, jim_nvp_target_event, &n); if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_target_event, 1); + jim_getopt_nvp_unknown(goi, jim_nvp_target_event, 1); return e; } @@ -5469,26 +5471,20 @@ COMMAND_HANDLER(handle_target_debug_reason) return ERROR_OK; } -static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +COMMAND_HANDLER(handle_target_invoke_event) { - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc != 1) { - const char *cmd_name = Jim_GetString(argv[0], NULL); - Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); - return JIM_ERR; - } - struct jim_nvp *n; - int e = jim_getopt_nvp(&goi, nvp_target_event, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(&goi, nvp_target_event, 1); - return e; + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + const struct nvp *n = nvp_name2value(nvp_target_event, CMD_ARGV[0]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_target_event, NULL, CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); + + struct target *target = get_current_target(CMD_CTX); target_handle_event(target, n->value); - return JIM_OK; + return ERROR_OK; } static const struct command_registration target_instance_command_handlers[] = { @@ -5670,7 +5666,7 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "invoke-event", .mode = COMMAND_EXEC, - .jim_handler = jim_target_invoke_event, + .handler = handle_target_invoke_event, .help = "invoke handler for specified event", .usage = "event_name", }, From 29e4a366222b96aac89dbec11e5f4a83a6a83bbe Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 23:01:44 +0100 Subject: [PATCH 1161/1312] target: rewrite command 'target create' as COMMAND_HANDLER Rewrite only the command, but still use the old jimtcl specific code shared with 'configure' and 'cget'. Change-Id: I7cf220e494f0ebbf123f8075b1feb9251fd7f569 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8827 Tested-by: jenkins --- src/target/target.c | 147 ++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 82 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 3f16caaffe..9d9d73a28e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5673,44 +5673,29 @@ static const struct command_registration target_instance_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static int target_create(struct jim_getopt_info *goi) +COMMAND_HANDLER(handle_target_create) { - Jim_Obj *new_cmd; - Jim_Cmd *cmd; - const char *cp; - int e; + int retval = ERROR_OK; int x; - struct target *target; - struct command_context *cmd_ctx; - cmd_ctx = current_command_context(goi->interp); - assert(cmd_ctx); - - if (goi->argc < 3) { - Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); - return JIM_ERR; - } + if (CMD_ARGC < 4) + return ERROR_COMMAND_SYNTAX_ERROR; - /* COMMAND */ - jim_getopt_obj(goi, &new_cmd); - /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); - if (cmd) { - cp = Jim_GetString(new_cmd, NULL); - Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); - return JIM_ERR; + /* check if the target name clashes with an existing command name */ + Jim_Cmd *jimcmd = Jim_GetCommand(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], JIM_NONE); + if (jimcmd) { + command_print(CMD, "Command/target: %s Exists", CMD_ARGV[0]); + return ERROR_FAIL; } /* TYPE */ - e = jim_getopt_string(goi, &cp, NULL); - if (e != JIM_OK) - return e; + const char *cp = CMD_ARGV[1]; struct transport *tr = get_current_transport(); if (tr && tr->override_target) { - e = tr->override_target(&cp); - if (e != ERROR_OK) { - LOG_ERROR("The selected transport doesn't support this target"); - return JIM_ERR; + retval = tr->override_target(&cp); + if (retval != ERROR_OK) { + command_print(CMD, "The selected transport doesn't support this target"); + return retval; } LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD"); } @@ -5722,28 +5707,29 @@ static int target_create(struct jim_getopt_info *goi) } } if (!target_types[x]) { - Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); + char *all = NULL; for (x = 0 ; target_types[x] ; x++) { - if (target_types[x + 1]) { - Jim_AppendStrings(goi->interp, - Jim_GetResult(goi->interp), - target_types[x]->name, - ", ", NULL); - } else { - Jim_AppendStrings(goi->interp, - Jim_GetResult(goi->interp), - " or ", - target_types[x]->name, NULL); + char *prev = all; + if (all) + all = alloc_printf("%s, %s", all, target_types[x]->name); + else + all = alloc_printf("%s", target_types[x]->name); + free(prev); + if (!all) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; } } - return JIM_ERR; + command_print(CMD, "Unknown target type %s, try one of %s", cp, all); + free(all); + return ERROR_FAIL; } /* Create it */ - target = calloc(1, sizeof(struct target)); + struct target *target = calloc(1, sizeof(struct target)); if (!target) { LOG_ERROR("Out of memory"); - return JIM_ERR; + return ERROR_FAIL; } /* set empty smp cluster */ @@ -5754,7 +5740,7 @@ static int target_create(struct jim_getopt_info *goi) if (!target->type) { LOG_ERROR("Out of memory"); free(target); - return JIM_ERR; + return ERROR_FAIL; } memcpy(target->type, target_types[x], sizeof(struct target_type)); @@ -5787,7 +5773,7 @@ static int target_create(struct jim_getopt_info *goi) LOG_ERROR("Out of memory"); free(target->type); free(target); - return JIM_ERR; + return ERROR_FAIL; } target->dbgmsg = NULL; @@ -5801,45 +5787,54 @@ static int target_create(struct jim_getopt_info *goi) target->gdb_port_override = NULL; target->gdb_max_connections = 1; - cp = Jim_GetString(new_cmd, NULL); - target->cmd_name = strdup(cp); + target->cmd_name = strdup(CMD_ARGV[0]); if (!target->cmd_name) { LOG_ERROR("Out of memory"); free(target->trace_info); free(target->type); free(target); - return JIM_ERR; + return ERROR_FAIL; } /* Do the rest as "configure" options */ - goi->is_configure = true; - e = target_configure(goi, target); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 2, CMD_JIMTCL_ARGV + 2); + + goi.is_configure = 1; + int e = target_configure(&goi, target); + + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); if (e == JIM_OK) { if (target->has_dap) { if (!target->dap_configured) { - Jim_SetResultString(goi->interp, "-dap ?name? required when creating target", -1); - e = JIM_ERR; + command_print(CMD, "-dap ?name? required when creating target"); + retval = ERROR_COMMAND_ARGUMENT_INVALID; } } else { if (!target->tap_configured) { - Jim_SetResultString(goi->interp, "-chain-position ?name? required when creating target", -1); - e = JIM_ERR; + command_print(CMD, "-chain-position ?name? required when creating target"); + retval = ERROR_COMMAND_ARGUMENT_INVALID; } } /* tap must be set after target was configured */ if (!target->tap) - e = JIM_ERR; + retval = ERROR_COMMAND_ARGUMENT_INVALID; + } else { + retval = ERROR_FAIL; } - if (e != JIM_OK) { + if (retval != ERROR_OK) { rtos_destroy(target); free(target->gdb_port_override); free(target->trace_info); free(target->type); free(target->private_config); free(target); - return e; + return retval; } if (target->endianness == TARGET_ENDIAN_UNKNOWN) { @@ -5848,8 +5843,8 @@ static int target_create(struct jim_getopt_info *goi) } if (target->type->target_create) { - e = (*(target->type->target_create))(target, goi->interp); - if (e != ERROR_OK) { + retval = (*target->type->target_create)(target, CMD_CTX->interp); + if (retval != ERROR_OK) { LOG_DEBUG("target_create failed"); free(target->cmd_name); rtos_destroy(target); @@ -5858,15 +5853,15 @@ static int target_create(struct jim_getopt_info *goi) free(target->type); free(target->private_config); free(target); - return JIM_ERR; + return retval; } } /* create the target specific commands */ if (target->type->commands) { - e = register_commands(cmd_ctx, NULL, target->type->commands); - if (e != ERROR_OK) - LOG_ERROR("unable to register '%s' commands", cp); + retval = register_commands(CMD_CTX, NULL, target->type->commands); + if (retval != ERROR_OK) + LOG_ERROR("unable to register '%s' commands", CMD_ARGV[0]); } /* now - create the new target name command */ @@ -5881,7 +5876,7 @@ static int target_create(struct jim_getopt_info *goi) }; const struct command_registration target_commands[] = { { - .name = cp, + .name = CMD_ARGV[0], .mode = COMMAND_ANY, .help = "target command group", .usage = "", @@ -5889,8 +5884,8 @@ static int target_create(struct jim_getopt_info *goi) }, COMMAND_REGISTRATION_DONE }; - e = register_commands_override_target(cmd_ctx, NULL, target_commands, target); - if (e != ERROR_OK) { + retval = register_commands_override_target(CMD_CTX, NULL, target_commands, target); + if (retval != ERROR_OK) { if (target->type->deinit_target) target->type->deinit_target(target); free(target->cmd_name); @@ -5899,14 +5894,14 @@ static int target_create(struct jim_getopt_info *goi) free(target->trace_info); free(target->type); free(target); - return JIM_ERR; + return retval; } /* append to end of list */ append_to_list_all_targets(target); - cmd_ctx->current_target = target; - return JIM_OK; + CMD_CTX->current_target = target; + return ERROR_OK; } COMMAND_HANDLER(handle_target_current) @@ -6027,18 +6022,6 @@ COMMAND_HANDLER(handle_target_smp) return retval; } -static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 3) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - " [ ...]"); - return JIM_ERR; - } - return target_create(&goi); -} - static const struct command_registration target_subcommand_handlers[] = { { .name = "init", @@ -6050,7 +6033,7 @@ static const struct command_registration target_subcommand_handlers[] = { { .name = "create", .mode = COMMAND_CONFIG, - .jim_handler = jim_target_create, + .handler = handle_target_create, .usage = "name type '-chain-position' name [options ...]", .help = "Creates and selects a new target", }, From 1d9b34baa3c5087f2a3387523c6c556b4e4f1afb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 2 Dec 2023 23:40:56 +0100 Subject: [PATCH 1162/1312] target: rewrite commands 'configure' and 'cget' as COMMAND_HANDLER Rewrite only the command, but still use the old jimtcl specific code shared with 'target create'. Change-Id: Ie5e1c9eb237531121c2d143d1732cf281dfdc9ff Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8828 Tested-by: jenkins --- src/target/target.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 9d9d73a28e..4bd2f24cca 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5223,22 +5223,28 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) return JIM_OK; } -static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +COMMAND_HANDLER(handle_target_configure) { - struct command *c = jim_to_command(interp); + if (!CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.is_configure = !strcmp(c->name, "configure"); - if (goi.argc < 1) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - "missing: -option ..."); - return JIM_ERR; - } - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); - return target_configure(&goi, target); + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC, CMD_JIMTCL_ARGV); + goi.is_configure = !strcmp(CMD_NAME, "configure"); + + struct target *target = get_current_target(CMD_CTX); + int e = target_configure(&goi, target); + + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + + if (e != JIM_OK) + return ERROR_FAIL; + + return ERROR_OK; } COMMAND_HANDLER(handle_target_examine) @@ -5491,14 +5497,14 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "configure", .mode = COMMAND_ANY, - .jim_handler = jim_target_configure, + .handler = handle_target_configure, .help = "configure a new target for use", .usage = "[target_attribute ...]", }, { .name = "cget", .mode = COMMAND_ANY, - .jim_handler = jim_target_configure, + .handler = handle_target_configure, .help = "returns the specified target attribute", .usage = "target_attribute", }, From 61890e3dc3201ce38e5af7f6b561389a123448e0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Dec 2023 15:41:27 +0100 Subject: [PATCH 1163/1312] target: rewrite function target_configure() as COMMAND_HELPER The function target_configure() is used by the commands 'target create', 'configure' and 'cget', already rewritten as COMMAND_HANDLER. Rewrite the common function as COMMAND_HELPER. While there: - fix the check on arguments, even if it should be coded better; - keep jimtcl code for target_type::target_jim_configure() and for rtos_create(); these would be rewritten later on. Change-Id: I7e5699ca6d124e34d3b2199714e3ce584bfcce80 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8829 Tested-by: jenkins --- src/target/target.c | 434 +++++++++++++++++++++++--------------------- 1 file changed, 225 insertions(+), 209 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 4bd2f24cca..99481622db 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -214,8 +214,6 @@ static const struct nvp nvp_target_event[] = { { .name = NULL, .value = -1 } }; -static const struct jim_nvp *jim_nvp_target_event = (const struct jim_nvp *)nvp_target_event; - static const struct nvp nvp_target_state[] = { { .name = "unknown", .value = TARGET_UNKNOWN }, { .name = "running", .value = TARGET_RUNNING }, @@ -238,7 +236,7 @@ static const struct nvp nvp_target_debug_reason[] = { { .name = NULL, .value = -1 }, }; -static const struct jim_nvp nvp_target_endian[] = { +static const struct nvp nvp_target_endian[] = { { .name = "big", .value = TARGET_BIG_ENDIAN }, { .name = "little", .value = TARGET_LITTLE_ENDIAN }, { .name = "be", .value = TARGET_BIG_ENDIAN }, @@ -2844,8 +2842,7 @@ COMMAND_HANDLER(handle_targets_command) marker, target_name(target), target_type_name(target), - jim_nvp_value2name_simple(nvp_target_endian, - target->endianness)->name, + nvp_value2name(nvp_target_endian, target->endianness)->name, target->tap->dotted_name, state); } @@ -4859,7 +4856,7 @@ enum target_cfg_param { TCFG_GDB_MAX_CONNECTIONS, }; -static struct jim_nvp nvp_config_opts[] = { +static struct nvp nvp_config_opts[] = { { .name = "-type", .value = TCFG_TYPE }, { .name = "-event", .value = TCFG_EVENT }, { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, @@ -4877,78 +4874,71 @@ static struct jim_nvp nvp_config_opts[] = { { .name = NULL, .value = -1 } }; -static int target_configure(struct jim_getopt_info *goi, struct target *target) +static COMMAND_HELPER(target_configure, struct target *target, unsigned int index, bool is_configure) { - struct jim_nvp *n; - Jim_Obj *o; - jim_wide w; - int e; + const struct nvp *n; + int retval; /* parse config or cget options ... */ - while (goi->argc > 0) { - Jim_SetEmptyResult(goi->interp); - /* jim_getopt_debug(goi); */ - + while (index < CMD_ARGC) { if (target->type->target_jim_configure) { /* target defines a configure function */ /* target gets first dibs on parameters */ - e = (*(target->type->target_jim_configure))(target, goi); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index); + goi.is_configure = is_configure; + int e = (*target->type->target_jim_configure)(target, &goi); + index = CMD_ARGC - goi.argc; if (e == JIM_OK) { /* more? */ continue; } if (e == JIM_ERR) { /* An error */ - return e; + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + return ERROR_FAIL; } /* otherwise we 'continue' below */ } - e = jim_getopt_nvp(goi, nvp_config_opts, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_config_opts, 0); - return e; + n = nvp_name2value(nvp_config_opts, CMD_ARGV[index]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_config_opts, NULL, CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; } + index++; switch (n->value) { case TCFG_TYPE: /* not settable */ - if (goi->is_configure) { - Jim_SetResultFormatted(goi->interp, - "not settable: %s", n->name); - return JIM_ERR; - } else { -no_params: - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, - goi->argc, goi->argv, - "NO PARAMS"); - return JIM_ERR; - } + if (is_configure) { + command_print(CMD, "not settable: %s", n->name); + return ERROR_COMMAND_ARGUMENT_INVALID; } - Jim_SetResultString(goi->interp, - target_type_name(target), -1); + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%s", target_type_name(target)); /* loop for more */ break; + case TCFG_EVENT: - if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); - return JIM_ERR; + if (index == CMD_ARGC) { + command_print(CMD, "missing event-name"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - e = jim_getopt_nvp(goi, jim_nvp_target_event, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, jim_nvp_target_event, 1); - return e; + n = nvp_name2value(nvp_target_event, CMD_ARGV[index]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_target_event, CMD_ARGV[index - 1], CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; } + index++; - if (goi->is_configure) { - if (goi->argc != 1) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); - return JIM_ERR; - } - } else { - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); - return JIM_ERR; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing event-body"); + return ERROR_COMMAND_ARGUMENT_INVALID; } } @@ -4964,20 +4954,20 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) if (&teap->list == &target->events_action) teap = NULL; - if (goi->is_configure) { + if (is_configure) { /* START_DEPRECATED_TPIU */ if (n->value == TARGET_EVENT_TRACE_CONFIG) LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); /* END_DEPRECATED_TPIU */ - jim_getopt_obj(goi, &o); - if (Jim_Length(o) == 0) { + if (strlen(CMD_ARGV[index]) == 0) { /* empty action, drop existing one */ if (teap) { list_del(&teap->list); Jim_DecrRefCount(teap->interp, teap->body); free(teap); } + index++; break; } @@ -4988,10 +4978,12 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) replace = false; } teap->event = n->value; - teap->interp = goi->interp; + teap->interp = CMD_CTX->interp; if (teap->body) Jim_DecrRefCount(teap->interp, teap->body); - teap->body = Jim_DuplicateObj(goi->interp, o); + /* use jim object to keep its reference on tcl file and line */ + /* TODO: need duplicate? isn't IncrRefCount enough? */ + teap->body = Jim_DuplicateObj(teap->interp, CMD_JIMTCL_ARGV[index++]); /* * FIXME: * Tcl/TK - "tk events" have a nice feature. @@ -5008,219 +5000,266 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) /* add to head of event list */ list_add(&teap->list, &target->events_action); } - Jim_SetEmptyResult(goi->interp); } else { - /* get */ - if (!teap) - Jim_SetEmptyResult(goi->interp); - else - Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); + /* cget */ + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (teap) + command_print(CMD, "%s", Jim_GetString(teap->body, NULL)); } } /* loop for more */ break; case TCFG_WORK_AREA_VIRT: - if (goi->is_configure) { - target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_virt = w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_virt); + index++; target->working_area_virt_spec = true; + target_free_all_working_areas(target); } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, TARGET_ADDR_FMT, target->working_area_virt); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); /* loop for more */ break; case TCFG_WORK_AREA_PHYS: - if (goi->is_configure) { - target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_phys = w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_phys); + index++; target->working_area_phys_spec = true; + target_free_all_working_areas(target); } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, TARGET_ADDR_FMT, target->working_area_phys); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); /* loop for more */ break; case TCFG_WORK_AREA_SIZE: - if (goi->is_configure) { + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->working_area_size); + index++; target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_size = w; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "0x%08" PRIx32, target->working_area_size); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); /* loop for more */ break; case TCFG_WORK_AREA_BACKUP: - if (goi->is_configure) { + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + retval = command_parse_bool_arg(CMD_ARGV[index], &target->backup_working_area); + if (retval != ERROR_OK) + return retval; + index++; target_free_all_working_areas(target); - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - /* make this boolean */ - target->backup_working_area = (w != 0); } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, target->backup_working_area ? "1" : "0"); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area ? 1 : 0)); - /* loop for more e*/ + /* loop for more */ break; - case TCFG_ENDIAN: - if (goi->is_configure) { - e = jim_getopt_nvp(goi, nvp_target_endian, &n); - if (e != JIM_OK) { - jim_getopt_nvp_unknown(goi, nvp_target_endian, 1); - return e; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + n = nvp_name2value(nvp_target_endian, CMD_ARGV[index]); + if (!n->name) { + nvp_unknown_command_print(CMD, nvp_target_endian, CMD_ARGV[index - 1], CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; } + index++; target->endianness = n->value; } else { - if (goi->argc != 0) - goto no_params; - } - n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness); - if (!n->name) { - target->endianness = TARGET_LITTLE_ENDIAN; - n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness); + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + n = nvp_value2name(nvp_target_endian, target->endianness); + if (!n->name) { + target->endianness = TARGET_LITTLE_ENDIAN; + n = nvp_value2name(nvp_target_endian, target->endianness); + } + command_print(CMD, "%s", n->name); } - Jim_SetResultString(goi->interp, n->name, -1); /* loop for more */ break; case TCFG_COREID: - if (goi->is_configure) { - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->coreid = (int32_t)w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(s32, CMD_ARGV[index], target->coreid); + index++; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%" PRIi32, target->coreid); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->coreid)); /* loop for more */ break; case TCFG_CHAIN_POSITION: - if (goi->is_configure) { - Jim_Obj *o_t; - struct jtag_tap *tap; - + if (is_configure) { if (target->has_dap) { - Jim_SetResultString(goi->interp, - "target requires -dap parameter instead of -chain-position!", -1); - return JIM_ERR; + command_print(CMD, "target requires -dap parameter instead of -chain-position!"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - e = jim_getopt_obj(goi, &o_t); - if (e != JIM_OK) - return e; - tap = jtag_tap_by_jim_obj(goi->interp, o_t); - if (!tap) - return JIM_ERR; + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[index]); + if (!tap) { + command_print(CMD, "Tap '%s' could not be found", CMD_ARGV[index]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + index++; target->tap = tap; target->tap_configured = true; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%s", target->tap->dotted_name); } - Jim_SetResultString(goi->interp, target->tap->dotted_name, -1); - /* loop for more e*/ + /* loop for more */ break; + case TCFG_DBGBASE: - if (goi->is_configure) { - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->dbgbase = (uint32_t)w; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->dbgbase); + index++; target->dbgbase_set = true; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "0x%08" PRIx32, target->dbgbase); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); /* loop for more */ break; + case TCFG_RTOS: - /* RTOS */ - { - int result = rtos_create(goi, target); - if (result != JIM_OK) - return result; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index); + index++; + goi.is_configure = true; + int resval = rtos_create(&goi, target); + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + if (resval != JIM_OK) + return ERROR_FAIL; + } else { + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + if (target->rtos) + command_print(CMD, "%s", target->rtos->type->name); } /* loop for more */ break; case TCFG_DEFER_EXAMINE: - /* DEFER_EXAMINE */ - target->defer_examine = true; + if (is_configure) + target->defer_examine = true; + else + command_print(CMD, "%s", target->defer_examine ? "true" : "false"); /* loop for more */ break; case TCFG_GDB_PORT: - if (goi->is_configure) { - struct command_context *cmd_ctx = current_command_context(goi->interp); - if (cmd_ctx->mode != COMMAND_CONFIG) { - Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1); - return JIM_ERR; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + /* TODO: generalize test of COMMAND_CONFIG */ + if (CMD_CTX->mode != COMMAND_CONFIG) { + command_print(CMD, "-gdb-port must be configured before 'init'"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - const char *s; - e = jim_getopt_string(goi, &s, NULL); - if (e != JIM_OK) - return e; + char *s = strdup(CMD_ARGV[index]); + if (!s) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } free(target->gdb_port_override); - target->gdb_port_override = strdup(s); + target->gdb_port_override = s; + index++; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%s", target->gdb_port_override ? target->gdb_port_override : "undefined"); } - Jim_SetResultString(goi->interp, target->gdb_port_override ? target->gdb_port_override : "undefined", -1); /* loop for more */ break; case TCFG_GDB_MAX_CONNECTIONS: - if (goi->is_configure) { - struct command_context *cmd_ctx = current_command_context(goi->interp); - if (cmd_ctx->mode != COMMAND_CONFIG) { - Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1); - return JIM_ERR; + if (is_configure) { + if (index == CMD_ARGC) { + command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + if (CMD_CTX->mode != COMMAND_CONFIG) { + command_print(CMD, "-gdb-max-connections must be configured before 'init'"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - e = jim_getopt_wide(goi, &w); - if (e != JIM_OK) - return e; - target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w; + COMMAND_PARSE_NUMBER(int, CMD_ARGV[index], target->gdb_max_connections); + index++; + if (target->gdb_max_connections < 0) + target->gdb_max_connections = CONNECTION_LIMIT_UNLIMITED; } else { - if (goi->argc != 0) - goto no_params; + if (index != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "%d", target->gdb_max_connections); } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections)); + /* loop for more */ break; } - } /* while (goi->argc) */ - + } - /* done - we return */ - return JIM_OK; + return ERROR_OK; } COMMAND_HANDLER(handle_target_configure) @@ -5228,23 +5267,11 @@ COMMAND_HANDLER(handle_target_configure) if (!CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; - struct jim_getopt_info goi; - - jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC, CMD_JIMTCL_ARGV); - goi.is_configure = !strcmp(CMD_NAME, "configure"); + bool is_configure = !strcmp(CMD_NAME, "configure"); struct target *target = get_current_target(CMD_CTX); - int e = target_configure(&goi, target); - - int reslen; - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); - if (reslen > 0) - command_print(CMD, "%s", result); - - if (e != JIM_OK) - return ERROR_FAIL; - return ERROR_OK; + return CALL_COMMAND_HANDLER(target_configure, target, 0, is_configure); } COMMAND_HANDLER(handle_target_examine) @@ -5803,18 +5830,9 @@ COMMAND_HANDLER(handle_target_create) } /* Do the rest as "configure" options */ - struct jim_getopt_info goi; - jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 2, CMD_JIMTCL_ARGV + 2); - - goi.is_configure = 1; - int e = target_configure(&goi, target); - - int reslen; - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); - if (reslen > 0) - command_print(CMD, "%s", result); - - if (e == JIM_OK) { + bool is_configure = true; + retval = CALL_COMMAND_HANDLER(target_configure, target, 2, is_configure); + if (retval == ERROR_OK) { if (target->has_dap) { if (!target->dap_configured) { command_print(CMD, "-dap ?name? required when creating target"); @@ -5829,8 +5847,6 @@ COMMAND_HANDLER(handle_target_create) /* tap must be set after target was configured */ if (!target->tap) retval = ERROR_COMMAND_ARGUMENT_INVALID; - } else { - retval = ERROR_FAIL; } if (retval != ERROR_OK) { From 9a09d38478e2fbe7a9482af11b0fafb04689355d Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Apr 2025 14:10:28 +0200 Subject: [PATCH 1164/1312] target: drop unused parameter to target_create() The parameter Jim_Interp to the target API target_create() is not used by any target. Drop it. Change-Id: I67c492078a6c808db974505f9e297c45165f64d0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8831 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/aarch64.c | 4 ++-- src/target/arc.c | 2 +- src/target/arm11.c | 2 +- src/target/arm720t.c | 2 +- src/target/arm7tdmi.c | 2 +- src/target/arm920t.c | 2 +- src/target/arm926ejs.c | 2 +- src/target/arm946e.c | 2 +- src/target/arm966e.c | 2 +- src/target/arm9tdmi.c | 2 +- src/target/avr32_ap7k.c | 2 +- src/target/avrt.c | 4 ++-- src/target/cortex_a.c | 4 ++-- src/target/cortex_m.c | 2 +- src/target/dsp563xx.c | 2 +- src/target/dsp5680xx.c | 2 +- src/target/esirisc.c | 2 +- src/target/espressif/esp32.c | 2 +- src/target/espressif/esp32s2.c | 2 +- src/target/espressif/esp32s3.c | 2 +- src/target/fa526.c | 2 +- src/target/feroceon.c | 4 ++-- src/target/hla_target.c | 3 +-- src/target/ls1_sap.c | 2 +- src/target/mem_ap.c | 2 +- src/target/mips_m4k.c | 2 +- src/target/mips_mips64.c | 2 +- src/target/openrisc/or1k.c | 2 +- src/target/quark_d20xx.c | 2 +- src/target/quark_x10xx.c | 2 +- src/target/riscv/riscv.c | 2 +- src/target/stm8.c | 3 +-- src/target/target.c | 2 +- src/target/target_type.h | 2 +- src/target/xscale.c | 2 +- src/target/xtensa/xtensa_chip.c | 2 +- 36 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ce7808e3ac..101cb14408 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2814,7 +2814,7 @@ static int aarch64_init_arch_info(struct target *target, return ERROR_OK; } -static int armv8r_target_create(struct target *target, Jim_Interp *interp) +static int armv8r_target_create(struct target *target) { struct aarch64_private_config *pc = target->private_config; struct aarch64_common *aarch64; @@ -2833,7 +2833,7 @@ static int armv8r_target_create(struct target *target, Jim_Interp *interp) return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap); } -static int aarch64_target_create(struct target *target, Jim_Interp *interp) +static int aarch64_target_create(struct target *target) { struct aarch64_private_config *pc = target->private_config; struct aarch64_common *aarch64; diff --git a/src/target/arc.c b/src/target/arc.c index 8757cafedc..f2482c25ef 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -1424,7 +1424,7 @@ static void arc_deinit_target(struct target *target) } -static int arc_target_create(struct target *target, Jim_Interp *interp) +static int arc_target_create(struct target *target) { struct arc_common *arc = calloc(1, sizeof(*arc)); diff --git a/src/target/arm11.c b/src/target/arm11.c index 756b36b959..583830f948 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -1079,7 +1079,7 @@ static int arm11_remove_breakpoint(struct target *target, return ERROR_OK; } -static int arm11_target_create(struct target *target, Jim_Interp *interp) +static int arm11_target_create(struct target *target) { struct arm11_common *arm11; diff --git a/src/target/arm720t.c b/src/target/arm720t.c index beab632c25..d1433dde72 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -412,7 +412,7 @@ static int arm720t_init_arch_info(struct target *target, return ERROR_OK; } -static int arm720t_target_create(struct target *target, Jim_Interp *interp) +static int arm720t_target_create(struct target *target) { struct arm720t_common *arm720t = calloc(1, sizeof(*arm720t)); diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 393d3b46af..2f59254afd 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -669,7 +669,7 @@ int arm7tdmi_init_arch_info(struct target *target, return ERROR_OK; } -static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp) +static int arm7tdmi_target_create(struct target *target) { struct arm7_9_common *arm7_9; diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 53b4d9d15f..95cfd7ceb2 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -833,7 +833,7 @@ static int arm920t_init_arch_info(struct target *target, return ERROR_OK; } -static int arm920t_target_create(struct target *target, Jim_Interp *interp) +static int arm920t_target_create(struct target *target) { struct arm920t_common *arm920t; diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index add90c9978..0531106562 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -702,7 +702,7 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm return ERROR_OK; } -static int arm926ejs_target_create(struct target *target, Jim_Interp *interp) +static int arm926ejs_target_create(struct target *target) { struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common)); diff --git a/src/target/arm946e.c b/src/target/arm946e.c index 03f7e443fb..828e70f4bc 100644 --- a/src/target/arm946e.c +++ b/src/target/arm946e.c @@ -79,7 +79,7 @@ static int arm946e_init_arch_info(struct target *target, return ERROR_OK; } -static int arm946e_target_create(struct target *target, Jim_Interp *interp) +static int arm946e_target_create(struct target *target) { struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common)); diff --git a/src/target/arm966e.c b/src/target/arm966e.c index 8598d29d9b..b6bcc8ba97 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -38,7 +38,7 @@ int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e return ERROR_OK; } -static int arm966e_target_create(struct target *target, Jim_Interp *interp) +static int arm966e_target_create(struct target *target) { struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common)); diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index 7e31306b6c..8ab12de320 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -765,7 +765,7 @@ int arm9tdmi_init_arch_info(struct target *target, return ERROR_OK; } -static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp) +static int arm9tdmi_target_create(struct target *target) { struct arm7_9_common *arm7_9 = calloc(1, sizeof(struct arm7_9_common)); diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index 1b051dc014..94962c2055 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -510,7 +510,7 @@ static int avr32_ap7k_init_target(struct command_context *cmd_ctx, return ERROR_OK; } -static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp) +static int avr32_ap7k_target_create(struct target *target) { struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct avr32_ap7k_common)); diff --git a/src/target/avrt.c b/src/target/avrt.c index 3afe320157..e25718bcc2 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -16,7 +16,7 @@ #define AVR_JTAG_INS_LEN 4 /* forward declarations */ -static int avr_target_create(struct target *target, Jim_Interp *interp); +static int avr_target_create(struct target *target); static int avr_init_target(struct command_context *cmd_ctx, struct target *target); static int avr_arch_state(struct target *target); @@ -68,7 +68,7 @@ struct target_type avr_target = { .init_target = avr_init_target, }; -static int avr_target_create(struct target *target, Jim_Interp *interp) +static int avr_target_create(struct target *target) { struct avr_common *avr = calloc(1, sizeof(struct avr_common)); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 9c60645586..ee27e1b217 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -3126,7 +3126,7 @@ static int cortex_a_init_arch_info(struct target *target, return ERROR_OK; } -static int cortex_a_target_create(struct target *target, Jim_Interp *interp) +static int cortex_a_target_create(struct target *target) { struct cortex_a_common *cortex_a; struct adiv5_private_config *pc; @@ -3148,7 +3148,7 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp) return cortex_a_init_arch_info(target, cortex_a, pc->dap); } -static int cortex_r4_target_create(struct target *target, Jim_Interp *interp) +static int cortex_r4_target_create(struct target *target) { struct cortex_a_common *cortex_a; struct adiv5_private_config *pc; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index e17f23c1d3..ba9d83d79f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2916,7 +2916,7 @@ static int cortex_m_init_arch_info(struct target *target, return ERROR_OK; } -static int cortex_m_target_create(struct target *target, Jim_Interp *interp) +static int cortex_m_target_create(struct target *target) { struct adiv5_private_config *pc; diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 9b6f4756c9..dc85a21800 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -880,7 +880,7 @@ static void dsp563xx_invalidate_x_context(struct target *target, } } -static int dsp563xx_target_create(struct target *target, Jim_Interp *interp) +static int dsp563xx_target_create(struct target *target) { struct dsp563xx_common *dsp563xx = calloc(1, sizeof(struct dsp563xx_common)); diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index 3f9a6742c4..65efbae324 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -855,7 +855,7 @@ static int eonce_pc_store(struct target *target) return ERROR_OK; } -static int dsp5680xx_target_create(struct target *target, Jim_Interp *interp) +static int dsp5680xx_target_create(struct target *target) { struct dsp5680xx_common *dsp5680xx = calloc(1, sizeof(struct dsp5680xx_common)); diff --git a/src/target/esirisc.c b/src/target/esirisc.c index da40928da9..fac5dc72ee 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -1575,7 +1575,7 @@ static int esirisc_identify(struct target *target) return ERROR_OK; } -static int esirisc_target_create(struct target *target, Jim_Interp *interp) +static int esirisc_target_create(struct target *target) { struct jtag_tap *tap = target->tap; struct esirisc_common *esirisc; diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 4deb5e0709..399ba8e7cd 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -326,7 +326,7 @@ static const struct esp_semihost_ops esp32_semihost_ops = { .prepare = esp32_disable_wdts }; -static int esp32_target_create(struct target *target, Jim_Interp *interp) +static int esp32_target_create(struct target *target) { struct xtensa_debug_module_config esp32_dm_cfg = { .dbg_ops = &esp32_dbg_ops, diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index 4f3914f66a..b86e43e626 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -445,7 +445,7 @@ static const struct esp_semihost_ops esp32s2_semihost_ops = { .prepare = esp32s2_disable_wdts }; -static int esp32s2_target_create(struct target *target, Jim_Interp *interp) +static int esp32s2_target_create(struct target *target) { struct xtensa_debug_module_config esp32s2_dm_cfg = { .dbg_ops = &esp32s2_dbg_ops, diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 7507c11c24..82413f77fb 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -320,7 +320,7 @@ static const struct esp_semihost_ops esp32s3_semihost_ops = { .prepare = esp32s3_disable_wdts }; -static int esp32s3_target_create(struct target *target, Jim_Interp *interp) +static int esp32s3_target_create(struct target *target) { struct xtensa_debug_module_config esp32s3_dm_cfg = { .dbg_ops = &esp32s3_dbg_ops, diff --git a/src/target/fa526.c b/src/target/fa526.c index 38b7ab2e9d..d832d3e7d1 100644 --- a/src/target/fa526.c +++ b/src/target/fa526.c @@ -329,7 +329,7 @@ static int fa526_init_arch_info(struct target *target, return ERROR_OK; } -static int fa526_target_create(struct target *target, Jim_Interp *interp) +static int fa526_target_create(struct target *target) { struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common)); diff --git a/src/target/feroceon.c b/src/target/feroceon.c index 840ca1b62b..cf2c838b7d 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -622,7 +622,7 @@ static void feroceon_common_setup(struct target *target) arm7_9->wp1_used_default = -1; } -static int feroceon_target_create(struct target *target, Jim_Interp *interp) +static int feroceon_target_create(struct target *target) { struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common)); @@ -640,7 +640,7 @@ static int feroceon_target_create(struct target *target, Jim_Interp *interp) return ERROR_OK; } -static int dragonite_target_create(struct target *target, Jim_Interp *interp) +static int dragonite_target_create(struct target *target) { struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common)); diff --git a/src/target/hla_target.c b/src/target/hla_target.c index ef05df2027..983cd87394 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -187,8 +187,7 @@ static int adapter_init_target(struct command_context *cmd_ctx, return ERROR_OK; } -static int adapter_target_create(struct target *target, - Jim_Interp *interp) +static int adapter_target_create(struct target *target) { LOG_DEBUG("%s", __func__); struct adiv5_private_config *pc = target->private_config; diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c index 692f4cc9e4..49335a8b9f 100644 --- a/src/target/ls1_sap.c +++ b/src/target/ls1_sap.c @@ -17,7 +17,7 @@ struct ls1_sap { struct jtag_tap *tap; }; -static int ls1_sap_target_create(struct target *target, Jim_Interp *interp) +static int ls1_sap_target_create(struct target *target) { struct ls1_sap *ls1_sap = calloc(1, sizeof(struct ls1_sap)); diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index fdc52c3071..c5618c9ccd 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -24,7 +24,7 @@ struct mem_ap { uint64_t ap_num; }; -static int mem_ap_target_create(struct target *target, Jim_Interp *interp) +static int mem_ap_target_create(struct target *target) { struct mem_ap *mem_ap; struct adiv5_private_config *pc; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index dc74501086..4e27914a9d 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -1158,7 +1158,7 @@ static int mips_m4k_init_arch_info(struct target *target, return ERROR_OK; } -static int mips_m4k_target_create(struct target *target, Jim_Interp *interp) +static int mips_m4k_target_create(struct target *target) { struct mips_m4k_common *mips_m4k = calloc(1, sizeof(struct mips_m4k_common)); diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c index 85e3779375..a181a154ee 100644 --- a/src/target/mips_mips64.c +++ b/src/target/mips_mips64.c @@ -1082,7 +1082,7 @@ static int mips_mips64_init_target(struct command_context *cmd_ctx, return mips64_build_reg_cache(target); } -static int mips_mips64_target_create(struct target *target, Jim_Interp *interp) +static int mips_mips64_target_create(struct target *target) { struct mips_mips64_common *mips_mips64; struct mips64_common *mips64; diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index 4b9d3bca68..4aa2bd7347 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -1097,7 +1097,7 @@ static int or1k_init_target(struct command_context *cmd_ctx, return ERROR_OK; } -static int or1k_target_create(struct target *target, Jim_Interp *interp) +static int or1k_target_create(struct target *target) { if (!target->tap) return ERROR_FAIL; diff --git a/src/target/quark_d20xx.c b/src/target/quark_d20xx.c index 90cf6670ec..931f0dab7d 100644 --- a/src/target/quark_d20xx.c +++ b/src/target/quark_d20xx.c @@ -32,7 +32,7 @@ #include "lakemont.h" #include "x86_32_common.h" -static int quark_d20xx_target_create(struct target *t, Jim_Interp *interp) +static int quark_d20xx_target_create(struct target *t) { struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common)); if (!x86_32) { diff --git a/src/target/quark_x10xx.c b/src/target/quark_x10xx.c index 0daa642b85..2abc32ab7b 100644 --- a/src/target/quark_x10xx.c +++ b/src/target/quark_x10xx.c @@ -40,7 +40,7 @@ #include "lakemont.h" #include "x86_32_common.h" -static int quark_x10xx_target_create(struct target *t, Jim_Interp *interp) +static int quark_x10xx_target_create(struct target *t) { struct x86_32_common *x86_32 = calloc(1, sizeof(*x86_32)); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 6a8577f5cb..11ef8f9b92 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -427,7 +427,7 @@ static struct target_type *get_target_type(struct target *target) } } -static int riscv_create_target(struct target *target, Jim_Interp *interp) +static int riscv_create_target(struct target *target) { LOG_DEBUG("riscv_create_target()"); target->arch_info = calloc(1, sizeof(struct riscv_info)); diff --git a/src/target/stm8.c b/src/target/stm8.c index 76482e8789..c80ea0eb20 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -1106,8 +1106,7 @@ static int stm8_init_arch_info(struct target *target, return ERROR_OK; } -static int stm8_target_create(struct target *target, - Jim_Interp *interp) +static int stm8_target_create(struct target *target) { struct stm8_common *stm8 = calloc(1, sizeof(struct stm8_common)); diff --git a/src/target/target.c b/src/target/target.c index 99481622db..40c8d3ed36 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5865,7 +5865,7 @@ COMMAND_HANDLER(handle_target_create) } if (target->type->target_create) { - retval = (*target->type->target_create)(target, CMD_CTX->interp); + retval = (*target->type->target_create)(target); if (retval != ERROR_OK) { LOG_DEBUG("target_create failed"); free(target->cmd_name); diff --git a/src/target/target_type.h b/src/target/target_type.h index ce98cbad27..eddedbf34f 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -194,7 +194,7 @@ struct target_type { const struct command_registration *commands; /* called when target is created */ - int (*target_create)(struct target *target, Jim_Interp *interp); + int (*target_create)(struct target *target); /* called for various config parameters */ /* returns JIM_CONTINUE - if option not understood */ diff --git a/src/target/xscale.c b/src/target/xscale.c index 5cc790a311..84318a905f 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -3012,7 +3012,7 @@ static int xscale_init_arch_info(struct target *target, return ERROR_OK; } -static int xscale_target_create(struct target *target, Jim_Interp *interp) +static int xscale_target_create(struct target *target) { struct xscale_common *xscale; diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index ce6d35cabf..aab7ee37c5 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -81,7 +81,7 @@ static const struct xtensa_power_ops xtensa_chip_dm_pwr_ops = { .queue_reg_write = xtensa_dm_queue_pwr_reg_write }; -static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp) +static int xtensa_chip_target_create(struct target *target) { struct xtensa_debug_module_config xtensa_chip_dm_cfg = { .dbg_ops = &xtensa_chip_dm_dbg_ops, From 797dc7aba74152115898084dd00a50757b20c985 Mon Sep 17 00:00:00 2001 From: HAOUES Ahmed Date: Tue, 25 Mar 2025 14:29:30 +0100 Subject: [PATCH 1165/1312] flash/stm32l4x: support STM32C05/09x devices STM32C05/09x devices are similar to STM32C03/07x devices Change-Id: I77c803356c32f06699c14622828585609c90a136 Signed-off-by: HAOUES Ahmed Reviewed-on: https://review.openocd.org/c/openocd/+/8618 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/stm32l4x.c | 34 ++++++++++++++++++++++++++++++++++ src/flash/nor/stm32l4x.h | 2 ++ 2 files changed, 36 insertions(+) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index fa57db8bbf..f16333201b 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -303,10 +303,18 @@ static const struct stm32l4_rev stm32c03xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, }; +static const struct stm32l4_rev stm32c05xx_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32c071xx_revs[] = { { 0x1001, "Z" }, }; +static const struct stm32l4_rev stm32c09xx_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32g05_g06xx_revs[] = { { 0x1000, "A" }, }; @@ -450,6 +458,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = DEVID_STM32C05XX, + .revs = stm32c05xx_revs, + .num_revs = ARRAY_SIZE(stm32c05xx_revs), + .device_str = "STM32C05xx", + .max_flash_size_kb = 64, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75A0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, { .id = DEVID_STM32C071XX, .revs = stm32c071xx_revs, @@ -462,6 +482,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_base = 0x1FFF7000, .otp_size = 1024, }, + { + .id = DEVID_STM32C09XX, + .revs = stm32c09xx_revs, + .num_revs = ARRAY_SIZE(stm32c09xx_revs), + .device_str = "STM32C09xx", + .max_flash_size_kb = 256, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75A0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, { .id = DEVID_STM32U53_U54XX, .revs = stm32u53_u54xx_revs, @@ -2021,7 +2053,9 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32L43_L44XX: case DEVID_STM32C01XX: case DEVID_STM32C03XX: + case DEVID_STM32C05XX: case DEVID_STM32C071XX: + case DEVID_STM32C09XX: case DEVID_STM32G05_G06XX: case DEVID_STM32G07_G08XX: case DEVID_STM32U031XX: diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 3199d4f6dc..07b3615a24 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -88,6 +88,8 @@ #define DEVID_STM32L47_L48XX 0x415 #define DEVID_STM32L43_L44XX 0x435 #define DEVID_STM32C01XX 0x443 +#define DEVID_STM32C05XX 0x44C +#define DEVID_STM32C09XX 0x44D #define DEVID_STM32C03XX 0x453 #define DEVID_STM32U53_U54XX 0x455 #define DEVID_STM32G05_G06XX 0x456 From 498e5590297e11a9c952d4210c6236fe8105241f Mon Sep 17 00:00:00 2001 From: Junhui Liu Date: Wed, 26 Mar 2025 23:05:39 +0800 Subject: [PATCH 1166/1312] tcl/target: Add RCPU support for Spacemit K1 Add support for the Real-Time CPU (RCPU) of K1, which is a 32-bit RISC-V N308 High-Efficiency Processor Core designed by Nuclei System Technology Co. Ltd. The JTAG interface can be configured to connect to either X60s or RCPU processors. To enable JTAG for RCPU, set TARGET to "rcpu". For example: openocd -c "set TARGET rcpu" -f interface/cmsis-dap.cfg \ -f target/spacemit-k1.cfg Change-Id: I9cd62fac332137afac17efa52702818de8f0b6f5 Signed-off-by: Junhui Liu Reviewed-on: https://review.openocd.org/c/openocd/+/8821 Reviewed-by: liangzhen Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/spacemit-k1.cfg | 50 ++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/tcl/target/spacemit-k1.cfg b/tcl/target/spacemit-k1.cfg index ef5d7833dd..e57d1adbc8 100644 --- a/tcl/target/spacemit-k1.cfg +++ b/tcl/target/spacemit-k1.cfg @@ -10,6 +10,21 @@ transport select jtag adapter speed 2000 +# Set TARGET to "rcpu" to enable JTAG for RCPU +if { [info exists TARGET] } { + set _TARGET $TARGET +} else { + set _TARGET x60 +} + +if { $_TARGET == "rcpu" } { + set CPUTAPID 0x10308A6D + set DRVAL 0xe +} else { + set CPUTAPID 0x10000E21 + set DRVAL 0xa +} + if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { @@ -23,44 +38,49 @@ if { [info exists CORES] } { } if { [info exists SECJTAG] } { - jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000E21 + jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $CPUTAPID } else { jtag newtap pre unknown -irlen 1 -expected-id 0x00000000 -disable jtag configure pre.unknown -event tap-enable "" - jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000E21 -disable + jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $CPUTAPID -disable jtag configure $_CHIPNAME.cpu -event tap-enable "" jtag newtap post unknown -irlen 9 -expected-id 0x08501C0D -ignore-version jtag configure post.unknown -event setup { - global _CHIPNAME + global _CHIPNAME DRVAL irscan post.unknown 0x98 - drscan post.unknown 16 0xa + drscan post.unknown 16 $DRVAL jtag tapenable pre.unknown jtag tapenable $_CHIPNAME.cpu } } -set _TARGETNAME $_CHIPNAME.cpu -set DBGBASE {0x0 0x400} -set _smp_command "target smp" +set _TARGETNAME $_CHIPNAME.cpu_$_TARGET + +if { $_TARGET == "rcpu" } { + target create $_TARGETNAME.0 riscv -chain-position $_CHIPNAME.cpu +} else { + set DBGBASE {0x0 0x400} + set _smp_command "target smp" -for { set _core 0 } { $_core < $_cores } { incr _core } { - target create $_TARGETNAME.$_core riscv -chain-position $_TARGETNAME \ - -coreid [expr {$_core % 4}] -dbgbase [lindex $DBGBASE [expr {$_core / 4}]] + for { set _core 0 } { $_core < $_cores } { incr _core } { + target create $_TARGETNAME.$_core riscv -chain-position $_CHIPNAME.cpu \ + -coreid [expr {$_core % 4}] -dbgbase [lindex $DBGBASE [expr {$_core / 4}]] - if { [expr {$_core % 4}] == 0 } { - $_TARGETNAME.$_core configure -rtos hwthread + if { [expr {$_core % 4}] == 0 } { + $_TARGETNAME.$_core configure -rtos hwthread + } + + set _smp_command "$_smp_command $_TARGETNAME.$_core" } - set _smp_command "$_smp_command $_TARGETNAME.$_core" + eval $_smp_command } -eval $_smp_command - set _SPEED 8000 $_TARGETNAME.0 configure -event examine-start { From 2aa0592e0fd90218ff55446ebb3a9233017e59f7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 6 Apr 2025 14:59:50 +0200 Subject: [PATCH 1167/1312] flash: stellaris: fix deprecated command The driver directly runs a TCL command that has been renamed with commit 4d99e77419e3 ("jtag/hla: Restructure commands"), while the original name has been deprecated. Update the TCL command to the new syntax. Change-Id: I2fc9ef9a209bae1d78951e253d54164b2ac00cdd Signed-off-by: Antonio Borneo Fixes: 4d99e77419e3 ("jtag/hla: Restructure commands") Reviewed-on: https://review.openocd.org/c/openocd/+/8832 Reviewed-by: zapb Tested-by: jenkins --- src/flash/nor/stellaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 1f53b2f35e..f7dcc6f0e3 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -1342,7 +1342,7 @@ COMMAND_HANDLER(stellaris_handle_recover_command) * cycle to recover. */ - Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", NULL, 0); + Jim_Eval_Named(CMD_CTX->interp, "catch { hla command \"debug unlock\" }", NULL, 0); if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) { retval = ERROR_OK; goto user_action; From ea775d49fc71253a95986eb5b1254b4861bdeb97 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Fri, 3 Nov 2023 15:55:41 -0500 Subject: [PATCH 1168/1312] flash/nor/rp2040: add RP2350 support TV: Extracted RP2040/2350 flash driver part only. Fixed style problems. Change-Id: I88a7d5aa0a239ae93d72bd5671686b19c6ca11ad Signed-off-by: Tomas Vanek Signed-off-by: graham sanderson Reviewed-on: https://review.openocd.org/c/openocd/+/8440 Tested-by: jenkins --- src/flash/nor/rp2040.c | 483 +++++++++++++++++++++++------------------ 1 file changed, 274 insertions(+), 209 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index b2ebd9c49e..c53b54754a 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -9,14 +9,19 @@ #include #include #include "spi.h" +#include /* NOTE THAT THIS CODE REQUIRES FLASH ROUTINES in BOOTROM WITH FUNCTION TABLE PTR AT 0x00000010 Your gdbinit should load the bootrom.elf if appropriate */ /* this is 'M' 'u', 1 (version) */ -#define BOOTROM_MAGIC 0x01754d +#define BOOTROM_RP2040_MAGIC 0x01754d +/* this is 'M' 'u', 2 (version) */ +#define BOOTROM_RP2350_MAGIC 0x02754d #define BOOTROM_MAGIC_ADDR 0x00000010 +#define RT_ARM_FUNC 0x1 + /* Call a ROM function via the debug trampoline Up to four arguments passed in r0...r3 as per ABI Function address is passed in r7 @@ -31,6 +36,48 @@ #define FUNC_FLASH_RANGE_PROGRAM MAKE_TAG('R', 'P') #define FUNC_FLASH_FLUSH_CACHE MAKE_TAG('F', 'C') #define FUNC_FLASH_ENTER_CMD_XIP MAKE_TAG('C', 'X') +#define FUNC_BOOTROM_STATE_RESET MAKE_TAG('S', 'R') + +// these form a bit set +#define BOOTROM_STATE_RESET_CURRENT_CORE 0x01 +#define BOOTROM_STATE_RESET_OTHER_CORE 0x02 +#define BOOTROM_STATE_RESET_GLOBAL_STATE 0x04 + +#define ACCESSCTRL_LOCK_OFFSET 0x40060000u +#define ACCESSCTRL_LOCK_DEBUG_BITS 0x00000008u +#define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u +#define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u + +// Calling bootrom functions requires the redundancy coprocessor (RCP) to be +// initialised. Usually this is done first thing by the bootrom, but the +// debugger may skip this, e.g. by resetting the cores and then running a +// NO_FLASH binary, or by reset-halting the cores before flash programming. +// +// The first case can be handled by a stub in the binary itself to initialise +// the RCP with dummy values if the bootrom has not already initialised it. +// (Note this case is only reachable via the debugger.) The second case +// requires the debugger itself to initialise the RCP, using this stub code: + +static const int rcp_init_code_bkpt_offset = 24; +static const uint16_t rcp_init_code[] = { + // Just enable the RCP which is fine if it already was (we assume no other + // co-processors are enabled at this point to save space) + 0x4806, // ldr r0, = PPB_BASE + M33_CPACR_OFFSET + 0xf45f, 0x4140, // movs r1, #M33_CPACR_CP7_BITS + 0x6001, // str r1, [r0] + // Only initialize canary seeds if they haven't been (as to do so twice is a fault) + 0xee30, 0xf710, // mrc p7, #1, r15, c0, c0, #0 + 0xd404, // bmi 1f + // Todo should we use something random here and pass it into the algorithm? + 0xec40, 0x0780, // mcrr p7, #8, r0, r0, c0 + 0xec40, 0x0781, // mcrr p7, #8, r0, r0, c1 + // Let other core know + 0xbf40, // sev + // 1: + 0xbe00, // bkpt (end of algorithm) + 0x0000, // pad + 0xed88, 0xe000 // PPB_BASE + M33_CPACR_OFFSET +}; struct rp2040_flash_bank { /* flag indicating successful flash probe */ @@ -46,33 +93,31 @@ struct rp2040_flash_bank { uint16_t jump_flash_range_program; uint16_t jump_flush_cache; uint16_t jump_enter_cmd_xip; - /* detected model of SPI flash */ - const struct flash_device *dev; + uint16_t jump_bootrom_reset_state; }; -/* guessed SPI flash description if autodetection disabled (same as win w25q16jv) */ -static const struct flash_device rp2040_default_spi_device = - FLASH_ID("autodetect disabled", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0, 0x100, 0x10000, 0); - static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16_t *symbol) { - uint32_t magic; + uint32_t magic, magic_addr; + bool found_rp2040_magic, found_rp2350_magic; + magic_addr = BOOTROM_MAGIC_ADDR; int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic); if (err != ERROR_OK) return err; magic &= 0xffffff; /* ignore bootrom version */ - if (magic != BOOTROM_MAGIC) { - if (!((magic ^ BOOTROM_MAGIC)&0xffff)) - LOG_ERROR("Incorrect RP2040 BOOT ROM version"); - else - LOG_ERROR("RP2040 BOOT ROM not found"); + + found_rp2040_magic = magic == BOOTROM_RP2040_MAGIC; + found_rp2350_magic = magic == BOOTROM_RP2350_MAGIC; + + if (!(found_rp2040_magic || found_rp2350_magic)) { + LOG_ERROR("RP2040/RP2350 BOOT ROM not found"); return ERROR_FAIL; } /* dereference the table pointer */ uint16_t table_entry; - err = target_read_u16(target, BOOTROM_MAGIC_ADDR + 4, &table_entry); + err = target_read_u16(target, magic_addr + 4, &table_entry); if (err != ERROR_OK) return err; @@ -82,16 +127,29 @@ static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16 if (err != ERROR_OK) return err; if (entry_tag == tag) { - /* 16 bit symbol is next */ - return target_read_u16(target, table_entry + 2, symbol); + if (found_rp2350_magic) { + uint16_t flags; + /* flags are next */ + err = target_read_u16(target, table_entry + 4, &flags); + if (err != ERROR_OK) + return err; + // + if (flags & RT_ARM_FUNC) { + /* 16 bit symbol */ + return target_read_u16(target, table_entry + 2, symbol); + } + } else { + /* 16 bit symbol is next */ + return target_read_u16(target, table_entry + 2, symbol); + } } - table_entry += 4; + table_entry += found_rp2350_magic ? 6 : 4; } while (entry_tag); return ERROR_FAIL; } static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank *priv, - uint16_t func_offset, uint32_t argdata[], unsigned int n_args, unsigned int timeout_ms) + uint16_t func_offset, uint32_t argdata[], unsigned int n_args) { char *regnames[4] = { "r0", "r1", "r2", "r3" }; @@ -103,9 +161,10 @@ static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank } target_addr_t stacktop = priv->stack->address + priv->stack->size; - LOG_TARGET_DEBUG(target, "Calling ROM func @0x%" PRIx16 " with %u arguments", func_offset, n_args); + LOG_DEBUG("Calling ROM func @0x%" PRIx16 " with %d arguments", func_offset, n_args); + LOG_DEBUG("Calling on core \"%s\"", target->cmd_name); - struct reg_param args[ARRAY_SIZE(regnames) + 2]; + struct reg_param args[ARRAY_SIZE(regnames) + 12]; struct armv7m_algorithm alg_info; for (unsigned int i = 0; i < n_args; ++i) { @@ -113,14 +172,36 @@ static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank buf_set_u32(args[i].value, 0, 32, argdata[i]); } /* Pass function pointer in r7 */ - init_reg_param(&args[n_args], "r7", 32, PARAM_OUT); - buf_set_u32(args[n_args].value, 0, 32, func_offset); - /* Setup stack */ - init_reg_param(&args[n_args + 1], "sp", 32, PARAM_OUT); - buf_set_u32(args[n_args + 1].value, 0, 32, stacktop); - unsigned int n_reg_params = n_args + 2; /* User arguments + r7 + sp */ - - for (unsigned int i = 0; i < n_reg_params; ++i) + unsigned int extra_args = 0; + init_reg_param(&args[n_args + extra_args], "r7", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, func_offset); + /* Set stack pointer, have seen the caching get confused by the aliases of sp so + take the shotgun approach*/ + init_reg_param(&args[n_args + extra_args], "msp_s", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + init_reg_param(&args[n_args + extra_args], "msp_ns", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + init_reg_param(&args[n_args + extra_args], "psp_s", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + init_reg_param(&args[n_args + extra_args], "psp_ns", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + init_reg_param(&args[n_args + extra_args], "msp", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + init_reg_param(&args[n_args + extra_args], "psp", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + init_reg_param(&args[n_args + extra_args], "sp", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); + /* Clear stack pointer limits, as they may be above the algorithm stack */ + init_reg_param(&args[n_args + extra_args], "msplim_s", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); + init_reg_param(&args[n_args + extra_args], "psplim_s", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); + init_reg_param(&args[n_args + extra_args], "msplim_ns", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); + init_reg_param(&args[n_args + extra_args], "psplim_ns", 32, PARAM_OUT); + buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); + + for (unsigned int i = 0; i < n_args + extra_args; ++i) LOG_DEBUG("Set %s = 0x%" PRIx32, args[i].reg_name, buf_get_u32(args[i].value, 0, 32)); /* Actually call the function */ @@ -129,82 +210,158 @@ static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank int err = target_run_algorithm( target, 0, NULL, /* No memory arguments */ - n_reg_params, args, /* User arguments + r7 + sp */ + n_args + extra_args, args, /* User arguments + r7 + SPs */ priv->jump_debug_trampoline, priv->jump_debug_trampoline_end, - timeout_ms, + 3000, /* 3s timeout */ &alg_info ); - - for (unsigned int i = 0; i < n_reg_params; ++i) + for (unsigned int i = 0; i < n_args + extra_args; ++i) destroy_reg_param(&args[i]); - if (err != ERROR_OK) - LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16, func_offset); - + LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16 "\n", func_offset); return err; } -/* Finalize flash write/erase/read ID - * - flush cache - * - enters memory-mapped (XIP) mode to make flash data visible - * - deallocates target ROM func stack if previously allocated - */ -static int rp2040_finalize_stack_free(struct flash_bank *bank) +static int rp2350_init_core(struct target *target, struct rp2040_flash_bank *priv) { - struct rp2040_flash_bank *priv = bank->driver_priv; - struct target *target = bank->target; + if (!priv->stack) { + LOG_ERROR("no stack for flash programming code"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } - /* Always flush before returning to execute-in-place, to invalidate stale - * cache contents. The flush call also restores regular hardware-controlled - * chip select following a rp2040_flash_exit_xip(). - */ - LOG_DEBUG("Flushing flash cache after write behind"); - int err = rp2040_call_rom_func(target, priv, priv->jump_flush_cache, NULL, 0, 1000); + struct armv7m_algorithm alg_info; + + // copy rcp_init code onto stack, as we don't actually need any stack during the call + if (priv->stack->size < sizeof(rcp_init_code)) { + LOG_ERROR("Working area too small for rcp_init"); + return ERROR_BUF_TOO_SMALL; + } + + // Attempt to reset ACCESSCTRL before running RCP init, in case Secure + // access to SRAM has been blocked. (Also ROM, QMI regs are needed later) + uint32_t accessctrl_lock_reg; + if (target_read_u32(target, ACCESSCTRL_LOCK_OFFSET, &accessctrl_lock_reg) != ERROR_OK) { + LOG_ERROR("Failed to read ACCESSCTRL lock register"); + // Failed to read an APB register which should always be readable from + // any security/privilege level. Something fundamental is wrong. E.g.: + // + // - The debugger is attempting to perform Secure bus accesses on a + // system where Secure debug has been disabled + // - clk_sys or busfabric clock are stopped (try doing a rescue reset) + return ERROR_FAIL; + } + if (accessctrl_lock_reg & ACCESSCTRL_LOCK_DEBUG_BITS) { + LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail.\n"); + } else { + LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET\n"); + target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u); + } + + int err = target_write_memory(target, + priv->stack->address, + 1, + sizeof(rcp_init_code), + (const uint8_t *)rcp_init_code + ); if (err != ERROR_OK) { - LOG_ERROR("Failed to flush flash cache"); - /* Intentionally continue after error and try to setup xip anyway */ + LOG_ERROR("Failed to load rcp_init algorithm into RAM\n"); + return ERROR_FAIL; } - LOG_DEBUG("Configuring SSI for execute-in-place"); - err = rp2040_call_rom_func(target, priv, priv->jump_enter_cmd_xip, NULL, 0, 1000); - if (err != ERROR_OK) - LOG_ERROR("Failed to set SSI to XIP mode"); + LOG_DEBUG("Calling rcp_init core \"%s\" code at 0x%" PRIx16 "\n", target->cmd_name, (uint32_t)priv->stack->address); + + /* Actually call the function */ + alg_info.common_magic = ARMV7M_COMMON_MAGIC; + alg_info.core_mode = ARM_MODE_THREAD; + err = target_run_algorithm(target, + 0, NULL, /* No memory arguments */ + 0, NULL, /* No register arguments */ + priv->stack->address, + priv->stack->address + rcp_init_code_bkpt_offset, + 1000, /* 1s timeout */ + &alg_info + ); + if (err != ERROR_OK) { + LOG_ERROR("Failed to invoke rcp_init\n"); + return err; + } + + uint32_t reset_args[1] = { + BOOTROM_STATE_RESET_CURRENT_CORE + }; + if (!priv->jump_bootrom_reset_state) { + LOG_WARNING("RP2350 flash: no bootrom_reset_method\n"); + } else { + err = rp2040_call_rom_func(target, priv, priv->jump_bootrom_reset_state, reset_args, ARRAY_SIZE(reset_args)); + if (err != ERROR_OK) { + LOG_ERROR("RP2040 flash: failed to call reset core state"); + return err; + } + } - target_free_working_area(target, priv->stack); - priv->stack = NULL; return err; } -/* Prepare flash write/erase/read ID - * - allocates a stack for target ROM func - * - switches the SPI interface from memory-mapped mode to direct command mode - * Always pair with a call of rp2040_finalize_stack_free() - * after flash operation finishes or fails. - */ -static int rp2040_stack_grab_and_prep(struct flash_bank *bank) +static int setup_for_rom_call(struct flash_bank *bank) { struct rp2040_flash_bank *priv = bank->driver_priv; + struct target *target = bank->target; - /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */ - const int STACK_SIZE = 256; - int err = target_alloc_working_area(target, STACK_SIZE, &priv->stack); + int err = ERROR_OK; + if (!priv->stack) { + /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */ + const int STACK_SIZE = 256; + target_alloc_working_area(bank->target, STACK_SIZE, &priv->stack); + if (err != ERROR_OK) { + LOG_ERROR("Could not allocate stack for flash programming code"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } + + // Flash algorithms must run in Secure state + uint32_t dscsr; + (void)target_read_u32(target, DCB_DSCSR, &dscsr); + LOG_DEBUG("DSCSR: %08x\n", dscsr); + if (!(dscsr & DSCSR_CDS)) { + LOG_DEBUG("Setting Current Domain Secure in DSCSR\n"); + (void)target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); + (void)target_read_u32(target, DCB_DSCSR, &dscsr); + LOG_DEBUG("DSCSR*: %08x\n", dscsr); + } + + // hacky RP2350 check + if (target_to_arm(target)->arch == ARM_ARCH_V8M) { + err = rp2350_init_core(target, priv); + if (err != ERROR_OK) { + LOG_ERROR("RP2350 flash: failed to init core"); + return err; + } + } + return err; +} + +static int setup_for_raw_flash_cmd(struct flash_bank *bank) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + int err = setup_for_rom_call(bank); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0); if (err != ERROR_OK) { - LOG_ERROR("Could not allocate stack for flash programming code"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + LOG_ERROR("RP2040 flash: failed to setup for rom call"); + return err; } LOG_DEBUG("Connecting internal flash"); - err = rp2040_call_rom_func(target, priv, priv->jump_connect_internal_flash, NULL, 0, 1000); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0); if (err != ERROR_OK) { - LOG_ERROR("Failed to connect internal flash"); + LOG_ERROR("RP2040 flash: failed to connect internal flash"); return err; } LOG_DEBUG("Kicking flash out of XIP mode"); - err = rp2040_call_rom_func(target, priv, priv->jump_flash_exit_xip, NULL, 0, 1000); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_exit_xip, NULL, 0); if (err != ERROR_OK) { - LOG_ERROR("Failed to exit flash XIP mode"); + LOG_ERROR("RP2040 flash: failed to exit flash XIP mode"); return err; } @@ -217,27 +374,17 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui struct rp2040_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; + struct working_area *bounce; - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - struct working_area *bounce = NULL; - - int err = rp2040_stack_grab_and_prep(bank); + int err = setup_for_raw_flash_cmd(bank); if (err != ERROR_OK) - goto cleanup; - - unsigned int avail_pages = target_get_working_area_avail(target) / priv->dev->pagesize; - /* We try to allocate working area rounded down to device page size, - * al least 1 page, at most the write data size - */ - unsigned int chunk_size = MIN(MAX(avail_pages, 1) * priv->dev->pagesize, count); - err = target_alloc_working_area(target, chunk_size, &bounce); - if (err != ERROR_OK) { + return err; + + // Allocate as much memory as possible, rounded down to a whole number of flash pages + const unsigned int chunk_size = target_get_working_area_avail(target) & ~0xffu; + if (chunk_size == 0 || target_alloc_working_area(target, chunk_size, &bounce) != ERROR_OK) { LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue"); - goto cleanup; + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } LOG_DEBUG("Allocated flash bounce buffer @" TARGET_ADDR_FMT, bounce->address); @@ -255,8 +402,7 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui bounce->address, /* data */ write_size /* count */ }; - err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program, - args, ARRAY_SIZE(args), 3000); + err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args)); if (err != ERROR_OK) { LOG_ERROR("Failed to invoke flash programming code on target"); break; @@ -266,40 +412,44 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui offset += write_size; count -= write_size; } - -cleanup: target_free_working_area(target, bounce); - rp2040_finalize_stack_free(bank); + if (err != ERROR_OK) + return err; + /* Flash is successfully programmed. We can now do a bit of poking to make the flash + contents visible to us via memory-mapped (XIP) interface in the 0x1... memory region */ + LOG_DEBUG("Flushing flash cache after write behind"); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0); + if (err != ERROR_OK) { + LOG_ERROR("RP2040 write: failed to flush flash cache"); + return err; + } + LOG_DEBUG("Configuring SSI for execute-in-place"); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_enter_cmd_xip, NULL, 0); + if (err != ERROR_OK) + LOG_ERROR("RP2040 write: failed to flush flash cache"); return err; } static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last) { struct rp2040_flash_bank *priv = bank->driver_priv; - struct target *target = bank->target; - - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - uint32_t start_addr = bank->sectors[first].offset; uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr; LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr); - int err = rp2040_stack_grab_and_prep(bank); + int err = setup_for_raw_flash_cmd(bank); if (err != ERROR_OK) - goto cleanup; + return err; LOG_DEBUG("Remote call flash_range_erase"); uint32_t args[4] = { bank->sectors[first].offset, /* addr */ bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset, /* count */ - priv->dev->sectorsize, /* block_size */ - priv->dev->erase_cmd /* block_cmd */ + 65536, /* block_size */ + 0xd8 /* block_cmd */ }; /* @@ -309,15 +459,10 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c In theory, the function algorithm provides for erasing both a smaller "sector" (4096 bytes) and - an optional larger "block" (size and command provided in args). + an optional larger "block" (size and command provided in args). OpenOCD's spi.c only uses "block" sizes. */ - unsigned int timeout_ms = 2000 * (last - first) + 1000; - err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_erase, - args, ARRAY_SIZE(args), timeout_ms); - -cleanup: - rp2040_finalize_stack_free(bank); + err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); return err; } @@ -325,67 +470,11 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig /* ----------------------------------------------------------------------------- Driver probing etc */ -static int rp2040_ssel_active(struct target *target, bool active) -{ - const target_addr_t qspi_ctrl_addr = 0x4001800c; - const uint32_t qspi_ctrl_outover_low = 2UL << 8; - const uint32_t qspi_ctrl_outover_high = 3UL << 8; - uint32_t state = (active) ? qspi_ctrl_outover_low : qspi_ctrl_outover_high; - uint32_t val; - - int err = target_read_u32(target, qspi_ctrl_addr, &val); - if (err != ERROR_OK) - return err; - - val = (val & ~qspi_ctrl_outover_high) | state; - - err = target_write_u32(target, qspi_ctrl_addr, val); - if (err != ERROR_OK) - return err; - - return ERROR_OK; -} - -static int rp2040_spi_read_flash_id(struct target *target, uint32_t *devid) -{ - uint32_t device_id = 0; - const target_addr_t ssi_dr0 = 0x18000060; - - int err = rp2040_ssel_active(target, true); - - /* write RDID request into SPI peripheral's FIFO */ - for (int count = 0; (count < 4) && (err == ERROR_OK); count++) - err = target_write_u32(target, ssi_dr0, SPIFLASH_READ_ID); - - /* by this time, there is a receive FIFO entry for every write */ - for (int count = 0; (count < 4) && (err == ERROR_OK); count++) { - uint32_t status; - err = target_read_u32(target, ssi_dr0, &status); - - device_id >>= 8; - device_id |= (status & 0xFF) << 24; - } - - if (err == ERROR_OK) - *devid = device_id >> 8; - - int err2 = rp2040_ssel_active(target, false); - if (err2 != ERROR_OK) - LOG_ERROR("SSEL inactive failed"); - - return err; -} - static int rp2040_flash_probe(struct flash_bank *bank) { struct rp2040_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - int err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE, &priv->jump_debug_trampoline); if (err != ERROR_OK) { LOG_ERROR("Debug trampoline not found in RP2040 ROM."); @@ -417,6 +506,7 @@ static int rp2040_flash_probe(struct flash_bank *bank) LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2040 ROM."); return err; } + LOG_WARNING("GOT FLASH ERASE AT %08x\n", (int)priv->jump_flash_range_erase); err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_PROGRAM, &priv->jump_flash_range_program); if (err != ERROR_OK) { @@ -436,50 +526,25 @@ static int rp2040_flash_probe(struct flash_bank *bank) return err; } - if (bank->size) { - /* size overridden, suppress reading SPI flash ID */ - priv->dev = &rp2040_default_spi_device; - LOG_DEBUG("SPI flash autodetection disabled, using configured size"); - - } else { - /* zero bank size in cfg, read SPI flash ID and autodetect */ - err = rp2040_stack_grab_and_prep(bank); - - uint32_t device_id = 0; - if (err == ERROR_OK) - err = rp2040_spi_read_flash_id(target, &device_id); - - rp2040_finalize_stack_free(bank); - - if (err != ERROR_OK) - return err; - - /* search for a SPI flash Device ID match */ - priv->dev = NULL; - for (const struct flash_device *p = flash_devices; p->name ; p++) - if (p->device_id == device_id) { - priv->dev = p; - break; - } - - if (!priv->dev) { - LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id); - return ERROR_FAIL; - } - LOG_INFO("Found flash device '%s' (ID 0x%08" PRIx32 ")", - priv->dev->name, priv->dev->device_id); - - bank->size = priv->dev->size_in_bytes; + err = rp2040_lookup_symbol(target, FUNC_BOOTROM_STATE_RESET, &priv->jump_bootrom_reset_state); + if (err != ERROR_OK) { + priv->jump_bootrom_reset_state = 0; +// LOG_ERROR("Function FUNC_BOOTROM_STATE_RESET not found in RP2040 ROM."); +// return err; } /* the Boot ROM flash_range_program() routine requires page alignment */ - bank->write_start_alignment = priv->dev->pagesize; - bank->write_end_alignment = priv->dev->pagesize; + bank->write_start_alignment = 256; + bank->write_end_alignment = 256; + + // Max size -- up to two devices (two chip selects) in adjacent 24-bit address windows + bank->size = 32 * 1024 * 1024; + + bank->num_sectors = bank->size / 4096; - bank->num_sectors = bank->size / priv->dev->sectorsize; - LOG_INFO("RP2040 B0 Flash Probe: %" PRIu32 " bytes @" TARGET_ADDR_FMT ", in %u sectors\n", + LOG_INFO("RP2040 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n", bank->size, bank->base, bank->num_sectors); - bank->sectors = alloc_block_array(0, priv->dev->sectorsize, bank->num_sectors); + bank->sectors = alloc_block_array(0, 4096, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; From 1ed49addc5030f6df414657ead6bfc70a0deabd9 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Wed, 14 Jul 2021 16:36:13 +0100 Subject: [PATCH 1169/1312] flash/nor/rp2040: Add RISC-V ROM algorithm batch call support And add support for A1 ROM table. TV: cortex_m smp change removed. Fixed style problems. 'uint' replaced by unsigned int Change-Id: Iff2710fa0734dc7074d8d490d8fae43dc27c0c2a Signed-off-by: Tomas Vanek Signed-off-by: Luke Wren Reviewed-on: https://review.openocd.org/c/openocd/+/8441 Tested-by: jenkins --- src/flash/nor/rp2040.c | 876 ++++++++++++++++++++++++++++------------- 1 file changed, 599 insertions(+), 277 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index c53b54754a..1e582b433a 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -11,32 +11,27 @@ #include "spi.h" #include -/* NOTE THAT THIS CODE REQUIRES FLASH ROUTINES in BOOTROM WITH FUNCTION TABLE PTR AT 0x00000010 - Your gdbinit should load the bootrom.elf if appropriate */ - /* this is 'M' 'u', 1 (version) */ #define BOOTROM_RP2040_MAGIC 0x01754d /* this is 'M' 'u', 2 (version) */ #define BOOTROM_RP2350_MAGIC 0x02754d #define BOOTROM_MAGIC_ADDR 0x00000010 -#define RT_ARM_FUNC 0x1 - -/* Call a ROM function via the debug trampoline - Up to four arguments passed in r0...r3 as per ABI - Function address is passed in r7 - the trampoline is needed because OpenOCD "algorithm" code insists on sw breakpoints. */ - #define MAKE_TAG(a, b) (((b)<<8) | a) -#define FUNC_DEBUG_TRAMPOLINE MAKE_TAG('D', 'T') -#define FUNC_DEBUG_TRAMPOLINE_END MAKE_TAG('D', 'E') -#define FUNC_FLASH_EXIT_XIP MAKE_TAG('E', 'X') -#define FUNC_CONNECT_INTERNAL_FLASH MAKE_TAG('I', 'F') -#define FUNC_FLASH_RANGE_ERASE MAKE_TAG('R', 'E') -#define FUNC_FLASH_RANGE_PROGRAM MAKE_TAG('R', 'P') -#define FUNC_FLASH_FLUSH_CACHE MAKE_TAG('F', 'C') -#define FUNC_FLASH_ENTER_CMD_XIP MAKE_TAG('C', 'X') -#define FUNC_BOOTROM_STATE_RESET MAKE_TAG('S', 'R') +#define FUNC_FLASH_EXIT_XIP MAKE_TAG('E', 'X') +#define FUNC_CONNECT_INTERNAL_FLASH MAKE_TAG('I', 'F') +#define FUNC_FLASH_RANGE_ERASE MAKE_TAG('R', 'E') +#define FUNC_FLASH_RANGE_PROGRAM MAKE_TAG('R', 'P') +#define FUNC_FLASH_FLUSH_CACHE MAKE_TAG('F', 'C') +#define FUNC_FLASH_ENTER_CMD_XIP MAKE_TAG('C', 'X') +#define FUNC_BOOTROM_STATE_RESET MAKE_TAG('S', 'R') +#define FUNC_FLASH_RESET_ADDRESS_TRANS MAKE_TAG('R', 'A') + +/* ROM table flags for RP2350 A1 ROM onwards */ +#define RT_FLAG_FUNC_RISCV 0x01 +#define RT_FLAG_FUNC_ARM_SEC 0x04 +#define RT_FLAG_FUNC_ARM_NONSEC 0x10 +#define RT_FLAG_DATA 0x40 // these form a bit set #define BOOTROM_STATE_RESET_CURRENT_CORE 0x01 @@ -48,10 +43,14 @@ #define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u #define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u -// Calling bootrom functions requires the redundancy coprocessor (RCP) to be -// initialised. Usually this is done first thing by the bootrom, but the -// debugger may skip this, e.g. by resetting the cores and then running a -// NO_FLASH binary, or by reset-halting the cores before flash programming. +#define RP2XXX_MAX_ALGO_STACK_USAGE 1024 +#define RP2XXX_MAX_RAM_ALGO_SIZE 1024 + +// Calling bootrom functions on Arm RP2350 requires the redundancy +// coprocessor (RCP) to be initialised. Usually this is done first thing by +// the bootrom, but the debugger may skip this, e.g. by resetting the cores +// and then running a NO_FLASH binary, or by reset-halting the cores before +// flash programming. // // The first case can be handled by a stub in the binary itself to initialise // the RCP with dummy values if the bootrom has not already initialised it. @@ -59,186 +58,500 @@ // requires the debugger itself to initialise the RCP, using this stub code: static const int rcp_init_code_bkpt_offset = 24; -static const uint16_t rcp_init_code[] = { +static const uint8_t rcp_init_code[] = { // Just enable the RCP which is fine if it already was (we assume no other // co-processors are enabled at this point to save space) - 0x4806, // ldr r0, = PPB_BASE + M33_CPACR_OFFSET - 0xf45f, 0x4140, // movs r1, #M33_CPACR_CP7_BITS - 0x6001, // str r1, [r0] + 0x06, 0x48, // ldr r0, = PPB_BASE + M33_CPACR_OFFSET + 0x5f, 0xf4, 0x40, 0x41, // movs r1, #M33_CPACR_CP7_BITS + 0x01, 0x60, // str r1, [r0] // Only initialize canary seeds if they haven't been (as to do so twice is a fault) - 0xee30, 0xf710, // mrc p7, #1, r15, c0, c0, #0 - 0xd404, // bmi 1f + 0x30, 0xee, 0x10, 0xf7, // mrc p7, #1, r15, c0, c0, #0 + 0x04, 0xd4, // bmi 1f // Todo should we use something random here and pass it into the algorithm? - 0xec40, 0x0780, // mcrr p7, #8, r0, r0, c0 - 0xec40, 0x0781, // mcrr p7, #8, r0, r0, c1 + 0x40, 0xec, 0x80, 0x07, // mcrr p7, #8, r0, r0, c0 + 0x40, 0xec, 0x81, 0x07, // mcrr p7, #8, r0, r0, c1 // Let other core know - 0xbf40, // sev + 0x40, 0xbf, // sev // 1: - 0xbe00, // bkpt (end of algorithm) - 0x0000, // pad - 0xed88, 0xe000 // PPB_BASE + M33_CPACR_OFFSET + 0x00, 0xbe, // bkpt (end of algorithm) + 0x00, 0x00, // pad + 0x88, 0xed, 0x00, 0xe0 // PPB_BASE + M33_CPACR_OFFSET }; +// An algorithm stub that can be concatenated with a null-terminated list of +// (PC, SP, r0-r3) records to perform a batch of ROM calls under a single +// OpenOCD algorithm call, to save on algorithm overhead: +#define ROM_CALL_BATCH_ALGO_SIZE_BYTES 32 +static const int rp2xxx_rom_call_batch_algo_bkpt_offset = ROM_CALL_BATCH_ALGO_SIZE_BYTES - 2; +static const uint8_t rp2xxx_rom_call_batch_algo_armv6m[ROM_CALL_BATCH_ALGO_SIZE_BYTES] = { +// <_start>: + 0x07, 0xa7, // add r7, pc, #28 ; (adr r7, 20 <_args>) +// <_do_next>: + 0x10, 0xcf, // ldmia r7!, {r4} + 0x00, 0x2c, // cmp r4, #0 + 0x0a, 0xd0, // beq.n 1e <_done> + 0x20, 0xcf, // ldmia r7!, {r5} + 0xad, 0x46, // mov sp, r5 + 0x0f, 0xcf, // ldmia r7!, {r0, r1, r2, r3} + 0xa0, 0x47, // blx r4 + 0xf7, 0xe7, // b.n 2 <_do_next> + 0xc0, 0x46, // nop + 0xc0, 0x46, // nop + 0xc0, 0x46, // nop + 0xc0, 0x46, // nop + 0xc0, 0x46, // nop + 0xc0, 0x46, // nop +// <_done>: + 0x00, 0xbe, // bkpt 0x0000 +// <_args>: +}; + +// The same as rom_call_batch_algo_armv6m, but clearing stack limits before setting stack: +static const uint8_t rp2xxx_rom_call_batch_algo_armv8m[ROM_CALL_BATCH_ALGO_SIZE_BYTES] = { +// <_start>: + 0x07, 0xa7, // add r7, pc, #28 ; (adr r7, 20 <_args>) + 0x00, 0x20, // movs r0, #0 + 0x80, 0xf3, 0x0a, 0x88, // msr MSPLIM, r0 + 0x80, 0xf3, 0x0b, 0x88, // msr PSPLIM, r0 +// <_do_next>: + 0x10, 0xcf, // ldmia r7!, {r4} + 0x00, 0x2c, // cmp r4, #0 + 0x05, 0xd0, // beq.n 1e <_done> + 0x20, 0xcf, // ldmia r7!, {r5} + 0xad, 0x46, // mov sp, r5 + 0x0f, 0xcf, // ldmia r7!, {r0, r1, r2, r3} + 0xa0, 0x47, // blx r4 + 0xf7, 0xe7, // b.n c <_do_next> + 0xc0, 0x46, // nop +// <_done>: + 0x00, 0xbe, // bkpt 0x0000 +// <_args>: +}; + +// The same as rom_call_batch_algo_armv6m, but placing arguments in a0-a3 on RISC-V: +static const uint8_t rp2xxx_rom_call_batch_algo_riscv[ROM_CALL_BATCH_ALGO_SIZE_BYTES] = { +// <_start>: + 0x97, 0x04, 0x00, 0x00, // auipc s1,0 + 0x93, 0x84, 0x04, 0x02, // add s1,s1,32 # 20 <_args> +// <_do_next>: + 0x98, 0x40, // lw a4,0(s1) + 0x11, 0xcb, // beqz a4,1e <_done> + 0x03, 0xa1, 0x44, 0x00, // lw sp,4(s1) + 0x88, 0x44, // lw a0,8(s1) + 0xcc, 0x44, // lw a1,12(s1) + 0x90, 0x48, // lw a2,16(s1) + 0xd4, 0x48, // lw a3,20(s1) + 0xe1, 0x04, // add s1,s1,24 + 0x02, 0x97, // jalr a4 + 0xf5, 0xb7, // j 8 <_do_next> +// <_done>: + 0x02, 0x90, // ebreak +// <_args>: +}; + +typedef struct rp2xxx_rom_call_batch_record { + uint32_t pc; + uint32_t sp; + uint32_t args[4]; +} rp2xxx_rom_call_batch_record_t; + struct rp2040_flash_bank { /* flag indicating successful flash probe */ bool probed; /* stack used by Boot ROM calls */ struct working_area *stack; + /* static code scratchpad used for RAM algorithms -- allocated in advance + so that higher-level calls can just grab all remaining workarea: */ + struct working_area *ram_algo_space; /* function jump table populated by rp2040_flash_probe() */ - uint16_t jump_debug_trampoline; - uint16_t jump_debug_trampoline_end; uint16_t jump_flash_exit_xip; uint16_t jump_connect_internal_flash; uint16_t jump_flash_range_erase; uint16_t jump_flash_range_program; uint16_t jump_flush_cache; + uint16_t jump_flash_reset_address_trans; uint16_t jump_enter_cmd_xip; uint16_t jump_bootrom_reset_state; }; -static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16_t *symbol) +#ifndef LOG_ROM_SYMBOL_DEBUG +#define LOG_ROM_SYMBOL_DEBUG LOG_DEBUG +#endif + +static int rp2040_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out) { - uint32_t magic, magic_addr; - bool found_rp2040_magic, found_rp2350_magic; - magic_addr = BOOTROM_MAGIC_ADDR; - int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic); + LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2040 table", tag & 0xff, (tag >> 8) & 0xff); + if (flags != RT_FLAG_FUNC_ARM_SEC && flags != RT_FLAG_DATA) { + /* Note RT flags do not exist on RP2040, so just sanity check that we + are asked for a type of thing that actually exists in the ROM table */ + LOG_ERROR("Only data and Secure Arm functions can be looked up in RP2040 ROM table"); + return ERROR_FAIL; + } + + uint16_t ptr_to_entry; + const unsigned int offset_magic_to_table_ptr = flags == RT_FLAG_DATA ? 6 : 4; + int err = target_read_u16(target, BOOTROM_MAGIC_ADDR + offset_magic_to_table_ptr, &ptr_to_entry); if (err != ERROR_OK) return err; - magic &= 0xffffff; /* ignore bootrom version */ - - found_rp2040_magic = magic == BOOTROM_RP2040_MAGIC; - found_rp2350_magic = magic == BOOTROM_RP2350_MAGIC; + uint16_t entry_tag; + do { + err = target_read_u16(target, ptr_to_entry, &entry_tag); + if (err != ERROR_OK) + return err; + if (entry_tag == tag) { + /* 16 bit symbol is next */ + err = target_read_u16(target, ptr_to_entry + 2, symbol_out); + if (err != ERROR_OK) + return err; + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); + return ERROR_OK; + } + ptr_to_entry += 4; + } while (entry_tag); + *symbol_out = 0; + return ERROR_FAIL; +} - if (!(found_rp2040_magic || found_rp2350_magic)) { - LOG_ERROR("RP2040/RP2350 BOOT ROM not found"); - return ERROR_FAIL; +static int rp2350_a0_lookup_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out) +{ + LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2350 A0 table", tag & 0xff, (tag >> 8) & 0xff); + + /* RP2350 A0 table format is the same as RP2040 except with 16 bits of + flags after each 16-bit pointer. We ignore the flags, as each symbol + only has one datum associated with it. */ + + uint32_t magic_ptr = BOOTROM_MAGIC_ADDR; + if (flags == RT_FLAG_FUNC_RISCV) { + /* RP2350 A0 used split function tables for Arm/RISC-V -- not used on + any other device or any other version of this device. There is a + well-known RISC-V table at the top of ROM, matching the well-known + Arm table at the bottom of ROM. */ + magic_ptr = 0x7decu; + } else if (flags != RT_FLAG_FUNC_ARM_SEC) { + LOG_WARNING("Ignoring non-default flags for RP2350 A0 lookup, hope you like Secure Arm functions"); } - /* dereference the table pointer */ - uint16_t table_entry; - err = target_read_u16(target, magic_addr + 4, &table_entry); + uint16_t ptr_to_entry; + const unsigned int offset_magic_to_table_ptr = 4; + int err = target_read_u16(target, magic_ptr + offset_magic_to_table_ptr, &ptr_to_entry); if (err != ERROR_OK) return err; uint16_t entry_tag; do { - err = target_read_u16(target, table_entry, &entry_tag); + err = target_read_u16(target, ptr_to_entry, &entry_tag); if (err != ERROR_OK) return err; if (entry_tag == tag) { - if (found_rp2350_magic) { - uint16_t flags; - /* flags are next */ - err = target_read_u16(target, table_entry + 4, &flags); - if (err != ERROR_OK) - return err; - // - if (flags & RT_ARM_FUNC) { - /* 16 bit symbol */ - return target_read_u16(target, table_entry + 2, symbol); - } - } else { - /* 16 bit symbol is next */ - return target_read_u16(target, table_entry + 2, symbol); - } + err = target_read_u16(target, ptr_to_entry + 2, symbol_out); + if (err != ERROR_OK) + return err; + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); + return ERROR_OK; } - table_entry += found_rp2350_magic ? 6 : 4; + ptr_to_entry += 6; } while (entry_tag); + *symbol_out = 0; return ERROR_FAIL; } -static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank *priv, - uint16_t func_offset, uint32_t argdata[], unsigned int n_args) +static int rp2350_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out) { - char *regnames[4] = { "r0", "r1", "r2", "r3" }; + LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2350 A1 table", tag & 0xff, (tag >> 8) & 0xff); + uint32_t ptr_to_entry; + int err = target_read_u32(target, BOOTROM_MAGIC_ADDR + 4, &ptr_to_entry); + if (err != ERROR_OK) + return err; - assert(n_args <= ARRAY_SIZE(regnames)); /* only allow register arguments */ + /* On RP2350 A1, Each entry has a flag bitmap identifying the type of its + contents. The entry contains one halfword of data for each set flag + bit. There may be both Arm and RISC-V entries under the same tag, or + separate Arm Secure/NonSecure entries (or all three, why not). */ - if (!priv->stack) { - LOG_ERROR("no stack for flash programming code"); + while (true) { + uint16_t entry_tag, entry_flags; + + err = target_read_u16(target, ptr_to_entry, &entry_tag); + if (err != ERROR_OK) + return err; + if (entry_tag == 0) { + *symbol_out = 0; + return ERROR_FAIL; + } + ptr_to_entry += 2; + + err = target_read_u16(target, ptr_to_entry, &entry_flags); + if (err != ERROR_OK) + return err; + ptr_to_entry += 2; + + uint16_t matching_flags = flags & entry_flags; + + if (tag == entry_tag && matching_flags != 0) { + /* This is our entry, seek to the correct data item and return it. */ + bool is_riscv_func = matching_flags & RT_FLAG_FUNC_RISCV; + while (!(matching_flags & 1)) { + if (entry_flags & 1) + ptr_to_entry += 2; + + matching_flags >>= 1; + entry_flags >>= 1; + } + if (is_riscv_func) { + /* For RISC-V, the table entry itself is the entry point -- trick + to make shared function implementations smaller */ + *symbol_out = ptr_to_entry; + return ERROR_OK; + } + err = target_read_u16(target, ptr_to_entry, symbol_out); + if (err != ERROR_OK) + return err; + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); + return ERROR_OK; + } + /* Skip past this entry */ + while (entry_flags) { + if (entry_flags & 1) + ptr_to_entry += 2; + + entry_flags >>= 1; + } + } +} + +static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out) +{ + uint32_t magic; + int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic); + if (err != ERROR_OK) + return err; + + /* Ignore version */ + magic &= 0xffffff; + + if (magic == BOOTROM_RP2350_MAGIC) { + /* Distinguish old-style RP2350 ROM table (A0, and earlier A1 builds) + based on position of table -- a high address means it is shared with + RISC-V, i.e. new-style. */ + uint32_t table_ptr; + err = target_read_u32(target, BOOTROM_MAGIC_ADDR + 4, &table_ptr); + if (err != ERROR_OK) + return err; + if (table_ptr < 0x7c00) + return rp2350_a0_lookup_symbol(target, tag, flags, symbol_out); + else + return rp2350_lookup_rom_symbol(target, tag, flags, symbol_out); + + } else if (magic == BOOTROM_RP2040_MAGIC) { + return rp2040_lookup_rom_symbol(target, tag, flags, symbol_out); + } + LOG_ERROR("RP2040/RP2350 BOOT ROM not found"); + return ERROR_FAIL; +} + +static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2040_flash_bank *priv) +{ + const uint16_t symtype_func = is_arm(target_to_arm(target)) + ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV; + int err; + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_EXIT_XIP, + symtype_func, &priv->jump_flash_exit_xip); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2xxx ROM."); + return err; + } + + err = rp2xxx_lookup_rom_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, + symtype_func, &priv->jump_connect_internal_flash); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2xxx ROM."); + return err; + } + + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RANGE_ERASE, symtype_func, &priv->jump_flash_range_erase); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2xxx ROM."); + return err; + } + + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RANGE_PROGRAM, symtype_func, &priv->jump_flash_range_program); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2xxx ROM."); + return err; + } + + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_FLUSH_CACHE, symtype_func, &priv->jump_flush_cache); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2xxx ROM."); + return err; + } + + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, symtype_func, &priv->jump_enter_cmd_xip); + if (err != ERROR_OK) { + LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2xxx ROM."); + return err; + } + + // From this point are optional functions which do not exist on e.g. RP2040 + // or pre-production RP2350 ROM versions: + + err = rp2xxx_lookup_rom_symbol(target, FUNC_BOOTROM_STATE_RESET, symtype_func, &priv->jump_bootrom_reset_state); + if (err != ERROR_OK) { + priv->jump_bootrom_reset_state = 0; + LOG_WARNING("Function FUNC_BOOTROM_STATE_RESET not found in RP2xxx ROM. (probably an RP2040 or an RP2350 A0)"); + } + + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RESET_ADDRESS_TRANS, + symtype_func, &priv->jump_flash_reset_address_trans); + if (err != ERROR_OK) { + priv->jump_flash_reset_address_trans = 0; + LOG_WARNING("Function FUNC_FLASH_RESET_ADDRESS_TRANS not found in RP2xxx ROM. (probably an RP2040 or an RP2350 A0)"); + } + return ERROR_OK; +} + +// Call a list of PC + SP + r0-r3 function call tuples with a single OpenOCD +// algorithm invocation, to amortise the algorithm overhead over multiple calls: +static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2040_flash_bank *priv, + rp2xxx_rom_call_batch_record_t *calls, unsigned int n_calls) +{ + // Note +1 is for the null terminator + unsigned int batch_words = 1 + (ROM_CALL_BATCH_ALGO_SIZE_BYTES + + n_calls * sizeof(rp2xxx_rom_call_batch_record_t) + ) / sizeof(uint32_t); + + if (!priv->ram_algo_space) { + LOG_ERROR("No RAM code space allocated for ROM call"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - target_addr_t stacktop = priv->stack->address + priv->stack->size; + if (priv->ram_algo_space->size < batch_words * sizeof(uint32_t)) { + LOG_ERROR("RAM code space too small for call batch size of %u\n", n_calls); + return ERROR_BUF_TOO_SMALL; + } - LOG_DEBUG("Calling ROM func @0x%" PRIx16 " with %d arguments", func_offset, n_args); + LOG_DEBUG("Calling batch of %u ROM functions:", n_calls); + for (unsigned int i = 0; i < n_calls; ++i) { + LOG_DEBUG(" func @ %" PRIx32, calls[i].pc); + LOG_DEBUG(" sp = %" PRIx32, calls[i].sp); + for (int j = 0; j < 4; ++j) + LOG_DEBUG(" a%d = %" PRIx32, j, calls[i].args[j]); + } LOG_DEBUG("Calling on core \"%s\"", target->cmd_name); - struct reg_param args[ARRAY_SIZE(regnames) + 12]; - struct armv7m_algorithm alg_info; + if (n_calls <= 0) { + LOG_DEBUG("Returning early from call of 0 ROM functions"); + return ERROR_OK; + } - for (unsigned int i = 0; i < n_args; ++i) { - init_reg_param(&args[i], regnames[i], 32, PARAM_OUT); - buf_set_u32(args[i].value, 0, 32, argdata[i]); - } - /* Pass function pointer in r7 */ - unsigned int extra_args = 0; - init_reg_param(&args[n_args + extra_args], "r7", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, func_offset); - /* Set stack pointer, have seen the caching get confused by the aliases of sp so - take the shotgun approach*/ - init_reg_param(&args[n_args + extra_args], "msp_s", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - init_reg_param(&args[n_args + extra_args], "msp_ns", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - init_reg_param(&args[n_args + extra_args], "psp_s", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - init_reg_param(&args[n_args + extra_args], "psp_ns", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - init_reg_param(&args[n_args + extra_args], "msp", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - init_reg_param(&args[n_args + extra_args], "psp", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - init_reg_param(&args[n_args + extra_args], "sp", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, stacktop); - /* Clear stack pointer limits, as they may be above the algorithm stack */ - init_reg_param(&args[n_args + extra_args], "msplim_s", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); - init_reg_param(&args[n_args + extra_args], "psplim_s", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); - init_reg_param(&args[n_args + extra_args], "msplim_ns", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); - init_reg_param(&args[n_args + extra_args], "psplim_ns", 32, PARAM_OUT); - buf_set_u32(args[n_args + extra_args++].value, 0, 32, 0); - - for (unsigned int i = 0; i < n_args + extra_args; ++i) - LOG_DEBUG("Set %s = 0x%" PRIx32, args[i].reg_name, buf_get_u32(args[i].value, 0, 32)); + const uint8_t *algo_code; + if (is_arm(target_to_arm(target))) { + if (target_to_arm(target)->arch == ARM_ARCH_V8M) { + LOG_DEBUG("Using algo: rp2xxx_rom_call_batch_algo_armv8m"); + algo_code = rp2xxx_rom_call_batch_algo_armv8m; + } else { + LOG_DEBUG("Using algo: rp2xxx_rom_call_batch_algo_armv6m"); + algo_code = rp2xxx_rom_call_batch_algo_armv6m; + } + } else { + LOG_DEBUG("Using algo: rp2xxx_rom_call_batch_algo_riscv"); + algo_code = rp2xxx_rom_call_batch_algo_riscv; + } - /* Actually call the function */ - alg_info.common_magic = ARMV7M_COMMON_MAGIC; - alg_info.core_mode = ARM_MODE_THREAD; - int err = target_run_algorithm( - target, - 0, NULL, /* No memory arguments */ - n_args + extra_args, args, /* User arguments + r7 + SPs */ - priv->jump_debug_trampoline, priv->jump_debug_trampoline_end, - 3000, /* 3s timeout */ - &alg_info + int err = target_write_buffer(target, + priv->ram_algo_space->address, + ROM_CALL_BATCH_ALGO_SIZE_BYTES, + algo_code ); - for (unsigned int i = 0; i < n_args + extra_args; ++i) - destroy_reg_param(&args[i]); - if (err != ERROR_OK) - LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16 "\n", func_offset); - return err; + if (err != ERROR_OK) { + LOG_ERROR("Failed to write ROM batch algorithm to RAM code space\n"); + return err; + } + err = target_write_buffer(target, + priv->ram_algo_space->address + ROM_CALL_BATCH_ALGO_SIZE_BYTES, + n_calls * sizeof(rp2xxx_rom_call_batch_record_t), + (const uint8_t *)calls + ); + if (err != ERROR_OK) { + LOG_ERROR("Failed to write ROM batch records to RAM code space\n"); + return err; + } + err = target_write_u32(target, + priv->ram_algo_space->address + (batch_words - 1) * sizeof(uint32_t), + 0 + ); + if (err != ERROR_OK) { + LOG_ERROR("Failed to write null terminator for ROM batch records\n"); + return err; + } + + // Call into the ROM batch algorithm -- this will in turn call each ROM + // call specified by the batch records. + target_addr_t algo_start_addr = priv->ram_algo_space->address; + target_addr_t algo_end_addr = priv->ram_algo_space->address + rp2xxx_rom_call_batch_algo_bkpt_offset; + unsigned int algo_timeout_ms = 3000; + if (is_arm(target_to_arm(target))) { + struct armv7m_algorithm alg_info; + alg_info.common_magic = ARMV7M_COMMON_MAGIC; + alg_info.core_mode = ARM_MODE_THREAD; + err = target_run_algorithm(target, + 0, NULL, /* No memory arguments */ + 0, NULL, /* No register arguments */ + algo_start_addr, algo_end_addr, + algo_timeout_ms, + &alg_info + ); + } else { + // Presumed RISC-V -- there is no RISCV_COMMON_MAGIC on older OpenOCD + err = target_run_algorithm(target, + 0, NULL, /* No memory arguments */ + 0, NULL, /* No register arguments */ + algo_start_addr, algo_end_addr, + algo_timeout_ms, + NULL /* Currently no RISC-V-specific algorithm info */ + ); + } + if (err != ERROR_OK) { + LOG_ERROR("Failed to call ROM function batch\n"); + /* This case is hit when loading new ROM images on FPGA, but can also be + hit on real hardware if you swap two devices with different ROM + versions without restarting OpenOCD: */ + LOG_INFO("Repopulating ROM address cache after failed ROM call"); + /* We ignore the error because we have already failed, this is just + recovery for the next attempt. */ + (void)rp2xxx_populate_rom_pointer_cache(target, priv); + return err; + } + return ERROR_OK; } -static int rp2350_init_core(struct target *target, struct rp2040_flash_bank *priv) +// Call a single ROM function, using the default algorithm stack. +static int rp2xxx_call_rom_func(struct target *target, struct rp2040_flash_bank *priv, + uint16_t func_offset, uint32_t argdata[], unsigned int n_args) { + assert(n_args <= 4); /* only allow register arguments -- capped at just 4 on Arm */ + if (!priv->stack) { LOG_ERROR("no stack for flash programming code"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } + target_addr_t stacktop = priv->stack->address + priv->stack->size; - struct armv7m_algorithm alg_info; + rp2xxx_rom_call_batch_record_t call = { + .pc = func_offset, + .sp = stacktop + }; + for (unsigned int i = 0; i < n_args; ++i) + call.args[i] = argdata[i]; - // copy rcp_init code onto stack, as we don't actually need any stack during the call - if (priv->stack->size < sizeof(rcp_init_code)) { - LOG_ERROR("Working area too small for rcp_init"); - return ERROR_BUF_TOO_SMALL; - } + return rp2xxx_call_rom_func_batch(target, priv, &call, 1); +} - // Attempt to reset ACCESSCTRL before running RCP init, in case Secure - // access to SRAM has been blocked. (Also ROM, QMI regs are needed later) +static int rp2350_init_accessctrl(struct target *target) +{ + // Attempt to reset ACCESSCTRL, in case Secure access to SRAM has been + // blocked, which will stop us from loading/running algorithms such as RCP + // init. (Also ROM, QMI regs are needed later) uint32_t accessctrl_lock_reg; if (target_read_u32(target, ACCESSCTRL_LOCK_OFFSET, &accessctrl_lock_reg) != ERROR_OK) { LOG_ERROR("Failed to read ACCESSCTRL lock register"); @@ -254,30 +567,59 @@ static int rp2350_init_core(struct target *target, struct rp2040_flash_bank *pri LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail.\n"); } else { LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET\n"); - target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u); + return target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u); + } + return ERROR_OK; +} + +static int rp2350_init_arm_core0(struct target *target, struct rp2040_flash_bank *priv) +{ + // Flash algorithms (and the RCP init stub called by this function) must + // run in the Secure state, so flip the state now before attempting to + // execute any code on the core. + uint32_t dscsr; + (void)target_read_u32(target, DCB_DSCSR, &dscsr); + LOG_DEBUG("DSCSR: %08x\n", dscsr); + if (!(dscsr & DSCSR_CDS)) { + LOG_DEBUG("Setting Current Domain Secure in DSCSR\n"); + (void)target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); + (void)target_read_u32(target, DCB_DSCSR, &dscsr); + LOG_DEBUG("DSCSR*: %08x\n", dscsr); + } + + if (!priv->stack) { + LOG_ERROR("No stack for flash programming code"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + if (!priv->ram_algo_space || priv->ram_algo_space->size < sizeof(rcp_init_code)) { + LOG_ERROR("No algorithm space for rcp_init code"); + return ERROR_BUF_TOO_SMALL; } int err = target_write_memory(target, - priv->stack->address, + priv->ram_algo_space->address, 1, sizeof(rcp_init_code), - (const uint8_t *)rcp_init_code + rcp_init_code ); if (err != ERROR_OK) { LOG_ERROR("Failed to load rcp_init algorithm into RAM\n"); return ERROR_FAIL; } - LOG_DEBUG("Calling rcp_init core \"%s\" code at 0x%" PRIx16 "\n", target->cmd_name, (uint32_t)priv->stack->address); + LOG_DEBUG("Calling rcp_init on core \"%s\", code at 0x%" PRIx32 "\n", + target->cmd_name, (uint32_t)priv->ram_algo_space->address); /* Actually call the function */ + struct armv7m_algorithm alg_info; alg_info.common_magic = ARMV7M_COMMON_MAGIC; alg_info.core_mode = ARM_MODE_THREAD; err = target_run_algorithm(target, 0, NULL, /* No memory arguments */ 0, NULL, /* No register arguments */ - priv->stack->address, - priv->stack->address + rcp_init_code_bkpt_offset, + priv->ram_algo_space->address, + priv->ram_algo_space->address + rcp_init_code_bkpt_offset, 1000, /* 1s timeout */ &alg_info ); @@ -286,80 +628,75 @@ static int rp2350_init_core(struct target *target, struct rp2040_flash_bank *pri return err; } - uint32_t reset_args[1] = { - BOOTROM_STATE_RESET_CURRENT_CORE - }; - if (!priv->jump_bootrom_reset_state) { - LOG_WARNING("RP2350 flash: no bootrom_reset_method\n"); - } else { - err = rp2040_call_rom_func(target, priv, priv->jump_bootrom_reset_state, reset_args, ARRAY_SIZE(reset_args)); - if (err != ERROR_OK) { - LOG_ERROR("RP2040 flash: failed to call reset core state"); - return err; - } - } - return err; } -static int setup_for_rom_call(struct flash_bank *bank) +static int setup_for_raw_flash_cmd(struct flash_bank *bank) { struct rp2040_flash_bank *priv = bank->driver_priv; - struct target *target = bank->target; int err = ERROR_OK; + if (!priv->stack) { /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */ - const int STACK_SIZE = 256; - target_alloc_working_area(bank->target, STACK_SIZE, &priv->stack); + err = target_alloc_working_area(bank->target, RP2XXX_MAX_ALGO_STACK_USAGE, &priv->stack); if (err != ERROR_OK) { - LOG_ERROR("Could not allocate stack for flash programming code"); + LOG_ERROR("Could not allocate stack for flash programming code -- insufficient space"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } - // Flash algorithms must run in Secure state - uint32_t dscsr; - (void)target_read_u32(target, DCB_DSCSR, &dscsr); - LOG_DEBUG("DSCSR: %08x\n", dscsr); - if (!(dscsr & DSCSR_CDS)) { - LOG_DEBUG("Setting Current Domain Secure in DSCSR\n"); - (void)target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); - (void)target_read_u32(target, DCB_DSCSR, &dscsr); - LOG_DEBUG("DSCSR*: %08x\n", dscsr); + if (!priv->ram_algo_space) { + err = target_alloc_working_area(bank->target, RP2XXX_MAX_RAM_ALGO_SIZE, &priv->ram_algo_space); + if (err != ERROR_OK) { + LOG_ERROR("Could not allocate RAM code space for ROM calls -- insufficient space"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } } - // hacky RP2350 check - if (target_to_arm(target)->arch == ARM_ARCH_V8M) { - err = rp2350_init_core(target, priv); + // hacky RP2350 check -- either RISC-V or v8-M + if (is_arm(target_to_arm(target)) ? target_to_arm(target)->arch == ARM_ARCH_V8M : true) { + err = rp2350_init_accessctrl(target); if (err != ERROR_OK) { - LOG_ERROR("RP2350 flash: failed to init core"); + LOG_ERROR("Failed to init ACCESSCTRL before ROM call"); return err; } - } - return err; -} - -static int setup_for_raw_flash_cmd(struct flash_bank *bank) -{ - struct rp2040_flash_bank *priv = bank->driver_priv; - int err = setup_for_rom_call(bank); - err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0); - if (err != ERROR_OK) { - LOG_ERROR("RP2040 flash: failed to setup for rom call"); - return err; - } - - LOG_DEBUG("Connecting internal flash"); - err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0); - if (err != ERROR_OK) { - LOG_ERROR("RP2040 flash: failed to connect internal flash"); - return err; + if (is_arm(target_to_arm(target))) { + err = rp2350_init_arm_core0(target, priv); + if (err != ERROR_OK) { + LOG_ERROR("Failed to init Arm core 0 before ROM call"); + return err; + } + } + uint32_t reset_args[1] = { + BOOTROM_STATE_RESET_CURRENT_CORE + }; + if (!priv->jump_bootrom_reset_state) { + LOG_WARNING("RP2350 flash: no bootrom_reset_method\n"); + } else { + LOG_DEBUG("Clearing core 0 ROM state"); + err = rp2xxx_call_rom_func(target, priv, priv->jump_bootrom_reset_state, + reset_args, ARRAY_SIZE(reset_args)); + if (err != ERROR_OK) { + LOG_ERROR("RP2350 flash: failed to call reset core state"); + return err; + } + } } - LOG_DEBUG("Kicking flash out of XIP mode"); - err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_exit_xip, NULL, 0); + LOG_DEBUG("Connecting flash IOs and issuing XIP exit sequence to flash"); + rp2xxx_rom_call_batch_record_t calls[2] = { + { + .pc = priv->jump_connect_internal_flash, + .sp = priv->stack->address + priv->stack->size + }, + { + .pc = priv->jump_flash_exit_xip, + .sp = priv->stack->address + priv->stack->size + } + }; + err = rp2xxx_call_rom_func_batch(bank->target, priv, calls, 2); if (err != ERROR_OK) { LOG_ERROR("RP2040 flash: failed to exit flash XIP mode"); return err; @@ -368,6 +705,25 @@ static int setup_for_raw_flash_cmd(struct flash_bank *bank) return ERROR_OK; } +static void cleanup_after_raw_flash_cmd(struct flash_bank *bank) +{ + /* OpenOCD is prone to trashing work-area allocations on target state + transitions, which leaves us with stale work area pointers in our + driver state. Best to clean up our allocations manually after + completing each flash call, so we know to make fresh ones next time. */ + LOG_DEBUG("Cleaning up after flash operations"); + struct rp2040_flash_bank *priv = bank->driver_priv; + struct target *target = bank->target; + if (priv->stack) { + target_free_working_area(target, priv->stack); + priv->stack = 0; + } + if (priv->ram_algo_space) { + target_free_working_area(target, priv->ram_algo_space); + priv->ram_algo_space = 0; + } +} + static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset); @@ -378,13 +734,14 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui int err = setup_for_raw_flash_cmd(bank); if (err != ERROR_OK) - return err; + goto cleanup_and_return; // Allocate as much memory as possible, rounded down to a whole number of flash pages const unsigned int chunk_size = target_get_working_area_avail(target) & ~0xffu; if (chunk_size == 0 || target_alloc_working_area(target, chunk_size, &bounce) != ERROR_OK) { LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto cleanup_and_return; } LOG_DEBUG("Allocated flash bounce buffer @" TARGET_ADDR_FMT, bounce->address); @@ -402,7 +759,7 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui bounce->address, /* data */ write_size /* count */ }; - err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args)); + err = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args)); if (err != ERROR_OK) { LOG_ERROR("Failed to invoke flash programming code on target"); break; @@ -415,20 +772,43 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui target_free_working_area(target, bounce); if (err != ERROR_OK) - return err; + goto cleanup_and_return; + + // Flash is successfully programmed. We can now do a bit of poking to make + // the new flash contents visible to us via memory-mapped (XIP) interface + // in the 0x1... memory region. + // + // Note on RP2350 it's not *required* to call flash_enter_cmd_xip, since + // the ROM leaves flash XIPable by default in between direct-mode + // accesses, but there's no harm in calling it anyway. - /* Flash is successfully programmed. We can now do a bit of poking to make the flash - contents visible to us via memory-mapped (XIP) interface in the 0x1... memory region */ LOG_DEBUG("Flushing flash cache after write behind"); - err = rp2040_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0); + err = rp2xxx_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0); + + rp2xxx_rom_call_batch_record_t finishing_calls[3] = { + { + .pc = priv->jump_flush_cache, + .sp = priv->stack->address + priv->stack->size + }, + { + .pc = priv->jump_enter_cmd_xip, + .sp = priv->stack->address + priv->stack->size + }, + { + .pc = priv->jump_flash_reset_address_trans, + .sp = priv->stack->address + priv->stack->size + } + }; + // Note the last function does not exist on older devices: + int num_finishing_calls = priv->jump_flash_reset_address_trans ? 3 : 2; + + err = rp2xxx_call_rom_func_batch(target, priv, finishing_calls, num_finishing_calls); if (err != ERROR_OK) { LOG_ERROR("RP2040 write: failed to flush flash cache"); - return err; + goto cleanup_and_return; } - LOG_DEBUG("Configuring SSI for execute-in-place"); - err = rp2040_call_rom_func(bank->target, priv, priv->jump_enter_cmd_xip, NULL, 0); - if (err != ERROR_OK) - LOG_ERROR("RP2040 write: failed to flush flash cache"); +cleanup_and_return: + cleanup_after_raw_flash_cmd(bank); return err; } @@ -441,7 +821,7 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig int err = setup_for_raw_flash_cmd(bank); if (err != ERROR_OK) - return err; + goto cleanup_and_return; LOG_DEBUG("Remote call flash_range_erase"); @@ -452,18 +832,13 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig 0xd8 /* block_cmd */ }; - /* - The RP2040 Boot ROM provides a _flash_range_erase() API call documented in Section 2.8.3.1.3: - https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf - and the particular source code for said Boot ROM function can be found here: - https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c - - In theory, the function algorithm provides for erasing both a smaller "sector" (4096 bytes) and - an optional larger "block" (size and command provided in args). OpenOCD's spi.c only uses "block" sizes. - */ - - err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); + /* This ROM function will use the optimal mixture of 4k 20h and 64k D8h + erases, without over-erase, as long as you just tell OpenOCD that your + flash is made up of 4k sectors instead of letting it try to guess. */ + err = rp2xxx_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); +cleanup_and_return: + cleanup_after_raw_flash_cmd(bank); return err; } @@ -475,63 +850,9 @@ static int rp2040_flash_probe(struct flash_bank *bank) struct rp2040_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; - int err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE, &priv->jump_debug_trampoline); - if (err != ERROR_OK) { - LOG_ERROR("Debug trampoline not found in RP2040 ROM."); - return err; - } - priv->jump_debug_trampoline &= ~1u; /* mask off thumb bit */ - - err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE_END, &priv->jump_debug_trampoline_end); - if (err != ERROR_OK) { - LOG_ERROR("Debug trampoline end not found in RP2040 ROM."); - return err; - } - priv->jump_debug_trampoline_end &= ~1u; /* mask off thumb bit */ - - err = rp2040_lookup_symbol(target, FUNC_FLASH_EXIT_XIP, &priv->jump_flash_exit_xip); - if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2040 ROM."); - return err; - } - - err = rp2040_lookup_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, &priv->jump_connect_internal_flash); - if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2040 ROM."); - return err; - } - - err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_ERASE, &priv->jump_flash_range_erase); - if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2040 ROM."); - return err; - } - LOG_WARNING("GOT FLASH ERASE AT %08x\n", (int)priv->jump_flash_range_erase); - - err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_PROGRAM, &priv->jump_flash_range_program); - if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2040 ROM."); - return err; - } - - err = rp2040_lookup_symbol(target, FUNC_FLASH_FLUSH_CACHE, &priv->jump_flush_cache); - if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2040 ROM."); - return err; - } - - err = rp2040_lookup_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, &priv->jump_enter_cmd_xip); - if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2040 ROM."); + int err = rp2xxx_populate_rom_pointer_cache(target, priv); + if (err != ERROR_OK) return err; - } - - err = rp2040_lookup_symbol(target, FUNC_BOOTROM_STATE_RESET, &priv->jump_bootrom_reset_state); - if (err != ERROR_OK) { - priv->jump_bootrom_reset_state = 0; -// LOG_ERROR("Function FUNC_BOOTROM_STATE_RESET not found in RP2040 ROM."); -// return err; - } /* the Boot ROM flash_range_program() routine requires page alignment */ bank->write_start_alignment = 256; @@ -577,6 +898,7 @@ FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) { struct rp2040_flash_bank *priv; priv = malloc(sizeof(struct rp2040_flash_bank)); + memset(priv, 0, sizeof(struct rp2040_flash_bank)); priv->probed = false; /* Set up driver_priv */ From eb4a6342485a433ad01a18ef115236c2a29de900 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Sun, 24 Mar 2024 18:33:24 -0500 Subject: [PATCH 1170/1312] flash/nor/rp2040: RP2350 A1 changes TV: cortex_m.c changes removed. Change-Id: I85830f2d64f8afb86690737f9ae70dde5e6143e1 Signed-off-by: Tomas Vanek Signed-off-by: graham sanderson Reviewed-on: https://review.openocd.org/c/openocd/+/8442 Tested-by: jenkins --- src/flash/nor/rp2040.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 1e582b433a..764a034c6a 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -256,13 +256,10 @@ static int rp2350_a0_lookup_symbol(struct target *target, uint16_t tag, uint16_t return ERROR_FAIL; } -static int rp2350_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out) +static int rp2350_lookup_rom_symbol(struct target *target, uint32_t ptr_to_entry, + uint16_t tag, uint16_t flags, uint16_t *symbol_out) { LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2350 A1 table", tag & 0xff, (tag >> 8) & 0xff); - uint32_t ptr_to_entry; - int err = target_read_u32(target, BOOTROM_MAGIC_ADDR + 4, &ptr_to_entry); - if (err != ERROR_OK) - return err; /* On RP2350 A1, Each entry has a flag bitmap identifying the type of its contents. The entry contains one halfword of data for each set flag @@ -272,7 +269,7 @@ static int rp2350_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ while (true) { uint16_t entry_tag, entry_flags; - err = target_read_u16(target, ptr_to_entry, &entry_tag); + uint32_t err = target_read_u16(target, ptr_to_entry, &entry_tag); if (err != ERROR_OK) return err; if (entry_tag == 0) { @@ -341,7 +338,7 @@ static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ if (table_ptr < 0x7c00) return rp2350_a0_lookup_symbol(target, tag, flags, symbol_out); else - return rp2350_lookup_rom_symbol(target, tag, flags, symbol_out); + return rp2350_lookup_rom_symbol(target, table_ptr, tag, flags, symbol_out); } else if (magic == BOOTROM_RP2040_MAGIC) { return rp2040_lookup_rom_symbol(target, tag, flags, symbol_out); From 2e8e1a3da386685a2a572bcc85f043505a7b3d94 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 28 Jun 2024 16:41:48 +0100 Subject: [PATCH 1171/1312] flash/nor/rp2040: Fix up ROM table lookup for RP2350 A2 which has 16-bit well-known pointers. Change-Id: Ia0838a0b062f73a9c5751abb48f1b4d55100bd1d Signed-off-by: Tomas Vanek Signed-off-by: Luke Wren Reviewed-on: https://review.openocd.org/c/openocd/+/8443 Reviewed-by: Jonathan Bell Tested-by: jenkins --- src/flash/nor/rp2040.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 764a034c6a..a9995f8c6d 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -331,8 +331,8 @@ static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ /* Distinguish old-style RP2350 ROM table (A0, and earlier A1 builds) based on position of table -- a high address means it is shared with RISC-V, i.e. new-style. */ - uint32_t table_ptr; - err = target_read_u32(target, BOOTROM_MAGIC_ADDR + 4, &table_ptr); + uint16_t table_ptr; + err = target_read_u16(target, BOOTROM_MAGIC_ADDR + 4, &table_ptr); if (err != ERROR_OK) return err; if (table_ptr < 0x7c00) From ca966d3d7f28875e4872e691c3fdce27867ddab0 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Thu, 25 Jul 2024 10:55:41 +0100 Subject: [PATCH 1172/1312] flash/nor/rp2040: Avoid ROM call timeout on long erases by splitting into chunks Also add keep_alive() to erase/program to avoid nasty GDB message. TV: Fixed style problems. Signed-off-by: Tomas Vanek Signed-off-by: Luke Wren Change-Id: Ibb18775aeed192361ae1585bfdaad03760583cf3 Reviewed-on: https://review.openocd.org/c/openocd/+/8444 Tested-by: jenkins Reviewed-by: Jonathan Bell --- src/flash/nor/rp2040.c | 63 +++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index a9995f8c6d..9151b68789 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -510,11 +510,10 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2040_flash } if (err != ERROR_OK) { LOG_ERROR("Failed to call ROM function batch\n"); - /* This case is hit when loading new ROM images on FPGA, but can also be - hit on real hardware if you swap two devices with different ROM - versions without restarting OpenOCD: */ - LOG_INFO("Repopulating ROM address cache after failed ROM call"); - /* We ignore the error because we have already failed, this is just + /* This case is hit when loading new ROM images on FPGA, but can also be hit on real + hardware if you swap two devices with different ROM versions without restarting OpenOCD: */ + LOG_ROM_SYMBOL_DEBUG("Repopulating ROM address cache after failed ROM call"); + /* We ignore the error on this next call because we have already failed, this is just recovery for the next attempt. */ (void)rp2xxx_populate_rom_pointer_cache(target, priv); return err; @@ -757,6 +756,7 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui write_size /* count */ }; err = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args)); + keep_alive(); if (err != ERROR_OK) { LOG_ERROR("Failed to invoke flash programming code on target"); break; @@ -820,19 +820,50 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig if (err != ERROR_OK) goto cleanup_and_return; - LOG_DEBUG("Remote call flash_range_erase"); + uint32_t offset_next = bank->sectors[first].offset; + uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset; + + /* Break erase into multiple calls to avoid timeout on large erase. Choose 128k chunk which has + fairly low ROM call overhead and empirically seems to avoid the default keep_alive() limit + as well as our ROM call timeout. */ + const uint32_t erase_chunk_size = 128 * 1024; + + /* Promote log level for long erases to provide feedback */ + bool requires_loud_prints = offset_last - offset_next >= 2 * erase_chunk_size; + enum log_levels chunk_log_level = requires_loud_prints ? LOG_LVL_INFO : LOG_LVL_DEBUG; + + while (offset_next < offset_last) { + uint32_t remaining = offset_last - offset_next; + uint32_t call_size = remaining < erase_chunk_size ? remaining : erase_chunk_size; + /* Shorten the first call of a large erase if necessary to align subsequent calls */ + if (offset_next % erase_chunk_size != 0 && call_size == erase_chunk_size) + call_size = erase_chunk_size - offset_next % erase_chunk_size; + + LOG_CUSTOM_LEVEL(chunk_log_level, + " Erase chunk: 0x%08" PRIx32 " -> 0x%08" PRIx32, + offset_next, + offset_next + call_size - 1 + ); - uint32_t args[4] = { - bank->sectors[first].offset, /* addr */ - bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset, /* count */ - 65536, /* block_size */ - 0xd8 /* block_cmd */ - }; + /* This ROM function uses the optimal mixture of 4k 20h and 64k D8h erases, without + over-erase. This is why we force the flash_bank sector size attribute to 4k even if + OpenOCD prefers to give the block size instead. */ + uint32_t args[4] = { + offset_next, + call_size, + 65536, /* block_size */ + 0xd8 /* block_cmd */ + }; + + err = rp2xxx_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); + keep_alive(); + + if (err != ERROR_OK) + break; + + offset_next += call_size; + } - /* This ROM function will use the optimal mixture of 4k 20h and 64k D8h - erases, without over-erase, as long as you just tell OpenOCD that your - flash is made up of 4k sectors instead of letting it try to guess. */ - err = rp2xxx_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); cleanup_and_return: cleanup_after_raw_flash_cmd(bank); From 8f92e520bbd76917fd3ed18b9b9bb4099044da14 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Tue, 6 Aug 2024 11:57:04 +0100 Subject: [PATCH 1173/1312] flash/nor/rp2040: Fix incorrect erase bounds calculation when erase region does not start at 0 Signed-off-by: Tomas Vanek Signed-off-by: Luke Wren Change-Id: I2b9db61e8ac837b6c6431aacf3b73ed3a1772fbc Reviewed-on: https://review.openocd.org/c/openocd/+/8445 Tested-by: jenkins Reviewed-by: Jonathan Bell --- src/flash/nor/rp2040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 9151b68789..ed8341d1ff 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -821,7 +821,7 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig goto cleanup_and_return; uint32_t offset_next = bank->sectors[first].offset; - uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset; + uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size; /* Break erase into multiple calls to avoid timeout on large erase. Choose 128k chunk which has fairly low ROM call overhead and empirically seems to avoid the default keep_alive() limit From ba03d13c29fba9f5e4e97121c47eb3b7857aa92d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 6 Aug 2024 17:39:44 +0200 Subject: [PATCH 1174/1312] flash/nor/rp2040: allow flash size override from cfg Do not enforce hard-wired size 32 MiB Signed-off-by: Tomas Vanek Change-Id: I54608f75cc13996fda38ebd5d330e3b1893c2fd9 Reviewed-on: https://review.openocd.org/c/openocd/+/8446 Tested-by: jenkins Reviewed-by: Jonathan Bell Reviewed-by: Antonio Borneo --- src/flash/nor/rp2040.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index ed8341d1ff..5faba57a08 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -887,7 +887,10 @@ static int rp2040_flash_probe(struct flash_bank *bank) bank->write_end_alignment = 256; // Max size -- up to two devices (two chip selects) in adjacent 24-bit address windows - bank->size = 32 * 1024 * 1024; + if (bank->size == 0) { + /* TODO: get real flash size */ + bank->size = 32 * 1024 * 1024; + } bank->num_sectors = bank->size / 4096; From 15d92076b0c2d6198e2f60381e4dcb645ec9a110 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 17 Jul 2024 11:49:55 +0200 Subject: [PATCH 1175/1312] flash/nor/rp2040: allow arbitrary ROM API call from Tcl The new flash command could be handy for a reboot to BOOTSEL mode and for making (Q)SPI flash content visible at 0x10xxxxxx address mapping area after a rescue reset. Signed-off-by: Tomas Vanek Change-Id: I1b532afcc41a4051298313e685658e86c02c53f9 Reviewed-on: https://review.openocd.org/c/openocd/+/8447 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/rp2040.c | 87 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 5faba57a08..df9284d968 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -938,8 +938,95 @@ FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) return ERROR_OK; } + +COMMAND_HANDLER(rp2040_rom_api_call_handler) +{ + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct target *target = get_current_target(CMD->ctx); + + struct flash_bank *bank; + for (bank = flash_bank_list(); bank; bank = bank->next) { + if (bank->driver != &rp2040_flash) + continue; + + if (bank->target == target) + break; + } + + if (!bank) { + command_print(CMD, "[%s] No associated RP2xxx flash bank found", + target_name(target)); + return ERROR_FAIL; + } + + int retval = rp2040_flash_auto_probe(bank); + if (retval != ERROR_OK) { + command_print(CMD, "auto_probe failed"); + return retval; + } + + uint16_t tag = MAKE_TAG(CMD_ARGV[0][0], CMD_ARGV[0][1]); + + uint32_t args[4] = { 0 }; + for (unsigned int i = 0; i + 1 < CMD_ARGC && i < ARRAY_SIZE(args); i++) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i + 1], args[i]); + + retval = setup_for_raw_flash_cmd(bank); + if (retval != ERROR_OK) + goto cleanup_and_return; + + uint16_t symtype_func = is_arm(target_to_arm(target)) + ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV; + + uint16_t fc; + retval = rp2xxx_lookup_rom_symbol(target, tag, symtype_func, &fc); + if (retval != ERROR_OK) { + command_print(CMD, "Function %.2s not found in RP2xxx ROM.", + CMD_ARGV[0]); + goto cleanup_and_return; + } + + /* command_print() output gets lost if the command is called + * in an event handler, use LOG_INFO instead */ + LOG_INFO("RP2xxx ROM API function %.2s @ %04" PRIx16, CMD_ARGV[0], fc); + + struct rp2040_flash_bank *priv = bank->driver_priv; + retval = rp2xxx_call_rom_func(target, priv, fc, args, ARRAY_SIZE(args)); + if (retval != ERROR_OK) + command_print(CMD, "RP2xxx ROM API call failed"); + +cleanup_and_return: + cleanup_after_raw_flash_cmd(bank); + return retval; +} + +static const struct command_registration rp2040_exec_command_handlers[] = { + { + .name = "rom_api_call", + .mode = COMMAND_EXEC, + .help = "arbitrary ROM API call", + .usage = "fc [p0 [p1 [p2 [p3]]]]", + .handler = rp2040_rom_api_call_handler, + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration rp2040_command_handler[] = { + { + .name = "rp2xxx", + .mode = COMMAND_ANY, + .help = "rp2xxx flash controller commands", + .usage = "", + .chain = rp2040_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + const struct flash_driver rp2040_flash = { .name = "rp2040_flash", + .commands = rp2040_command_handler, .flash_bank_command = rp2040_flash_bank_command, .erase = rp2040_flash_erase, .write = rp2040_flash_write, From 2e49c99b1f919c2496c2d0140ada4ea5134c20a0 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 10 Aug 2024 16:10:43 +0200 Subject: [PATCH 1176/1312] flash/nor/rp2040: flash bank target switching for RP2350 RP2350 can switch either core to Cortex-M33 or RISC-V. The different architectures have to be supported as distinct targets in OpenOCD. Introduce 'rp2xxx _switch target' Tcl command to adapt flash bank to architecture changes. Keep the target and priv pointers intact until a flash operation is finished to prevent sudden change in the middle of write/erase. Signed-off-by: Tomas Vanek Change-Id: I764354ab469e253042128958dfe70c09d04d6411 Reviewed-on: https://review.openocd.org/c/openocd/+/8448 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/rp2040.c | 77 +++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index df9284d968..15a04fbb00 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -627,16 +627,13 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2040_flash_bank return err; } -static int setup_for_raw_flash_cmd(struct flash_bank *bank) +static int setup_for_raw_flash_cmd(struct target *target, struct rp2040_flash_bank *priv) { - struct rp2040_flash_bank *priv = bank->driver_priv; - struct target *target = bank->target; - int err = ERROR_OK; if (!priv->stack) { /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */ - err = target_alloc_working_area(bank->target, RP2XXX_MAX_ALGO_STACK_USAGE, &priv->stack); + err = target_alloc_working_area(target, RP2XXX_MAX_ALGO_STACK_USAGE, &priv->stack); if (err != ERROR_OK) { LOG_ERROR("Could not allocate stack for flash programming code -- insufficient space"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -644,7 +641,7 @@ static int setup_for_raw_flash_cmd(struct flash_bank *bank) } if (!priv->ram_algo_space) { - err = target_alloc_working_area(bank->target, RP2XXX_MAX_RAM_ALGO_SIZE, &priv->ram_algo_space); + err = target_alloc_working_area(target, RP2XXX_MAX_RAM_ALGO_SIZE, &priv->ram_algo_space); if (err != ERROR_OK) { LOG_ERROR("Could not allocate RAM code space for ROM calls -- insufficient space"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -692,7 +689,7 @@ static int setup_for_raw_flash_cmd(struct flash_bank *bank) .sp = priv->stack->address + priv->stack->size } }; - err = rp2xxx_call_rom_func_batch(bank->target, priv, calls, 2); + err = rp2xxx_call_rom_func_batch(target, priv, calls, 2); if (err != ERROR_OK) { LOG_ERROR("RP2040 flash: failed to exit flash XIP mode"); return err; @@ -701,15 +698,13 @@ static int setup_for_raw_flash_cmd(struct flash_bank *bank) return ERROR_OK; } -static void cleanup_after_raw_flash_cmd(struct flash_bank *bank) +static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2040_flash_bank *priv) { /* OpenOCD is prone to trashing work-area allocations on target state transitions, which leaves us with stale work area pointers in our driver state. Best to clean up our allocations manually after completing each flash call, so we know to make fresh ones next time. */ LOG_DEBUG("Cleaning up after flash operations"); - struct rp2040_flash_bank *priv = bank->driver_priv; - struct target *target = bank->target; if (priv->stack) { target_free_working_area(target, priv->stack); priv->stack = 0; @@ -728,7 +723,7 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui struct target *target = bank->target; struct working_area *bounce; - int err = setup_for_raw_flash_cmd(bank); + int err = setup_for_raw_flash_cmd(target, priv); if (err != ERROR_OK) goto cleanup_and_return; @@ -780,7 +775,7 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui // accesses, but there's no harm in calling it anyway. LOG_DEBUG("Flushing flash cache after write behind"); - err = rp2xxx_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0); + err = rp2xxx_call_rom_func(target, priv, priv->jump_flush_cache, NULL, 0); rp2xxx_rom_call_batch_record_t finishing_calls[3] = { { @@ -805,18 +800,19 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui goto cleanup_and_return; } cleanup_and_return: - cleanup_after_raw_flash_cmd(bank); + cleanup_after_raw_flash_cmd(target, priv); return err; } static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last) { struct rp2040_flash_bank *priv = bank->driver_priv; + struct target *target = bank->target; uint32_t start_addr = bank->sectors[first].offset; uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr; LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr); - int err = setup_for_raw_flash_cmd(bank); + int err = setup_for_raw_flash_cmd(target, priv); if (err != ERROR_OK) goto cleanup_and_return; @@ -855,7 +851,7 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig 0xd8 /* block_cmd */ }; - err = rp2xxx_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); + err = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args)); keep_alive(); if (err != ERROR_OK) @@ -866,7 +862,7 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig cleanup_and_return: - cleanup_after_raw_flash_cmd(bank); + cleanup_after_raw_flash_cmd(target, priv); return err; } @@ -973,7 +969,8 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) for (unsigned int i = 0; i + 1 < CMD_ARGC && i < ARRAY_SIZE(args); i++) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i + 1], args[i]); - retval = setup_for_raw_flash_cmd(bank); + struct rp2040_flash_bank *priv = bank->driver_priv; + retval = setup_for_raw_flash_cmd(target, priv); if (retval != ERROR_OK) goto cleanup_and_return; @@ -992,16 +989,51 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) * in an event handler, use LOG_INFO instead */ LOG_INFO("RP2xxx ROM API function %.2s @ %04" PRIx16, CMD_ARGV[0], fc); - struct rp2040_flash_bank *priv = bank->driver_priv; retval = rp2xxx_call_rom_func(target, priv, fc, args, ARRAY_SIZE(args)); if (retval != ERROR_OK) command_print(CMD, "RP2xxx ROM API call failed"); cleanup_and_return: - cleanup_after_raw_flash_cmd(bank); + cleanup_after_raw_flash_cmd(target, priv); return retval; } +COMMAND_HANDLER(rp2040_switch_target_handler) +{ + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct target *old_target = get_target(CMD_ARGV[0]); + if (!old_target) { + command_print(CMD, "Unrecognised old target %s", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + struct target *new_target = get_target(CMD_ARGV[1]); + if (!new_target) { + command_print(CMD, "Unrecognised new target %s", CMD_ARGV[1]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + struct flash_bank *bank; + for (bank = flash_bank_list(); bank; bank = bank->next) { + if (bank->driver == &rp2040_flash) { + if (bank->target == old_target) { + bank->target = new_target; + struct rp2040_flash_bank *priv = bank->driver_priv; + priv->probed = false; + return ERROR_OK; + } else if (bank->target == new_target) { + return ERROR_OK; + } + } + } + + command_print(CMD, "Neither old nor new target %s found in flash bank list", + CMD_ARGV[0]); + return ERROR_FAIL; +} + static const struct command_registration rp2040_exec_command_handlers[] = { { .name = "rom_api_call", @@ -1010,6 +1042,13 @@ static const struct command_registration rp2040_exec_command_handlers[] = { .usage = "fc [p0 [p1 [p2 [p3]]]]", .handler = rp2040_rom_api_call_handler, }, + { + .name = "_switch_target", + .mode = COMMAND_EXEC, + .help = "internal use", + .usage = "old_target new_target", + .handler = rp2040_switch_target_handler, + }, COMMAND_REGISTRATION_DONE }; From 69ee4457864af2657ce1b634887b26b838fc916f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 11 Aug 2024 15:03:05 +0200 Subject: [PATCH 1177/1312] tcl/target/rp2350: universal config for any combination of CM/RV cores RP2350 has 2 slots where either Cortex-M33 or RISC-V can be selected. Tcl variable USE_CORE selects what cores will be configured for debug. Signed-off-by: Tomas Vanek Change-Id: I56fe1aa94304bdfd1ec98bba57cc3fa792a35f69 Reviewed-on: https://review.openocd.org/c/openocd/+/8449 Tested-by: jenkins --- tcl/target/rp2350.cfg | 206 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 tcl/target/rp2350.cfg diff --git a/tcl/target/rp2350.cfg b/tcl/target/rp2350.cfg new file mode 100644 index 0000000000..775561f062 --- /dev/null +++ b/tcl/target/rp2350.cfg @@ -0,0 +1,206 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# RP2350 is a microcontroller with dual Cortex-M33 cores or dual Hazard3 RISC-V cores. +# https://www.raspberrypi.com/documentation/microcontrollers/rp2350.html + +transport select swd + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME rp2350 +} + +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x00040927 +} + +# Set to '1' to start rescue mode +if { [info exists RESCUE] } { + set _RESCUE $RESCUE +} else { + set _RESCUE 0 +} + +# Set to 'cm0' or 'cm1' for Cortex-M33 single core configuration +# To keep compatibility with RP2040 aliases '0' and '1' are provided for Cortex-M33 cores +# Use 'rv0' or 'rv1' for RISC-V single core configuration +# List more for a multicore configuration +if { [info exists USE_CORE] } { + set _USE_CORE $USE_CORE +} else { + # defaults to both Cortex-M33 cores + set _USE_CORE { cm0 cm1 } +} + +swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID + +if { [info exists SWD_MULTIDROP] } { + dap create $_CHIPNAME.dap -adiv6 -chain-position $_CHIPNAME.cpu -dp-id 0x0040927 -instance-id 0 +} else { + dap create $_CHIPNAME.dap -adiv6 -chain-position $_CHIPNAME.cpu +} + +# Cortex-M33 core 0 +if { [lsearch $_USE_CORE cm0] >= 0 || [lsearch $_USE_CORE 0] >= 0 } { + set _TARGETNAME_CM0 $_CHIPNAME.cm0 + set _TARGETNAME_0 $_TARGETNAME_CM0 +} + +# RISC-V core 0 +if { [lsearch $_USE_CORE rv0] >= 0 } { + set _TARGETNAME_RV0 $_CHIPNAME.rv0 + if { ![info exists _TARGETNAME_0] } { + set _TARGETNAME_0 $_TARGETNAME_RV0 + } +} + +# Cortex-M33 core 1 +if { [lsearch $_USE_CORE cm1] >= 0 || [lsearch $_USE_CORE 1] >= 0 } { + set _TARGETNAME_CM1 $_CHIPNAME.cm1 + set _TARGETNAME_1 $_TARGETNAME_CM1 +} + +# RISC-V core 1 +if { [lsearch $_USE_CORE rv1] >= 0 } { + set _TARGETNAME_RV1 $_CHIPNAME.rv1 + if { ![info exists _TARGETNAME_1] } { + set _TARGETNAME_1 $_TARGETNAME_RV1 + } +} + + +if { [info exists _TARGETNAME_CM0] } { + target create $_TARGETNAME_CM0 cortex_m -dap $_CHIPNAME.dap -ap-num 0x2000 + # srst does not exist; use SYSRESETREQ to perform a soft reset + $_TARGETNAME_CM0 cortex_m reset_config sysresetreq + + # After a rescue reset the cache requires invalidate to allow SPI flash + # reads from the XIP cached mapping area + $_TARGETNAME_CM0 configure -event reset-init { rp2xxx rom_api_call FC } +} + +if { [info exists _TARGETNAME_RV0] } { + target create $_TARGETNAME_RV0 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 0 + $_TARGETNAME_RV0 riscv set_enable_virt2phys off + + # Workaround for stray IO_QSPI: GPIO_QSPI_SD1_CTRL: INOVER bit in RISC-V BOOTSEL + $_TARGETNAME_RV0 configure -event reset-init { mww 0x4003002c 0 } + + if { [info exists _TARGETNAME_CM0] } { + # just for setting after init when the event become-available is not fired + $_TARGETNAME_RV0 configure -event examine-end "rp2xxx _switch_target $_TARGETNAME_CM0 $_TARGETNAME_RV0" + } +} + +if { [info exists _TARGETNAME_CM1] } { + target create $_TARGETNAME_CM1 cortex_m -dap $_CHIPNAME.dap -ap-num 0x4000 + $_TARGETNAME_CM1 cortex_m reset_config sysresetreq +} + +if { [info exists _TARGETNAME_RV1] } { + target create $_TARGETNAME_RV1 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 1 + $_TARGETNAME_RV1 riscv set_enable_virt2phys off +} + +if { [info exists USE_SMP] } { + set _USE_SMP $USE_SMP +} elseif { [info exists _TARGETNAME_CM0] == [info exists _TARGETNAME_CM1] + && [info exists _TARGETNAME_RV0] == [info exists _TARGETNAME_RV1] } { + set _USE_SMP 1 +} else { + set _USE_SMP 0 +} +if { $_USE_SMP } { + if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_CM1] } { + $_TARGETNAME_CM0 configure -rtos hwthread + $_TARGETNAME_CM1 configure -rtos hwthread + target smp $_TARGETNAME_CM0 $_TARGETNAME_CM1 + } + if { [info exists _TARGETNAME_RV0] && [info exists _TARGETNAME_RV1] } { + $_TARGETNAME_RV0 configure -rtos hwthread + $_TARGETNAME_RV1 configure -rtos hwthread + target smp $_TARGETNAME_RV0 $_TARGETNAME_RV1 + } +} + +if { [info exists _TARGETNAME_0] } { + set _FLASH_TARGET $_TARGETNAME_0 +} +if { ![info exists _FLASH_TARGET] && [info exists _TARGETNAME_1] } { + set _FLASH_TARGET $_TARGETNAME_1 + if { [info exists _TARGETNAME_CM1] && [info exists _TARGETNAME_RV1] } { + echo "Info : $_CHIPNAME.flash will be handled by $_TARGETNAME_1 without switching" + } +} +if { [info exists _FLASH_TARGET] } { + $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE + if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_RV0] } { + $_TARGETNAME_RV0 configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE + echo "Info : $_CHIPNAME.flash will be handled by the active one of $_FLASH_TARGET and $_TARGETNAME_RV0 cores" + } + set _FLASHNAME $_CHIPNAME.flash + set _FLASHSIZE 0x00400000 + flash bank $_FLASHNAME rp2040_flash 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET +} + +if { [info exists _TARGETNAME_1] } { + # Alias to ensure gdb connecting to core 1 gets the correct memory map + flash bank $_CHIPNAME.alias virtual 0x10000000 0 0 0 $_TARGETNAME_1 $_FLASHNAME +} + +if { [info exists _TARGETNAME_0] } { + # Select core 0 + targets $_TARGETNAME_0 +} + +# Cold reset resets everything except DP +proc cold_reset { { __CHIPNAME "" } } { + if { $__CHIPNAME == "" } { + global _CHIPNAME + set __CHIPNAME $_CHIPNAME + } + poll off + # set CDBGRSTREQ (and keep set CSYSPWRUPREQ and CDBGPWRUPREQ) + $__CHIPNAME.dap dpreg 4 0x54000000 + set dpstat [$__CHIPNAME.dap dpreg 4] + if { [expr { $dpstat & 0xcc000000 }] != 0xcc000000 } { + echo "Warn : dpstat_reset failed, DP STAT $dpstat" + } + $__CHIPNAME.dap dpreg 4 0x50000000 + dap init + poll on +} + +# Rescue reset resets everything except DP and RP_AP +# Both Cortex-M33 cores stop in bootrom +proc rescue_reset { { __CHIPNAME "" } } { + if { $__CHIPNAME == "" } { + global _CHIPNAME + set __CHIPNAME $_CHIPNAME + } + poll off + # set bit RESCUE_RESTART in RP_AP: CTRL register + $__CHIPNAME.dap apreg 0x80000 0 0x80000000 + $__CHIPNAME.dap apreg 0x80000 0 0 + dap init + poll on + if { [lsearch [target names] $__CHIPNAME.cm0] < 0 } { + echo "Info : restart OpenOCD with 'set USE_CORE { cm0 cm1 }' to debug after rescue" + } +} + +if { $_RESCUE } { + init + rescue_reset +} From 22dfd0efaddaa70baf9e65aff661554c4497909a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 13 Aug 2024 16:23:20 +0200 Subject: [PATCH 1178/1312] tcl/target/rp2350: workarounds for ROM API issues A0 chip: remove pad isolation A2 chip: instead of reset init fixes we will fix the flash driver with the following patch by Luke Wren: 8729: flash/nor/rp2xxx: fix flash operation after halt in RISC-V bootsel https://review.openocd.org/c/openocd/+/8729 I don't have A1 version to test. Signed-off-by: Tomas Vanek Change-Id: I9e9fab04ead929fe6e0a17c6c2f32a6f02e9beb9 Reviewed-on: https://review.openocd.org/c/openocd/+/8450 Tested-by: jenkins --- tcl/target/rp2350.cfg | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tcl/target/rp2350.cfg b/tcl/target/rp2350.cfg index 775561f062..d2465bd2fe 100644 --- a/tcl/target/rp2350.cfg +++ b/tcl/target/rp2350.cfg @@ -94,8 +94,7 @@ if { [info exists _TARGETNAME_RV0] } { target create $_TARGETNAME_RV0 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 0 $_TARGETNAME_RV0 riscv set_enable_virt2phys off - # Workaround for stray IO_QSPI: GPIO_QSPI_SD1_CTRL: INOVER bit in RISC-V BOOTSEL - $_TARGETNAME_RV0 configure -event reset-init { mww 0x4003002c 0 } + $_TARGETNAME_RV0 configure -event reset-init "_rv_reset_init" if { [info exists _TARGETNAME_CM0] } { # just for setting after init when the event become-available is not fired @@ -204,3 +203,22 @@ if { $_RESCUE } { init rescue_reset } + +proc _rv_reset_init { } { + set chip_id [format 0x%08x [read_memory 0x40000000 32 1]] + + # Version related workarounds + switch $chip_id { + 0x00004927 { # A0 + # remove IO_QSPI isolation + mww 0x40030014 0 + mww 0x4003001c 0 + mww 0x40030024 0 + mww 0x4003002c 0 + mww 0x40030034 0 + mww 0x4003003c 0 + } + } + + rp2xxx rom_api_call FC +} From 2e1a76368eed7aac8054e6ccb7c8104bad421a70 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 09:10:31 +0200 Subject: [PATCH 1179/1312] flash/nor/rp2040: detect flash size including SFDP Also keep size override by FLASHSIZE Tcl variable possible. Partially backported from former upstream rp2040.c Signed-off-by: Tomas Vanek Change-Id: I224c3644450e8b46e35714bfc5436219ffdee563 Reviewed-on: https://review.openocd.org/c/openocd/+/8451 Tested-by: jenkins --- src/flash/nor/rp2040.c | 301 +++++++++++++++++++++++++++++++++++++++-- tcl/target/rp2350.cfg | 16 ++- 2 files changed, 299 insertions(+), 18 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 15a04fbb00..0e592f9124 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -9,6 +9,7 @@ #include #include #include "spi.h" +#include "sfdp.h" #include /* this is 'M' 'u', 1 (version) */ @@ -43,6 +44,32 @@ #define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u #define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u +#define RP2040_SSI_DR0 0x18000060 +#define RP2040_QSPI_CTRL 0x4001800c + +#define RP2040_QSPI_CTRL_OUTOVER_MASK (3ul << 8) +#define RP2040_QSPI_CTRL_OUTOVER_LOW (2ul << 8) +#define RP2040_QSPI_CTRL_OUTOVER_HIGH (3ul << 8) + +#define RP2350_QMI_DIRECT_CSR 0x400d0000 +#define RP2350_QMI_DIRECT_TX 0x400d0004 +#define RP2350_QMI_DIRECT_RX 0x400d0008 + +#define RP2350_QMI_DIRECT_CSR_EN BIT(0) +#define RP2350_QMI_DIRECT_CSR_ASSERT_CS0N BIT(2) +#define RP2350_QMI_DIRECT_TX_NOPUSH BIT(20) +#define RP2350_QMI_DIRECT_TX_OE BIT(19) + +#define RP2XXX_SYSINFO_CHIP_ID 0x40000000 +#define RP2XXX_CHIP_ID_PART_MANUFACTURER(id) ((id) & 0x0fffffff) +#define RP2XXX_CHIP_ID_MANUFACTURER 0x493 +#define RP2XXX_MK_PART(part) (((part) << 12) | (RP2XXX_CHIP_ID_MANUFACTURER << 1) | 1) +#define RP2040_CHIP_ID_PART 0x0002 +#define IS_RP2040(id) (RP2XXX_CHIP_ID_PART_MANUFACTURER(id) == RP2XXX_MK_PART(RP2040_CHIP_ID_PART)) +#define RP2350_CHIP_ID_PART 0x0004 +#define IS_RP2350(id) (RP2XXX_CHIP_ID_PART_MANUFACTURER(id) == RP2XXX_MK_PART(RP2350_CHIP_ID_PART)) +#define RP2XXX_CHIP_ID_REVISION(id) ((id) >> 28) + #define RP2XXX_MAX_ALGO_STACK_USAGE 1024 #define RP2XXX_MAX_RAM_ALGO_SIZE 1024 @@ -156,10 +183,9 @@ typedef struct rp2xxx_rom_call_batch_record { } rp2xxx_rom_call_batch_record_t; struct rp2040_flash_bank { - /* flag indicating successful flash probe */ - bool probed; - /* stack used by Boot ROM calls */ - struct working_area *stack; + bool probed; /* flag indicating successful flash probe */ + uint32_t id; /* cached SYSINFO CHIP_ID */ + struct working_area *stack; /* stack used by Boot ROM calls */ /* static code scratchpad used for RAM algorithms -- allocated in advance so that higher-level calls can just grab all remaining workarea: */ struct working_area *ram_algo_space; @@ -172,6 +198,11 @@ struct rp2040_flash_bank { uint16_t jump_flash_reset_address_trans; uint16_t jump_enter_cmd_xip; uint16_t jump_bootrom_reset_state; + + char dev_name[20]; + bool size_override; + struct flash_device spi_dev; /* detected model of SPI flash */ + unsigned int sfdp_dummy, sfdp_dummy_detect; }; #ifndef LOG_ROM_SYMBOL_DEBUG @@ -869,37 +900,276 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig /* ----------------------------------------------------------------------------- Driver probing etc */ + +static int rp2040_ssel_active(struct target *target, bool active) +{ + uint32_t state = active ? RP2040_QSPI_CTRL_OUTOVER_LOW : RP2040_QSPI_CTRL_OUTOVER_HIGH; + uint32_t val; + + int err = target_read_u32(target, RP2040_QSPI_CTRL, &val); + if (err != ERROR_OK) + return err; + + val = (val & ~RP2040_QSPI_CTRL_OUTOVER_MASK) | state; + + err = target_write_u32(target, RP2040_QSPI_CTRL, val); + if (err != ERROR_OK) + return err; + + return ERROR_OK; +} + +static int rp2040_spi_tx_rx(struct target *target, + const uint8_t *tx, unsigned int tx_len, + unsigned int dummy_len, + uint8_t *rx, unsigned int rx_len) +{ + int retval, retval2; + + retval = rp2040_ssel_active(target, true); + if (retval != ERROR_OK) { + LOG_ERROR("QSPI select failed"); + goto deselect; + } + + unsigned int tx_cnt = 0; + unsigned int rx_cnt = 0; + unsigned int xfer_len = tx_len + dummy_len + rx_len; + while (rx_cnt < xfer_len) { + int in_flight = tx_cnt - rx_cnt; + if (tx_cnt < xfer_len && in_flight < 14) { + uint32_t dr = tx_cnt < tx_len ? tx[tx_cnt] : 0; + retval = target_write_u32(target, RP2040_SSI_DR0, dr); + if (retval != ERROR_OK) + break; + + tx_cnt++; + continue; + } + uint32_t dr; + retval = target_read_u32(target, RP2040_SSI_DR0, &dr); + if (retval != ERROR_OK) + break; + + if (rx_cnt >= tx_len + dummy_len) + rx[rx_cnt - tx_len - dummy_len] = (uint8_t)dr; + + rx_cnt++; + } + +deselect: + retval2 = rp2040_ssel_active(target, false); + + if (retval != ERROR_OK) { + LOG_ERROR("QSPI Tx/Rx failed"); + return retval; + } + if (retval2 != ERROR_OK) + LOG_ERROR("QSPI deselect failed"); + + return retval2; +} + +static int rp2350_spi_tx_rx(struct target *target, + const uint8_t *tx, unsigned int tx_len, + unsigned int dummy_len, + uint8_t *rx, unsigned int rx_len) +{ + uint32_t direct_csr; + int retval = target_read_u32(target, RP2350_QMI_DIRECT_CSR, &direct_csr); + if (retval != ERROR_OK) { + LOG_ERROR("QMI DIRECT_CSR read failed"); + return retval; + } + direct_csr |= RP2350_QMI_DIRECT_CSR_EN | RP2350_QMI_DIRECT_CSR_ASSERT_CS0N; + retval = target_write_u32(target, RP2350_QMI_DIRECT_CSR, direct_csr); + if (retval != ERROR_OK) { + LOG_ERROR("QMI DIRECT mode enable failed"); + goto deselect; + } + + unsigned int tx_cnt = 0; + unsigned int rx_cnt = 0; + unsigned int xfer_len = tx_len + dummy_len + rx_len; + while (tx_cnt < xfer_len || rx_cnt < rx_len) { + int in_flight = tx_cnt - tx_len - dummy_len - rx_cnt; + if (tx_cnt < xfer_len && in_flight < 4) { + uint32_t tx_cmd; + if (tx_cnt < tx_len) + tx_cmd = tx[tx_cnt] | RP2350_QMI_DIRECT_TX_NOPUSH | RP2350_QMI_DIRECT_TX_OE; + else if (tx_cnt < tx_len + dummy_len) + tx_cmd = RP2350_QMI_DIRECT_TX_NOPUSH; + else + tx_cmd = 0; + + retval = target_write_u32(target, RP2350_QMI_DIRECT_TX, tx_cmd); + if (retval != ERROR_OK) + break; + + tx_cnt++; + continue; + } + if (rx_cnt < rx_len) { + uint32_t dr; + retval = target_read_u32(target, RP2350_QMI_DIRECT_RX, &dr); + if (retval != ERROR_OK) + break; + + rx[rx_cnt] = (uint8_t)dr; + rx_cnt++; + } + } + +deselect: + direct_csr &= ~(RP2350_QMI_DIRECT_CSR_EN | RP2350_QMI_DIRECT_CSR_ASSERT_CS0N); + int retval2 = target_write_u32(target, RP2350_QMI_DIRECT_CSR, direct_csr); + + if (retval != ERROR_OK) { + LOG_ERROR("QSPI Tx/Rx failed"); + return retval; + } + if (retval2 != ERROR_OK) + LOG_ERROR("QMI DIRECT mode disable failed"); + + return retval2; +} + +static int rp2xxx_spi_tx_rx(struct flash_bank *bank, + const uint8_t *tx, unsigned int tx_len, + unsigned int dummy_len, + uint8_t *rx, unsigned int rx_len) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + struct target *target = bank->target; + + if (IS_RP2040(priv->id)) + return rp2040_spi_tx_rx(target, tx, tx_len, dummy_len, rx, rx_len); + else if (IS_RP2350(priv->id)) + return rp2350_spi_tx_rx(target, tx, tx_len, dummy_len, rx, rx_len); + else + return ERROR_FAIL; +} + +static int rp2xxx_read_sfdp_block(struct flash_bank *bank, uint32_t addr, + unsigned int words, uint32_t *buffer) +{ + struct rp2040_flash_bank *priv = bank->driver_priv; + + uint8_t cmd[4] = { SPIFLASH_READ_SFDP }; + uint8_t data[4 * words + priv->sfdp_dummy_detect]; + + h_u24_to_be(&cmd[1], addr); + + int retval = rp2xxx_spi_tx_rx(bank, cmd, sizeof(cmd), priv->sfdp_dummy, + data, 4 * words + priv->sfdp_dummy_detect); + if (retval != ERROR_OK) + return retval; + + if (priv->sfdp_dummy_detect) { + for (unsigned int i = 0; i < priv->sfdp_dummy_detect; i++) + if (le_to_h_u32(&data[i]) == SFDP_MAGIC) { + priv->sfdp_dummy_detect = 0; + priv->sfdp_dummy = i; + break; + } + for (unsigned int i = 0; i < words; i++) + buffer[i] = le_to_h_u32(&data[4 * i + priv->sfdp_dummy]); + } else { + for (unsigned int i = 0; i < words; i++) + buffer[i] = le_to_h_u32(&data[4 * i]); + } + return retval; +} + static int rp2040_flash_probe(struct flash_bank *bank) { struct rp2040_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; - int err = rp2xxx_populate_rom_pointer_cache(target, priv); - if (err != ERROR_OK) - return err; + int retval = target_read_u32(target, RP2XXX_SYSINFO_CHIP_ID, &priv->id); + if (retval != ERROR_OK) { + LOG_ERROR("SYSINFO CHIP_ID read failed"); + return retval; + } + if (!IS_RP2040(priv->id) && !IS_RP2350(priv->id)) { + LOG_ERROR("Unknown SYSINFO CHIP_ID 0x%08" PRIx32, priv->id); + return ERROR_FLASH_BANK_INVALID; + } + + retval = rp2xxx_populate_rom_pointer_cache(target, priv); + if (retval != ERROR_OK) + return retval; /* the Boot ROM flash_range_program() routine requires page alignment */ bank->write_start_alignment = 256; bank->write_end_alignment = 256; - // Max size -- up to two devices (two chip selects) in adjacent 24-bit address windows + uint32_t flash_id = 0; + if (priv->size_override) { + priv->spi_dev.name = "size override"; + LOG_DEBUG("SPI flash autodetection disabled, using configured size"); + } else { + bank->size = 0; + + (void)setup_for_raw_flash_cmd(target, priv); + /* ignore error, flash size detection could work anyway */ + + const uint8_t cmd[] = { SPIFLASH_READ_ID }; + uint8_t data[3]; + retval = rp2xxx_spi_tx_rx(bank, cmd, sizeof(cmd), 0, data, sizeof(data)); + if (retval == ERROR_OK) { + flash_id = le_to_h_u24(data); + + /* search for a SPI flash Device ID match */ + for (const struct flash_device *p = flash_devices; p->name ; p++) { + if (p->device_id == flash_id) { + priv->spi_dev = *p; + bank->size = p->size_in_bytes; + break; + } + } + } + + if (bank->size == 0) { + priv->sfdp_dummy_detect = 8; + priv->sfdp_dummy = 0; + retval = spi_sfdp(bank, &priv->spi_dev, &rp2xxx_read_sfdp_block); + if (retval == ERROR_OK) + bank->size = priv->spi_dev.size_in_bytes; + } + + cleanup_after_raw_flash_cmd(target, priv); + } + + snprintf(priv->dev_name, sizeof(priv->dev_name), "%s rev %u", + IS_RP2350(priv->id) ? "RP2350" : "RP2040", + RP2XXX_CHIP_ID_REVISION(priv->id)); + if (bank->size == 0) { - /* TODO: get real flash size */ - bank->size = 32 * 1024 * 1024; + LOG_ERROR("%s, QSPI Flash id = 0x%06" PRIx32 " not recognised", + priv->dev_name, flash_id); + return ERROR_FLASH_BANK_INVALID; } bank->num_sectors = bank->size / 4096; - LOG_INFO("RP2040 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n", - bank->size, bank->base, bank->num_sectors); + if (priv->size_override) { + LOG_INFO("%s, QSPI Flash size override = %u KiB in %u sectors", + priv->dev_name, bank->size / 1024, bank->num_sectors); + } else { + LOG_INFO("%s, QSPI Flash %s id = 0x%06" PRIx32 " size = %u KiB in %u sectors", + priv->dev_name, priv->spi_dev.name, flash_id, + bank->size / 1024, bank->num_sectors); + } + + free(bank->sectors); bank->sectors = alloc_block_array(0, 4096, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; - if (err == ERROR_OK) - priv->probed = true; + priv->probed = true; - return err; + return ERROR_OK; } static int rp2040_flash_auto_probe(struct flash_bank *bank) @@ -927,6 +1197,7 @@ FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) priv = malloc(sizeof(struct rp2040_flash_bank)); memset(priv, 0, sizeof(struct rp2040_flash_bank)); priv->probed = false; + priv->size_override = bank->size != 0; /* Set up driver_priv */ bank->driver_priv = priv; diff --git a/tcl/target/rp2350.cfg b/tcl/target/rp2350.cfg index d2465bd2fe..dc26cde190 100644 --- a/tcl/target/rp2350.cfg +++ b/tcl/target/rp2350.cfg @@ -19,6 +19,14 @@ if { [info exists WORKAREASIZE] } { set _WORKAREASIZE 0x10000 } +# Nonzero FLASHSIZE supresses QSPI flash size detection +if { [info exists FLASHSIZE] } { + set _FLASHSIZE $FLASHSIZE +} else { + # Detect QSPI flash size based on flash ID or SFDP + set _FLASHSIZE 0 +} + if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { @@ -143,13 +151,15 @@ if { ![info exists _FLASH_TARGET] && [info exists _TARGETNAME_1] } { } } if { [info exists _FLASH_TARGET] } { - $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE + # QSPI flash size detection during gdb connect requires to back-up RAM + set _WKA_BACKUP [expr { $_FLASHSIZE == 0 }] + $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup $_WKA_BACKUP if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_RV0] } { - $_TARGETNAME_RV0 configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE + $_TARGETNAME_RV0 configure -work-area-phys 0x20010000 \ + -work-area-size $_WORKAREASIZE -work-area-backup $_WKA_BACKUP echo "Info : $_CHIPNAME.flash will be handled by the active one of $_FLASH_TARGET and $_TARGETNAME_RV0 cores" } set _FLASHNAME $_CHIPNAME.flash - set _FLASHSIZE 0x00400000 flash bank $_FLASHNAME rp2040_flash 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET } From 20d1d4405d73fe47efc07cb109454c088a8ecbc8 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 09:39:42 +0200 Subject: [PATCH 1180/1312] flash/nor/rp2040: add missing TARGET_HALTED checks Flash erase and write require this guard, unfortunately it is also partially needed in the flash probe. Partially backported from former upstream rp2040.c Signed-off-by: Tomas Vanek Change-Id: Ie8a240e66c3ed68e08f872cbbfdd90a6d80e1f1e Reviewed-on: https://review.openocd.org/c/openocd/+/8452 Tested-by: jenkins --- src/flash/nor/rp2040.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 0e592f9124..65c1e095b1 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -752,6 +752,12 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui struct rp2040_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + struct working_area *bounce; int err = setup_for_raw_flash_cmd(target, priv); @@ -839,6 +845,12 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig { struct rp2040_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + uint32_t start_addr = bank->sectors[first].offset; uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr; LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr); @@ -1109,6 +1121,11 @@ static int rp2040_flash_probe(struct flash_bank *bank) priv->spi_dev.name = "size override"; LOG_DEBUG("SPI flash autodetection disabled, using configured size"); } else { + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + bank->size = 0; (void)setup_for_raw_flash_cmd(target, priv); @@ -1240,6 +1257,11 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) for (unsigned int i = 0; i + 1 < CMD_ARGC && i < ARRAY_SIZE(args); i++) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i + 1], args[i]); + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + struct rp2040_flash_bank *priv = bank->driver_priv; retval = setup_for_raw_flash_cmd(target, priv); if (retval != ERROR_OK) From 26729aa8b089230bf0896c32df9a4b7ae3ef6fee Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 10:41:55 +0200 Subject: [PATCH 1181/1312] flash/nor/rp2040: improve flash write buffer size computation While on it: Define the names for the fixed flash page/sector sizes and use them instead of magic values. Fix memory leak on error return. Partially backported from former upstream rp2040.c Signed-off-by: Tomas Vanek Change-Id: If51c912f4d381ee47756a70f616ecdbee1ac0da7 Reviewed-on: https://review.openocd.org/c/openocd/+/8453 Tested-by: jenkins --- src/flash/nor/rp2040.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index 65c1e095b1..c28bc85096 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -73,6 +73,9 @@ #define RP2XXX_MAX_ALGO_STACK_USAGE 1024 #define RP2XXX_MAX_RAM_ALGO_SIZE 1024 +#define RP2XXX_ROM_API_FIXED_FLASH_PAGE 256 +#define RP2XXX_ROM_API_FIXED_FLASH_SECTOR 4096 + // Calling bootrom functions on Arm RP2350 requires the redundancy // coprocessor (RCP) to be initialised. Usually this is done first thing by // the bootrom, but the debugger may skip this, e.g. by resetting the cores @@ -758,17 +761,19 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui return ERROR_TARGET_NOT_HALTED; } - struct working_area *bounce; + struct working_area *bounce = NULL; int err = setup_for_raw_flash_cmd(target, priv); if (err != ERROR_OK) goto cleanup_and_return; - // Allocate as much memory as possible, rounded down to a whole number of flash pages - const unsigned int chunk_size = target_get_working_area_avail(target) & ~0xffu; - if (chunk_size == 0 || target_alloc_working_area(target, chunk_size, &bounce) != ERROR_OK) { + unsigned int avail_pages = target_get_working_area_avail(target) / RP2XXX_ROM_API_FIXED_FLASH_PAGE; + /* We try to allocate working area rounded down to device page size, + * al least 1 page, at most the write data size */ + unsigned int chunk_size = MIN(MAX(avail_pages, 1) * RP2XXX_ROM_API_FIXED_FLASH_PAGE, count); + err = target_alloc_working_area(target, chunk_size, &bounce); + if (err != ERROR_OK) { LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue"); - err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; goto cleanup_and_return; } @@ -787,7 +792,8 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui bounce->address, /* data */ write_size /* count */ }; - err = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args)); + err = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_program, + args, ARRAY_SIZE(args)); keep_alive(); if (err != ERROR_OK) { LOG_ERROR("Failed to invoke flash programming code on target"); @@ -798,7 +804,6 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui offset += write_size; count -= write_size; } - target_free_working_area(target, bounce); if (err != ERROR_OK) goto cleanup_and_return; @@ -837,6 +842,8 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui goto cleanup_and_return; } cleanup_and_return: + target_free_working_area(target, bounce); + cleanup_after_raw_flash_cmd(target, priv); return err; } @@ -1113,8 +1120,8 @@ static int rp2040_flash_probe(struct flash_bank *bank) return retval; /* the Boot ROM flash_range_program() routine requires page alignment */ - bank->write_start_alignment = 256; - bank->write_end_alignment = 256; + bank->write_start_alignment = RP2XXX_ROM_API_FIXED_FLASH_PAGE; + bank->write_end_alignment = RP2XXX_ROM_API_FIXED_FLASH_PAGE; uint32_t flash_id = 0; if (priv->size_override) { @@ -1168,7 +1175,7 @@ static int rp2040_flash_probe(struct flash_bank *bank) return ERROR_FLASH_BANK_INVALID; } - bank->num_sectors = bank->size / 4096; + bank->num_sectors = bank->size / RP2XXX_ROM_API_FIXED_FLASH_SECTOR; if (priv->size_override) { LOG_INFO("%s, QSPI Flash size override = %u KiB in %u sectors", @@ -1180,7 +1187,7 @@ static int rp2040_flash_probe(struct flash_bank *bank) } free(bank->sectors); - bank->sectors = alloc_block_array(0, 4096, bank->num_sectors); + bank->sectors = alloc_block_array(0, RP2XXX_ROM_API_FIXED_FLASH_SECTOR, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; From c914cfceab54245fae1aefd70e20d0ed549f9308 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 10:47:36 +0200 Subject: [PATCH 1182/1312] flash/nor/rp2040: refactor finalizing calls and use them after erase Invalidate cache and restore flash XIP mode after erase and also in error cleanup after write/erase. Signed-off-by: Tomas Vanek Change-Id: If7e0c2d75f50f923e6bcbf0aa7bab53fe91b6cc8 Reviewed-on: https://review.openocd.org/c/openocd/+/8454 Tested-by: jenkins --- src/flash/nor/rp2040.c | 78 +++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c index c28bc85096..514cea8b69 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2040.c @@ -732,6 +732,42 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2040_flash_ba return ERROR_OK; } +static int rp2xxx_invalidate_cache_restore_xip(struct target *target, struct rp2040_flash_bank *priv) +{ + // Flash content has changed. We can now do a bit of poking to make + // the new flash contents visible to us via memory-mapped (XIP) interface + // in the 0x1... memory region. + + LOG_DEBUG("Flushing flash cache after write behind"); + + rp2xxx_rom_call_batch_record_t finishing_calls[2] = { + { + .pc = priv->jump_flush_cache, + .sp = priv->stack->address + priv->stack->size + }, + { + .sp = priv->stack->address + priv->stack->size + }, + }; + + int num_finishing_calls = 1; + // Note on RP2350 it's not *required* to call flash_enter_cmd_xip, since + // the ROM leaves flash XIPable by default in between direct-mode + // accesses + if (IS_RP2040(priv->id)) { + finishing_calls[num_finishing_calls++].pc = priv->jump_enter_cmd_xip; + } else if (priv->jump_flash_reset_address_trans) { + // Note flash_reset_address_trans function does not exist on older devices + finishing_calls[num_finishing_calls++].pc = priv->jump_flash_reset_address_trans; + } + + int retval = rp2xxx_call_rom_func_batch(target, priv, finishing_calls, num_finishing_calls); + if (retval != ERROR_OK) + LOG_ERROR("RP2040 write: failed to flush flash cache/restore XIP"); + + return retval; +} + static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2040_flash_bank *priv) { /* OpenOCD is prone to trashing work-area allocations on target state @@ -805,45 +841,12 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui count -= write_size; } - if (err != ERROR_OK) - goto cleanup_and_return; - - // Flash is successfully programmed. We can now do a bit of poking to make - // the new flash contents visible to us via memory-mapped (XIP) interface - // in the 0x1... memory region. - // - // Note on RP2350 it's not *required* to call flash_enter_cmd_xip, since - // the ROM leaves flash XIPable by default in between direct-mode - // accesses, but there's no harm in calling it anyway. - - LOG_DEBUG("Flushing flash cache after write behind"); - err = rp2xxx_call_rom_func(target, priv, priv->jump_flush_cache, NULL, 0); - - rp2xxx_rom_call_batch_record_t finishing_calls[3] = { - { - .pc = priv->jump_flush_cache, - .sp = priv->stack->address + priv->stack->size - }, - { - .pc = priv->jump_enter_cmd_xip, - .sp = priv->stack->address + priv->stack->size - }, - { - .pc = priv->jump_flash_reset_address_trans, - .sp = priv->stack->address + priv->stack->size - } - }; - // Note the last function does not exist on older devices: - int num_finishing_calls = priv->jump_flash_reset_address_trans ? 3 : 2; - - err = rp2xxx_call_rom_func_batch(target, priv, finishing_calls, num_finishing_calls); - if (err != ERROR_OK) { - LOG_ERROR("RP2040 write: failed to flush flash cache"); - goto cleanup_and_return; - } cleanup_and_return: target_free_working_area(target, bounce); + /* Don't propagate error or user gets fooled the flash write failed */ + (void)rp2xxx_invalidate_cache_restore_xip(target, priv); + cleanup_after_raw_flash_cmd(target, priv); return err; } @@ -912,6 +915,9 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig cleanup_and_return: + /* Don't propagate error or user gets fooled the flash erase failed */ + (void)rp2xxx_invalidate_cache_restore_xip(target, priv); + cleanup_after_raw_flash_cmd(target, priv); return err; } From 63f94bbab864d78e19ff86eda0836a5ff35b4a1b Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 11:29:21 +0200 Subject: [PATCH 1183/1312] flash/nor/rp2040: refactoring: change rp2040 to rp2xxx While on it use calloc() instead of malloc()/memset() Drop useless implementation of rp2040_flash_free_driver_priv() - exactly same as default_flash_free_driver_priv() Code style fixes forced by checkpatch Signed-off-by: Tomas Vanek Change-Id: I5c56c4a7d586c0dcab164a45e8f6200ea9a3bd1d Reviewed-on: https://review.openocd.org/c/openocd/+/8455 Tested-by: jenkins --- src/flash/nor/Makefile.am | 2 +- src/flash/nor/driver.h | 2 +- src/flash/nor/drivers.c | 2 +- src/flash/nor/{rp2040.c => rp2xxx.c} | 102 ++++++++++++--------------- tcl/target/rp2040.cfg | 2 +- tcl/target/rp2350.cfg | 2 +- 6 files changed, 52 insertions(+), 60 deletions(-) rename src/flash/nor/{rp2040.c => rp2xxx.c} (94%) diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 147807fbaa..7a81b282b6 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -59,7 +59,7 @@ NOR_DRIVERS = \ %D%/psoc6.c \ %D%/qn908x.c \ %D%/renesas_rpchf.c \ - %D%/rp2040.c \ + %D%/rp2xxx.c \ %D%/rsl10.c \ %D%/sfdp.c \ %D%/sh_qspi.c \ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 794566f121..3b57ef9ff0 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -289,7 +289,7 @@ extern const struct flash_driver psoc5lp_nvl_flash; extern const struct flash_driver psoc6_flash; extern const struct flash_driver qn908x_flash; extern const struct flash_driver renesas_rpchf_flash; -extern const struct flash_driver rp2040_flash; +extern const struct flash_driver rp2xxx_flash; extern const struct flash_driver rsl10_flash; extern const struct flash_driver sh_qspi_flash; extern const struct flash_driver sim3x_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 67d86243b7..3770bfbd3c 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -66,7 +66,7 @@ static const struct flash_driver * const flash_drivers[] = { &psoc6_flash, &qn908x_flash, &renesas_rpchf_flash, - &rp2040_flash, + &rp2xxx_flash, &sh_qspi_flash, &sim3x_flash, &stellaris_flash, diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2xxx.c similarity index 94% rename from src/flash/nor/rp2040.c rename to src/flash/nor/rp2xxx.c index 514cea8b69..e58fc8a29b 100644 --- a/src/flash/nor/rp2040.c +++ b/src/flash/nor/rp2xxx.c @@ -185,14 +185,14 @@ typedef struct rp2xxx_rom_call_batch_record { uint32_t args[4]; } rp2xxx_rom_call_batch_record_t; -struct rp2040_flash_bank { +struct rp2xxx_flash_bank { bool probed; /* flag indicating successful flash probe */ uint32_t id; /* cached SYSINFO CHIP_ID */ struct working_area *stack; /* stack used by Boot ROM calls */ /* static code scratchpad used for RAM algorithms -- allocated in advance so that higher-level calls can just grab all remaining workarea: */ struct working_area *ram_algo_space; - /* function jump table populated by rp2040_flash_probe() */ + /* function jump table populated by rp2xxx_flash_probe() */ uint16_t jump_flash_exit_xip; uint16_t jump_connect_internal_flash; uint16_t jump_flash_range_erase; @@ -381,7 +381,7 @@ static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ return ERROR_FAIL; } -static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2040_flash_bank *priv) +static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xxx_flash_bank *priv) { const uint16_t symtype_func = is_arm(target_to_arm(target)) ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV; @@ -444,7 +444,7 @@ static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp204 // Call a list of PC + SP + r0-r3 function call tuples with a single OpenOCD // algorithm invocation, to amortise the algorithm overhead over multiple calls: -static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2040_flash_bank *priv, +static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash_bank *priv, rp2xxx_rom_call_batch_record_t *calls, unsigned int n_calls) { // Note +1 is for the null terminator @@ -556,7 +556,7 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2040_flash } // Call a single ROM function, using the default algorithm stack. -static int rp2xxx_call_rom_func(struct target *target, struct rp2040_flash_bank *priv, +static int rp2xxx_call_rom_func(struct target *target, struct rp2xxx_flash_bank *priv, uint16_t func_offset, uint32_t argdata[], unsigned int n_args) { assert(n_args <= 4); /* only allow register arguments -- capped at just 4 on Arm */ @@ -602,7 +602,7 @@ static int rp2350_init_accessctrl(struct target *target) return ERROR_OK; } -static int rp2350_init_arm_core0(struct target *target, struct rp2040_flash_bank *priv) +static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank *priv) { // Flash algorithms (and the RCP init stub called by this function) must // run in the Secure state, so flip the state now before attempting to @@ -661,7 +661,7 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2040_flash_bank return err; } -static int setup_for_raw_flash_cmd(struct target *target, struct rp2040_flash_bank *priv) +static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_bank *priv) { int err = ERROR_OK; @@ -725,14 +725,14 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2040_flash_ba }; err = rp2xxx_call_rom_func_batch(target, priv, calls, 2); if (err != ERROR_OK) { - LOG_ERROR("RP2040 flash: failed to exit flash XIP mode"); + LOG_ERROR("RP2xxx flash: failed to exit flash XIP mode"); return err; } return ERROR_OK; } -static int rp2xxx_invalidate_cache_restore_xip(struct target *target, struct rp2040_flash_bank *priv) +static int rp2xxx_invalidate_cache_restore_xip(struct target *target, struct rp2xxx_flash_bank *priv) { // Flash content has changed. We can now do a bit of poking to make // the new flash contents visible to us via memory-mapped (XIP) interface @@ -763,12 +763,12 @@ static int rp2xxx_invalidate_cache_restore_xip(struct target *target, struct rp2 int retval = rp2xxx_call_rom_func_batch(target, priv, finishing_calls, num_finishing_calls); if (retval != ERROR_OK) - LOG_ERROR("RP2040 write: failed to flush flash cache/restore XIP"); + LOG_ERROR("RP2xxx: failed to flush flash cache/restore XIP"); return retval; } -static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2040_flash_bank *priv) +static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2xxx_flash_bank *priv) { /* OpenOCD is prone to trashing work-area allocations on target state transitions, which leaves us with stale work area pointers in our @@ -785,11 +785,11 @@ static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2040_fla } } -static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) +static int rp2xxx_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset); - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; if (target->state != TARGET_HALTED) { @@ -851,9 +851,9 @@ static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui return err; } -static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +static int rp2xxx_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last) { - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; if (target->state != TARGET_HALTED) { @@ -863,7 +863,7 @@ static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsig uint32_t start_addr = bank->sectors[first].offset; uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr; - LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr); + LOG_DEBUG("erase %d bytes starting at 0x%" PRIx32, length, start_addr); int err = setup_for_raw_flash_cmd(target, priv); if (err != ERROR_OK) @@ -1064,7 +1064,7 @@ static int rp2xxx_spi_tx_rx(struct flash_bank *bank, unsigned int dummy_len, uint8_t *rx, unsigned int rx_len) { - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; if (IS_RP2040(priv->id)) @@ -1078,7 +1078,7 @@ static int rp2xxx_spi_tx_rx(struct flash_bank *bank, static int rp2xxx_read_sfdp_block(struct flash_bank *bank, uint32_t addr, unsigned int words, uint32_t *buffer) { - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; uint8_t cmd[4] = { SPIFLASH_READ_SFDP }; uint8_t data[4 * words + priv->sfdp_dummy_detect]; @@ -1106,9 +1106,9 @@ static int rp2xxx_read_sfdp_block(struct flash_bank *bank, uint32_t addr, return retval; } -static int rp2040_flash_probe(struct flash_bank *bank) +static int rp2xxx_flash_probe(struct flash_bank *bank) { - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; int retval = target_read_u32(target, RP2XXX_SYSINFO_CHIP_ID, &priv->id); @@ -1202,31 +1202,23 @@ static int rp2040_flash_probe(struct flash_bank *bank) return ERROR_OK; } -static int rp2040_flash_auto_probe(struct flash_bank *bank) +static int rp2xxx_flash_auto_probe(struct flash_bank *bank) { - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; if (priv->probed) return ERROR_OK; - return rp2040_flash_probe(bank); -} - -static void rp2040_flash_free_driver_priv(struct flash_bank *bank) -{ - free(bank->driver_priv); - bank->driver_priv = NULL; + return rp2xxx_flash_probe(bank); } /* ----------------------------------------------------------------------------- Driver boilerplate */ -FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) +FLASH_BANK_COMMAND_HANDLER(rp2xxx_flash_bank_command) { - struct rp2040_flash_bank *priv; - priv = malloc(sizeof(struct rp2040_flash_bank)); - memset(priv, 0, sizeof(struct rp2040_flash_bank)); - priv->probed = false; + struct rp2xxx_flash_bank *priv; + priv = calloc(1, sizeof(struct rp2xxx_flash_bank)); priv->size_override = bank->size != 0; /* Set up driver_priv */ @@ -1236,7 +1228,7 @@ FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command) } -COMMAND_HANDLER(rp2040_rom_api_call_handler) +COMMAND_HANDLER(rp2xxx_rom_api_call_handler) { if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -1245,7 +1237,7 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) struct flash_bank *bank; for (bank = flash_bank_list(); bank; bank = bank->next) { - if (bank->driver != &rp2040_flash) + if (bank->driver != &rp2xxx_flash) continue; if (bank->target == target) @@ -1258,7 +1250,7 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) return ERROR_FAIL; } - int retval = rp2040_flash_auto_probe(bank); + int retval = rp2xxx_flash_auto_probe(bank); if (retval != ERROR_OK) { command_print(CMD, "auto_probe failed"); return retval; @@ -1275,7 +1267,7 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) return ERROR_TARGET_NOT_HALTED; } - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; retval = setup_for_raw_flash_cmd(target, priv); if (retval != ERROR_OK) goto cleanup_and_return; @@ -1304,7 +1296,7 @@ COMMAND_HANDLER(rp2040_rom_api_call_handler) return retval; } -COMMAND_HANDLER(rp2040_switch_target_handler) +COMMAND_HANDLER(rp2xxx_switch_target_handler) { if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -1323,10 +1315,10 @@ COMMAND_HANDLER(rp2040_switch_target_handler) struct flash_bank *bank; for (bank = flash_bank_list(); bank; bank = bank->next) { - if (bank->driver == &rp2040_flash) { + if (bank->driver == &rp2xxx_flash) { if (bank->target == old_target) { bank->target = new_target; - struct rp2040_flash_bank *priv = bank->driver_priv; + struct rp2xxx_flash_bank *priv = bank->driver_priv; priv->probed = false; return ERROR_OK; } else if (bank->target == new_target) { @@ -1340,44 +1332,44 @@ COMMAND_HANDLER(rp2040_switch_target_handler) return ERROR_FAIL; } -static const struct command_registration rp2040_exec_command_handlers[] = { +static const struct command_registration rp2xxx_exec_command_handlers[] = { { .name = "rom_api_call", .mode = COMMAND_EXEC, .help = "arbitrary ROM API call", .usage = "fc [p0 [p1 [p2 [p3]]]]", - .handler = rp2040_rom_api_call_handler, + .handler = rp2xxx_rom_api_call_handler, }, { .name = "_switch_target", .mode = COMMAND_EXEC, .help = "internal use", .usage = "old_target new_target", - .handler = rp2040_switch_target_handler, + .handler = rp2xxx_switch_target_handler, }, COMMAND_REGISTRATION_DONE }; -static const struct command_registration rp2040_command_handler[] = { +static const struct command_registration rp2xxx_command_handler[] = { { .name = "rp2xxx", .mode = COMMAND_ANY, .help = "rp2xxx flash controller commands", .usage = "", - .chain = rp2040_exec_command_handlers, + .chain = rp2xxx_exec_command_handlers, }, COMMAND_REGISTRATION_DONE }; -const struct flash_driver rp2040_flash = { - .name = "rp2040_flash", - .commands = rp2040_command_handler, - .flash_bank_command = rp2040_flash_bank_command, - .erase = rp2040_flash_erase, - .write = rp2040_flash_write, +const struct flash_driver rp2xxx_flash = { + .name = "rp2xxx", + .commands = rp2xxx_command_handler, + .flash_bank_command = rp2xxx_flash_bank_command, + .erase = rp2xxx_flash_erase, + .write = rp2xxx_flash_write, .read = default_flash_read, - .probe = rp2040_flash_probe, - .auto_probe = rp2040_flash_auto_probe, + .probe = rp2xxx_flash_probe, + .auto_probe = rp2xxx_flash_auto_probe, .erase_check = default_flash_blank_check, - .free_driver_priv = rp2040_flash_free_driver_priv + .free_driver_priv = default_flash_free_driver_priv }; diff --git a/tcl/target/rp2040.cfg b/tcl/target/rp2040.cfg index 5e78c69310..5fae390b41 100644 --- a/tcl/target/rp2040.cfg +++ b/tcl/target/rp2040.cfg @@ -99,7 +99,7 @@ if { $_USE_CORE == 1 } { # The flash is probed during gdb connect if gdb memory_map is enabled (by default). $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup 1 set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME rp2040_flash 0x10000000 0 0 0 $_FLASH_TARGET +flash bank $_FLASHNAME rp2xxx 0x10000000 0 0 0 $_FLASH_TARGET if { $_BOTH_CORES } { # Alias to ensure gdb connecting to core 1 gets the correct memory map diff --git a/tcl/target/rp2350.cfg b/tcl/target/rp2350.cfg index dc26cde190..b7617acd4c 100644 --- a/tcl/target/rp2350.cfg +++ b/tcl/target/rp2350.cfg @@ -160,7 +160,7 @@ if { [info exists _FLASH_TARGET] } { echo "Info : $_CHIPNAME.flash will be handled by the active one of $_FLASH_TARGET and $_TARGETNAME_RV0 cores" } set _FLASHNAME $_CHIPNAME.flash - flash bank $_FLASHNAME rp2040_flash 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET + flash bank $_FLASHNAME rp2xxx 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET } if { [info exists _TARGETNAME_1] } { From 9fce121366c86e77e84b9d20c7d1c7dbb38710d5 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 17:14:17 +0200 Subject: [PATCH 1184/1312] doc: document changes in rp2xxx flash driver Namely the driver name changed from rp2040_flash and added RP2350 support. Signed-off-by: Tomas Vanek Change-Id: I2ec9e62786002d71f655dbe0edc9f2e9ac4141b7 Reviewed-on: https://review.openocd.org/c/openocd/+/8456 Tested-by: jenkins --- doc/openocd.texi | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 9ff524b749..32a2895ecf 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7872,15 +7872,29 @@ locked, but can still mass erase the whole flash. @end deffn @end deffn -@deffn {Flash Driver} {rp2040} -Supports RP2040 "Raspberry Pi Pico" microcontroller. -RP2040 is a dual-core device with two CM0+ cores. Both cores share the same -Flash/RAM/MMIO address space. Non-volatile storage is achieved with an -external QSPI flash; a Boot ROM provides helper functions. +@deffn {Flash Driver} {rp2xxx} +Supports RP2040 "Raspberry Pi Pico" microcontroller and RP2350 Pico 2 +RP2040 is a dual-core device with two CM0+ cores. +RP2350 is a dual-core device with two slots switched to either Cortex-M33 +or Hazard3 RISC-V core. +Both cores share the same Flash/RAM/MMIO address space. +Non-volatile storage is achieved with an external QSPI flash; +a Boot ROM provides helper functions. @example -flash bank $_FLASHNAME rp2040_flash $_FLASHBASE $_FLASHSIZE 1 32 $_TARGETNAME +flash bank $_FLASHNAME rp2xxx $_FLASHBASE $_FLASHSIZE 0 0 $_TARGETNAME @end example + +@deffn {Command} {rp2xxx rom_api_call} fc [p0 [p1 [p2 [p3]]]] +A utility for calling ROM API function with two characters lookup code +@var{fc} and up to 4 optional parameters @var{p0 p1 p2 p3}. +The call is supported on the target where the flash bank is configured +(core0). +@end deffn + +@deffn {Command} {rp2xxx _switch_target} old_target new_target +A command used internally by rp2350.cfg when the core type is switched. +@end deffn @end deffn @deffn {Flash Driver} {rsl10} From d29c1c6d6df31f64ae5593babc65cfdffa312def Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 14 Aug 2024 17:43:13 +0200 Subject: [PATCH 1185/1312] flash/nor/rp2xxx: minor code improvements Add error messages and proper error propagation. Type cleaning. Use saved chip id. Cosmetics: separating lines added. Signed-off-by: Tomas Vanek Change-Id: I151e684e1fbfc9476ec429036caf85f4c9329547 Reviewed-on: https://review.openocd.org/c/openocd/+/8457 Tested-by: jenkins Reviewed-by: Jonathan Bell --- src/flash/nor/rp2xxx.c | 49 +++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index e58fc8a29b..909d3f14d6 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -233,11 +233,13 @@ static int rp2040_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ err = target_read_u16(target, ptr_to_entry, &entry_tag); if (err != ERROR_OK) return err; + if (entry_tag == tag) { /* 16 bit symbol is next */ err = target_read_u16(target, ptr_to_entry + 2, symbol_out); if (err != ERROR_OK) return err; + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); return ERROR_OK; } @@ -277,10 +279,12 @@ static int rp2350_a0_lookup_symbol(struct target *target, uint16_t tag, uint16_t err = target_read_u16(target, ptr_to_entry, &entry_tag); if (err != ERROR_OK) return err; + if (entry_tag == tag) { err = target_read_u16(target, ptr_to_entry + 2, symbol_out); if (err != ERROR_OK) return err; + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); return ERROR_OK; } @@ -303,9 +307,10 @@ static int rp2350_lookup_rom_symbol(struct target *target, uint32_t ptr_to_entry while (true) { uint16_t entry_tag, entry_flags; - uint32_t err = target_read_u16(target, ptr_to_entry, &entry_tag); + int err = target_read_u16(target, ptr_to_entry, &entry_tag); if (err != ERROR_OK) return err; + if (entry_tag == 0) { *symbol_out = 0; return ERROR_FAIL; @@ -315,6 +320,7 @@ static int rp2350_lookup_rom_symbol(struct target *target, uint32_t ptr_to_entry err = target_read_u16(target, ptr_to_entry, &entry_flags); if (err != ERROR_OK) return err; + ptr_to_entry += 2; uint16_t matching_flags = flags & entry_flags; @@ -338,6 +344,7 @@ static int rp2350_lookup_rom_symbol(struct target *target, uint32_t ptr_to_entry err = target_read_u16(target, ptr_to_entry, symbol_out); if (err != ERROR_OK) return err; + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); return ERROR_OK; } @@ -426,18 +433,23 @@ static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xx // From this point are optional functions which do not exist on e.g. RP2040 // or pre-production RP2350 ROM versions: + if (IS_RP2040(priv->id)) { + priv->jump_bootrom_reset_state = 0; + priv->jump_flash_reset_address_trans = 0; + return ERROR_OK; + } err = rp2xxx_lookup_rom_symbol(target, FUNC_BOOTROM_STATE_RESET, symtype_func, &priv->jump_bootrom_reset_state); if (err != ERROR_OK) { priv->jump_bootrom_reset_state = 0; - LOG_WARNING("Function FUNC_BOOTROM_STATE_RESET not found in RP2xxx ROM. (probably an RP2040 or an RP2350 A0)"); + LOG_WARNING("Function FUNC_BOOTROM_STATE_RESET not found in RP2xxx ROM. (probably an RP2350 A0)"); } err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RESET_ADDRESS_TRANS, symtype_func, &priv->jump_flash_reset_address_trans); if (err != ERROR_OK) { priv->jump_flash_reset_address_trans = 0; - LOG_WARNING("Function FUNC_FLASH_RESET_ADDRESS_TRANS not found in RP2xxx ROM. (probably an RP2040 or an RP2350 A0)"); + LOG_WARNING("Function FUNC_FLASH_RESET_ADDRESS_TRANS not found in RP2xxx ROM. (probably an RP2350 A0)"); } return ERROR_OK; } @@ -465,7 +477,7 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash for (unsigned int i = 0; i < n_calls; ++i) { LOG_DEBUG(" func @ %" PRIx32, calls[i].pc); LOG_DEBUG(" sp = %" PRIx32, calls[i].sp); - for (int j = 0; j < 4; ++j) + for (unsigned int j = 0; j < 4; ++j) LOG_DEBUG(" a%d = %" PRIx32, j, calls[i].args[j]); } LOG_DEBUG("Calling on core \"%s\"", target->cmd_name); @@ -607,14 +619,22 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank // Flash algorithms (and the RCP init stub called by this function) must // run in the Secure state, so flip the state now before attempting to // execute any code on the core. + int retval; uint32_t dscsr; - (void)target_read_u32(target, DCB_DSCSR, &dscsr); + retval = target_read_u32(target, DCB_DSCSR, &dscsr); + if (retval != ERROR_OK) { + LOG_ERROR("RP2350 init ARM core: DSCSR read failed"); + return retval; + } + LOG_DEBUG("DSCSR: %08x\n", dscsr); if (!(dscsr & DSCSR_CDS)) { LOG_DEBUG("Setting Current Domain Secure in DSCSR\n"); - (void)target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); - (void)target_read_u32(target, DCB_DSCSR, &dscsr); - LOG_DEBUG("DSCSR*: %08x\n", dscsr); + retval = target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); + if (retval != ERROR_OK) { + LOG_ERROR("RP2350 init ARM core: DSCSR read failed"); + return retval; + } } if (!priv->stack) { @@ -682,8 +702,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba } } - // hacky RP2350 check -- either RISC-V or v8-M - if (is_arm(target_to_arm(target)) ? target_to_arm(target)->arch == ARM_ARCH_V8M : true) { + if (IS_RP2350(priv->id)) { err = rp2350_init_accessctrl(target); if (err != ERROR_OK) { LOG_ERROR("Failed to init ACCESSCTRL before ROM call"); @@ -861,16 +880,16 @@ static int rp2xxx_flash_erase(struct flash_bank *bank, unsigned int first, unsig return ERROR_TARGET_NOT_HALTED; } - uint32_t start_addr = bank->sectors[first].offset; - uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr; - LOG_DEBUG("erase %d bytes starting at 0x%" PRIx32, length, start_addr); + uint32_t offset_start = bank->sectors[first].offset; + uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size; + uint32_t length = offset_last - offset_start; + LOG_DEBUG("erase %d bytes starting at 0x%" PRIx32, length, offset_start); int err = setup_for_raw_flash_cmd(target, priv); if (err != ERROR_OK) goto cleanup_and_return; - uint32_t offset_next = bank->sectors[first].offset; - uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size; + uint32_t offset_next = offset_start; /* Break erase into multiple calls to avoid timeout on large erase. Choose 128k chunk which has fairly low ROM call overhead and empirically seems to avoid the default keep_alive() limit From a9608871692be6cda4d73ae837b4313747370ff8 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 16 Aug 2024 22:53:36 +0200 Subject: [PATCH 1186/1312] flash/nor/rp2xxx: drop couple of Java-like const The compiler knows what variable remains constant during its lifetime and there is no need to emphasise constantness. Change-Id: Ib515f96a3c77afea87274f33b8ccac7a71bfb932 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8459 Tested-by: jenkins Reviewed-by: Jonathan Bell --- src/flash/nor/rp2xxx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index 909d3f14d6..5d0255b61e 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -223,7 +223,7 @@ static int rp2040_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ } uint16_t ptr_to_entry; - const unsigned int offset_magic_to_table_ptr = flags == RT_FLAG_DATA ? 6 : 4; + unsigned int offset_magic_to_table_ptr = flags == RT_FLAG_DATA ? 6 : 4; int err = target_read_u16(target, BOOTROM_MAGIC_ADDR + offset_magic_to_table_ptr, &ptr_to_entry); if (err != ERROR_OK) return err; @@ -390,8 +390,8 @@ static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xxx_flash_bank *priv) { - const uint16_t symtype_func = is_arm(target_to_arm(target)) - ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV; + uint16_t symtype_func = is_arm(target_to_arm(target)) + ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV; int err; err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_EXIT_XIP, symtype_func, &priv->jump_flash_exit_xip); From f039fe7f9d1ecfc1ca25574d5527c35db119e77b Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 16 Aug 2024 23:35:06 +0200 Subject: [PATCH 1187/1312] flash/nor/rp2xxx: fix endianness error struct rp2xxx_rom_call_batch_record consists of uint32_t in the host endianness. Therefore it should be converted to the target endianness not just simply copied by target_write_buffer(). Concatenate algo code, converted batch records and terminator to the host resident buffer and copy it at once to the target and save some adapter turnaround times. While on it remove typedef rp2xxx_rom_call_batch_record_t Change-Id: I0e698396003869bee5dde4141d48ddd7d62b3cbc Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8460 Reviewed-by: Jonathan Bell Tested-by: jenkins --- src/flash/nor/rp2xxx.c | 59 +++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index 5d0255b61e..fce501703d 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -179,11 +179,11 @@ static const uint8_t rp2xxx_rom_call_batch_algo_riscv[ROM_CALL_BATCH_ALGO_SIZE_B // <_args>: }; -typedef struct rp2xxx_rom_call_batch_record { +struct rp2xxx_rom_call_batch_record { uint32_t pc; uint32_t sp; uint32_t args[4]; -} rp2xxx_rom_call_batch_record_t; +}; struct rp2xxx_flash_bank { bool probed; /* flag indicating successful flash probe */ @@ -457,18 +457,18 @@ static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xx // Call a list of PC + SP + r0-r3 function call tuples with a single OpenOCD // algorithm invocation, to amortise the algorithm overhead over multiple calls: static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash_bank *priv, - rp2xxx_rom_call_batch_record_t *calls, unsigned int n_calls) + struct rp2xxx_rom_call_batch_record *calls, unsigned int n_calls) { - // Note +1 is for the null terminator - unsigned int batch_words = 1 + (ROM_CALL_BATCH_ALGO_SIZE_BYTES + - n_calls * sizeof(rp2xxx_rom_call_batch_record_t) - ) / sizeof(uint32_t); + // Note + sizeof(uint32_t) is for the null terminator + unsigned int batch_size = ROM_CALL_BATCH_ALGO_SIZE_BYTES + + n_calls * sizeof(struct rp2xxx_rom_call_batch_record) + + sizeof(uint32_t); if (!priv->ram_algo_space) { LOG_ERROR("No RAM code space allocated for ROM call"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - if (priv->ram_algo_space->size < batch_words * sizeof(uint32_t)) { + if (priv->ram_algo_space->size < batch_size) { LOG_ERROR("RAM code space too small for call batch size of %u\n", n_calls); return ERROR_BUF_TOO_SMALL; } @@ -501,32 +501,31 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash algo_code = rp2xxx_rom_call_batch_algo_riscv; } + uint8_t *batch_bf = malloc(batch_size); + if (!batch_bf) { + LOG_ERROR("No memory for batch buffer"); + return ERROR_FAIL; + } + memcpy(batch_bf, algo_code, ROM_CALL_BATCH_ALGO_SIZE_BYTES); + unsigned int words = n_calls * sizeof(struct rp2xxx_rom_call_batch_record) + / sizeof(uint32_t); + target_buffer_set_u32_array(target, + &batch_bf[ROM_CALL_BATCH_ALGO_SIZE_BYTES], words, + (const uint32_t *)calls); + /* Null terminator */ + target_buffer_set_u32(target, &batch_bf[batch_size - sizeof(uint32_t)], 0); + int err = target_write_buffer(target, priv->ram_algo_space->address, - ROM_CALL_BATCH_ALGO_SIZE_BYTES, - algo_code + batch_size, + batch_bf ); + free(batch_bf); + if (err != ERROR_OK) { LOG_ERROR("Failed to write ROM batch algorithm to RAM code space\n"); return err; } - err = target_write_buffer(target, - priv->ram_algo_space->address + ROM_CALL_BATCH_ALGO_SIZE_BYTES, - n_calls * sizeof(rp2xxx_rom_call_batch_record_t), - (const uint8_t *)calls - ); - if (err != ERROR_OK) { - LOG_ERROR("Failed to write ROM batch records to RAM code space\n"); - return err; - } - err = target_write_u32(target, - priv->ram_algo_space->address + (batch_words - 1) * sizeof(uint32_t), - 0 - ); - if (err != ERROR_OK) { - LOG_ERROR("Failed to write null terminator for ROM batch records\n"); - return err; - } // Call into the ROM batch algorithm -- this will in turn call each ROM // call specified by the batch records. @@ -579,7 +578,7 @@ static int rp2xxx_call_rom_func(struct target *target, struct rp2xxx_flash_bank } target_addr_t stacktop = priv->stack->address + priv->stack->size; - rp2xxx_rom_call_batch_record_t call = { + struct rp2xxx_rom_call_batch_record call = { .pc = func_offset, .sp = stacktop }; @@ -732,7 +731,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba } LOG_DEBUG("Connecting flash IOs and issuing XIP exit sequence to flash"); - rp2xxx_rom_call_batch_record_t calls[2] = { + struct rp2xxx_rom_call_batch_record calls[2] = { { .pc = priv->jump_connect_internal_flash, .sp = priv->stack->address + priv->stack->size @@ -759,7 +758,7 @@ static int rp2xxx_invalidate_cache_restore_xip(struct target *target, struct rp2 LOG_DEBUG("Flushing flash cache after write behind"); - rp2xxx_rom_call_batch_record_t finishing_calls[2] = { + struct rp2xxx_rom_call_batch_record finishing_calls[2] = { { .pc = priv->jump_flush_cache, .sp = priv->stack->address + priv->stack->size From 376d11c2e38303094976186d59502ab7d3073452 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 17 Aug 2024 16:21:06 +0200 Subject: [PATCH 1188/1312] tcl/target/rp2040: add flash size override and reset init event Allow flash size override and suppress flash size detection by setting FLASHSIZE Tcl variable. reset-init event calls 'connect XIP' ROM API function to make flash content accessible at the XIP mapping memory area. Ported from rp2350.cfg Change-Id: I9b352b1ef6d4c6d4b78a6b61e900ce01355c8eff Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8461 Reviewed-by: Jonathan Bell Tested-by: jenkins --- tcl/target/rp2040.cfg | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tcl/target/rp2040.cfg b/tcl/target/rp2040.cfg index 5fae390b41..f64d4322b1 100644 --- a/tcl/target/rp2040.cfg +++ b/tcl/target/rp2040.cfg @@ -20,6 +20,14 @@ if { [info exists WORKAREASIZE] } { set _WORKAREASIZE 0x10000 } +# Nonzero FLASHSIZE supresses QSPI flash size detection +if { [info exists FLASHSIZE] } { + set _FLASHSIZE $FLASHSIZE +} else { + # Detect QSPI flash size based on flash ID or SFDP + set _FLASHSIZE 0 +} + if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { @@ -74,6 +82,10 @@ if { $_USE_CORE != 1 } { target create $_TARGETNAME_0 cortex_m -dap $_CHIPNAME.dap0 -coreid 0 # srst does not exist; use SYSRESETREQ to perform a soft reset $_TARGETNAME_0 cortex_m reset_config sysresetreq + + # After a rescue reset and fi BOOTSEL is halted connect the flash to enable + # reads from the XIP cached mapping area + $_TARGETNAME_0 configure -event reset-init { rp2xxx rom_api_call 0 CX } } # core 1 @@ -95,11 +107,11 @@ if { $_USE_CORE == 1 } { } else { set _FLASH_TARGET $_TARGETNAME_0 } -# Backup the work area. The flash probe runs an algorithm on the target CPU. -# The flash is probed during gdb connect if gdb memory_map is enabled (by default). -$_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup 1 +# QSPI flash size detection during gdb connect requires to back-up RAM +set _WKA_BACKUP [expr { $_FLASHSIZE == 0 }] +$_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup $_WKA_BACKUP set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME rp2xxx 0x10000000 0 0 0 $_FLASH_TARGET +flash bank $_FLASHNAME rp2xxx 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET if { $_BOTH_CORES } { # Alias to ensure gdb connecting to core 1 gets the correct memory map From 5bb7dbc2312f4ce84224720eb258ebcae2089e28 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 13 Dec 2024 21:56:45 +0100 Subject: [PATCH 1189/1312] flash/nor/rp2xxx: fix flash operation after halt in RISC-V bootsel Calling ROM API set_bootrom_stack() function allows ROM API functionality after OpenOCD halt or reset halt in RISC-V bootloder (emulated ARM code) Change-Id: I3b255738d61876e876a94207804d9cbe1a7593c2 Signed-off-by: Tomas Vanek Signed-off-by: Luke Wren Reviewed-on: https://review.openocd.org/c/openocd/+/8729 Tested-by: jenkins --- src/flash/nor/rp2xxx.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index fce501703d..280f077c1c 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -26,6 +26,7 @@ #define FUNC_FLASH_FLUSH_CACHE MAKE_TAG('F', 'C') #define FUNC_FLASH_ENTER_CMD_XIP MAKE_TAG('C', 'X') #define FUNC_BOOTROM_STATE_RESET MAKE_TAG('S', 'R') +#define FUNC_BOOTROM_SET_STACK MAKE_TAG('S', 'S') #define FUNC_FLASH_RESET_ADDRESS_TRANS MAKE_TAG('R', 'A') /* ROM table flags for RP2350 A1 ROM onwards */ @@ -201,6 +202,7 @@ struct rp2xxx_flash_bank { uint16_t jump_flash_reset_address_trans; uint16_t jump_enter_cmd_xip; uint16_t jump_bootrom_reset_state; + uint16_t jump_bootrom_set_varm_stack; char dev_name[20]; bool size_override; @@ -445,6 +447,15 @@ static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xx LOG_WARNING("Function FUNC_BOOTROM_STATE_RESET not found in RP2xxx ROM. (probably an RP2350 A0)"); } + if (!is_arm(target_to_arm(target))) { + err = rp2xxx_lookup_rom_symbol(target, FUNC_BOOTROM_SET_STACK, symtype_func, + &priv->jump_bootrom_set_varm_stack); + if (err != ERROR_OK) { + priv->jump_bootrom_set_varm_stack = 0; + LOG_WARNING("Function FUNC_BOOTROM_SET_STACK not found in RP2xxx ROM. (probably an RP2350 A0)"); + } + } + err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RESET_ADDRESS_TRANS, symtype_func, &priv->jump_flash_reset_address_trans); if (err != ERROR_OK) { @@ -720,6 +731,9 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba if (!priv->jump_bootrom_reset_state) { LOG_WARNING("RP2350 flash: no bootrom_reset_method\n"); } else { + /* This is mainly required to clear varmulet_enclosing_cpu pointers on RISC-V, in case + an Arm -> RISC-V call has been interrupted (these pointers are used to handle + reentrant calls to the ROM emulator) */ LOG_DEBUG("Clearing core 0 ROM state"); err = rp2xxx_call_rom_func(target, priv, priv->jump_bootrom_reset_state, reset_args, ARRAY_SIZE(reset_args)); @@ -728,6 +742,39 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba return err; } } + if (!is_arm(target_to_arm(target)) && priv->jump_bootrom_set_varm_stack) { + /* Pass {0, 0} to set_varmulet_user_stack() to enable automatic emulation of Arm APIs + using the ROM's default stacks. Usually the bootrom does this before exiting to user + code, but it needs to be done manually when the USB bootloader has been interrupted. */ + LOG_DEBUG("Enabling default Arm emulator stacks for RISC-V ROM calls\n"); + struct working_area *set_stack_mem_args; + err = target_alloc_working_area(target, 2 * sizeof(uint32_t), &set_stack_mem_args); + if (err != ERROR_OK) { + LOG_ERROR("Failed to allocate memory for arguments to set_varmulet_user_stack()"); + return err; + } + + err = target_write_u32(target, set_stack_mem_args->address, 0); + if (err == ERROR_OK) + err = target_write_u32(target, set_stack_mem_args->address + 4, 0); + + if (err != ERROR_OK) { + LOG_ERROR("Failed to initialise memory arguments for set_varmulet_user_stack()"); + target_free_working_area(target, set_stack_mem_args); + return err; + } + + uint32_t set_stack_register_args[1] = { + set_stack_mem_args->address + }; + err = rp2xxx_call_rom_func(target, priv, priv->jump_bootrom_set_varm_stack, + set_stack_register_args, ARRAY_SIZE(set_stack_register_args)); + target_free_working_area(target, set_stack_mem_args); + if (err != ERROR_OK) { + LOG_ERROR("Failed to initialise Arm emulation stacks for RISC-V: 0x%08" PRIx32, err); + return err; + } + } } LOG_DEBUG("Connecting flash IOs and issuing XIP exit sequence to flash"); From bf66d95be2db83da2694d20970c4b8db8e5de969 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 21 Mar 2025 21:30:13 +0100 Subject: [PATCH 1190/1312] flash/nor/rp2xxx: fix LOG_xxx messages Use proper format specifiers for uint16_t and uint32_t arguments. Use LOG_TARGET_DEBUG instead of target->cmd_name as a parameter. Use command_print() in command handler. Drop dots and new lines at end of messages. Change-Id: I37c7d3680a352210b1d7e69f2c9b4ba0efe6ec15 Signed-off-by: Tomas Vanek Reported-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8809 Tested-by: jenkins --- src/flash/nor/rp2xxx.c | 63 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index 280f077c1c..2b22e52eb8 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -242,7 +242,7 @@ static int rp2040_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ if (err != ERROR_OK) return err; - LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04" PRIx16, *symbol_out); return ERROR_OK; } ptr_to_entry += 4; @@ -287,7 +287,7 @@ static int rp2350_a0_lookup_symbol(struct target *target, uint16_t tag, uint16_t if (err != ERROR_OK) return err; - LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04" PRIx16, *symbol_out); return ERROR_OK; } ptr_to_entry += 6; @@ -347,7 +347,7 @@ static int rp2350_lookup_rom_symbol(struct target *target, uint32_t ptr_to_entry if (err != ERROR_OK) return err; - LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04x", *symbol_out); + LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04" PRIx16, *symbol_out); return ERROR_OK; } /* Skip past this entry */ @@ -398,38 +398,38 @@ static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xx err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_EXIT_XIP, symtype_func, &priv->jump_flash_exit_xip); if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2xxx ROM."); + LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2xxx ROM"); return err; } err = rp2xxx_lookup_rom_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, symtype_func, &priv->jump_connect_internal_flash); if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2xxx ROM."); + LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2xxx ROM"); return err; } err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RANGE_ERASE, symtype_func, &priv->jump_flash_range_erase); if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2xxx ROM."); + LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2xxx ROM"); return err; } err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RANGE_PROGRAM, symtype_func, &priv->jump_flash_range_program); if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2xxx ROM."); + LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2xxx ROM"); return err; } err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_FLUSH_CACHE, symtype_func, &priv->jump_flush_cache); if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2xxx ROM."); + LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2xxx ROM"); return err; } err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, symtype_func, &priv->jump_enter_cmd_xip); if (err != ERROR_OK) { - LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2xxx ROM."); + LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2xxx ROM"); return err; } @@ -480,18 +480,17 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (priv->ram_algo_space->size < batch_size) { - LOG_ERROR("RAM code space too small for call batch size of %u\n", n_calls); + LOG_ERROR("RAM code space too small for call batch size of %u", n_calls); return ERROR_BUF_TOO_SMALL; } - LOG_DEBUG("Calling batch of %u ROM functions:", n_calls); + LOG_TARGET_DEBUG(target, "Calling batch of %u ROM functions:", n_calls); for (unsigned int i = 0; i < n_calls; ++i) { LOG_DEBUG(" func @ %" PRIx32, calls[i].pc); LOG_DEBUG(" sp = %" PRIx32, calls[i].sp); for (unsigned int j = 0; j < 4; ++j) - LOG_DEBUG(" a%d = %" PRIx32, j, calls[i].args[j]); + LOG_DEBUG(" a%u = %" PRIx32, j, calls[i].args[j]); } - LOG_DEBUG("Calling on core \"%s\"", target->cmd_name); if (n_calls <= 0) { LOG_DEBUG("Returning early from call of 0 ROM functions"); @@ -534,7 +533,7 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash free(batch_bf); if (err != ERROR_OK) { - LOG_ERROR("Failed to write ROM batch algorithm to RAM code space\n"); + LOG_ERROR("Failed to write ROM batch algorithm to RAM code space"); return err; } @@ -565,7 +564,7 @@ static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash ); } if (err != ERROR_OK) { - LOG_ERROR("Failed to call ROM function batch\n"); + LOG_ERROR("Failed to call ROM function batch"); /* This case is hit when loading new ROM images on FPGA, but can also be hit on real hardware if you swap two devices with different ROM versions without restarting OpenOCD: */ LOG_ROM_SYMBOL_DEBUG("Repopulating ROM address cache after failed ROM call"); @@ -616,9 +615,9 @@ static int rp2350_init_accessctrl(struct target *target) return ERROR_FAIL; } if (accessctrl_lock_reg & ACCESSCTRL_LOCK_DEBUG_BITS) { - LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail.\n"); + LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail"); } else { - LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET\n"); + LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET"); return target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u); } return ERROR_OK; @@ -637,9 +636,9 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank return retval; } - LOG_DEBUG("DSCSR: %08x\n", dscsr); + LOG_DEBUG("DSCSR: 0x%08" PRIx32, dscsr); if (!(dscsr & DSCSR_CDS)) { - LOG_DEBUG("Setting Current Domain Secure in DSCSR\n"); + LOG_DEBUG("Setting Current Domain Secure in DSCSR"); retval = target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); if (retval != ERROR_OK) { LOG_ERROR("RP2350 init ARM core: DSCSR read failed"); @@ -664,12 +663,12 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank rcp_init_code ); if (err != ERROR_OK) { - LOG_ERROR("Failed to load rcp_init algorithm into RAM\n"); + LOG_ERROR("Failed to load rcp_init algorithm into RAM"); return ERROR_FAIL; } - LOG_DEBUG("Calling rcp_init on core \"%s\", code at 0x%" PRIx32 "\n", - target->cmd_name, (uint32_t)priv->ram_algo_space->address); + LOG_TARGET_DEBUG(target, "Calling rcp_init, code at " TARGET_ADDR_FMT, + priv->ram_algo_space->address); /* Actually call the function */ struct armv7m_algorithm alg_info; @@ -684,7 +683,7 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank &alg_info ); if (err != ERROR_OK) { - LOG_ERROR("Failed to invoke rcp_init\n"); + LOG_ERROR("Failed to invoke rcp_init"); return err; } @@ -729,7 +728,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba BOOTROM_STATE_RESET_CURRENT_CORE }; if (!priv->jump_bootrom_reset_state) { - LOG_WARNING("RP2350 flash: no bootrom_reset_method\n"); + LOG_WARNING("RP2350 flash: no bootrom_reset_method"); } else { /* This is mainly required to clear varmulet_enclosing_cpu pointers on RISC-V, in case an Arm -> RISC-V call has been interrupted (these pointers are used to handle @@ -746,7 +745,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba /* Pass {0, 0} to set_varmulet_user_stack() to enable automatic emulation of Arm APIs using the ROM's default stacks. Usually the bootrom does this before exiting to user code, but it needs to be done manually when the USB bootloader has been interrupted. */ - LOG_DEBUG("Enabling default Arm emulator stacks for RISC-V ROM calls\n"); + LOG_DEBUG("Enabling default Arm emulator stacks for RISC-V ROM calls"); struct working_area *set_stack_mem_args; err = target_alloc_working_area(target, 2 * sizeof(uint32_t), &set_stack_mem_args); if (err != ERROR_OK) { @@ -771,7 +770,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba set_stack_register_args, ARRAY_SIZE(set_stack_register_args)); target_free_working_area(target, set_stack_mem_args); if (err != ERROR_OK) { - LOG_ERROR("Failed to initialise Arm emulation stacks for RISC-V: 0x%08" PRIx32, err); + LOG_ERROR("Failed to initialise Arm emulation stacks for RISC-V"); return err; } } @@ -852,7 +851,7 @@ static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2xxx_fla static int rp2xxx_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { - LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset); + LOG_DEBUG("Writing %" PRIu32 " bytes starting at 0x%" PRIx32, count, offset); struct rp2xxx_flash_bank *priv = bank->driver_priv; struct target *target = bank->target; @@ -882,7 +881,8 @@ static int rp2xxx_flash_write(struct flash_bank *bank, const uint8_t *buffer, ui while (count > 0) { uint32_t write_size = count > chunk_size ? chunk_size : count; - LOG_DEBUG("Writing %d bytes to offset 0x%" PRIx32, write_size, offset); + LOG_DEBUG("Writing %" PRIu32 " bytes to offset 0x%" PRIx32, + write_size, offset); err = target_write_buffer(target, bounce->address, write_size, buffer); if (err != ERROR_OK) { LOG_ERROR("Could not load data into target bounce buffer"); @@ -929,7 +929,8 @@ static int rp2xxx_flash_erase(struct flash_bank *bank, unsigned int first, unsig uint32_t offset_start = bank->sectors[first].offset; uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size; uint32_t length = offset_last - offset_start; - LOG_DEBUG("erase %d bytes starting at 0x%" PRIx32, length, offset_start); + LOG_DEBUG("erase %" PRIu32 " bytes starting at 0x%" PRIx32, + length, offset_start); int err = setup_for_raw_flash_cmd(target, priv); if (err != ERROR_OK) @@ -1328,7 +1329,7 @@ COMMAND_HANDLER(rp2xxx_rom_api_call_handler) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i + 1], args[i]); if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); + command_print(CMD, "Target not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -1343,7 +1344,7 @@ COMMAND_HANDLER(rp2xxx_rom_api_call_handler) uint16_t fc; retval = rp2xxx_lookup_rom_symbol(target, tag, symtype_func, &fc); if (retval != ERROR_OK) { - command_print(CMD, "Function %.2s not found in RP2xxx ROM.", + command_print(CMD, "Function %.2s not found in RP2xxx ROM", CMD_ARGV[0]); goto cleanup_and_return; } From 4d4c45cfd25703f39f9e2413b22d91a48c4b4565 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 21 Mar 2025 21:56:39 +0100 Subject: [PATCH 1191/1312] flash/nor/rp2xxx: define macro BOOTROM_MAGIC_MASK and use it instead of magic value. Change-Id: I5d006aaf990d4ef3a82e622b1e41cd2bfec359f7 Signed-off-by: Tomas Vanek Reported-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8810 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/flash/nor/rp2xxx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index 2b22e52eb8..85c5911041 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -16,6 +16,7 @@ #define BOOTROM_RP2040_MAGIC 0x01754d /* this is 'M' 'u', 2 (version) */ #define BOOTROM_RP2350_MAGIC 0x02754d +#define BOOTROM_MAGIC_MASK 0xffffff #define BOOTROM_MAGIC_ADDR 0x00000010 #define MAKE_TAG(a, b) (((b)<<8) | a) @@ -368,7 +369,7 @@ static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_ return err; /* Ignore version */ - magic &= 0xffffff; + magic &= BOOTROM_MAGIC_MASK; if (magic == BOOTROM_RP2350_MAGIC) { /* Distinguish old-style RP2350 ROM table (A0, and earlier A1 builds) From cbd7987c7ca2656b60bc8964bb1d9b7819e66ccb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 19 Apr 2025 11:03:46 +0200 Subject: [PATCH 1192/1312] target: stm8: drop include file stm8.h The file stm8.h is only included by stm8.c and provides some basic declaration that can be simply part of the C file. Drop the file stm8.h and move its content in stm8.c Replace the macro 'STM8_NUM_CORE_REGS' with the existing macro 'STM8_NUM_REGS'. While there: - drop the useless include of "hello.h". Change-Id: Iecd1a27f0630cdbbfd51033d34aa3d468aa63464 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8856 Tested-by: jenkins Reviewed-by: zapb --- src/target/Makefile.am | 1 - src/target/stm8.c | 49 ++++++++++++++++++++++++++++++-- src/target/stm8.h | 63 ------------------------------------------ 3 files changed, 47 insertions(+), 66 deletions(-) delete mode 100644 src/target/stm8.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 1fc7d2afa6..1a76864180 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -224,7 +224,6 @@ ARC_SRC = \ %D%/avr32_mem.h \ %D%/avr32_regs.h \ %D%/semihosting_common.h \ - %D%/stm8.h \ %D%/lakemont.h \ %D%/x86_32_common.h \ %D%/arm_cti.h \ diff --git a/src/target/stm8.c b/src/target/stm8.c index c80ea0eb20..81c41f2b2a 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -13,14 +13,12 @@ #include #include "target.h" #include "target_type.h" -#include "hello.h" #include "jtag/interface.h" #include "jtag/jtag.h" #include "jtag/swim.h" #include "register.h" #include "breakpoints.h" #include "algorithm.h" -#include "stm8.h" static struct reg_cache *stm8_build_reg_cache(struct target *target); static int stm8_read_core_reg(struct target *target, unsigned int num); @@ -54,6 +52,8 @@ static const struct { { 5, "cc", 8, REG_TYPE_UINT8, "general", "org.gnu.gdb.stm8.core", 0 }, }; +#define STM8_COMMON_MAGIC 0x53544D38U + #define STM8_NUM_REGS ARRAY_SIZE(stm8_regs) #define STM8_PC 0 #define STM8_A 1 @@ -168,6 +168,51 @@ struct stm8_comparator { enum hw_break_type type; }; +struct stm8_common { + unsigned int common_magic; + + void *arch_info; + struct reg_cache *core_cache; + uint32_t core_regs[STM8_NUM_REGS]; + + /* working area for fastdata access */ + struct working_area *fast_data_area; + + bool swim_configured; + bool bp_scanned; + uint8_t num_hw_bpoints; + uint8_t num_hw_bpoints_avail; + struct stm8_comparator *hw_break_list; + uint32_t blocksize; + uint32_t flashstart; + uint32_t flashend; + uint32_t eepromstart; + uint32_t eepromend; + uint32_t optionstart; + uint32_t optionend; + bool enable_step_irq; + + bool enable_stm8l; + uint32_t flash_cr2; + uint32_t flash_ncr2; + uint32_t flash_iapsr; + uint32_t flash_dukr; + uint32_t flash_pukr; + + /* cc value used for interrupt flags restore */ + uint32_t cc; + bool cc_valid; + + /* register cache to processor synchronization */ + int (*read_core_reg)(struct target *target, unsigned int num); + int (*write_core_reg)(struct target *target, unsigned int num); +}; + +static struct stm8_common *target_to_stm8(struct target *target) +{ + return target->arch_info; +} + static int stm8_adapter_read_memory(struct target *target, uint32_t addr, int size, int count, void *buf) { diff --git a/src/target/stm8.h b/src/target/stm8.h deleted file mode 100644 index 55e1071aba..0000000000 --- a/src/target/stm8.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/* -* OpenOCD STM8 target driver -* Copyright (C) 2017 Ake Rehnman -* ake.rehnman(at)gmail.com -*/ - -#ifndef OPENOCD_TARGET_STM8_H -#define OPENOCD_TARGET_STM8_H - -struct target; - -#define STM8_COMMON_MAGIC 0x53544D38U -#define STM8_NUM_CORE_REGS 6 - -struct stm8_common { - unsigned int common_magic; - - void *arch_info; - struct reg_cache *core_cache; - uint32_t core_regs[STM8_NUM_CORE_REGS]; - - /* working area for fastdata access */ - struct working_area *fast_data_area; - - bool swim_configured; - bool bp_scanned; - uint8_t num_hw_bpoints; - uint8_t num_hw_bpoints_avail; - struct stm8_comparator *hw_break_list; - uint32_t blocksize; - uint32_t flashstart; - uint32_t flashend; - uint32_t eepromstart; - uint32_t eepromend; - uint32_t optionstart; - uint32_t optionend; - bool enable_step_irq; - - bool enable_stm8l; - uint32_t flash_cr2; - uint32_t flash_ncr2; - uint32_t flash_iapsr; - uint32_t flash_dukr; - uint32_t flash_pukr; - - /* cc value used for interrupt flags restore */ - uint32_t cc; - bool cc_valid; - - /* register cache to processor synchronization */ - int (*read_core_reg)(struct target *target, unsigned int num); - int (*write_core_reg)(struct target *target, unsigned int num); -}; - -static inline struct stm8_common * -target_to_stm8(struct target *target) -{ - return target->arch_info; -} - -#endif /* OPENOCD_TARGET_STM8_H */ From c3fae349692c7c2d0eac95a04da648ba95a558a0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 16 Mar 2025 14:31:01 +0100 Subject: [PATCH 1193/1312] adapter: replace 'interface' with 'adapter driver' Comments and output strings still reference the term 'interface', while 'adapter driver' should be used. While there, drop the useless test if CMD_ARGV[0] is an empty string, as this is not possible when CMD_ARGC > 0. Change-Id: I7b46b5dd3cec53d8b5b7559d941ee9ae3bd1d89b Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8808 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/adapter.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 2fcbd609e8..0bdfe7b134 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -187,7 +187,6 @@ int adapter_init(struct command_context *cmd_ctx) int adapter_quit(void) { if (is_adapter_initialized() && adapter_driver->quit) { - /* close the JTAG interface */ int result = adapter_driver->quit(); if (result != ERROR_OK) LOG_ERROR("failed: %d", result); @@ -380,7 +379,7 @@ bool adapter_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, size_t path COMMAND_HANDLER(handle_adapter_name) { - /* return the name of the interface */ + /* return the name of the adapter driver */ /* TCL code might need to know the exact type... */ /* FUTURE: we allow this as a means to "set" the interface. */ @@ -414,14 +413,14 @@ COMMAND_HANDLER(handle_adapter_driver_command) { int retval; - /* check whether the interface is already configured */ + /* check whether the adapter driver is already configured */ if (adapter_driver) { - LOG_WARNING("Interface already configured, ignoring"); + LOG_WARNING("Adapter driver already configured, ignoring"); return ERROR_OK; } - /* interface name is a mandatory argument */ - if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0') + /* adapter driver name is a mandatory argument */ + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; for (unsigned int i = 0; adapter_drivers[i]; i++) { @@ -439,10 +438,10 @@ COMMAND_HANDLER(handle_adapter_driver_command) return allow_transports(CMD_CTX, adapter_driver->transports); } - /* no valid interface was found (i.e. the configuration option, - * didn't match one of the compiled-in interfaces + /* no valid adapter driver was found (i.e. the configuration option, + * didn't match one of the compiled-in drivers */ - LOG_ERROR("The specified debug interface was not found (%s)", + LOG_ERROR("The specified adapter driver was not found (%s)", CMD_ARGV[0]); command_print(CMD, "The following adapter drivers are available:"); CALL_COMMAND_HANDLER(dump_adapter_driver_list); From da50873d5ebe558ee545c1a00f31df9e23f45456 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 Jan 2025 18:41:41 +0100 Subject: [PATCH 1194/1312] adapter: list supported transports beside adapter name Modify the command 'adapter list' to output the list of transports supported by each adapter driver. Drop the line number, as there is no real interest on it. Format the output as a TCL dictionary indexed by the adapter name and containing the transports in a TCL list. E.g: dummy { jtag } ftdi { jtag swd } This format is easily handled by TCL scripts, e.g.: dict get [adapter list] ftdi Document the command output. Change-Id: I69f73b71da2f1756866a63bc2c0ba33459a29063 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8691 Tested-by: jenkins --- doc/openocd.texi | 11 +++++++++++ src/jtag/adapter.c | 14 +++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 32a2895ecf..d85812824f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2414,6 +2414,17 @@ target. @deffn {Command} {adapter list} List the debug adapter drivers that have been built into the running copy of OpenOCD. + +The output is formatted as a Tcl dictionary indexed by the adapter name +and containing the transports in a Tcl list. +@example +dummy @{ jtag @} +ftdi @{ jtag swd @} +@end example +This format is easily handled by Tcl scripts: +@example +dict get [adapter list] ftdi +@end example @end deffn @anchor{adapter gpio} diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 0bdfe7b134..6947217461 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -393,9 +393,21 @@ COMMAND_HANDLER(handle_adapter_name) COMMAND_HANDLER(dump_adapter_driver_list) { + int max_len = 0; + for (unsigned int i = 0; adapter_drivers[i]; i++) { + int len = strlen(adapter_drivers[i]->name); + if (max_len < len) + max_len = len; + } + for (unsigned int i = 0; adapter_drivers[i]; i++) { const char *name = adapter_drivers[i]->name; - command_print(CMD, "%u: %s", i + 1, name); + const char * const *transports = adapter_drivers[i]->transports; + + command_print_sameline(CMD, "%-*s {", max_len, name); + for (unsigned int j = 0; transports[j]; j++) + command_print_sameline(CMD, " %s", transports[j]); + command_print(CMD, " }"); } return ERROR_OK; From 9a5de74423503d1bd16e16b77b4e0e6d19913057 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 4 Jan 2025 16:54:14 +0100 Subject: [PATCH 1195/1312] transport: deprecate auto-selection of transport Historically, if the user does not specify a transport, OpenOCD select automatically the first transport listed in the adapter driver. This auto-selection can behave differently by changing adapter, so the transport should be enforced in the configuration file. Deprecate the auto-selection and print a warning message when a transport gets auto-selected. There are two cases: - adapter offers one transport only. The code early auto-selects the transport but does not print anything. If later the user selects the transport then no deprecation will be printed during 'transport init'; - user runs 'transport select', e.g. in 'swj-dp' script, and this triggers the auto-selection and the deprecated message. Change-Id: I2e55b9dcc6da77ca937978fbfb36bc365b803f0d Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8692 Reviewed-by: Jan Matyas Reviewed-by: zapb Tested-by: jenkins --- src/transport/transport.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/transport/transport.c b/src/transport/transport.c index 0af1360369..4a1f71d406 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -52,6 +52,11 @@ static struct transport *transport_list; */ static const char * const *allowed_transports; +/** + * Adapter supports a single transport; it has been auto-selected + */ +static bool transport_single_is_autoselected; + /** * The transport being used for the current OpenOCD session. */ static struct transport *session; @@ -104,7 +109,8 @@ int allow_transports(struct command_context *ctx, const char * const *vector) /* autoselect if there's no choice ... */ if (!vector[1]) { - LOG_INFO("only one transport option; autoselecting '%s'", vector[0]); + LOG_DEBUG("only one transport option; autoselecting '%s'", vector[0]); + transport_single_is_autoselected = true; return transport_select(ctx, vector[0]); } @@ -182,6 +188,11 @@ COMMAND_HANDLER(handle_transport_init) return ERROR_FAIL; } + if (transport_single_is_autoselected) + LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". " + "Use 'transport select %s' to suppress this message.", + session->name, session->name); + return session->init(CMD_CTX); } @@ -216,8 +227,9 @@ COMMAND_HANDLER(handle_transport_select) command_print(CMD, "Debug adapter does not support any transports? Check config file order."); return ERROR_FAIL; } - LOG_INFO("auto-selecting first available session transport \"%s\". " - "To override use 'transport select '.", allowed_transports[0]); + LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". " + "Use 'transport select %s' to suppress this message.", + allowed_transports[0], allowed_transports[0]); int retval = transport_select(CMD_CTX, allowed_transports[0]); if (retval != ERROR_OK) return retval; @@ -229,6 +241,11 @@ COMMAND_HANDLER(handle_transport_select) /* assign transport */ if (session) { if (!strcmp(session->name, CMD_ARGV[0])) { + if (transport_single_is_autoselected) { + /* Nothing to do, but also nothing to complain */ + transport_single_is_autoselected = false; + return ERROR_OK; + } LOG_WARNING("Transport \"%s\" was already selected", session->name); return ERROR_OK; } From 236208a5ff2db5f502444b32da1df3fd17b692fb Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 22 Dec 2024 17:06:12 +0100 Subject: [PATCH 1196/1312] transport: use a bitmask for the transport Move the transport's names in a local array in the transport framework. Replace the string struct transport::name, that identifies the transport, with a bitmask where each bit corresponds to one of the available transports. Change-Id: I6bdf7264d5979c355299f63fcf80bf54dcd95cee Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8674 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/core.c | 10 +++--- src/jtag/hla/hla_transport.c | 19 ++++++---- src/jtag/swim.c | 2 +- src/target/adi_v5_dapdirect.c | 4 +-- src/target/adi_v5_swd.c | 2 +- src/transport/transport.c | 68 +++++++++++++++++++++++++++++------ src/transport/transport.h | 28 ++++++++++++--- 7 files changed, 102 insertions(+), 31 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index 030c173be6..6dd2144c63 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1823,7 +1823,7 @@ static int jtag_select(struct command_context *ctx) } static struct transport jtag_transport = { - .name = "jtag", + .id = TRANSPORT_JTAG, .select = jtag_select, .init = jtag_init, }; @@ -1868,7 +1868,7 @@ int adapter_resets(int trst, int srst) transport_is_swim()) { if (trst == TRST_ASSERT) { LOG_ERROR("transport %s has no trst signal", - get_current_transport()->name); + get_current_transport_name()); return ERROR_FAIL; } @@ -1884,7 +1884,7 @@ int adapter_resets(int trst, int srst) return ERROR_OK; LOG_ERROR("reset is not supported on transport %s", - get_current_transport()->name); + get_current_transport_name()); return ERROR_FAIL; } @@ -1903,7 +1903,7 @@ int adapter_assert_reset(void) return adapter_system_reset(1); else if (get_current_transport()) LOG_ERROR("reset is not supported on %s", - get_current_transport()->name); + get_current_transport_name()); else LOG_ERROR("transport is not selected"); return ERROR_FAIL; @@ -1920,7 +1920,7 @@ int adapter_deassert_reset(void) return adapter_system_reset(0); else if (get_current_transport()) LOG_ERROR("reset is not supported on %s", - get_current_transport()->name); + get_current_transport_name()); else LOG_ERROR("transport is not selected"); return ERROR_FAIL; diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c index b826eb0fe6..333825eff1 100644 --- a/src/jtag/hla/hla_transport.c +++ b/src/jtag/hla/hla_transport.c @@ -177,15 +177,20 @@ static int hl_transport_init(struct command_context *cmd_ctx) return ERROR_FAIL; } - LOG_DEBUG("current transport %s", transport->name); + LOG_DEBUG("current transport %s", get_current_transport_name()); /* get selected transport as enum */ - tr = HL_TRANSPORT_UNKNOWN; - - if (strcmp(transport->name, "hla_swd") == 0) + switch (transport->id) { + case TRANSPORT_HLA_SWD: tr = HL_TRANSPORT_SWD; - else if (strcmp(transport->name, "hla_jtag") == 0) + break; + case TRANSPORT_HLA_JTAG: tr = HL_TRANSPORT_JTAG; + break; + default: + tr = HL_TRANSPORT_UNKNOWN; + break; + } int retval = hl_interface_open(tr); @@ -213,14 +218,14 @@ static int hl_swd_transport_select(struct command_context *cmd_ctx) } static struct transport hl_swd_transport = { - .name = "hla_swd", + .id = TRANSPORT_HLA_SWD, .select = hl_swd_transport_select, .init = hl_transport_init, .override_target = hl_interface_override_target, }; static struct transport hl_jtag_transport = { - .name = "hla_jtag", + .id = TRANSPORT_HLA_JTAG, .select = hl_jtag_transport_select, .init = hl_transport_init, .override_target = hl_interface_override_target, diff --git a/src/jtag/swim.c b/src/jtag/swim.c index de3e106a1a..004a9fd4f2 100644 --- a/src/jtag/swim.c +++ b/src/jtag/swim.c @@ -136,7 +136,7 @@ static int swim_transport_init(struct command_context *cmd_ctx) } static struct transport swim_transport = { - .name = "swim", + .id = TRANSPORT_SWIM, .select = swim_transport_select, .init = swim_transport_init, }; diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c index d198dacf39..07ea313d19 100644 --- a/src/target/adi_v5_dapdirect.c +++ b/src/target/adi_v5_dapdirect.c @@ -207,13 +207,13 @@ static int dapdirect_init(struct command_context *ctx) } static struct transport dapdirect_jtag_transport = { - .name = "dapdirect_jtag", + .id = TRANSPORT_DAPDIRECT_JTAG, .select = dapdirect_jtag_select, .init = dapdirect_init, }; static struct transport dapdirect_swd_transport = { - .name = "dapdirect_swd", + .id = TRANSPORT_DAPDIRECT_SWD, .select = dapdirect_swd_select, .init = dapdirect_init, }; diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index e50f8f1371..2d286136a5 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -756,7 +756,7 @@ static int swd_init(struct command_context *ctx) } static struct transport swd_transport = { - .name = "swd", + .id = TRANSPORT_SWD, .select = swd_select, .init = swd_init, }; diff --git a/src/transport/transport.c b/src/transport/transport.c index 4a1f71d406..411b0a5e0f 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -30,6 +30,8 @@ * messaging and error handling. */ +#include +#include #include #include #include @@ -43,6 +45,20 @@ extern struct command_context *global_cmd_ctx; */ /** List of transports known to OpenOCD. */ +static const struct { + unsigned int id; + const char *name; +} transport_names[] = { + { TRANSPORT_JTAG, "jtag", }, + { TRANSPORT_SWD, "swd", }, + { TRANSPORT_HLA_JTAG, "hla_jtag", }, + { TRANSPORT_HLA_SWD, "hla_swd", }, + { TRANSPORT_DAPDIRECT_JTAG, "dapdirect_jtag", }, + { TRANSPORT_DAPDIRECT_SWD, "dapdirect_swd", }, + { TRANSPORT_SWIM, "swim", }, +}; + +/** List of transports registered in OpenOCD. */ static struct transport *transport_list; /** @@ -60,12 +76,26 @@ static bool transport_single_is_autoselected; /** * The transport being used for the current OpenOCD session. */ static struct transport *session; +static const char *transport_name(unsigned int id) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++) + if (id == transport_names[i].id) + return transport_names[i].name; + + return NULL; +} + +static bool is_transport_id_valid(unsigned int id) +{ + return (id != 0) && ((id & ~TRANSPORT_VALID_MASK) == 0) && IS_PWR_OF_2(id); +} + static int transport_select(struct command_context *ctx, const char *name) { /* name may only identify a known transport; * caller guarantees session's transport isn't yet set.*/ for (struct transport *t = transport_list; t; t = t->next) { - if (strcmp(t->name, name) == 0) { + if (!strcmp(transport_name(t->id), name)) { int retval = t->select(ctx); /* select() registers commands specific to this * transport, and may also reset the link, e.g. @@ -74,7 +104,7 @@ static int transport_select(struct command_context *ctx, const char *name) if (retval == ERROR_OK) session = t; else - LOG_ERROR("Error selecting '%s' as transport", t->name); + LOG_ERROR("Error selecting '%s' as transport", name); return retval; } } @@ -136,20 +166,28 @@ int transport_register(struct transport *new_transport) { struct transport *t; + if (!is_transport_id_valid(new_transport->id)) { + LOG_ERROR("invalid transport ID 0x%x", new_transport->id); + return ERROR_FAIL; + } + for (t = transport_list; t; t = t->next) { - if (strcmp(t->name, new_transport->name) == 0) { - LOG_ERROR("transport name already used"); + if (t->id == new_transport->id) { + LOG_ERROR("transport '%s' already registered", + transport_name(t->id)); return ERROR_FAIL; } } if (!new_transport->select || !new_transport->init) - LOG_ERROR("invalid transport %s", new_transport->name); + LOG_ERROR("invalid transport %s", + transport_name(new_transport->id)); /* splice this into the list */ new_transport->next = transport_list; transport_list = new_transport; - LOG_DEBUG("register '%s'", new_transport->name); + LOG_DEBUG("register '%s' (ID %d)", + transport_name(new_transport->id), new_transport->id); return ERROR_OK; } @@ -166,6 +204,14 @@ struct transport *get_current_transport(void) return session; } +const char *get_current_transport_name(void) +{ + if (!session || !is_transport_id_valid(session->id)) + NULL; + + return transport_name(session->id); +} + /*-----------------------------------------------------------------------*/ /* @@ -191,7 +237,7 @@ COMMAND_HANDLER(handle_transport_init) if (transport_single_is_autoselected) LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". " "Use 'transport select %s' to suppress this message.", - session->name, session->name); + transport_name(session->id), transport_name(session->id)); return session->init(CMD_CTX); } @@ -204,7 +250,7 @@ COMMAND_HANDLER(handle_transport_list) command_print(CMD, "The following transports are available:"); for (struct transport *t = transport_list; t; t = t->next) - command_print(CMD, "\t%s", t->name); + command_print(CMD, "\t%s", transport_name(t->id)); return ERROR_OK; } @@ -234,19 +280,19 @@ COMMAND_HANDLER(handle_transport_select) if (retval != ERROR_OK) return retval; } - command_print(CMD, "%s", session->name); + command_print(CMD, "%s", transport_name(session->id)); return ERROR_OK; } /* assign transport */ if (session) { - if (!strcmp(session->name, CMD_ARGV[0])) { + if (!strcmp(transport_name(session->id), CMD_ARGV[0])) { if (transport_single_is_autoselected) { /* Nothing to do, but also nothing to complain */ transport_single_is_autoselected = false; return ERROR_OK; } - LOG_WARNING("Transport \"%s\" was already selected", session->name); + LOG_WARNING("Transport \"%s\" was already selected", CMD_ARGV[0]); return ERROR_OK; } command_print(CMD, "Can't change session's transport after the initial selection was made"); diff --git a/src/transport/transport.h b/src/transport/transport.h index 2e3dcc61aa..dde7c6ba76 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -12,8 +12,27 @@ #include "config.h" #endif +#include "helper/bits.h" #include "helper/command.h" +#define TRANSPORT_JTAG BIT(0) +#define TRANSPORT_SWD BIT(1) +#define TRANSPORT_HLA_JTAG BIT(2) +#define TRANSPORT_HLA_SWD BIT(3) +#define TRANSPORT_DAPDIRECT_JTAG BIT(4) +#define TRANSPORT_DAPDIRECT_SWD BIT(5) +#define TRANSPORT_SWIM BIT(6) + +/* mask for valid ID */ +#define TRANSPORT_VALID_MASK \ + (TRANSPORT_JTAG | \ + TRANSPORT_SWD | \ + TRANSPORT_HLA_JTAG | \ + TRANSPORT_HLA_SWD | \ + TRANSPORT_DAPDIRECT_JTAG | \ + TRANSPORT_DAPDIRECT_SWD | \ + TRANSPORT_SWIM) + /** * Wrapper for transport lifecycle operations. * @@ -34,11 +53,10 @@ */ struct transport { /** - * Each transport has a unique name, used to select it - * from among the alternatives. Examples might include - * "jtag", * "swd", "AVR_ISP" and more. + * Each transport has a unique ID, used to select it + * from among the alternatives. */ - const char *name; + unsigned int id; /** * When a transport is selected, this method registers @@ -75,6 +93,8 @@ int transport_register(struct transport *new_transport); struct transport *get_current_transport(void); +const char *get_current_transport_name(void); + int transport_register_commands(struct command_context *ctx); int allow_transports(struct command_context *ctx, const char * const *vector); From a500b2ce67eb80870dfbd5d73118e822ac99ef88 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 12 Feb 2025 16:39:18 +0100 Subject: [PATCH 1197/1312] adapter: use bitmask for driver's transports In every driver, replace the array of strings with a bitmask that lists the supported transports. Add an extra field to carry the former first listed transport as a "preferred" transport. It would be used as default when no command 'transport select' is used. This keeps backward compatibility with scripts that do not define the transport, relying on such default. Change-Id: I4976583f1a38fdcc1f85045023dc7c629001f743 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8675 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/adapter.c | 12 +++--- src/jtag/drivers/am335xgpio.c | 5 +-- src/jtag/drivers/amt_jtagaccel.c | 3 +- src/jtag/drivers/angie.c | 3 +- src/jtag/drivers/arm-jtag-ew.c | 3 +- src/jtag/drivers/at91rm9200.c | 3 +- src/jtag/drivers/bcm2835gpio.c | 5 +-- src/jtag/drivers/buspirate.c | 5 +-- src/jtag/drivers/cmsis_dap.c | 5 +-- src/jtag/drivers/dmem.c | 5 +-- src/jtag/drivers/dummy.c | 3 +- src/jtag/drivers/ep93xx.c | 3 +- src/jtag/drivers/esp_usb_jtag.c | 3 +- src/jtag/drivers/ft232r.c | 3 +- src/jtag/drivers/ftdi.c | 5 +-- src/jtag/drivers/gw16012.c | 3 +- src/jtag/drivers/imx_gpio.c | 5 +-- src/jtag/drivers/jlink.c | 5 +-- src/jtag/drivers/jtag_dpi.c | 3 +- src/jtag/drivers/jtag_vpi.c | 3 +- src/jtag/drivers/kitprog.c | 5 +-- src/jtag/drivers/linuxgpiod.c | 5 +-- src/jtag/drivers/linuxspidev.c | 6 +-- src/jtag/drivers/opendous.c | 3 +- src/jtag/drivers/openjtag.c | 3 +- src/jtag/drivers/osbdm.c | 3 +- src/jtag/drivers/parport.c | 3 +- src/jtag/drivers/presto.c | 3 +- src/jtag/drivers/remote_bitbang.c | 5 +-- src/jtag/drivers/rlink.c | 3 +- src/jtag/drivers/rshim.c | 5 +-- src/jtag/drivers/stlink_usb.c | 5 +-- src/jtag/drivers/sysfsgpio.c | 5 +-- src/jtag/drivers/ulink.c | 3 +- src/jtag/drivers/usb_blaster/usb_blaster.c | 3 +- src/jtag/drivers/usbprog.c | 3 +- src/jtag/drivers/vdebug.c | 5 +-- src/jtag/drivers/vsllink.c | 5 +-- src/jtag/drivers/xds110.c | 5 +-- src/jtag/drivers/xlnx-pcie-xvc.c | 5 +-- src/jtag/hla/hla_interface.c | 3 +- src/jtag/hla/hla_interface.h | 2 - src/jtag/hla/hla_transport.c | 2 - src/jtag/interface.h | 15 +++++-- src/transport/transport.c | 47 +++++++++++++--------- src/transport/transport.h | 5 ++- 46 files changed, 129 insertions(+), 113 deletions(-) diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 6947217461..6785a74ef1 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -16,6 +16,7 @@ #include "minidriver.h" #include "interface.h" #include "interfaces.h" +#include #include /** @@ -24,7 +25,6 @@ */ struct adapter_driver *adapter_driver; -const char * const jtag_only[] = { "jtag", NULL }; enum adapter_clk_mode { CLOCK_MODE_UNSELECTED = 0, @@ -402,11 +402,12 @@ COMMAND_HANDLER(dump_adapter_driver_list) for (unsigned int i = 0; adapter_drivers[i]; i++) { const char *name = adapter_drivers[i]->name; - const char * const *transports = adapter_drivers[i]->transports; + unsigned int transport_ids = adapter_drivers[i]->transport_ids; command_print_sameline(CMD, "%-*s {", max_len, name); - for (unsigned int j = 0; transports[j]; j++) - command_print_sameline(CMD, " %s", transports[j]); + for (unsigned int j = BIT(0); j & TRANSPORT_VALID_MASK; j <<= 1) + if (j & transport_ids) + command_print_sameline(CMD, " %s", transport_name(j)); command_print(CMD, " }"); } @@ -447,7 +448,8 @@ COMMAND_HANDLER(handle_adapter_driver_command) adapter_driver = adapter_drivers[i]; - return allow_transports(CMD_CTX, adapter_driver->transports); + return allow_transports(CMD_CTX, adapter_driver->transport_ids, + adapter_driver->transport_preferred_id); } /* no valid adapter driver was found (i.e. the configuration option, diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index cacf4e7c79..a4727cc891 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -350,8 +350,6 @@ static const struct command_registration am335xgpio_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const char * const am335xgpio_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface am335xgpio_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, @@ -494,7 +492,8 @@ static int am335xgpio_quit(void) struct adapter_driver am335xgpio_adapter_driver = { .name = "am335xgpio", - .transports = am335xgpio_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = am335xgpio_command_handlers, .init = am335xgpio_init, diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index 80254ff074..633c20413a 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -579,7 +579,8 @@ static struct jtag_interface amt_jtagaccel_interface = { struct adapter_driver amt_jtagaccel_adapter_driver = { .name = "amt_jtagaccel", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = amtjtagaccel_command_handlers, .init = amt_jtagaccel_init, diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 46a4c82e5b..56a118eaed 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -2388,7 +2388,8 @@ static struct jtag_interface angie_interface = { struct adapter_driver angie_adapter_driver = { .name = "angie", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .init = angie_init, .quit = angie_quit, diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index 45e03840ea..9d8c592edb 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -486,7 +486,8 @@ static struct jtag_interface armjtagew_interface = { struct adapter_driver armjtagew_adapter_driver = { .name = "arm-jtag-ew", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = armjtagew_command_handlers, .init = armjtagew_init, diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c index a77e29aa6e..ddcf857a6b 100644 --- a/src/jtag/drivers/at91rm9200.c +++ b/src/jtag/drivers/at91rm9200.c @@ -186,7 +186,8 @@ static struct jtag_interface at91rm9200_interface = { struct adapter_driver at91rm9200_adapter_driver = { .name = "at91rm9200", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = at91rm9200_command_handlers, .init = at91rm9200_init, diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index e8689aa037..1a105aac44 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -590,15 +590,14 @@ static int bcm2835gpio_quit(void) } -static const char * const bcm2835_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface bcm2835gpio_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, }; struct adapter_driver bcm2835gpio_adapter_driver = { .name = "bcm2835gpio", - .transports = bcm2835_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = bcm2835gpio_command_handlers, .init = bcm2835gpio_init, diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index 93f0ba3838..4283616adc 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -534,15 +534,14 @@ static const struct swd_driver buspirate_swd = { .run = buspirate_swd_run_queue, }; -static const char * const buspirate_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface buspirate_interface = { .execute_queue = buspirate_execute_queue, }; struct adapter_driver buspirate_adapter_driver = { .name = "buspirate", - .transports = buspirate_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = buspirate_command_handlers, .init = buspirate_init, diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index be9ebaed58..2bfcfcc2b0 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -2314,8 +2314,6 @@ static const struct swd_driver cmsis_dap_swd_driver = { .run = cmsis_dap_swd_run_queue, }; -static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL }; - static struct jtag_interface cmsis_dap_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = cmsis_dap_execute_queue, @@ -2323,7 +2321,8 @@ static struct jtag_interface cmsis_dap_interface = { struct adapter_driver cmsis_dap_adapter_driver = { .name = "cmsis-dap", - .transports = cmsis_dap_transport, + .transport_ids = TRANSPORT_SWD | TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_SWD, .commands = cmsis_dap_command_handlers, .init = cmsis_dap_init, diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c index 4dc582115c..e50e84aeeb 100644 --- a/src/jtag/drivers/dmem.c +++ b/src/jtag/drivers/dmem.c @@ -604,11 +604,10 @@ static const struct dap_ops dmem_dap_ops = { .run = dmem_dp_run, }; -static const char *const dmem_dap_transport[] = { "dapdirect_swd", NULL }; - struct adapter_driver dmem_dap_adapter_driver = { .name = "dmem", - .transports = dmem_dap_transport, + .transport_ids = TRANSPORT_DAPDIRECT_SWD, + .transport_preferred_id = TRANSPORT_DAPDIRECT_SWD, .commands = dmem_dap_command_handlers, .init = dmem_dap_init, diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index 79b29fbae7..471668c3ab 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -140,7 +140,8 @@ static struct jtag_interface dummy_interface = { struct adapter_driver dummy_adapter_driver = { .name = "dummy", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = dummy_command_handlers, .init = &dummy_init, diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c index ea9faf19b7..f3e1676f9f 100644 --- a/src/jtag/drivers/ep93xx.c +++ b/src/jtag/drivers/ep93xx.c @@ -46,7 +46,8 @@ static struct jtag_interface ep93xx_interface = { struct adapter_driver ep93xx_adapter_driver = { .name = "ep93xx", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .init = ep93xx_init, .quit = ep93xx_quit, diff --git a/src/jtag/drivers/esp_usb_jtag.c b/src/jtag/drivers/esp_usb_jtag.c index 9504059543..a133035110 100644 --- a/src/jtag/drivers/esp_usb_jtag.c +++ b/src/jtag/drivers/esp_usb_jtag.c @@ -784,7 +784,8 @@ static struct jtag_interface esp_usb_jtag_interface = { struct adapter_driver esp_usb_adapter_driver = { .name = "esp_usb_jtag", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = esp_usb_jtag_commands, .init = esp_usb_jtag_init, diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index f4e5af4dd4..f88e4b9408 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -900,7 +900,8 @@ static struct jtag_interface ft232r_interface = { struct adapter_driver ft232r_adapter_driver = { .name = "ft232r", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = ft232r_command_handlers, .init = ft232r_init, diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index ec0ae4c00b..a8f6f60159 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -1247,8 +1247,6 @@ static const struct swd_driver ftdi_swd = { .run = ftdi_swd_run_queue, }; -static const char * const ftdi_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface ftdi_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = ftdi_execute_queue, @@ -1256,7 +1254,8 @@ static struct jtag_interface ftdi_interface = { struct adapter_driver ftdi_adapter_driver = { .name = "ftdi", - .transports = ftdi_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = ftdi_command_handlers, .init = ftdi_initialize, diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index 7200e757c7..805065f1f4 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -514,7 +514,8 @@ static struct jtag_interface gw16012_interface = { struct adapter_driver gw16012_adapter_driver = { .name = "gw16012", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = gw16012_command_handlers, .init = gw16012_init, diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c index 18dc2ddf67..a4a76ca5a3 100644 --- a/src/jtag/drivers/imx_gpio.c +++ b/src/jtag/drivers/imx_gpio.c @@ -417,8 +417,6 @@ static const struct command_registration imx_gpio_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface imx_gpio_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, @@ -426,7 +424,8 @@ static struct jtag_interface imx_gpio_interface = { struct adapter_driver imx_gpio_adapter_driver = { .name = "imx_gpio", - .transports = imx_gpio_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = imx_gpio_command_handlers, .init = imx_gpio_init, diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 4d15cf5e63..9caf37f6f0 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -2264,15 +2264,14 @@ static const struct swd_driver jlink_swd = { .run = &jlink_swd_run_queue, }; -static const char * const jlink_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface jlink_interface = { .execute_queue = &jlink_execute_queue, }; struct adapter_driver jlink_adapter_driver = { .name = "jlink", - .transports = jlink_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = jlink_command_handlers, .init = &jlink_init, diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c index 046186a619..d6418d39c7 100644 --- a/src/jtag/drivers/jtag_dpi.c +++ b/src/jtag/drivers/jtag_dpi.c @@ -398,7 +398,8 @@ static struct jtag_interface jtag_dpi_interface = { struct adapter_driver jtag_dpi_adapter_driver = { .name = "jtag_dpi", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = jtag_dpi_command_handlers, .init = jtag_dpi_init, .quit = jtag_dpi_quit, diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index f6cb3de5d2..fac27b3060 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -666,7 +666,8 @@ static struct jtag_interface jtag_vpi_interface = { struct adapter_driver jtag_vpi_adapter_driver = { .name = "jtag_vpi", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = jtag_vpi_command_handlers, .init = jtag_vpi_init, diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c index 98b0d16681..88e301cebc 100644 --- a/src/jtag/drivers/kitprog.c +++ b/src/jtag/drivers/kitprog.c @@ -908,11 +908,10 @@ static const struct swd_driver kitprog_swd = { .run = kitprog_swd_run_queue, }; -static const char * const kitprog_transports[] = { "swd", NULL }; - struct adapter_driver kitprog_adapter_driver = { .name = "kitprog", - .transports = kitprog_transports, + .transport_ids = TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_SWD, .commands = kitprog_command_handlers, .init = kitprog_init, diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index eda7b1a80e..36c7e04934 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -425,8 +425,6 @@ static int linuxgpiod_init(void) return ERROR_JTAG_INIT_FAILED; } -static const char *const linuxgpiod_transport[] = { "swd", "jtag", NULL }; - static struct jtag_interface linuxgpiod_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, @@ -434,7 +432,8 @@ static struct jtag_interface linuxgpiod_interface = { struct adapter_driver linuxgpiod_adapter_driver = { .name = "linuxgpiod", - .transports = linuxgpiod_transport, + .transport_ids = TRANSPORT_SWD | TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_SWD, .init = linuxgpiod_init, .quit = linuxgpiod_quit, diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c index 18abdc7db3..396f1a19a9 100644 --- a/src/jtag/drivers/linuxspidev.c +++ b/src/jtag/drivers/linuxspidev.c @@ -616,12 +616,10 @@ static const struct command_registration spidev_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -// Only SWD transport supported -static const char *const spidev_transports[] = { "swd", NULL }; - struct adapter_driver linuxspidev_adapter_driver = { .name = "linuxspidev", - .transports = spidev_transports, + .transport_ids = TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_SWD, .commands = spidev_command_handlers, .init = spidev_init, diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index 999afb3fc7..04626cb1e5 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -229,7 +229,8 @@ static struct jtag_interface opendous_interface = { struct adapter_driver opendous_adapter_driver = { .name = "opendous", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = opendous_command_handlers, .init = opendous_init, diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 14bcc171eb..943ad854e8 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -931,7 +931,8 @@ static struct jtag_interface openjtag_interface = { struct adapter_driver openjtag_adapter_driver = { .name = "openjtag", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = openjtag_command_handlers, .init = openjtag_init, diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index 80f66d197e..de2e1f8ebe 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -684,7 +684,8 @@ static struct jtag_interface osbdm_interface = { struct adapter_driver osbdm_adapter_driver = { .name = "osbdm", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .init = osbdm_init, .quit = osbdm_quit, diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index 3b20fe2478..143f3bde1f 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -533,7 +533,8 @@ static struct jtag_interface parport_interface = { struct adapter_driver parport_adapter_driver = { .name = "parport", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = parport_command_handlers, .init = parport_init, diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c index f6e13f7eb4..84b881cdc8 100644 --- a/src/jtag/drivers/presto.c +++ b/src/jtag/drivers/presto.c @@ -528,7 +528,8 @@ static struct jtag_interface presto_interface = { struct adapter_driver presto_adapter_driver = { .name = "presto", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .init = presto_jtag_init, .quit = presto_jtag_quit, diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index bb608ba0a5..449c616545 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -412,8 +412,6 @@ COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command) return ERROR_COMMAND_SYNTAX_ERROR; } -static const char * const remote_bitbang_transports[] = { "jtag", "swd", NULL }; - COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_use_remote_sleep_command) { if (CMD_ARGC != 1) @@ -484,7 +482,8 @@ static struct jtag_interface remote_bitbang_interface = { struct adapter_driver remote_bitbang_adapter_driver = { .name = "remote_bitbang", - .transports = remote_bitbang_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = remote_bitbang_command_handlers, .init = &remote_bitbang_init, diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index 6ea3729a5f..a818996255 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -1675,7 +1675,8 @@ static struct jtag_interface rlink_interface = { struct adapter_driver rlink_adapter_driver = { .name = "rlink", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .init = rlink_init, .quit = rlink_quit, diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index b37fe8c453..89bdadd698 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -508,11 +508,10 @@ static const struct dap_ops rshim_dap_ops = { .quit = rshim_disconnect, }; -static const char *const rshim_dap_transport[] = { "dapdirect_swd", NULL }; - struct adapter_driver rshim_dap_adapter_driver = { .name = "rshim", - .transports = rshim_dap_transport, + .transport_ids = TRANSPORT_DAPDIRECT_SWD, + .transport_preferred_id = TRANSPORT_DAPDIRECT_SWD, .commands = rshim_dap_command_handlers, .init = rshim_dap_init, diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index d77f28b0f4..e018f71cd9 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -5217,11 +5217,10 @@ static const struct swim_driver stlink_swim_ops = { .reconnect = stlink_swim_op_reconnect, }; -static const char *const stlink_dap_transport[] = { "dapdirect_swd", "dapdirect_jtag", "swim", NULL }; - struct adapter_driver stlink_dap_adapter_driver = { .name = "st-link", - .transports = stlink_dap_transport, + .transport_ids = TRANSPORT_DAPDIRECT_SWD | TRANSPORT_DAPDIRECT_JTAG | TRANSPORT_SWIM, + .transport_preferred_id = TRANSPORT_DAPDIRECT_SWD, .commands = stlink_dap_command_handlers, .init = stlink_dap_init, diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c index ccd3974a42..279b35377c 100644 --- a/src/jtag/drivers/sysfsgpio.c +++ b/src/jtag/drivers/sysfsgpio.c @@ -545,8 +545,6 @@ static const struct command_registration sysfsgpio_command_handlers[] = { static int sysfsgpio_init(void); static int sysfsgpio_quit(void); -static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL }; - static struct jtag_interface sysfsgpio_interface = { .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, @@ -554,7 +552,8 @@ static struct jtag_interface sysfsgpio_interface = { struct adapter_driver sysfsgpio_adapter_driver = { .name = "sysfsgpio", - .transports = sysfsgpio_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = sysfsgpio_command_handlers, .init = sysfsgpio_init, diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 0a13bf6d44..417d560cde 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -2271,7 +2271,8 @@ static struct jtag_interface ulink_interface = { struct adapter_driver ulink_adapter_driver = { .name = "ulink", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = ulink_command_handlers, .init = ulink_init, diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 1782cc424e..81344664e2 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -1057,7 +1057,8 @@ static struct jtag_interface usb_blaster_interface = { struct adapter_driver usb_blaster_adapter_driver = { .name = "usb_blaster", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .commands = ublast_command_handlers, .init = ublast_init, diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index 24407f0037..264b45f721 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -590,7 +590,8 @@ static struct jtag_interface usbprog_interface = { struct adapter_driver usbprog_adapter_driver = { .name = "usbprog", - .transports = jtag_only, + .transport_ids = TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_JTAG, .init = usbprog_init, .quit = usbprog_quit, diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index fd1e6a7e7b..38685950a8 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -1342,11 +1342,10 @@ static const struct dap_ops vdebug_dap_ops = { .quit = NULL, /* optional */ }; -static const char *const vdebug_transports[] = { "jtag", "dapdirect_swd", NULL }; - struct adapter_driver vdebug_adapter_driver = { .name = "vdebug", - .transports = vdebug_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_DAPDIRECT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .speed = vdebug_jtag_speed, .khz = vdebug_jtag_khz, .speed_div = vdebug_jtag_div, diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index c10ed13800..145f0682ac 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -913,8 +913,6 @@ static const struct command_registration vsllink_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -static const char * const vsllink_transports[] = {"jtag", "swd", NULL}; - static const struct swd_driver vsllink_swd_driver = { .init = vsllink_swd_init, .switch_seq = vsllink_swd_switch_seq, @@ -930,7 +928,8 @@ static struct jtag_interface vsllink_interface = { struct adapter_driver vsllink_adapter_driver = { .name = "vsllink", - .transports = vsllink_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = vsllink_command_handlers, .init = vsllink_init, diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index c84371001f..d1bb705908 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -2058,15 +2058,14 @@ static const struct swd_driver xds110_swd_driver = { .run = xds110_swd_run_queue, }; -static const char * const xds110_transport[] = { "swd", "jtag", NULL }; - static struct jtag_interface xds110_interface = { .execute_queue = xds110_execute_queue, }; struct adapter_driver xds110_adapter_driver = { .name = "xds110", - .transports = xds110_transport, + .transport_ids = TRANSPORT_SWD | TRANSPORT_JTAG, + .transport_preferred_id = TRANSPORT_SWD, .commands = xds110_command_handlers, .init = xds110_init, diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index 37c6777e4e..3baa183d95 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -690,11 +690,10 @@ static const struct swd_driver xlnx_pcie_xvc_swd_ops = { .run = xlnx_pcie_xvc_swd_run_queue, }; -static const char * const xlnx_pcie_xvc_transports[] = { "jtag", "swd", NULL }; - struct adapter_driver xlnx_pcie_xvc_adapter_driver = { .name = "xlnx_pcie_xvc", - .transports = xlnx_pcie_xvc_transports, + .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD, + .transport_preferred_id = TRANSPORT_JTAG, .commands = xlnx_pcie_xvc_command_handlers, .init = &xlnx_pcie_xvc_init, diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index 96862b0d05..a9d196ccec 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -367,7 +367,8 @@ static const struct command_registration hl_interface_command_handlers[] = { struct adapter_driver hl_adapter_driver = { .name = "hla", - .transports = hl_transports, + .transport_ids = TRANSPORT_HLA_SWD | TRANSPORT_HLA_JTAG, + .transport_preferred_id = TRANSPORT_HLA_SWD, .commands = hl_interface_command_handlers, .init = hl_interface_init, diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index f1550d9915..c0ee05498d 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -15,8 +15,6 @@ struct target; /** */ enum e_hl_transports; -/** */ -extern const char *hl_transports[]; #define HLA_MAX_USB_IDS 16 diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c index 333825eff1..d8ece0776b 100644 --- a/src/jtag/hla/hla_transport.c +++ b/src/jtag/hla/hla_transport.c @@ -231,8 +231,6 @@ static struct transport hl_jtag_transport = { .override_target = hl_interface_override_target, }; -const char *hl_transports[] = { "hla_swd", "hla_jtag", NULL }; - static void hl_constructor(void) __attribute__ ((constructor)); static void hl_constructor(void) { diff --git a/src/jtag/interface.h b/src/jtag/interface.h index b2d7123fd4..475dbed36e 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -17,6 +17,7 @@ #include #include #include +#include /* @file * The "Cable Helper API" is what the cable drivers can use to help @@ -208,8 +209,16 @@ struct adapter_driver { /** The name of the interface driver. */ const char * const name; - /** transports supported in C code (NULL terminated vector) */ - const char * const *transports; + /** + * Bitmask of transport IDs supported in C code. + */ + unsigned int transport_ids; + + /** + * ID of transport that gets auto-selected when not specified by the user. + * The auto-selection of transport is DEPRECATED. + */ + unsigned int transport_preferred_id; /** * The interface driver may register additional commands to expose @@ -354,8 +363,6 @@ struct adapter_driver { const struct swim_driver *swim_ops; }; -extern const char * const jtag_only[]; - int adapter_resets(int assert_trst, int assert_srst); int adapter_assert_reset(void); int adapter_deassert_reset(void); diff --git a/src/transport/transport.c b/src/transport/transport.c index 411b0a5e0f..b7a3913cc4 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -62,11 +62,15 @@ static const struct { static struct transport *transport_list; /** - * NULL-terminated Vector of names of transports which the - * currently selected debug adapter supports. This is declared - * by the time that adapter is fully set up. + * Bitmask of transport IDs which the currently selected debug adapter supports. + * This is declared by the time that adapter is fully set up. */ -static const char * const *allowed_transports; +static unsigned int allowed_transports; + +/** + * Transport ID auto-selected when not specified by the user. + */ +static unsigned int preferred_transport; /** * Adapter supports a single transport; it has been auto-selected @@ -76,7 +80,7 @@ static bool transport_single_is_autoselected; /** * The transport being used for the current OpenOCD session. */ static struct transport *session; -static const char *transport_name(unsigned int id) +const char *transport_name(unsigned int id) { for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++) if (id == transport_names[i].id) @@ -118,13 +122,14 @@ static int transport_select(struct command_context *ctx, const char *name) * to declare the set of transports supported by an adapter. When * there is only one member of that set, it is automatically selected. */ -int allow_transports(struct command_context *ctx, const char * const *vector) +int allow_transports(struct command_context *ctx, unsigned int transport_ids, + unsigned int transport_preferred_id) { /* NOTE: caller is required to provide only a list - * of *valid* transport names + * of *valid* transports * * REVISIT should we validate that? and insist there's - * at least one non-NULL element in that list? + * at least one valid element in that list? * * ... allow removals, e.g. external strapping prevents use * of one transport; C code should be definitive about what @@ -135,13 +140,14 @@ int allow_transports(struct command_context *ctx, const char * const *vector) return ERROR_FAIL; } - allowed_transports = vector; + allowed_transports = transport_ids; + preferred_transport = transport_preferred_id; /* autoselect if there's no choice ... */ - if (!vector[1]) { - LOG_DEBUG("only one transport option; autoselecting '%s'", vector[0]); + if (IS_PWR_OF_2(transport_ids)) { + LOG_DEBUG("only one transport option; autoselecting '%s'", transport_name(transport_ids)); transport_single_is_autoselected = true; - return transport_select(ctx, vector[0]); + return transport_select(ctx, transport_name(transport_ids)); } return ERROR_OK; @@ -226,10 +232,9 @@ COMMAND_HANDLER(handle_transport_init) /* no session transport configured, print transports then fail */ LOG_ERROR("Transports available:"); - const char * const *vector = allowed_transports; - while (*vector) { - LOG_ERROR("%s", *vector); - vector++; + for (unsigned int i = BIT(0); i & TRANSPORT_VALID_MASK; i <<= 1) { + if (i & allowed_transports) + LOG_ERROR("%s", transport_name(i)); } return ERROR_FAIL; } @@ -275,8 +280,9 @@ COMMAND_HANDLER(handle_transport_select) } LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". " "Use 'transport select %s' to suppress this message.", - allowed_transports[0], allowed_transports[0]); - int retval = transport_select(CMD_CTX, allowed_transports[0]); + transport_name(preferred_transport), + transport_name(preferred_transport)); + int retval = transport_select(CMD_CTX, transport_name(preferred_transport)); if (retval != ERROR_OK) return retval; } @@ -310,8 +316,9 @@ COMMAND_HANDLER(handle_transport_select) return ERROR_FAIL; } - for (unsigned int i = 0; allowed_transports[i]; i++) { - if (!strcmp(allowed_transports[i], CMD_ARGV[0])) { + for (unsigned int i = BIT(0); i & TRANSPORT_VALID_MASK; i <<= 1) { + if ((i & allowed_transports) + && !strcmp(transport_name(i), CMD_ARGV[0])) { int retval = transport_select(CMD_CTX, CMD_ARGV[0]); if (retval != ERROR_OK) return retval; diff --git a/src/transport/transport.h b/src/transport/transport.h index dde7c6ba76..f6f0f4f4db 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -95,9 +95,12 @@ struct transport *get_current_transport(void); const char *get_current_transport_name(void); +const char *transport_name(unsigned int id); + int transport_register_commands(struct command_context *ctx); -int allow_transports(struct command_context *ctx, const char * const *vector); +int allow_transports(struct command_context *ctx, unsigned int transport_ids, + unsigned int transport_preferred_id); bool transport_is_jtag(void); bool transport_is_swd(void); From 8485eb141554851d6cfcf6faf47c5934d13bf040 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 22 Dec 2024 23:59:19 +0100 Subject: [PATCH 1198/1312] transport: validate the transport id's from the driver Verify that it contains only valid transports. While JTAG and SWD are the more permissive transports, the respective 'dapdirect' versions are slightly limited, and the respective 'hla' versions are even more limited. A driver should not provide two version of the same transport. Verify that only one JTAG and only one SWD transport is present. Verify that the preferred transport is valid too. Change-Id: Iace2f881dd65fc763e81b33e6a7113961a7008af Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8676 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Jan Matyas --- src/transport/transport.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/transport/transport.c b/src/transport/transport.c index b7a3913cc4..59f76ad31d 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -125,21 +125,37 @@ static int transport_select(struct command_context *ctx, const char *name) int allow_transports(struct command_context *ctx, unsigned int transport_ids, unsigned int transport_preferred_id) { - /* NOTE: caller is required to provide only a list - * of *valid* transports - * - * REVISIT should we validate that? and insist there's - * at least one valid element in that list? - * - * ... allow removals, e.g. external strapping prevents use - * of one transport; C code should be definitive about what - * can be used when all goes well. - */ if (allowed_transports || session) { LOG_ERROR("Can't modify the set of allowed transports."); return ERROR_FAIL; } + /* validate the values in transport_ids and transport_preferred_id */ + if (transport_ids == 0 || (transport_ids & ~TRANSPORT_VALID_MASK) != 0) { + LOG_ERROR("BUG: Unknown transport IDs %lu", transport_ids & ~TRANSPORT_VALID_MASK); + return ERROR_FAIL; + } + + if ((transport_ids & transport_preferred_id) == 0 + || !IS_PWR_OF_2(transport_preferred_id)) { + LOG_ERROR("BUG: Invalid adapter transport_preferred_id"); + return ERROR_FAIL; + } + + unsigned int mask = transport_ids & + (TRANSPORT_JTAG | TRANSPORT_HLA_JTAG | TRANSPORT_DAPDIRECT_JTAG); + if (mask && !IS_PWR_OF_2(mask)) { + LOG_ERROR("BUG: Multiple JTAG transports"); + return ERROR_FAIL; + } + + mask = transport_ids & + (TRANSPORT_SWD | TRANSPORT_HLA_SWD | TRANSPORT_DAPDIRECT_SWD); + if (mask && !IS_PWR_OF_2(mask)) { + LOG_ERROR("BUG: Multiple SWD transports"); + return ERROR_FAIL; + } + allowed_transports = transport_ids; preferred_transport = transport_preferred_id; From 9643379d30fee381e92200ef9ed0caaeae580dad Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 31 Dec 2024 16:29:46 +0100 Subject: [PATCH 1199/1312] transport: use helper/list.h for the list of transports No behavioral change, just use the list's helpers. Change-Id: I69712648ef77689bfe6acc4811adad7293fb9009 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8684 Reviewed-by: zapb Tested-by: jenkins --- src/transport/transport.c | 14 ++++++++------ src/transport/transport.h | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/transport/transport.c b/src/transport/transport.c index 59f76ad31d..8a210fe94c 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -59,7 +60,7 @@ static const struct { }; /** List of transports registered in OpenOCD. */ -static struct transport *transport_list; +static OOCD_LIST_HEAD(transport_list); /** * Bitmask of transport IDs which the currently selected debug adapter supports. @@ -98,7 +99,8 @@ static int transport_select(struct command_context *ctx, const char *name) { /* name may only identify a known transport; * caller guarantees session's transport isn't yet set.*/ - for (struct transport *t = transport_list; t; t = t->next) { + struct transport *t; + list_for_each_entry(t, &transport_list, lh) { if (!strcmp(transport_name(t->id), name)) { int retval = t->select(ctx); /* select() registers commands specific to this @@ -193,7 +195,7 @@ int transport_register(struct transport *new_transport) return ERROR_FAIL; } - for (t = transport_list; t; t = t->next) { + list_for_each_entry(t, &transport_list, lh) { if (t->id == new_transport->id) { LOG_ERROR("transport '%s' already registered", transport_name(t->id)); @@ -206,8 +208,7 @@ int transport_register(struct transport *new_transport) transport_name(new_transport->id)); /* splice this into the list */ - new_transport->next = transport_list; - transport_list = new_transport; + list_add(&new_transport->lh, &transport_list); LOG_DEBUG("register '%s' (ID %d)", transport_name(new_transport->id), new_transport->id); @@ -270,7 +271,8 @@ COMMAND_HANDLER(handle_transport_list) command_print(CMD, "The following transports are available:"); - for (struct transport *t = transport_list; t; t = t->next) + struct transport *t; + list_for_each_entry(t, &transport_list, lh) command_print(CMD, "\t%s", transport_name(t->id)); return ERROR_OK; diff --git a/src/transport/transport.h b/src/transport/transport.h index f6f0f4f4db..5445bcf3b2 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -14,6 +14,7 @@ #include "helper/bits.h" #include "helper/command.h" +#include "helper/list.h" #define TRANSPORT_JTAG BIT(0) #define TRANSPORT_SWD BIT(1) @@ -84,9 +85,9 @@ struct transport { int (*override_target)(const char **targetname); /** - * Transports are stored in a singly linked list. + * Transports are stored in a linked list. */ - struct transport *next; + struct list_head lh; }; int transport_register(struct transport *new_transport); From 98c09dc257739440f25f5cd23ca9bbd495e5742a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 31 Dec 2024 17:01:41 +0100 Subject: [PATCH 1200/1312] transport: store the transports sorted by alphabetic name order While this operation has no real interest so far, it will be used later to avoid listing twice protocols with the same name. Change-Id: I59f3634830f94dc992d28863cf29d5d869726918 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8685 Tested-by: jenkins Reviewed-by: zapb --- src/transport/transport.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/transport/transport.c b/src/transport/transport.c index 8a210fe94c..755e21054e 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -59,7 +59,7 @@ static const struct { { TRANSPORT_SWIM, "swim", }, }; -/** List of transports registered in OpenOCD. */ +/** List of transports registered in OpenOCD, alphabetically sorted per name. */ static OOCD_LIST_HEAD(transport_list); /** @@ -207,8 +207,14 @@ int transport_register(struct transport *new_transport) LOG_ERROR("invalid transport %s", transport_name(new_transport->id)); - /* splice this into the list */ - list_add(&new_transport->lh, &transport_list); + /* splice this into the list, sorted in alphabetic order */ + list_for_each_entry(t, &transport_list, lh) { + if (strcmp(transport_name(t->id), + transport_name(new_transport->id)) >= 0) + break; + } + list_add_tail(&new_transport->lh, &t->lh); + LOG_DEBUG("register '%s' (ID %d)", transport_name(new_transport->id), new_transport->id); From c1c4d489df4bbbc2902c0e4ef744157994f1b22a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 12 Feb 2025 16:30:46 +0100 Subject: [PATCH 1201/1312] transport: allow transport name jtag/swd for hla and dapdirect The transport used on adapter's wires is either 'jtag' or 'swd' but, depending on the adapter, in the command 'transport select' we have to use either 'jtag' or 'swd' or the similar 'hla_jtag', 'hla_swd', 'dapdirect_jtag' or 'dapdirect_swd'. This becomes cumbersome when we just want to change adapter and we get forced to modify the 'transport select' command too. There is no reason for an adapter driver to support two of the similar transports. In fact 'dapdirect' one is a superset of the 'hla', and the native 'jtag' or 'swd' is a superset of the 'dapdirect' one. While the adapter could support more than one similar transports, its adapter driver should only support the most complete of these similar transports. Modify the 'transport select' code to accept 'jtag' or 'swd' for the 'dapdirect' and the 'hla' adapters too. Issue a deprecated message for the old 'dapdirect' and 'hla' transport names. In command 'transport list', print only the transport names that can be selected through 'transport select' skipping information about 'dapdirect' and 'hla' versions and avoid duplicated entries. This improvement was listed in the TODO file. Update it! Change-Id: I626b50e7a94c141c042eab388cd1ffe77eb864c2 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8677 Tested-by: jenkins --- README | 2 +- TODO | 2 - doc/openocd.texi | 14 +++--- src/transport/transport.c | 93 +++++++++++++++++++++++++++------------ 4 files changed, 70 insertions(+), 41 deletions(-) diff --git a/README b/README index fba758cfef..d9cc8f3eb0 100644 --- a/README +++ b/README @@ -42,7 +42,7 @@ openocd -f interface/ftdi/jtagkey2.cfg -c "transport select jtag" \ ``` ``` -openocd -f interface/stlink.cfg -c "transport select hla_swd" \ +openocd -f interface/stlink.cfg -c "transport select swd" \ -f target/stm32l0.cfg ``` diff --git a/TODO b/TODO index e4dded0ce6..239b358f57 100644 --- a/TODO +++ b/TODO @@ -60,8 +60,6 @@ changes pending in gerrit. to replicate it in the drivers, apart in case the driver sets TRST independently - add .hla_ops to "adapter" -- HLA is a API level (.hla_ops). Transport should simply be {jtag,swd}, - not {hla_jtag,hla_swd}. @subsection thelistadapterjtagcore JTAG Core diff --git a/doc/openocd.texi b/doc/openocd.texi index d85812824f..f557a55fee 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3783,10 +3783,8 @@ JTAG supports both debugging and boundary scan testing. Flash programming support is built on top of debug support. JTAG transport is selected with the command @command{transport select -jtag}. Unless your adapter uses either @ref{hla_interface,the hla interface -driver} (in which case the command is @command{transport select hla_jtag}) -or @ref{st_link_dap_interface,the st-link interface driver} (in which case -the command is @command{transport select dapdirect_jtag}). +jtag}. This command has to be used also for @ref{hla_interface,the hla interface +driver} and @ref{st_link_dap_interface,the st-link interface driver}. @subsection SWD Transport @cindex SWD @@ -3799,10 +3797,8 @@ Flash programming support is built on top of debug support. (Some processors support both JTAG and SWD.) SWD transport is selected with the command @command{transport select -swd}. Unless your adapter uses either @ref{hla_interface,the hla interface -driver} (in which case the command is @command{transport select hla_swd}) -or @ref{st_link_dap_interface,the st-link interface driver} (in which case -the command is @command{transport select dapdirect_swd}). +swd}. This command has to be used also for @ref{hla_interface,the hla interface +driver} and @ref{st_link_dap_interface,the st-link interface driver}. @deffn {Config Command} {swd newdap} ... Declares a single DAP which uses SWD transport. @@ -10889,7 +10885,7 @@ baud with our custom divisor to get 12MHz) @item OpenOCD invocation line: @example openocd -f interface/stlink.cfg \ --c "transport select dapdirect_swd" \ +-c "transport select swd" \ -f target/stm32l1.cfg \ -c "stm32l1.tpiu configure -protocol uart" \ -c "stm32l1.tpiu configure -traceclk 24000000 -pin-freq 12000000" \ diff --git a/src/transport/transport.c b/src/transport/transport.c index 755e21054e..ab5be490fb 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -49,14 +49,16 @@ extern struct command_context *global_cmd_ctx; static const struct { unsigned int id; const char *name; + const char *full_name; + const char *deprecated_name; } transport_names[] = { - { TRANSPORT_JTAG, "jtag", }, - { TRANSPORT_SWD, "swd", }, - { TRANSPORT_HLA_JTAG, "hla_jtag", }, - { TRANSPORT_HLA_SWD, "hla_swd", }, - { TRANSPORT_DAPDIRECT_JTAG, "dapdirect_jtag", }, - { TRANSPORT_DAPDIRECT_SWD, "dapdirect_swd", }, - { TRANSPORT_SWIM, "swim", }, + { TRANSPORT_JTAG, "jtag", "jtag", NULL, }, + { TRANSPORT_SWD, "swd", "swd", NULL, }, + { TRANSPORT_HLA_JTAG, "jtag", "jtag (hla)", "hla_jtag", }, + { TRANSPORT_HLA_SWD, "swd", "swd (hla)", "hla_swd", }, + { TRANSPORT_DAPDIRECT_JTAG, "jtag", "jtag (dapdirect)", "dapdirect_jtag", }, + { TRANSPORT_DAPDIRECT_SWD, "swd", "swd (dapdirect)", "dapdirect_swd", }, + { TRANSPORT_SWIM, "swim", "swim", NULL, }, }; /** List of transports registered in OpenOCD, alphabetically sorted per name. */ @@ -90,18 +92,36 @@ const char *transport_name(unsigned int id) return NULL; } +static const char *transport_full_name(unsigned int id) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++) + if (id == transport_names[i].id) + return transport_names[i].full_name; + + return NULL; +} + +static const char *transport_deprecated_name(unsigned int id) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++) + if (id == transport_names[i].id) + return transport_names[i].deprecated_name; + + return NULL; +} + static bool is_transport_id_valid(unsigned int id) { return (id != 0) && ((id & ~TRANSPORT_VALID_MASK) == 0) && IS_PWR_OF_2(id); } -static int transport_select(struct command_context *ctx, const char *name) +static int transport_select(struct command_context *ctx, unsigned int transport_id) { /* name may only identify a known transport; * caller guarantees session's transport isn't yet set.*/ struct transport *t; list_for_each_entry(t, &transport_list, lh) { - if (!strcmp(transport_name(t->id), name)) { + if (t->id == transport_id) { int retval = t->select(ctx); /* select() registers commands specific to this * transport, and may also reset the link, e.g. @@ -110,12 +130,14 @@ static int transport_select(struct command_context *ctx, const char *name) if (retval == ERROR_OK) session = t; else - LOG_ERROR("Error selecting '%s' as transport", name); + LOG_ERROR("Error selecting '%s' as transport", + transport_full_name(transport_id)); return retval; } } - LOG_ERROR("No transport named '%s' is available.", name); + LOG_ERROR("No transport named '%s' is available.", + transport_full_name(transport_id)); return ERROR_FAIL; } @@ -165,7 +187,7 @@ int allow_transports(struct command_context *ctx, unsigned int transport_ids, if (IS_PWR_OF_2(transport_ids)) { LOG_DEBUG("only one transport option; autoselecting '%s'", transport_name(transport_ids)); transport_single_is_autoselected = true; - return transport_select(ctx, transport_name(transport_ids)); + return transport_select(ctx, transport_ids); } return ERROR_OK; @@ -205,7 +227,7 @@ int transport_register(struct transport *new_transport) if (!new_transport->select || !new_transport->init) LOG_ERROR("invalid transport %s", - transport_name(new_transport->id)); + transport_full_name(new_transport->id)); /* splice this into the list, sorted in alphabetic order */ list_for_each_entry(t, &transport_list, lh) { @@ -216,7 +238,7 @@ int transport_register(struct transport *new_transport) list_add_tail(&new_transport->lh, &t->lh); LOG_DEBUG("register '%s' (ID %d)", - transport_name(new_transport->id), new_transport->id); + transport_full_name(new_transport->id), new_transport->id); return ERROR_OK; } @@ -238,7 +260,7 @@ const char *get_current_transport_name(void) if (!session || !is_transport_id_valid(session->id)) NULL; - return transport_name(session->id); + return transport_full_name(session->id); } /*-----------------------------------------------------------------------*/ @@ -257,7 +279,7 @@ COMMAND_HANDLER(handle_transport_init) LOG_ERROR("Transports available:"); for (unsigned int i = BIT(0); i & TRANSPORT_VALID_MASK; i <<= 1) { if (i & allowed_transports) - LOG_ERROR("%s", transport_name(i)); + LOG_ERROR("%s", transport_full_name(i)); } return ERROR_FAIL; } @@ -265,7 +287,7 @@ COMMAND_HANDLER(handle_transport_init) if (transport_single_is_autoselected) LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". " "Use 'transport select %s' to suppress this message.", - transport_name(session->id), transport_name(session->id)); + transport_full_name(session->id), transport_name(session->id)); return session->init(CMD_CTX); } @@ -278,8 +300,14 @@ COMMAND_HANDLER(handle_transport_list) command_print(CMD, "The following transports are available:"); struct transport *t; - list_for_each_entry(t, &transport_list, lh) - command_print(CMD, "\t%s", transport_name(t->id)); + const char *prev_name = NULL; + /* list is sorted, don't print duplicated transport names */ + list_for_each_entry(t, &transport_list, lh) { + const char *name = transport_name(t->id); + if (!prev_name || strcmp(prev_name, name)) + command_print(CMD, "\t%s", name); + prev_name = name; + } return ERROR_OK; } @@ -304,19 +332,21 @@ COMMAND_HANDLER(handle_transport_select) } LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". " "Use 'transport select %s' to suppress this message.", - transport_name(preferred_transport), + transport_full_name(preferred_transport), transport_name(preferred_transport)); - int retval = transport_select(CMD_CTX, transport_name(preferred_transport)); + int retval = transport_select(CMD_CTX, preferred_transport); if (retval != ERROR_OK) return retval; } - command_print(CMD, "%s", transport_name(session->id)); + command_print(CMD, "%s", transport_full_name(session->id)); return ERROR_OK; } /* assign transport */ if (session) { - if (!strcmp(transport_name(session->id), CMD_ARGV[0])) { + if (!strcmp(transport_name(session->id), CMD_ARGV[0]) + || (transport_deprecated_name(session->id) + && !strcmp(transport_deprecated_name(session->id), CMD_ARGV[0]))) { if (transport_single_is_autoselected) { /* Nothing to do, but also nothing to complain */ transport_single_is_autoselected = false; @@ -341,12 +371,17 @@ COMMAND_HANDLER(handle_transport_select) } for (unsigned int i = BIT(0); i & TRANSPORT_VALID_MASK; i <<= 1) { - if ((i & allowed_transports) - && !strcmp(transport_name(i), CMD_ARGV[0])) { - int retval = transport_select(CMD_CTX, CMD_ARGV[0]); - if (retval != ERROR_OK) - return retval; - return ERROR_OK; + if (!(i & allowed_transports)) + continue; + + if (!strcmp(transport_name(i), CMD_ARGV[0])) + return transport_select(CMD_CTX, i); + + if (transport_deprecated_name(i) + && !strcmp(transport_deprecated_name(i), CMD_ARGV[0])) { + LOG_WARNING("DEPRECATED! use 'transport select %s', not 'transport select %s'", + transport_name(i), transport_deprecated_name(i)); + return transport_select(CMD_CTX, i); } } From ad53fe659b46657ddf16a08f8dc4f4d0c5df8901 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 23 Dec 2024 18:10:10 +0100 Subject: [PATCH 1202/1312] tcl: convert transport select to jtag and swd Convert every transport select command: - hla_swd -> swd - dapdirect_swd -> swd - hla_jtag -> jtag - dapdirect_jtag -> jtag Change-Id: I81971e06f7aefd21a570a4e098cf3822a775464b Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8678 Reviewed-by: zapb Tested-by: jenkins --- tcl/board/ek-lm4f120xl.cfg | 2 +- tcl/board/ek-lm4f232.cfg | 2 +- tcl/board/st_b-l475e-iot01a.cfg | 2 +- tcl/board/st_nucleo_f0.cfg | 2 +- tcl/board/st_nucleo_f103rb.cfg | 2 +- tcl/board/st_nucleo_f3.cfg | 2 +- tcl/board/st_nucleo_f4.cfg | 2 +- tcl/board/st_nucleo_f7.cfg | 2 +- tcl/board/st_nucleo_g0.cfg | 2 +- tcl/board/st_nucleo_g4.cfg | 2 +- tcl/board/st_nucleo_h743zi.cfg | 2 +- tcl/board/st_nucleo_h745zi.cfg | 2 +- tcl/board/st_nucleo_l073rz.cfg | 2 +- tcl/board/st_nucleo_l1.cfg | 2 +- tcl/board/st_nucleo_l4.cfg | 2 +- tcl/board/st_nucleo_l5.cfg | 2 +- tcl/board/st_nucleo_wb55.cfg | 2 +- tcl/board/stm320518_eval_stlink.cfg | 2 +- tcl/board/stm3220g_eval_stlink.cfg | 2 +- tcl/board/stm3241g_eval_stlink.cfg | 2 +- tcl/board/stm32429i_eval_stlink.cfg | 2 +- tcl/board/stm32439i_eval_stlink.cfg | 2 +- tcl/board/stm32f0discovery.cfg | 2 +- tcl/board/stm32f3discovery.cfg | 2 +- tcl/board/stm32f412g-disco.cfg | 2 +- tcl/board/stm32f413h-disco.cfg | 2 +- tcl/board/stm32f429disc1.cfg | 2 +- tcl/board/stm32f429discovery.cfg | 2 +- tcl/board/stm32f469discovery.cfg | 2 +- tcl/board/stm32f469i-disco.cfg | 2 +- tcl/board/stm32f4discovery.cfg | 2 +- tcl/board/stm32f723e-disco.cfg | 2 +- tcl/board/stm32f746g-disco.cfg | 2 +- tcl/board/stm32f769i-disco.cfg | 2 +- tcl/board/stm32f7discovery.cfg | 2 +- tcl/board/stm32h735g-disco.cfg | 2 +- tcl/board/stm32h745i-disco.cfg | 2 +- tcl/board/stm32h747i-disco.cfg | 2 +- tcl/board/stm32h750b-disco.cfg | 2 +- tcl/board/stm32h7b3i-disco.cfg | 2 +- tcl/board/stm32h7x3i_eval.cfg | 2 +- tcl/board/stm32l0discovery.cfg | 2 +- tcl/board/stm32l476g-disco.cfg | 2 +- tcl/board/stm32l496g-disco.cfg | 2 +- tcl/board/stm32l4discovery.cfg | 2 +- tcl/board/stm32l4p5g-disco.cfg | 2 +- tcl/board/stm32l4r9i-disco.cfg | 2 +- tcl/board/stm32ldiscovery.cfg | 2 +- tcl/board/stm32mp13x_dk.cfg | 2 +- tcl/board/stm32mp15x_dk2.cfg | 2 +- tcl/board/stm32vldiscovery.cfg | 2 +- tcl/board/ti_dk-tm4c129.cfg | 2 +- tcl/board/ti_ek-tm4c123gxl.cfg | 2 +- tcl/board/ti_ek-tm4c1294xl.cfg | 2 +- tcl/board/vd_a53x2_dap.cfg | 2 +- tcl/board/vd_a75x4_dap.cfg | 2 +- tcl/board/vd_m4_dap.cfg | 2 +- tcl/interface/nulink.cfg | 2 +- tcl/interface/rshim.cfg | 2 +- tcl/interface/stlink.cfg | 4 ++-- 60 files changed, 61 insertions(+), 61 deletions(-) diff --git a/tcl/board/ek-lm4f120xl.cfg b/tcl/board/ek-lm4f120xl.cfg index db8b2010ba..44b1b1ea12 100644 --- a/tcl/board/ek-lm4f120xl.cfg +++ b/tcl/board/ek-lm4f120xl.cfg @@ -12,7 +12,7 @@ # source [find interface/ti-icdi.cfg] -transport select hla_jtag +transport select jtag set WORKAREASIZE 0x8000 set CHIPNAME lm4f120h5qr diff --git a/tcl/board/ek-lm4f232.cfg b/tcl/board/ek-lm4f232.cfg index 89b2c3ce88..bb7f9ea5b0 100644 --- a/tcl/board/ek-lm4f232.cfg +++ b/tcl/board/ek-lm4f232.cfg @@ -12,7 +12,7 @@ # source [find interface/ti-icdi.cfg] -transport select hla_jtag +transport select jtag set WORKAREASIZE 0x8000 set CHIPNAME lm4f23x diff --git a/tcl/board/st_b-l475e-iot01a.cfg b/tcl/board/st_b-l475e-iot01a.cfg index 3f3db125c8..5bdbdb4a26 100644 --- a/tcl/board/st_b-l475e-iot01a.cfg +++ b/tcl/board/st_b-l475e-iot01a.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/st_nucleo_f0.cfg b/tcl/board/st_nucleo_f0.cfg index 00c131fd64..4d80711275 100644 --- a/tcl/board/st_nucleo_f0.cfg +++ b/tcl/board/st_nucleo_f0.cfg @@ -10,7 +10,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f0x.cfg] diff --git a/tcl/board/st_nucleo_f103rb.cfg b/tcl/board/st_nucleo_f103rb.cfg index 892bdda99d..1b440ed9e7 100644 --- a/tcl/board/st_nucleo_f103rb.cfg +++ b/tcl/board/st_nucleo_f103rb.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f1x.cfg] diff --git a/tcl/board/st_nucleo_f3.cfg b/tcl/board/st_nucleo_f3.cfg index 38f49e3d5f..8ff57eecee 100644 --- a/tcl/board/st_nucleo_f3.cfg +++ b/tcl/board/st_nucleo_f3.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f3x.cfg] diff --git a/tcl/board/st_nucleo_f4.cfg b/tcl/board/st_nucleo_f4.cfg index 7617a17580..574417c967 100644 --- a/tcl/board/st_nucleo_f4.cfg +++ b/tcl/board/st_nucleo_f4.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f4x.cfg] diff --git a/tcl/board/st_nucleo_f7.cfg b/tcl/board/st_nucleo_f7.cfg index 41f8b21291..eaf79669ca 100644 --- a/tcl/board/st_nucleo_f7.cfg +++ b/tcl/board/st_nucleo_f7.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f7x.cfg] diff --git a/tcl/board/st_nucleo_g0.cfg b/tcl/board/st_nucleo_g0.cfg index f22a7e397e..c68d3d0e5a 100644 --- a/tcl/board/st_nucleo_g0.cfg +++ b/tcl/board/st_nucleo_g0.cfg @@ -12,7 +12,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32g0x.cfg] diff --git a/tcl/board/st_nucleo_g4.cfg b/tcl/board/st_nucleo_g4.cfg index 309f7a4c84..3debdc3815 100644 --- a/tcl/board/st_nucleo_g4.cfg +++ b/tcl/board/st_nucleo_g4.cfg @@ -12,7 +12,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32g4x.cfg] diff --git a/tcl/board/st_nucleo_h743zi.cfg b/tcl/board/st_nucleo_h743zi.cfg index be2d42fb8a..a996d744b1 100644 --- a/tcl/board/st_nucleo_h743zi.cfg +++ b/tcl/board/st_nucleo_h743zi.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32h7x_dual_bank.cfg] diff --git a/tcl/board/st_nucleo_h745zi.cfg b/tcl/board/st_nucleo_h745zi.cfg index 84865f422d..697d1972a0 100644 --- a/tcl/board/st_nucleo_h745zi.cfg +++ b/tcl/board/st_nucleo_h745zi.cfg @@ -3,7 +3,7 @@ # This is an ST NUCLEO-H745ZI-Q board with single STM32H745ZITx chip. source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # STM32H745xx devices are dual core (Cortex-M7 and Cortex-M4) set DUAL_CORE 1 diff --git a/tcl/board/st_nucleo_l073rz.cfg b/tcl/board/st_nucleo_l073rz.cfg index 317c86e21d..d1a2e07689 100644 --- a/tcl/board/st_nucleo_l073rz.cfg +++ b/tcl/board/st_nucleo_l073rz.cfg @@ -4,7 +4,7 @@ # http://www.st.com/en/evaluation-tools/nucleo-l073rz.html source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set WORKAREASIZE 0x2000 diff --git a/tcl/board/st_nucleo_l1.cfg b/tcl/board/st_nucleo_l1.cfg index d7474d0fe2..0ffc71dfee 100644 --- a/tcl/board/st_nucleo_l1.cfg +++ b/tcl/board/st_nucleo_l1.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32l1x_dual_bank.cfg] diff --git a/tcl/board/st_nucleo_l4.cfg b/tcl/board/st_nucleo_l4.cfg index b0a75afe02..dad3cc4b9a 100644 --- a/tcl/board/st_nucleo_l4.cfg +++ b/tcl/board/st_nucleo_l4.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32l4x.cfg] diff --git a/tcl/board/st_nucleo_l5.cfg b/tcl/board/st_nucleo_l5.cfg index 626914aa75..f3cb680c25 100644 --- a/tcl/board/st_nucleo_l5.cfg +++ b/tcl/board/st_nucleo_l5.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32l5x.cfg] diff --git a/tcl/board/st_nucleo_wb55.cfg b/tcl/board/st_nucleo_wb55.cfg index ab7307c683..79ddb1ccd2 100644 --- a/tcl/board/st_nucleo_wb55.cfg +++ b/tcl/board/st_nucleo_wb55.cfg @@ -6,7 +6,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32wbx.cfg] diff --git a/tcl/board/stm320518_eval_stlink.cfg b/tcl/board/stm320518_eval_stlink.cfg index 997bb4af95..8f4652eff9 100644 --- a/tcl/board/stm320518_eval_stlink.cfg +++ b/tcl/board/stm320518_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 8KB set WORKAREASIZE 0x2000 diff --git a/tcl/board/stm3220g_eval_stlink.cfg b/tcl/board/stm3220g_eval_stlink.cfg index 4233d04f15..d212bbc298 100644 --- a/tcl/board/stm3220g_eval_stlink.cfg +++ b/tcl/board/stm3220g_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm3241g_eval_stlink.cfg b/tcl/board/stm3241g_eval_stlink.cfg index 3bccd28661..e1ab2026b4 100644 --- a/tcl/board/stm3241g_eval_stlink.cfg +++ b/tcl/board/stm3241g_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32429i_eval_stlink.cfg b/tcl/board/stm32429i_eval_stlink.cfg index 7d04aa7f3a..ec7e10c437 100644 --- a/tcl/board/stm32429i_eval_stlink.cfg +++ b/tcl/board/stm32429i_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32439i_eval_stlink.cfg b/tcl/board/stm32439i_eval_stlink.cfg index b9ea084dfd..bac64c81a5 100644 --- a/tcl/board/stm32439i_eval_stlink.cfg +++ b/tcl/board/stm32439i_eval_stlink.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f0discovery.cfg b/tcl/board/stm32f0discovery.cfg index 398ecc1037..9a8e921538 100644 --- a/tcl/board/stm32f0discovery.cfg +++ b/tcl/board/stm32f0discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set WORKAREASIZE 0x2000 source [find target/stm32f0x.cfg] diff --git a/tcl/board/stm32f3discovery.cfg b/tcl/board/stm32f3discovery.cfg index 73c349a6ef..661082acfa 100644 --- a/tcl/board/stm32f3discovery.cfg +++ b/tcl/board/stm32f3discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f3x.cfg] diff --git a/tcl/board/stm32f412g-disco.cfg b/tcl/board/stm32f412g-disco.cfg index 30a9537f0b..e278062919 100644 --- a/tcl/board/stm32f412g-disco.cfg +++ b/tcl/board/stm32f412g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f413h-disco.cfg b/tcl/board/stm32f413h-disco.cfg index c82d0d4349..9a72c121c5 100644 --- a/tcl/board/stm32f413h-disco.cfg +++ b/tcl/board/stm32f413h-disco.cfg @@ -10,7 +10,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f429disc1.cfg b/tcl/board/stm32f429disc1.cfg index 0a8e7ef4e6..a5646c9ecc 100644 --- a/tcl/board/stm32f429disc1.cfg +++ b/tcl/board/stm32f429disc1.cfg @@ -7,7 +7,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32f4x.cfg] diff --git a/tcl/board/stm32f429discovery.cfg b/tcl/board/stm32f429discovery.cfg index 865602ab69..735254e7f6 100644 --- a/tcl/board/stm32f429discovery.cfg +++ b/tcl/board/stm32f429discovery.cfg @@ -7,7 +7,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f469discovery.cfg b/tcl/board/stm32f469discovery.cfg index c9acbbbd0c..7d39929064 100644 --- a/tcl/board/stm32f469discovery.cfg +++ b/tcl/board/stm32f469discovery.cfg @@ -7,7 +7,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f469i-disco.cfg b/tcl/board/stm32f469i-disco.cfg index 63c42c64e9..45ec9a2691 100644 --- a/tcl/board/stm32f469i-disco.cfg +++ b/tcl/board/stm32f469i-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f4discovery.cfg b/tcl/board/stm32f4discovery.cfg index d96e2dbd34..73ede7ed71 100644 --- a/tcl/board/stm32f4discovery.cfg +++ b/tcl/board/stm32f4discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 64KB set WORKAREASIZE 0x10000 diff --git a/tcl/board/stm32f723e-disco.cfg b/tcl/board/stm32f723e-disco.cfg index 0207956206..8acefff4c3 100644 --- a/tcl/board/stm32f723e-disco.cfg +++ b/tcl/board/stm32f723e-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 128KB set WORKAREASIZE 0x20000 diff --git a/tcl/board/stm32f746g-disco.cfg b/tcl/board/stm32f746g-disco.cfg index 75ff4ec1e2..04ed72cc50 100644 --- a/tcl/board/stm32f746g-disco.cfg +++ b/tcl/board/stm32f746g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 256KB set WORKAREASIZE 0x40000 diff --git a/tcl/board/stm32f769i-disco.cfg b/tcl/board/stm32f769i-disco.cfg index cd6383a700..89e197c525 100644 --- a/tcl/board/stm32f769i-disco.cfg +++ b/tcl/board/stm32f769i-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 256KB set WORKAREASIZE 0x40000 diff --git a/tcl/board/stm32f7discovery.cfg b/tcl/board/stm32f7discovery.cfg index 6fd6c64b3d..3f3bceb845 100644 --- a/tcl/board/stm32f7discovery.cfg +++ b/tcl/board/stm32f7discovery.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK/V2-1 source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 256KB set WORKAREASIZE 0x40000 diff --git a/tcl/board/stm32h735g-disco.cfg b/tcl/board/stm32h735g-disco.cfg index 327a36418c..e839c7a547 100644 --- a/tcl/board/stm32h735g-disco.cfg +++ b/tcl/board/stm32h735g-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set CHIPNAME stm32h735igk6 diff --git a/tcl/board/stm32h745i-disco.cfg b/tcl/board/stm32h745i-disco.cfg index 9da1daefc6..700f141d26 100644 --- a/tcl/board/stm32h745i-disco.cfg +++ b/tcl/board/stm32h745i-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set CHIPNAME stm32h745xih6 diff --git a/tcl/board/stm32h747i-disco.cfg b/tcl/board/stm32h747i-disco.cfg index 7f8eda8c45..e95ad8a12b 100644 --- a/tcl/board/stm32h747i-disco.cfg +++ b/tcl/board/stm32h747i-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set CHIPNAME stm32h747xih6 diff --git a/tcl/board/stm32h750b-disco.cfg b/tcl/board/stm32h750b-disco.cfg index 8b254f21fd..8f0f15b53e 100644 --- a/tcl/board/stm32h750b-disco.cfg +++ b/tcl/board/stm32h750b-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set CHIPNAME stm32h750xbh6 diff --git a/tcl/board/stm32h7b3i-disco.cfg b/tcl/board/stm32h7b3i-disco.cfg index df0d0a6f27..de009570f5 100644 --- a/tcl/board/stm32h7b3i-disco.cfg +++ b/tcl/board/stm32h7b3i-disco.cfg @@ -7,7 +7,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set CHIPNAME stm32h7b3lih6q diff --git a/tcl/board/stm32h7x3i_eval.cfg b/tcl/board/stm32h7x3i_eval.cfg index 508f10d5d1..1880bb871e 100644 --- a/tcl/board/stm32h7x3i_eval.cfg +++ b/tcl/board/stm32h7x3i_eval.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32h7x_dual_bank.cfg] diff --git a/tcl/board/stm32l0discovery.cfg b/tcl/board/stm32l0discovery.cfg index 59aed3405d..06d02ed024 100644 --- a/tcl/board/stm32l0discovery.cfg +++ b/tcl/board/stm32l0discovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set WORKAREASIZE 0x2000 source [find target/stm32l0.cfg] diff --git a/tcl/board/stm32l476g-disco.cfg b/tcl/board/stm32l476g-disco.cfg index fe33ffefb9..e3d4de3c0d 100644 --- a/tcl/board/stm32l476g-disco.cfg +++ b/tcl/board/stm32l476g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32l496g-disco.cfg b/tcl/board/stm32l496g-disco.cfg index 823fa6e380..a715bb058d 100644 --- a/tcl/board/stm32l496g-disco.cfg +++ b/tcl/board/stm32l496g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32l4discovery.cfg b/tcl/board/stm32l4discovery.cfg index 64a456b612..7f724f9bd2 100644 --- a/tcl/board/stm32l4discovery.cfg +++ b/tcl/board/stm32l4discovery.cfg @@ -8,7 +8,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32l4x.cfg] diff --git a/tcl/board/stm32l4p5g-disco.cfg b/tcl/board/stm32l4p5g-disco.cfg index 33bb9a7662..86c05a18d4 100644 --- a/tcl/board/stm32l4p5g-disco.cfg +++ b/tcl/board/stm32l4p5g-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32l4r9i-disco.cfg b/tcl/board/stm32l4r9i-disco.cfg index cbb86669f0..de23cc1ae5 100644 --- a/tcl/board/stm32l4r9i-disco.cfg +++ b/tcl/board/stm32l4r9i-disco.cfg @@ -6,7 +6,7 @@ # This is for using the onboard STLINK source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd # increase working area to 96KB set WORKAREASIZE 0x18000 diff --git a/tcl/board/stm32ldiscovery.cfg b/tcl/board/stm32ldiscovery.cfg index e39b52295a..38b8a8bd0a 100644 --- a/tcl/board/stm32ldiscovery.cfg +++ b/tcl/board/stm32ldiscovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set WORKAREASIZE 0x4000 source [find target/stm32l1.cfg] diff --git a/tcl/board/stm32mp13x_dk.cfg b/tcl/board/stm32mp13x_dk.cfg index 08377ca76a..8ece24844c 100644 --- a/tcl/board/stm32mp13x_dk.cfg +++ b/tcl/board/stm32mp13x_dk.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32mp13x.cfg] diff --git a/tcl/board/stm32mp15x_dk2.cfg b/tcl/board/stm32mp15x_dk2.cfg index 0e71e05ee0..ba1c7f78a6 100644 --- a/tcl/board/stm32mp15x_dk2.cfg +++ b/tcl/board/stm32mp15x_dk2.cfg @@ -6,7 +6,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32mp15x.cfg] diff --git a/tcl/board/stm32vldiscovery.cfg b/tcl/board/stm32vldiscovery.cfg index 57852bfd4f..d79c62ea43 100644 --- a/tcl/board/stm32vldiscovery.cfg +++ b/tcl/board/stm32vldiscovery.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd set WORKAREASIZE 0x2000 source [find target/stm32f1x.cfg] diff --git a/tcl/board/ti_dk-tm4c129.cfg b/tcl/board/ti_dk-tm4c129.cfg index d8210e32d2..e0574fa870 100644 --- a/tcl/board/ti_dk-tm4c129.cfg +++ b/tcl/board/ti_dk-tm4c129.cfg @@ -8,7 +8,7 @@ source [find interface/ti-icdi.cfg] -transport select hla_jtag +transport select jtag set WORKAREASIZE 0x8000 set CHIPNAME tm4c129xnczad diff --git a/tcl/board/ti_ek-tm4c123gxl.cfg b/tcl/board/ti_ek-tm4c123gxl.cfg index 91390fa82f..7b8fc267f5 100644 --- a/tcl/board/ti_ek-tm4c123gxl.cfg +++ b/tcl/board/ti_ek-tm4c123gxl.cfg @@ -8,7 +8,7 @@ source [find interface/ti-icdi.cfg] -transport select hla_jtag +transport select jtag set WORKAREASIZE 0x8000 set CHIPNAME tm4c123gh6pm diff --git a/tcl/board/ti_ek-tm4c1294xl.cfg b/tcl/board/ti_ek-tm4c1294xl.cfg index 63612c686b..8cceb49c96 100644 --- a/tcl/board/ti_ek-tm4c1294xl.cfg +++ b/tcl/board/ti_ek-tm4c1294xl.cfg @@ -8,7 +8,7 @@ source [find interface/ti-icdi.cfg] -transport select hla_jtag +transport select jtag set WORKAREASIZE 0x8000 set CHIPNAME tm4c1294ncpdt diff --git a/tcl/board/vd_a53x2_dap.cfg b/tcl/board/vd_a53x2_dap.cfg index bcf8b44098..3251afd066 100644 --- a/tcl/board/vd_a53x2_dap.cfg +++ b/tcl/board/vd_a53x2_dap.cfg @@ -13,7 +13,7 @@ set DBGBASE {0x80810000 0x80910000} set CTIBASE {0x80820000 0x80920000} # vdebug select transport -transport select dapdirect_swd +transport select swd # JTAG reset config, frequency and reset delay adapter speed 50000 diff --git a/tcl/board/vd_a75x4_dap.cfg b/tcl/board/vd_a75x4_dap.cfg index 5c2a2efe87..2f4406b038 100644 --- a/tcl/board/vd_a75x4_dap.cfg +++ b/tcl/board/vd_a75x4_dap.cfg @@ -13,7 +13,7 @@ set DBGBASE {0x01010000 0x01110000 0x01210000 0x01310000} set CTIBASE {0x01020000 0x01120000 0x01220000 0x01320000} # vdebug select transport -transport select dapdirect_swd +transport select swd # JTAG reset config, frequency and reset delay adapter speed 200000 diff --git a/tcl/board/vd_m4_dap.cfg b/tcl/board/vd_m4_dap.cfg index 5d3605aa37..f56334e834 100644 --- a/tcl/board/vd_m4_dap.cfg +++ b/tcl/board/vd_m4_dap.cfg @@ -9,7 +9,7 @@ set MEMSTART 0x00000000 set MEMSIZE 0x10000 # vdebug select transport -transport select dapdirect_swd +transport select swd adapter speed 25000 adapter srst delay 5 diff --git a/tcl/interface/nulink.cfg b/tcl/interface/nulink.cfg index 48dc20e241..be68347e73 100644 --- a/tcl/interface/nulink.cfg +++ b/tcl/interface/nulink.cfg @@ -10,4 +10,4 @@ hla device_desc "Nu-Link" hla vid_pid 0x0416 0x511b 0x0416 0x511c 0x0416 0x511d 0x0416 0x5200 0x0416 0x5201 # Only swd is supported -transport select hla_swd +transport select swd diff --git a/tcl/interface/rshim.cfg b/tcl/interface/rshim.cfg index 1d5da593e7..327212f681 100644 --- a/tcl/interface/rshim.cfg +++ b/tcl/interface/rshim.cfg @@ -5,4 +5,4 @@ # adapter driver rshim -transport select dapdirect_swd +transport select swd diff --git a/tcl/interface/stlink.cfg b/tcl/interface/stlink.cfg index 99c81c180c..962d192ec5 100644 --- a/tcl/interface/stlink.cfg +++ b/tcl/interface/stlink.cfg @@ -13,8 +13,8 @@ adapter driver st-link st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 -# transport select dapdirect_jtag -# transport select dapdirect_swd +# transport select jtag +# transport select swd # transport select swim # Optionally specify the serial number of usb device From 420f637cab324541230fbff0dea447cf40df3b0f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 23 Dec 2024 20:20:08 +0100 Subject: [PATCH 1203/1312] stlink: simplify the use of deprecated HLA transport Commit 34ec5536c0ba ("stlink: deprecate HLA support") makes hard to use the still functional HLA transport with the stlink listed in board config files. Now that the prefixes 'hla_' and 'dapdirect_' has been dropped from the transport name, allow overriding the transport by using the 'stlink-hla' script in front of the board file, e.g.: openocd -f interface/stlink-hla.cfg -f board/st_nucleo_f4.cfg Revert the documentation changes of the change above. Improve the documentation to explain how to use the compatibility HLA mode. Improve the error message in stlink driver to guide the user to update the stlink firmware and to use the compatibility HLA mode. Change-Id: I5d0bc7954511692cebe024bda2aaa72767b97681 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8679 Tested-by: jenkins --- doc/openocd.texi | 21 +++++++++++++++++++-- src/jtag/drivers/stlink_usb.c | 7 ++++++- tcl/interface/stlink.cfg | 6 ++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index f557a55fee..cbe5e86dab 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2497,7 +2497,7 @@ This command is only available if your libusb1 is at least version 1.0.16. Specifies the @var{serial_string} of the adapter to use. If this command is not specified, serial strings are not checked. Only the following adapter drivers use the serial string from this command: -arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (ti-icdi), jlink, kitprog, opendus, +arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus, openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110. @end deffn @@ -3205,16 +3205,19 @@ that OpenOCD would normally use to access the target. Currently supported adapters include the STMicroelectronics ST-LINK, TI ICDI and Nuvoton Nu-Link. + ST-LINK firmware version >= V2.J21.S4 recommended due to issues with earlier versions of firmware where serial number is reset after first use. Suggest using ST firmware update utility to upgrade ST-LINK firmware even if current version reported is V2.J21.S4. +The ST-LINK firmware update utility is available for download from +@url{https://www.st.com/en/development-tools/stsw-link007.html, ST website}. @deffn {Config Command} {hla device_desc} description Currently Not Supported. @end deffn -@deffn {Config Command} {hla layout} (@option{icdi}|@option{nulink}) +@deffn {Config Command} {hla layout} (@option{stlink}|@option{icdi}|@option{nulink}) Specifies the adapter layout to use. @end deffn @@ -3222,6 +3225,15 @@ Specifies the adapter layout to use. Pairs of vendor IDs and product IDs of the device. @end deffn +@deffn {Config Command} {hla stlink_backend} (usb | tcp [port]) +@emph{ST-Link only:} Choose between 'exclusive' USB communication (the default backend) or +'shared' mode using ST-Link TCP server (the default port is 7184). + +@emph{Note:} ST-Link TCP server is a binary application provided by ST +available from @url{https://www.st.com/en/development-tools/st-link-server.html, +ST-LINK server software module}. +@end deffn + @deffn {Command} {hla command} command Execute a custom adapter-specific command. The @var{command} string is passed as is to the underlying adapter layout handler. @@ -3236,6 +3248,11 @@ directly access the arm ADIv5 DAP. The older API that requires HLA transport is deprecated and will be dropped from OpenOCD. In mean time it's still available by using @file{interface/stlink-hla.cfg}. +The HLA interface file can be put as first command line argument to +force using is in place of the default DAP API. +@example +openocd -f interface/stlink-hla.cfg -f board/st_nucleo_f4.cfg +@end example The new API provide access to multiple AP on the same DAP, but the maximum number of the AP port is limited by the specific firmware version diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index e018f71cd9..5ee1f85261 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -5143,7 +5143,12 @@ static int stlink_dap_init(void) if ((mode != STLINK_MODE_DEBUG_SWIM) && !(stlink_dap_handle->version.flags & STLINK_F_HAS_DAP_REG)) { - LOG_ERROR("ST-Link version does not support DAP direct transport"); + LOG_ERROR("The firmware in the ST-Link adapter only supports deprecated HLA."); + LOG_ERROR("Please consider updating the ST-Link firmware with a version"); + LOG_ERROR("newer that V2J24 (2015), available for downloading on ST website:"); + LOG_ERROR(" https://www.st.com/en/development-tools/stsw-link007.html"); + LOG_ERROR("In mean time, you can re-run OpenOCD for ST-Link HLA as:"); + LOG_ERROR(" openocd -f interface/stlink-hla.cfg ..."); return ERROR_FAIL; } return ERROR_OK; diff --git a/tcl/interface/stlink.cfg b/tcl/interface/stlink.cfg index 962d192ec5..48c5656615 100644 --- a/tcl/interface/stlink.cfg +++ b/tcl/interface/stlink.cfg @@ -10,6 +10,12 @@ # SWIM transport is natively supported # +if { [adapter name] == "hla" } { + # Deprecated HLA adapter driver already selected. + # Quit silently, as the ST-LINK driver already complains. + return +} + adapter driver st-link st-link vid_pid 0x0483 0x3744 0x0483 0x3748 0x0483 0x374b 0x0483 0x374d 0x0483 0x374e 0x0483 0x374f 0x0483 0x3752 0x0483 0x3753 0x0483 0x3754 0x0483 0x3755 0x0483 0x3757 From d8a2f6dbcf5f0554def22d02f503fb242a604f84 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Fri, 11 Apr 2025 15:30:22 +0200 Subject: [PATCH 1204/1312] configure.ac: show the Amontec JTAG-Accelerator driver in the config summary Also enable this driver by default (auto). Change-Id: I7f592dd697c6ee150a81e151ff2333447cd9130d Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8835 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Antonio Borneo --- configure.ac | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 84ca03bf07..5c516efd16 100644 --- a/configure.ac +++ b/configure.ac @@ -190,6 +190,9 @@ m4_define([JTAG_VPI_ADAPTER], m4_define([RSHIM_ADAPTER], [[[rshim], [BlueField SoC via rshim], [RSHIM]]]) +m4_define([AMTJTAGACCEL_ADAPTER], + [[[amtjtagaccel], [Amontec JTAG-Accelerator driver], [AMTJTAGACCEL]]]) + # The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter # because there is an M4 macro called 'adapter'. m4_define([DUMMY_ADAPTER], @@ -320,6 +323,7 @@ AC_ARG_ADAPTERS([ JTAG_DPI_ADAPTER, JTAG_VPI_ADAPTER, RSHIM_ADAPTER, + AMTJTAGACCEL_ADAPTER, PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) @@ -338,10 +342,6 @@ AC_ARG_ENABLE([parport_giveio], [Enable use of giveio for parport (for CygWin only)]), [parport_use_giveio=$enableval], [parport_use_giveio=]) -AC_ARG_ENABLE([amtjtagaccel], - AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), - [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) - AS_CASE(["${host_cpu}"], [arm*|aarch64], [ AC_ARG_ENABLE([bcm2835gpio], @@ -576,12 +576,6 @@ AS_IF([test "x$parport_use_giveio" = "xyes"], [ AC_DEFINE([PARPORT_USE_GIVEIO], [0], [0 if you don't want parport to use giveio.]) ]) -AS_IF([test "x$build_amtjtagaccel" = "xyes"], [ - AC_DEFINE([BUILD_AMTJTAGACCEL], [1], [1 if you want the Amontec JTAG-Accelerator driver.]) -], [ - AC_DEFINE([BUILD_AMTJTAGACCEL], [0], [0 if you don't want the Amontec JTAG-Accelerator driver.]) -]) - AS_IF([test "x$build_gw16012" = "xyes"], [ AC_DEFINE([BUILD_GW16012], [1], [1 if you want the Gateworks GW16012 driver.]) ], [ @@ -719,6 +713,7 @@ PROCESS_ADAPTERS([JTAG_DPI_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([JTAG_VPI_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([RSHIM_ADAPTER], ["x$can_build_rshim" = "xyes"], [internal error: validation should happen beforehand]) +PROCESS_ADAPTERS([AMTJTAGACCEL_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -771,7 +766,6 @@ AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"]) AM_CONDITIONAL([AM335XGPIO], [test "x$build_am335xgpio" = "xyes"]) AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) -AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"]) AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) @@ -877,6 +871,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, JTAG_DPI_ADAPTER, JTAG_VPI_ADAPTER, RSHIM_ADAPTER, + AMTJTAGACCEL_ADAPTER, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], From fdd76c899f423c09e4fb4311387eeebfc215650e Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Thu, 10 Apr 2025 20:57:49 +0200 Subject: [PATCH 1205/1312] configure.ac: show the sysfsgpio adapter in the config summary Also enable this adapter by default (auto). Change-Id: I43b9f1a1873b381d015114da57efc1d78e6e7780 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8834 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 5c516efd16..9db378702e 100644 --- a/configure.ac +++ b/configure.ac @@ -164,6 +164,9 @@ m4_define([LIBFTDI_USB1_ADAPTERS], m4_define([LIBGPIOD_ADAPTERS], [[[linuxgpiod], [Linux GPIO bitbang through libgpiod], [LINUXGPIOD]]]) +m4_define([SYSFSGPIO_ADAPTER], + [[[sysfsgpio], [Linux GPIO bitbang through sysfs], [SYSFSGPIO]]]) + m4_define([REMOTE_BITBANG_ADAPTER], [[[remote_bitbang], [Remote Bitbang driver], [REMOTE_BITBANG]]]) @@ -315,6 +318,7 @@ AC_ARG_ADAPTERS([ LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + SYSFSGPIO_ADAPTER, REMOTE_BITBANG_ADAPTER, LINUXSPIDEV_ADAPTER, SERIAL_PORT_ADAPTERS, @@ -379,10 +383,6 @@ AC_ARG_ENABLE([gw16012], AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]), [build_gw16012=$enableval], [build_gw16012=no]) -AC_ARG_ENABLE([sysfsgpio], - AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), - [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) - can_build_rshim=no AS_CASE([$host_os], @@ -391,10 +391,6 @@ AS_CASE([$host_os], can_build_rshim=yes ], [ - AS_IF([test "x$build_sysfsgpio" = "xyes"], [ - AC_MSG_ERROR([sysfsgpio is only available on linux]) - ]) - AS_CASE([$host_os], [freebsd*], [ can_build_rshim=yes ], @@ -604,13 +600,6 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ ]) ]) -AS_IF([test "x$build_sysfsgpio" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_SYSFSGPIO], [1], [1 if you want the SysfsGPIO driver.]) -], [ - AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) -]) - PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [ use_libusb1=yes AC_DEFINE([HAVE_LIBUSB1], [1], [Define if you have libusb-1.x]) @@ -702,6 +691,7 @@ PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libu PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x]) PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpiod]) +PROCESS_ADAPTERS([SYSFSGPIO_ADAPTER], ["x$is_linux" = "xyes"], [Linux sysfs]) PROCESS_ADAPTERS([REMOTE_BITBANG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) @@ -720,6 +710,10 @@ AS_IF([test "x$enable_linuxgpiod" != "xno"], [ build_bitbang=yes ]) +AS_IF([test "x$enable_sysfsgpio" != "xno"], [ + build_bitbang=yes +]) + AS_IF([test "x$enable_remote_bitbang" != "xno"], [ build_bitbang=yes ]) @@ -767,7 +761,6 @@ AM_CONDITIONAL([AM335XGPIO], [test "x$build_am335xgpio" = "xyes"]) AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) -AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) AM_CONDITIONAL([IS_MINGW], [test "x$is_mingw" = "xyes"]) @@ -864,6 +857,7 @@ m4_foreach([adapter], [USB1_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + SYSFSGPIO_ADAPTER, REMOTE_BITBANG_ADAPTER, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, LINUXSPIDEV_ADAPTER, From 639b7432b81b8851155ab0d539c74ac183bb9bfa Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 13 Dec 2024 07:34:38 +0000 Subject: [PATCH 1206/1312] tcl/board: Add config for NUCLEO-U083RC Tested with NUCLEO-U083RC development board. Change-Id: I5e7ed1a9a19dbab70ee3155f92d67874c33b1ac2 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8649 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/st/nucleo-u083rc.cfg | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tcl/board/st/nucleo-u083rc.cfg diff --git a/tcl/board/st/nucleo-u083rc.cfg b/tcl/board/st/nucleo-u083rc.cfg new file mode 100644 index 0000000000..7b878adbc0 --- /dev/null +++ b/tcl/board/st/nucleo-u083rc.cfg @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# NUCLEO-U083RC +# https://www.st.com/en/evaluation-tools/nucleo-u083rc.html + +source [find interface/stlink.cfg] + +transport select dapdirect_swd + +source [find target/stm32u0x.cfg] + +reset_config srst_only From 98c95df228dd47ea736cea79a63f3302704cc669 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 14 Apr 2025 09:09:49 +0200 Subject: [PATCH 1207/1312] doc/openocd: Fix Tcl spelling Use 'Tcl' because it is the official spelling. While at it, fix some misspellings of 'Jim Tcl'. Change-Id: I084541a1cc0276d15a263b843ba740da04efc30a Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8852 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 88 ++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index cbe5e86dab..e0bdd5ca09 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -62,7 +62,7 @@ Documentation License''. * About:: About OpenOCD * Developers:: OpenOCD Developer Resources * Debug Adapter Hardware:: Debug Adapter Hardware -* About Jim-Tcl:: About Jim-Tcl +* About Jim Tcl:: About Jim Tcl * Running:: Running OpenOCD * OpenOCD Project Setup:: OpenOCD Project Setup * Config File Guidelines:: Config File Guidelines @@ -629,43 +629,43 @@ This is deprecated from Linux v5.3; prefer using @b{linuxgpiod}. @end itemize -@node About Jim-Tcl -@chapter About Jim-Tcl -@cindex Jim-Tcl +@node About Jim Tcl +@chapter About Jim Tcl +@cindex Jim Tcl @cindex tcl -OpenOCD uses a small ``Tcl Interpreter'' known as Jim-Tcl. +OpenOCD uses a small ``Tcl Interpreter'' known as Jim Tcl. This programming language provides a simple and extensible command interpreter. -All commands presented in this Guide are extensions to Jim-Tcl. +All commands presented in this Guide are extensions to Jim Tcl. You can use them as simple commands, without needing to learn much of anything about Tcl. Alternatively, you can write Tcl programs with them. You can learn more about Jim at its website, @url{http://jim.tcl.tk}. There is an active and responsive community, get on the mailing list -if you have any questions. Jim-Tcl maintainers also lurk on the +if you have any questions. Jim Tcl maintainers also lurk on the OpenOCD mailing list. @itemize @bullet @item @b{Jim vs. Tcl} -@* Jim-Tcl is a stripped down version of the well known Tcl language, -which can be found here: @url{http://www.tcl.tk}. Jim-Tcl has far -fewer features. Jim-Tcl is several dozens of .C files and .H files and +@* Jim Tcl is a stripped down version of the well known Tcl language, +which can be found here: @url{http://www.tcl.tk}. Jim Tcl has far +fewer features. Jim Tcl is several dozens of .C files and .H files and implements the basic Tcl command set. In contrast: Tcl 8.6 is a 4.2 MB .zip file containing 1540 files. @item @b{Missing Features} @* Our practice has been: Add/clone the real Tcl feature if/when -needed. We welcome Jim-Tcl improvements, not bloat. Also there -are a large number of optional Jim-Tcl features that are not +needed. We welcome Jim Tcl improvements, not bloat. Also there +are a large number of optional Jim Tcl features that are not enabled in OpenOCD. @item @b{Scripts} -@* OpenOCD configuration scripts are Jim-Tcl Scripts. OpenOCD's +@* OpenOCD configuration scripts are Jim Tcl Scripts. OpenOCD's command interpreter today is a mixture of (newer) -Jim-Tcl commands, and the (older) original command interpreter. +Jim Tcl commands, and the (older) original command interpreter. @item @b{Commands} @* At the OpenOCD telnet command line (or via the GDB monitor command) one @@ -674,10 +674,10 @@ Some of the commands documented in this guide are implemented as Tcl scripts, from a @file{startup.tcl} file internal to the server. @item @b{Historical Note} -@* Jim-Tcl was introduced to OpenOCD in spring 2008. Fall 2010, -before OpenOCD 0.5 release, OpenOCD switched to using Jim-Tcl -as a Git submodule, which greatly simplified upgrading Jim-Tcl -to benefit from new features and bugfixes in Jim-Tcl. +@* Jim Tcl was introduced to OpenOCD in spring 2008. Fall 2010, +before OpenOCD 0.5 release, OpenOCD switched to using Jim Tcl +as a Git submodule, which greatly simplified upgrading Jim Tcl +to benefit from new features and bugfixes in Jim Tcl. @item @b{Need a crash course in Tcl?} @*@xref{Tcl Crash Course}. @@ -796,7 +796,7 @@ those channels. If you are having problems, you can enable internal debug messages via the @option{-d} option. -Also it is possible to interleave Jim-Tcl commands w/config scripts using the +Also it is possible to interleave Jim Tcl commands w/config scripts using the @option{-c} command line switch. To enable debug output (when reporting problems or working on OpenOCD @@ -962,7 +962,7 @@ that can be tested in a later script. @end quotation Here we will focus on the simpler solution: one user config -file, including basic configuration plus any TCL procedures +file, including basic configuration plus any Tcl procedures to simplify your work. @section User Config Files @@ -1432,7 +1432,7 @@ In addition to target-specific utility code, another way that board and target config files communicate is by following a convention on how to use certain variables. -The full Tcl/Tk language supports ``namespaces'', but Jim-Tcl does not. +The full Tcl/Tk language supports ``namespaces'', but Jim Tcl does not. Thus the rule we follow in OpenOCD is this: Variables that begin with a leading underscore are temporary in nature, and can be modified and used at will within a target configuration file. @@ -1552,7 +1552,7 @@ configuration files for other JTAG tools Some of this code could probably be shared between different boards. For example, setting up a DRAM controller often doesn't differ by much except the bus width (16 bits or 32?) and memory timings, so a -reusable TCL procedure loaded by the @file{target.cfg} file might take +reusable Tcl procedure loaded by the @file{target.cfg} file might take those as parameters. Similarly with oscillator, PLL, and clock setup; and disabling the watchdog. @@ -2137,7 +2137,7 @@ corresponding subsystems: @end deffn At last, @command{init} executes all the commands that are specified in -the TCL list @var{post_init_commands}. The commands are executed in the +the Tcl list @var{post_init_commands}. The commands are executed in the same order they occupy in the list. If one of the commands fails, then the error is propagated and OpenOCD fails too. @example @@ -2222,7 +2222,7 @@ cause initialization to fail with "Unknown remote qXfer reply: OK". @deffn {Config Command} {tcl port} [number] Specify or query the port used for a simplified RPC -connection that can be used by clients to issue TCL commands and get the +connection that can be used by clients to issue Tcl commands and get the output from the Tcl engine. Intended as a machine interface. When not specified during the configuration stage, @@ -2233,7 +2233,7 @@ When specified as "disabled", this service is not activated. @deffn {Config Command} {telnet port} [number] Specify or query the port on which to listen for incoming telnet connections. -This port is intended for interaction with one human through TCL commands. +This port is intended for interaction with one human through Tcl commands. When not specified during the configuration stage, the port @var{number} defaults to 4444. When specified as "disabled", this service is not activated. @@ -2304,7 +2304,7 @@ The file name is @i{target_name}.xml. Hardware debuggers are parts of asynchronous systems, where significant events can happen at any time. The OpenOCD server needs to detect some of these events, -so it can report them to through TCL command line +so it can report them to through Tcl command line or to GDB. Examples of such events include: @@ -2345,7 +2345,7 @@ specific information about the current state is printed. An optional parameter allows background polling to be enabled and disabled. -You could use this from the TCL command shell, or +You could use this from the Tcl command shell, or from GDB using @command{monitor poll} command. Leave background polling enabled while you're using GDB. @example @@ -4527,7 +4527,7 @@ mechanism for debugger targets.) See the next section for information about the available events. The @code{configure} subcommand assigns an event handler, -a TCL string which is evaluated when the event is triggered. +a Tcl string which is evaluated when the event is triggered. The @code{cget} subcommand returns that handler. @end deffn @@ -4786,7 +4786,7 @@ The instance number is in bits 28..31 of DLPIDR value. @deffn {Command} {dap names} This command returns a list of all registered DAP objects. It it useful mainly -for TCL scripting. +for Tcl scripting. @end deffn @deffn {Command} {dap info} [@var{num}|@option{root}] @@ -5775,7 +5775,7 @@ until the programming session is finished. If you use @ref{programmingusinggdb,,Programming using GDB}, the target is prepared automatically in the event gdb-flash-erase-start -The jimtcl script @command{program} calls @command{reset init} explicitly. +The Tcl script @command{program} calls @command{reset init} explicitly. @section Erasing, Reading, Writing to Flash @cindex flash erasing @@ -7462,18 +7462,18 @@ mspm0_board_reset @end itemize -@deffn {TCL proc} {mspm0_board_reset} +@deffn {Tcl proc} {mspm0_board_reset} Performs an nRST toggle on the device. @end deffn -@deffn {TCL proc} {mspm0_mass_erase} +@deffn {Tcl proc} {mspm0_mass_erase} Sends the mass erase command to the SEC-AP mailbox and then performs an nRST toggle. Once the command has been fully processed by the ROM, all MAIN memory will be erased. NOTE: This command is not supported on MSPM0C* family of devices. @end deffn -@deffn {TCL proc} {mspm0_factory_reset} +@deffn {Tcl proc} {mspm0_factory_reset} Sends the factory reset command to the SEC-AP mailbox and then performs an nRST toggle. Once the command has been fully processed by the ROM, all MAIN memory will be erased and NONMAIN will be reset to its default @@ -7772,7 +7772,7 @@ flash bank super_flash_toc2_cm4 psoc6 0x16007C00 0 0 0 \ psoc6-specific commands @deffn {Command} {psoc6 reset_halt} -Command can be used to simulate broken Vector Catch from gdbinit or tcl scripts. +Command can be used to simulate broken Vector Catch from gdbinit or Tcl scripts. When invoked for CM0+ target, it will set break point at application entry point and issue SYSRESETREQ. This will reset both cores and all peripherals. CM0+ will reset CM4 during boot anyway so this is safe. On CM4 target, VECTRESET is used @@ -8987,7 +8987,7 @@ OpenOCD implements numerous ways to program the target flash, whether internal o Programming can be achieved by either using @ref{programmingusinggdb,,Programming using GDB}, or using the commands given in @ref{flashprogrammingcommands,,Flash Programming Commands}. -@*To simplify using the flash commands directly a jimtcl script is available that handles the programming and verify stage. +@*To simplify using the flash commands directly a Tcl script is available that handles the programming and verify stage. OpenOCD will program/verify/reset the target and optionally shutdown. The script is executed as follows and by default the following actions will be performed. @@ -9269,7 +9269,7 @@ non-zero exit code to the parent process. If user types CTRL-C or kills OpenOCD, the command @command{shutdown} will be automatically executed to cause OpenOCD to exit. -It is possible to specify, in the TCL list @var{pre_shutdown_commands} , a +It is possible to specify, in the Tcl list @var{pre_shutdown_commands} , a set of commands to be automatically executed before @command{shutdown} , e.g.: @example lappend pre_shutdown_commands @{echo "Goodbye, my friend ..."@} @@ -9858,7 +9858,7 @@ Add or replace usage text on the given @var{command_name}. @deffn {Command} {ms} Returns current time since the Epoch in ms (See: @url{https://en.wikipedia.org/wiki/Epoch_(computing)}). -Useful to compute delays in TCL. +Useful to compute delays in Tcl. @end deffn @node Architecture and Core Commands @@ -10175,7 +10175,7 @@ of the CTI. @deffn {Command} {cti names} Prints a list of names of all CTI objects created. This command is mainly -useful in TCL scripting. +useful in Tcl scripting. @end deffn @section Generic ARM @@ -10819,7 +10819,7 @@ protocol used for trace data: @end itemize @item @code{-event} @var{event_name} @var{event_body} -- assigns an event handler, -a TCL string which is evaluated when the event is triggered. The events +a Tcl string which is evaluated when the event is triggered. The events @code{pre-enable}, @code{post-enable}, @code{pre-disable} and @code{post-disable} are defined for TPIU/SWO. A typical use case for the event @code{pre-enable} is to enable the trace clock @@ -11643,7 +11643,7 @@ capabilities than most of the other processors and in addition there is an extension interface that allows SoC designers to add custom registers and instructions. For the OpenOCD that mostly means that set of core and AUX registers in target will vary and is not fixed for a particular processor -model. To enable extensibility several TCL commands are provided that allow to +model. To enable extensibility several Tcl commands are provided that allow to describe those optional registers in OpenOCD configuration files. Moreover those commands allow for a dynamic target features discovery. @@ -11798,12 +11798,12 @@ configuration comprises two categories: @end enumerate All common Xtensa support is built into the OpenOCD Xtensa target layer and -is enabled through a combination of TCL scripts: the target-specific +is enabled through a combination of Tcl scripts: the target-specific @file{target/xtensa.cfg} and a board-specific @file{board/xtensa-*.cfg}, similar to other target architectures. Importantly, core-specific configuration information must be provided by -the user, and takes the form of an @file{xtensa-core-XXX.cfg} TCL script that +the user, and takes the form of an @file{xtensa-core-XXX.cfg} Tcl script that defines the core's configurable features through a series of Xtensa configuration commands (detailed below). @@ -13376,7 +13376,7 @@ learning Tcl, the intent of this chapter is to give you some idea of how the Tcl scripts work. This chapter is written with two audiences in mind. (1) OpenOCD users -who need to understand a bit more of how Jim-Tcl works so they can do +who need to understand a bit more of how Jim Tcl works so they can do something useful, and (2) those that want to add a new command to OpenOCD. @@ -13536,7 +13536,7 @@ Often many of those parameters are in @{curly-braces@} - thus the variables inside are not expanded or replaced until later. Remember that every Tcl command looks like the classic ``main( argc, -argv )'' function in C. In JimTCL - they actually look like this: +argv )'' function in C. In Jim Tcl - they actually look like this: @example int From efafdd3c552e004525b4515c70ac03765e9b6fd6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 14 Apr 2025 09:11:36 +0200 Subject: [PATCH 1208/1312] doc/manual: Fix Tcl spelling Use 'Tcl' because it is the official spelling. While at it, fix some misspellings of 'Jim Tcl'. Change-Id: I2d96f63b0dbc96ae62fe00ae41d2eb16897250fb Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8853 Tested-by: jenkins Reviewed-by: Antonio Borneo --- README | 4 ++-- TODO | 18 +++++++++--------- doc/manual/helper.txt | 2 +- doc/manual/jtag.txt | 4 ++-- doc/manual/primer/docs.txt | 2 +- doc/manual/primer/tcl.txt | 28 ++++++++++++++-------------- doc/manual/scripting.txt | 14 +++++++------- doc/manual/server.txt | 34 +++++++++++++++++----------------- doc/manual/style.txt | 6 +++--- 9 files changed, 56 insertions(+), 56 deletions(-) diff --git a/README b/README index d9cc8f3eb0..875c85de3b 100644 --- a/README +++ b/README @@ -8,10 +8,10 @@ layered architecture of JTAG interface and TAP support including: - debug target support (e.g. ARM, MIPS): single-stepping, breakpoints/watchpoints, gprof profiling, etc; - flash chip drivers (e.g. CFI, NAND, internal flash); -- embedded TCL interpreter for easy scripting. +- embedded Tcl interpreter for easy scripting. Several network interfaces are available for interacting with OpenOCD: -telnet, TCL, and GDB. The GDB server enables OpenOCD to function as a +telnet, Tcl, and GDB. The GDB server enables OpenOCD to function as a "remote target" for source-level debugging of embedded systems using the GNU GDB program (and the others who talk GDB protocol, e.g. IDA Pro). diff --git a/TODO b/TODO index 239b358f57..803692d58e 100644 --- a/TODO +++ b/TODO @@ -12,14 +12,14 @@ may have evolved an idea since it was added here. Feel free to send patches to add or clarify items on this list, too. -@section thelisttcl TCL +@section thelisttcl Tcl -This section provides possible things to improve with OpenOCD's TCL support. +This section provides possible things to improve with OpenOCD's Tcl support. - Fix problem with incorrect line numbers reported for a syntax error in a reset init event. -- organize the TCL configurations: +- organize the Tcl configurations: - provide more directory structure for boards/targets? - factor configurations into layers (encapsulation and re-use) @@ -27,15 +27,15 @@ This section provides possible things to improve with OpenOCD's TCL support. parameters. Currently variables assigned through one such parameter command/script are unset before the next one is invoked. -- Isolate all TCL command support: +- Isolate all Tcl command support: - Pure C CLI implementations using --disable-builtin-tcl. - Allow developers to build new dongles using OpenOCD's JTAG core. - At first, provide only low-level JTAG support; target layer and above rely heavily on scripting event mechanisms. - - Allow full TCL support? add --with-tcl=/path/to/installed/tcl - - Move TCL support out of foo.[ch] and into foo_tcl.[ch] (other ideas?) + - Allow full Tcl support? add --with-tcl=/path/to/installed/tcl + - Move Tcl support out of foo.[ch] and into foo_tcl.[ch] (other ideas?) - See src/jtag/core.c and src/jtag/tcl.c for an example. - - allow some of these TCL command modules to be dynamically loadable? + - allow some of these Tcl command modules to be dynamically loadable? @section thelistadapter Adapter @@ -75,7 +75,7 @@ directly in minidriver API for better embedded host performance. The following tasks have been suggested for adding new core JTAG support: -- Improve autodetection of TAPs by supporting tcl escape procedures that +- Improve autodetection of TAPs by supporting Tcl escape procedures that can configure discovered TAPs based on IDCODE value ... they could: - Remove guessing for irlen - Allow non-default irmask/ircapture values @@ -133,7 +133,7 @@ TCP/IP packets handled by the server. - add BSDL support? A few possible options for the above: - -# Fake a TCL equivalent? + -# Fake a Tcl equivalent? -# Integrate an existing library? -# Write a new C implementation a la Jim? diff --git a/doc/manual/helper.txt b/doc/manual/helper.txt index b59fd664fb..6cf3c977bf 100644 --- a/doc/manual/helper.txt +++ b/doc/manual/helper.txt @@ -21,7 +21,7 @@ portability API. /** @page helperjim OpenOCD Jim API -The Jim API provides access to a small-footprint TCL implementation. +The Jim API provides access to a small-footprint Tcl implementation. Visit http://jim.tcl.tk/ for more information on Jim. diff --git a/doc/manual/jtag.txt b/doc/manual/jtag.txt index 2653fc78f5..5eb945013b 100644 --- a/doc/manual/jtag.txt +++ b/doc/manual/jtag.txt @@ -15,7 +15,7 @@ asynchronous transactions. - used by other modules - @subpage jtagtcl - - @b private TCL handling routines + - @b private Tcl handling routines - defined in @c src/jtag/tcl.c - registers and handles Jim commands that configure and use the JTAG core @@ -47,7 +47,7 @@ This section needs to be expanded. */ -/** @page jtagtcl JTAG TCL API +/** @page jtagtcl JTAG Tcl API This section needs to be expanded. diff --git a/doc/manual/primer/docs.txt b/doc/manual/primer/docs.txt index b1c0531375..1aefa17e6d 100644 --- a/doc/manual/primer/docs.txt +++ b/doc/manual/primer/docs.txt @@ -6,7 +6,7 @@ OpenOCD presently produces several kinds of documentation: - The User's Guide: - Focuses on using the OpenOCD software. - Details the installation, usage, and customization. - - Provides descriptions of public Jim/TCL script commands. + - Provides descriptions of public Jim Tcl script commands. - Written using GNU texinfo. - Created with 'make pdf' or 'make html'. - See @subpage primertexinfo and @ref styletexinfo. diff --git a/doc/manual/primer/tcl.txt b/doc/manual/primer/tcl.txt index eba2f552d0..6874f5566c 100644 --- a/doc/manual/primer/tcl.txt +++ b/doc/manual/primer/tcl.txt @@ -1,6 +1,6 @@ -/** @page primertcl OpenOCD TCL Primer +/** @page primertcl OpenOCD Tcl Primer -The @subpage scripting page provides additional TCL Primer material. +The @subpage scripting page provides additional Tcl Primer material. @verbatim @@ -8,15 +8,15 @@ The @subpage scripting page provides additional TCL Primer material. **************************************** This is a short introduction to 'un-scare' you about the language -known as TCL. It is structured as a guided tour through the files +known as Tcl. It is structured as a guided tour through the files written by me [Duane Ellis] - in early July 2008 for OpenOCD. Which uses the "JIM" embedded Tcl clone-ish language. -Thing described here are *totally* TCL generic... not Jim specific. +Thing described here are *totally* Tcl generic... not Jim specific. The goal of this document is to encourage you to add your own set of -chips to the TCL package - and most importantly you should know where +chips to the Tcl package - and most importantly you should know where you should put them - so they end up in an organized way. --Duane Ellis. @@ -57,14 +57,14 @@ Definition: Open: at91sam7x256.tcl === TCL TOUR === -A walk through --- For those who are new to TCL. +A walk through --- For those who are new to Tcl. Examine the file: at91sam7x256.tcl It starts with: source [find path/filename.tcl] -In TCL - this is very important. +In Tcl - this is very important. Rule #1 Everything is a string. Rule #2 If you think other wise See #1. @@ -130,7 +130,7 @@ First, there is a "for" loop - at level 0 This means it is evaluated when the file is parsed. == SIDEBAR: About The FOR command == -In TCL, "FOR" is a funny thing, it is not what you think it is. +In Tcl, "FOR" is a funny thing, it is not what you think it is. Syntactically - FOR is a just a command, it is not language construct like for(;;) in C... @@ -191,7 +191,7 @@ proc create_mask { MSB LSB } { Like "for" - PROC is really just a command that takes 3 parameters. The (1) NAME of the function, a (2) LIST of parameters, and a (3) BODY -Again, this is at "level 0" so it is a global function. (Yes, TCL +Again, this is at "level 0" so it is a global function. (Yes, Tcl supports local functions, you put them inside of a function} You'll see in some cases, I nest [brackets] a lot and in others I'm @@ -257,7 +257,7 @@ For example - 'show_mmr32_reg' is given the NAME of the register to display. The assumption is - the NAME is a global variable holding the address of that MMR. -The code does some tricks. The [set [set NAME]] is the TCL way +The code does some tricks. The [set [set NAME]] is the Tcl way of doing double variable interpolation - like makefiles... In a makefile or shell script you may have seen this: @@ -272,7 +272,7 @@ In a makefile or shell script you may have seen this: #BUILD = mac FOO = ${FOO_${BUILD}} -The "double [set] square bracket" thing is the TCL way, nothing more. +The "double [set] square bracket" thing is the Tcl way, nothing more. ---- @@ -352,7 +352,7 @@ tricks with interpretors. Function: show_mmr32_bits() -In this case, we use the special TCL command "upvar" which tcl's way +In this case, we use the special Tcl command "upvar" which is the Tcl way of passing things by reference. In this case, we want to reach up into the callers lexical scope and find the array named "NAMES" @@ -373,7 +373,7 @@ are basically identical... Second - there can be many of them. -In this case - I do some more TCL tricks to dynamically +In this case - I do some more Tcl tricks to dynamically create functions out of thin air. Some assumptions: @@ -409,7 +409,7 @@ And - declare that variable as GLOBAL so the world can find it. Then - we dynamically create a function - based on the register name. Look carefully at how that is done. You'll notice the FUNCTION BODY is -a string - not something in {braces}. Why? This is because we need TCL +a string - not something in {braces}. Why? This is because we need Tcl to evaluate the contents of that string "*NOW*" - when $vn exists not later, when the function "show_FOO" is invoked. diff --git a/doc/manual/scripting.txt b/doc/manual/scripting.txt index f8764e2d7c..48ba99bdaa 100644 --- a/doc/manual/scripting.txt +++ b/doc/manual/scripting.txt @@ -4,11 +4,11 @@ The scripting support is intended for developers of OpenOCD. It is not the intention that normal OpenOCD users will -use tcl scripting extensively, write lots of clever scripts, +use Tcl scripting extensively, write lots of clever scripts, or contribute back to OpenOCD. Target scripts can contain new procedures that end users may -tinker to their needs without really understanding tcl. +tinker to their needs without really understanding Tcl. Since end users are not expected to mess with the scripting language, the choice of language is not terribly important @@ -38,16 +38,16 @@ Default implementation of procedures in tcl/procedures.tcl. and will have no externally visible consequences. Tcl has an advantage in that it's syntax is backwards compatible with the current OpenOCD syntax. -- external scripting. Low level tcl functions will be defined - that return machine readable output. These low level tcl - functions constitute the tcl api. flash_banks is such - a low level tcl proc. "flash banks" is an example of +- external scripting. Low level Tcl functions will be defined + that return machine readable output. These low level Tcl + functions constitute the Tcl api. flash_banks is such + a low level Tcl proc. "flash banks" is an example of a command that has human readable output. The human readable output is expected to change in between versions of OpenOCD. The output from flash_banks may not be in the preferred form for the client. The client then has two choices a) parse the output from flash_banks - or b) write a small piece of tcl to output the + or b) write a small piece of Tcl to output the flash_banks output to a more suitable form. The latter may be simpler. diff --git a/doc/manual/server.txt b/doc/manual/server.txt index 8041c3df3d..20e48c1f43 100644 --- a/doc/manual/server.txt +++ b/doc/manual/server.txt @@ -43,7 +43,7 @@ with a script language: What follows hopefully shows how the plans to solve these problems materialized and help to explain the grand roadmap plan. -@subsection serverdocsjim Why JimTCL? The Internal Script Language +@subsection serverdocsjim Why Jim Tcl? The Internal Script Language At the time, the existing "command context schema" was proving itself insufficient. However, the problem was also considered from another @@ -57,14 +57,14 @@ OpenOCD. Yuck. OpenOCD already has a complex enough build system, why make it worse? The goal was to add a simple language that would be moderately easy to -work with and be self-contained. JimTCL is a single C and single H +work with and be self-contained. Jim Tcl is a single C and single H file, allowing OpenOCD to avoid the spider web of dependent packages. -@section serverdocstcl TCL Server Port +@section serverdocstcl Tcl Server Port -The TCL Server port was added in mid-2008. With embedded TCL, we can +The Tcl Server port was added in mid-2008. With embedded Tcl, we can write scripts internally to help things, or we can write "C" code that -interfaces well with TCL. +interfaces well with Tcl. From there, the developers wanted to create an external front-end that would be @a very usable and that @a any language could utilize, @@ -78,7 +78,7 @@ also support a high degree of interoperability with multiple systems. They are not human-centric protocols; more correctly, they are rigid, terse, simple ASCII protocols that are easily parsable by a script. -Thus, the TCL server -- a 'machine' type socket interface -- was added +Thus, the Tcl server -- a 'machine' type socket interface -- was added with the hope was it would output simple "name-value" pair type data. At the time, simple name/value pairs seemed reasonably easier to do at the time, though Maybe it should output JSON; @@ -107,7 +107,7 @@ What works easier and is less work is what is already present in every platform? The answer: A web browser. In other words, OpenOCD could serve out embedded web pages via "localhost" to your browser. -Long before OpenOCD had a TCL command line, Zylin AS built their ZY1000 +Long before OpenOCD had a Tcl command line, Zylin AS built their ZY1000 device with a built-in HTTP server. Later, they were willing to both contribute and integrate most of that work into the main tree. @@ -128,8 +128,8 @@ every language has it's own set of wack-ness, parameter marshaling is painful. What about "callbacks" and structures, and other mess. Imagine -debugging that system. When JimTCL was introduced Spencer Oliver had -quite a few well-put concerns (Summer 2008) about the idea of "TCL" +debugging that system. When Jim Tcl was introduced Spencer Oliver had +quite a few well-put concerns (Summer 2008) about the idea of "Tcl" taking over OpenOCD. His concern is and was: how do you debug something written in 2 different languages? A "SWIG" front-end is unlikely to help that situation. @@ -143,7 +143,7 @@ to Localhost or remote host, however one might want to make it work. A socket interface is very simple. One could write a Java application and serve it out via the embedded web server, could it - or something -like it talk to the built in TCL server? Yes, absolutely! We are on to +like it talk to the built in Tcl server? Yes, absolutely! We are on to something here. @subsection serverdocplatforms Platform Permutations @@ -167,9 +167,9 @@ the Socket Approach is used. @subsection serverdocfuture Development Scale Out -During 2008, Duane Ellis created some TCL scripts to display peripheral -register contents. For example, look at the sam7 TCL scripts, and the -stm32 TCL scripts. The hope was others would create more. +During 2008, Duane Ellis created some Tcl scripts to display peripheral +register contents. For example, look at the sam7 Tcl scripts, and the +stm32 Tcl scripts. The hope was others would create more. A good example of this is display/view the peripheral registers on @@ -208,7 +208,7 @@ upon it, sometimes that is the only scheme available. As a small group of developers, supporting all the platforms and targets in the debugger will be difficult, as there are enough problem with the plethora of Adapters, Chips, and different target boards. -Yes, the TCL interface might be suitable, but it has not received much +Yes, the Tcl interface might be suitable, but it has not received much love or attention. Perhaps it will after you read and understand this. One reason might be, this adds one more host side requirement to make @@ -247,8 +247,8 @@ Altogether, it provides a universally accessible GUI for OpenOCD. @section serverdocshtml Simple HTML Pages -There is (or could be) a simple "Jim TCL" function to read a memory -location. If that can be tied into a TCL script that can modify the +There is (or could be) a simple "Jim Tcl" function to read a memory +location. If that can be tied into a Tcl script that can modify the HTTP text, then we have a simple script-based web server with a JTAG engine under the hood. @@ -275,7 +275,7 @@ bit-banging JTAG Adapter serving web pages. @subsection serverdocshtmladv Advanced HTML Pages -Java or JavaScript could be used to talk back to the TCL port. One +Java or JavaScript could be used to talk back to the Tcl port. One could write a Java, AJAX, FLASH, or some other developer friendly toolbox and get a real cross-platform GUI interface. Sure, the interface is not native - but it is 100% cross-platform! diff --git a/doc/manual/style.txt b/doc/manual/style.txt index dc27e8767a..f7a12988fc 100644 --- a/doc/manual/style.txt +++ b/doc/manual/style.txt @@ -27,12 +27,12 @@ providing documentation, either as part of the C code or stand-alone. Feedback would be welcome to improve the OpenOCD guidelines. */ -/** @page styletcl TCL Style Guide +/** @page styletcl Tcl Style Guide -OpenOCD needs to expand its Jim/TCL Style Guide. +OpenOCD needs to expand its Jim Tcl Style Guide. Many of the guidelines listed on the @ref stylec page should apply to -OpenOCD's Jim/TCL code as well. +OpenOCD's Jim Tcl code as well. */ /** @page stylec C Style Guide From d567824f2ac267f61944aa839911f0b5bee98c4a Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 17 Aug 2024 12:35:30 +0200 Subject: [PATCH 1209/1312] doc/manual: Add guideline for configuration files The goal of this guideline is to have consistent and well-structured configurations files. The focus of this patch is on filenames and directory structure. A guideline for the content of the files should be included in a subsequent patch. This patch addresses a long outstanding task listed in 'Pending and Open Tasks'. Change-Id: Ib32dd8b9ed15c3f647cd8d74cfc79edf0e79a3df Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8854 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/manual/config_files.txt | 117 ++++++++++++++++++++++++++++++++++++ doc/manual/main.txt | 2 + 2 files changed, 119 insertions(+) create mode 100644 doc/manual/config_files.txt diff --git a/doc/manual/config_files.txt b/doc/manual/config_files.txt new file mode 100644 index 0000000000..db1cc14191 --- /dev/null +++ b/doc/manual/config_files.txt @@ -0,0 +1,117 @@ +/** @page config_files Configuration Files + +This page gives an overview of the different configuration files, what purpose they serve and how they are structured. +The goal of this guide is to ensure well-structured and consistent configuration files. + +All configuration files are stored in the @c tcl directory of the project directory. +These files must follow the @ref styletcl and @ref naming_convention. +There are different types of configuration files: + +- @ref interface_configs +- @ref target_configs +- @ref board_configs + +@note This guideline must be followed for new configuration files. +There may be configuration files that do not comply with this guide for legacy reasons. + + +@section interface_configs Interface + +This configuration file represents a debug (interface) adapter. +This is usually a USB device that provides an interface to one or more transports such as JTAG or SWD. +Other interfaces like ethernet or parallel port are also represented. + +A debug adapter configuration file must use the following scheme: + +@verbatim +tcl/interface/[vendor]/.cfg +@endverbatim + +The `vendor` directory for debug adapters is often omitted because multiple adapters from the same vendor can be represented by a common configuration file. +One counter example are FTDI-based debug adapters. +There are various devices, either standalone or development boards which use FTDI chips but use different chip models or settings. +Their corresponding configuration files are stored in the `ftdi` folder. + +The name of the `vendor` folder can also be a more generic term such as `parport` as it is used for parallel port based debug adapters. + +If it is foreseeable that new configuration files will be added in the future, create a `vendor` directory even if there is only a single file at the moment. +This prevents that files have to be moved in the future. + +@section target_configs Target + +This configuration file represents an actual chip. +For example, a microcontroller, FPGA, CPLD, or system on chip (SoC). +A target configuration file always represents an entire device series or family. + +A target configuration file must use the following scheme: + +@verbatim +tcl/target//.cfg +@endverbatim + +Use the device series or family as `target name`. +For example, the configuration file for the nRF54L series from Nordic Semiconductor is located here: + +@verbatim +tcl/target/nordic/nrf54l.cfg +@endverbatim + +If there are many similarities between different targets, use a common file to share large pieces of code. +Do not use a single file to represent multiple device series or families. + +@section board_configs Board + +This configuration file represents a circuit board, for example, a development board. +A board may also contain an on-board debug adapter. + +A board configuration file includes existing target and, if available, interface configuration files, since a target is used on many boards. + +Reuse existing target and interface configuration files whenever possible. +If a board needs an external debug adapter, do @b not write adapter specific configuration files. + + +A board configuration file must use the following scheme: + +@verbatim +tcl/board//[-suffix].cfg +@endverbatim + +For example, the board configuration file for the NUCLEO-U083RC from STMicroelectronics is located here: + +@verbatim +tcl/board/st/nucleo-u083rc.cfg +@endverbatim + +In case a board supports different features, a `suffix` can be used to indicate this. +Make sure that the suffix is short and meaningful. + +For example, the on-board debug adapter of the FRDM-KV11Z development board can be flashed with a SEGGER J-Link compatible firmware. +Hence, there is the following configuration file: + +@verbatim +tcl/board/nxp/frdm-kv11z-jlink.cfg +@endverbatim + +The use of a suffix should be chosen carefully. +In many cases it is sufficient to make a certain feature accessible via a variable. + +Use a single configuration file for each board. +If there are many similarities between different boards, use a common file to share large pieces of code. + + +@section naming_convention Naming Convention + + +The following naming conventions for configuration files and directories must be used: + +- Use only lower-case letters and digits for directory and filenames +- Use hyphen characters between consecutive words in identifiers (e.g. `more-than-one-word`) + +- Use a common abbreviation for the vendor name, such as + - @c ti for Texas Instruments + - @c st for STMicroelectronics + - @c silabs for Silicon Labs + +An extensive list of abbreviations for vendor names can be found [here](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/vendor-prefixes.yaml). + + */ diff --git a/doc/manual/main.txt b/doc/manual/main.txt index c28fbe2288..9da546b6d2 100644 --- a/doc/manual/main.txt +++ b/doc/manual/main.txt @@ -21,6 +21,8 @@ check the mailing list archives to find the status of your feature (or bug). - The @subpage releases page describes the project's release process. - The @subpage endianness provides hints about writing and testing endianness independent code for OpenOCD. +- The @subpage config_files page provides a guide for writing configuration files + for OpenOCD. @ref primer provide introductory materials for new developers on various specific topics. From afbd01b0a46f3a81fe6076c002ad66973dcfb64c Mon Sep 17 00:00:00 2001 From: Samuel Obuch Date: Thu, 13 Feb 2025 14:28:27 +0100 Subject: [PATCH 1210/1312] github/workflow: fix warnings for github actions - update runner to ubuntu-latest - pass GITHUB_TOKEN to delete-tag-and-release as input Change-Id: I83d69cfd7af7c44e67b1115ac843a0b41d6f87b9 Signed-off-by: Samuel Obuch Reviewed-on: https://review.openocd.org/c/openocd/+/8756 Reviewed-by: Antonio Borneo Tested-by: jenkins --- .github/workflows/snapshot.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 36b2f3bb3d..755e8f4e14 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -8,7 +8,7 @@ name: OpenOCD Snapshot jobs: package: - runs-on: [ubuntu-20.04] + runs-on: [ubuntu-latest] env: DL_DIR: ../downloads BUILD_DIR: ../build @@ -102,8 +102,8 @@ jobs: # add missing dlls cd $HOST-root/usr cp `$HOST-gcc --print-file-name=libwinpthread-1.dll` ./bin/ - # required by libftdi1.dll. For the gcc-mingw-10.3.x or later "libgcc_s_dw2-1.dll" will need to be copied. - cp `$HOST-gcc --print-file-name=libgcc_s_sjlj-1.dll` ./bin/ + # required by libftdi1.dll + cp `$HOST-gcc --print-file-name=libgcc_s_dw2-1.dll` ./bin/ # prepare the artifact ARTIFACT="openocd-${OPENOCD_TAG}-${HOST}.tar.gz" tar -czf $ARTIFACT * @@ -119,8 +119,7 @@ jobs: with: delete_release: true tag_name: ${{ env.RELEASE_NAME }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.GITHUB_TOKEN }} - name: Create Release uses: ncipollo/release-action@v1 with: From b3b790e4e01331f79b196f8312193ae0130d2394 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Dec 2023 22:54:51 +0100 Subject: [PATCH 1211/1312] rtos: rework rtos_create() To simplify the caller of rtos_create(), convert the code from jimtcl oriented to OpenOCD commands. While there, fix inconsistencies in almost every rtos create() method and reset rtos_auto_detect to better cooperate on run-time rtos configuration. Change-Id: I59c443aaed77a48174facdfc86db75d6b28c8480 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8830 Tested-by: jenkins --- src/rtos/chibios.c | 4 +-- src/rtos/ecos.c | 4 +-- src/rtos/embkernel.c | 4 +-- src/rtos/freertos.c | 4 +-- src/rtos/hwthread.c | 2 +- src/rtos/linux.c | 2 +- src/rtos/mqx.c | 4 +-- src/rtos/nuttx.c | 4 +-- src/rtos/rtkernel.c | 4 +-- src/rtos/rtos.c | 66 ++++++++++++++++++++++---------------------- src/rtos/rtos.h | 4 +-- src/rtos/threadx.c | 4 +-- src/target/target.c | 13 ++------- 13 files changed, 56 insertions(+), 63 deletions(-) diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c index af590c2cb1..0cd99e4720 100644 --- a/src/rtos/chibios.c +++ b/src/rtos/chibios.c @@ -515,10 +515,10 @@ static int chibios_create(struct target *target) for (unsigned int i = 0; i < ARRAY_SIZE(chibios_params_list); i++) if (strcmp(chibios_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&chibios_params_list[i]; - return 0; + return ERROR_OK; } LOG_WARNING("Could not find target \"%s\" in ChibiOS compatibility " "list", target_type_name(target)); - return -1; + return ERROR_FAIL; } diff --git a/src/rtos/ecos.c b/src/rtos/ecos.c index 7048b006e0..a70084b4fb 100644 --- a/src/rtos/ecos.c +++ b/src/rtos/ecos.c @@ -1213,12 +1213,12 @@ static int ecos_create(struct target *target) target->rtos->gdb_thread_packet = ecos_packet_hook; /* We do not currently use the target->rtos->gdb_target_for_threadid * hook. */ - return 0; + return ERROR_OK; } tnames++; } } LOG_ERROR("Could not find target in eCos compatibility list"); - return -1; + return ERROR_FAIL; } diff --git a/src/rtos/embkernel.c b/src/rtos/embkernel.c index 7e6de7902a..7ad937be59 100644 --- a/src/rtos/embkernel.c +++ b/src/rtos/embkernel.c @@ -115,11 +115,11 @@ static int embkernel_create(struct target *target) if (i >= ARRAY_SIZE(embkernel_params_list)) { LOG_WARNING("Could not find target \"%s\" in embKernel compatibility " "list", target_type_name(target)); - return -1; + return ERROR_FAIL; } target->rtos->rtos_specific_params = (void *) &embkernel_params_list[i]; - return 0; + return ERROR_OK; } static int embkernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embkernel_params *param, diff --git a/src/rtos/freertos.c b/src/rtos/freertos.c index 20977e07e9..bd7b4220e3 100644 --- a/src/rtos/freertos.c +++ b/src/rtos/freertos.c @@ -534,9 +534,9 @@ static int freertos_create(struct target *target) for (unsigned int i = 0; i < ARRAY_SIZE(freertos_params_list); i++) if (strcmp(freertos_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&freertos_params_list[i]; - return 0; + return ERROR_OK; } LOG_ERROR("Could not find target in FreeRTOS compatibility list"); - return -1; + return ERROR_FAIL; } diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 6332bd8ad0..76571c6b60 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -412,7 +412,7 @@ static int hwthread_create(struct target *target) target->rtos->thread_details = NULL; target->rtos->gdb_target_for_threadid = hwthread_target_for_threadid; target->rtos->gdb_thread_packet = hwthread_thread_packet; - return 0; + return ERROR_OK; } static int hwthread_read_buffer(struct rtos *rtos, target_addr_t address, diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 5efdc9f609..4ca02605ed 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -1424,7 +1424,7 @@ static int linux_os_create(struct target *target) /* initialize a default virt 2 phys translation */ os_linux->phys_mask = ~0xc0000000; os_linux->phys_base = 0x0; - return JIM_OK; + return ERROR_OK; } static char *linux_ps_command(struct target *target) diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c index 017fd2b01c..dbb48952f2 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -251,11 +251,11 @@ static int mqx_create( if (strcmp(mqx_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&mqx_params_list[i]; /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target_type_name(target)); */ - return 0; + return ERROR_OK; } } LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target_type_name(target)); - return -1; + return ERROR_FAIL; } /* diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 821e550885..27bf086c83 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -129,13 +129,13 @@ static int nuttx_create(struct target *target) if (i >= ARRAY_SIZE(nuttx_params_list)) { LOG_ERROR("Could not find \"%s\" target in NuttX compatibility list", target_type_name(target)); - return JIM_ERR; + return ERROR_FAIL; } /* We found a target in our list, copy its reference. */ target->rtos->rtos_specific_params = (void *)param; - return JIM_OK; + return ERROR_OK; } static int nuttx_smp_init(struct target *target) diff --git a/src/rtos/rtkernel.c b/src/rtos/rtkernel.c index aebbf3d94d..2be1996fcd 100644 --- a/src/rtos/rtkernel.c +++ b/src/rtos/rtkernel.c @@ -364,12 +364,12 @@ static int rtkernel_create(struct target *target) for (size_t i = 0; i < ARRAY_SIZE(rtkernel_params_list); i++) { if (strcmp(rtkernel_params_list[i].target_name, target_type_name(target)) == 0) { target->rtos->rtos_specific_params = (void *)&rtkernel_params_list[i]; - return 0; + return ERROR_OK; } } LOG_ERROR("Could not find target in rt-kernel compatibility list"); - return -1; + return ERROR_FAIL; } const struct rtos_type rtkernel_rtos = { diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 2c563d522b..5cac316ed3 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -57,7 +57,7 @@ static int os_alloc(struct target *target, const struct rtos_type *ostype) struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos)); if (!os) - return JIM_ERR; + return ERROR_FAIL; os->type = ostype; os->current_threadid = -1; @@ -69,7 +69,7 @@ static int os_alloc(struct target *target, const struct rtos_type *ostype) os->gdb_thread_packet = rtos_thread_packet; os->gdb_target_for_threadid = rtos_target_for_threadid; - return JIM_OK; + return ERROR_OK; } static void os_free(struct target *target) @@ -86,38 +86,26 @@ static void os_free(struct target *target) static int os_alloc_create(struct target *target, const struct rtos_type *ostype) { int ret = os_alloc(target, ostype); + if (ret != ERROR_OK) + return ret; - if (ret == JIM_OK) { - ret = target->rtos->type->create(target); - if (ret != JIM_OK) - os_free(target); - } + ret = target->rtos->type->create(target); + if (ret != ERROR_OK) + os_free(target); return ret; } -int rtos_create(struct jim_getopt_info *goi, struct target *target) +int rtos_create(struct command_invocation *cmd, struct target *target, + const char *rtos_name) { - int x; - const char *cp; - Jim_Obj *res; - int e; - - if (!goi->is_configure && goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); - return JIM_ERR; - } - os_free(target); + target->rtos_auto_detect = false; - e = jim_getopt_string(goi, &cp, NULL); - if (e != JIM_OK) - return e; - - if (strcmp(cp, "none") == 0) - return JIM_OK; + if (strcmp(rtos_name, "none") == 0) + return ERROR_OK; - if (strcmp(cp, "auto") == 0) { + if (strcmp(rtos_name, "auto") == 0) { /* Auto detect tries to look up all symbols for each RTOS, * and runs the RTOS driver's _detect() function when GDB * finds all symbols for any RTOS. See rtos_qsymbol(). */ @@ -128,17 +116,29 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target) return os_alloc(target, rtos_types[0]); } - for (x = 0; rtos_types[x]; x++) - if (strcmp(cp, rtos_types[x]->name) == 0) + for (int x = 0; rtos_types[x]; x++) + if (strcmp(rtos_name, rtos_types[x]->name) == 0) return os_alloc_create(target, rtos_types[x]); - Jim_SetResultFormatted(goi->interp, "Unknown RTOS type %s, try one of: ", cp); - res = Jim_GetResult(goi->interp); - for (x = 0; rtos_types[x]; x++) - Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL); - Jim_AppendStrings(goi->interp, res, ", auto or none", NULL); + char *all = NULL; + for (int x = 0; rtos_types[x]; x++) { + char *prev = all; + if (all) + all = alloc_printf("%s, %s", all, rtos_types[x]->name); + else + all = alloc_printf("%s", rtos_types[x]->name); + free(prev); + if (!all) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + } + + command_print(cmd, "Unknown RTOS type %s, try one of: %s, auto or none", + rtos_name, all); + free(all); - return JIM_ERR; + return ERROR_COMMAND_ARGUMENT_INVALID; } void rtos_destroy(struct target *target) diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 5ba8b26945..05beab1459 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -10,7 +10,6 @@ #include "server/server.h" #include "target/target.h" -#include typedef int64_t threadid_t; typedef int64_t symbol_address_t; @@ -113,7 +112,8 @@ struct rtos_register_stacking { #define GDB_THREAD_PACKET_NOT_CONSUMED (-40) -int rtos_create(struct jim_getopt_info *goi, struct target *target); +int rtos_create(struct command_invocation *cmd, struct target *target, + const char *rtos_name); void rtos_destroy(struct target *target); int rtos_set_reg(struct connection *connection, int reg_num, uint8_t *reg_value); diff --git a/src/rtos/threadx.c b/src/rtos/threadx.c index 61c49264e8..620f43cc8e 100644 --- a/src/rtos/threadx.c +++ b/src/rtos/threadx.c @@ -611,9 +611,9 @@ static int threadx_create(struct target *target) target->rtos->rtos_specific_params = (void *)&threadx_params_list[i]; target->rtos->current_thread = 0; target->rtos->thread_details = NULL; - return 0; + return ERROR_OK; } LOG_ERROR("Could not find target in ThreadX compatibility list"); - return -1; + return ERROR_FAIL; } diff --git a/src/target/target.c b/src/target/target.c index 40c8d3ed36..8ccab7e0ab 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5176,17 +5176,10 @@ static COMMAND_HELPER(target_configure, struct target *target, unsigned int inde command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]); return ERROR_COMMAND_ARGUMENT_INVALID; } - struct jim_getopt_info goi; - jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index); + retval = rtos_create(CMD, target, CMD_ARGV[index]); + if (retval != ERROR_OK) + return retval; index++; - goi.is_configure = true; - int resval = rtos_create(&goi, target); - int reslen; - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); - if (reslen > 0) - command_print(CMD, "%s", result); - if (resval != JIM_OK) - return ERROR_FAIL; } else { if (index != CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; From 3a879c7dcb718f7e575f5a35beeb42d0f67eaa85 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 18 Apr 2025 17:04:47 +0200 Subject: [PATCH 1212/1312] rtos: rework rtos_types[] and rtos_try_next() Drop the NULL sentinel at the end of the array and use ARRAY_SIZE() to bound the loops. Adapt rtos_try_next() to use ARRAY_SIZE(). While there: - change to bool the return type of rtos_try_next(); - move rtos_try_next() to avoid the forward declaration. Change-Id: I1bee11db943b670789e62f1bebe2509bbef451a0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8855 Tested-by: jenkins --- src/rtos/rtos.c | 53 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 5cac316ed3..216129b971 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -13,6 +13,7 @@ #include "target/target.h" #include "helper/log.h" #include "helper/binarybuffer.h" +#include "helper/types.h" #include "server/gdb_server.h" static const struct rtos_type *rtos_types[] = { @@ -31,11 +32,8 @@ static const struct rtos_type *rtos_types[] = { &rtkernel_rtos, /* keep this as last, as it always matches with rtos auto */ &hwthread_rtos, - NULL }; -static int rtos_try_next(struct target *target); - int rtos_smp_init(struct target *target) { if (target->rtos->type->smp_init) @@ -116,12 +114,12 @@ int rtos_create(struct command_invocation *cmd, struct target *target, return os_alloc(target, rtos_types[0]); } - for (int x = 0; rtos_types[x]; x++) + for (size_t x = 0; x < ARRAY_SIZE(rtos_types); x++) if (strcmp(rtos_name, rtos_types[x]->name) == 0) return os_alloc_create(target, rtos_types[x]); char *all = NULL; - for (int x = 0; rtos_types[x]; x++) { + for (size_t x = 0; x < ARRAY_SIZE(rtos_types); x++) { char *prev = all; if (all) all = alloc_printf("%s, %s", all, rtos_types[x]->name); @@ -155,6 +153,29 @@ int gdb_thread_packet(struct connection *connection, char const *packet, int pac return target->rtos->gdb_thread_packet(connection, packet, packet_size); } +static bool rtos_try_next(struct target *target) +{ + struct rtos *os = target->rtos; + + if (!os) + return false; + + for (size_t x = 0; x < ARRAY_SIZE(rtos_types) - 1; x++) { + if (os->type == rtos_types[x]) { + // Use next RTOS in the list + os->type = rtos_types[x + 1]; + + free(os->symbols); + os->symbols = NULL; + + return true; + } + } + + // No next RTOS to try + return false; +} + static struct symbol_table_elem *find_symbol(const struct rtos *os, const char *symbol) { struct symbol_table_elem *s; @@ -667,28 +688,6 @@ int rtos_generic_stack_read(struct target *target, return ERROR_OK; } -static int rtos_try_next(struct target *target) -{ - struct rtos *os = target->rtos; - const struct rtos_type **type = rtos_types; - - if (!os) - return 0; - - while (*type && os->type != *type) - type++; - - if (!*type || !*(++type)) - return 0; - - os->type = *type; - - free(os->symbols); - os->symbols = NULL; - - return 1; -} - int rtos_update_threads(struct target *target) { if ((target->rtos) && (target->rtos->type)) From 3954896d6e41298efd74e8bb7af60ec49efae809 Mon Sep 17 00:00:00 2001 From: Chien Wong Date: Tue, 8 Apr 2025 20:33:56 +0800 Subject: [PATCH 1213/1312] rtos/FreeRTOS: fix next pointer member offset in FreeRTOS lists Currently, we are using offset of xListEnd.pxPrevious in List_t for list_next_offset and offset of pxPrevious in ListItem_t for list_elem_next_offset. This is confusing. Fix this. As the related lists are doubly linked lists, only iteration order is changed without breaking functionality. Also document those offsets. Change-Id: I8beacc235ee781ab4e3b415fccad7b72ec55b098 Signed-off-by: Chien Wong Reviewed-on: https://review.openocd.org/c/openocd/+/8833 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/rtos/freertos.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rtos/freertos.c b/src/rtos/freertos.c index bd7b4220e3..5a9224ec08 100644 --- a/src/rtos/freertos.c +++ b/src/rtos/freertos.c @@ -30,12 +30,12 @@ struct freertos_params { const char *target_name; const unsigned char thread_count_width; const unsigned char pointer_width; - const unsigned char list_next_offset; - const unsigned char list_width; - const unsigned char list_elem_next_offset; - const unsigned char list_elem_content_offset; - const unsigned char thread_stack_offset; - const unsigned char thread_name_offset; + const unsigned char list_next_offset; /* offsetof(List_t, xListEnd.pxNext) */ + const unsigned char list_width; /* sizeof(List_t) */ + const unsigned char list_elem_next_offset; /* offsetof(ListItem_t, pxNext) */ + const unsigned char list_elem_content_offset; /* offsetof(ListItem_t, pvOwner) */ + const unsigned char thread_stack_offset; /* offsetof(TCB_t, pxTopOfStack) */ + const unsigned char thread_name_offset; /* offsetof(TCB_t, pcTaskName) */ const struct rtos_register_stacking *stacking_info_cm3; const struct rtos_register_stacking *stacking_info_cm4f; const struct rtos_register_stacking *stacking_info_cm4f_fpu; @@ -46,9 +46,9 @@ static const struct freertos_params freertos_params_list[] = { "cortex_m", /* target_name */ 4, /* thread_count_width; */ 4, /* pointer_width; */ - 16, /* list_next_offset; */ + 12, /* list_next_offset; */ 20, /* list_width; */ - 8, /* list_elem_next_offset; */ + 4, /* list_elem_next_offset; */ 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ @@ -60,9 +60,9 @@ static const struct freertos_params freertos_params_list[] = { "hla_target", /* target_name */ 4, /* thread_count_width; */ 4, /* pointer_width; */ - 16, /* list_next_offset; */ + 12, /* list_next_offset; */ 20, /* list_width; */ - 8, /* list_elem_next_offset; */ + 4, /* list_elem_next_offset; */ 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ From d71ed4f3bc58f97ec99f265e55faa1fed7e793ff Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 19 Apr 2025 16:28:50 +0200 Subject: [PATCH 1214/1312] target: armv7a: drop command 'cache_config l2x' The command was already tagged as deprecated in 2015 with commit 0df557728216 ("armv7a: remove l1 flush all data handler") but has never been removed. An equivalent command 'cache l2x conf' was introduced at the same time in commit cd440bd32a12 ("add armv7a_cache handlers"). Drop it and deprecate it. Replace the old command in the Tcl script. Change-Id: Ie24eccc99a78786903704d10ee1d9f6c924529b5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8857 Tested-by: jenkins --- doc/openocd.texi | 4 --- src/target/armv7a.c | 74 ------------------------------------------ src/target/startup.tcl | 6 ++++ tcl/target/u8500.cfg | 2 +- 4 files changed, 7 insertions(+), 79 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index e0bdd5ca09..ca357c7802 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -10710,10 +10710,6 @@ Display/set the current core displayed in GDB Selects whether interrupts will be processed when single stepping @end deffn -@deffn {Command} {cache_config l2x} [base way] -configure l2x cache -@end deffn - @deffn {Command} {cortex_a mmu dump} [@option{0}|@option{1}|@option{addr} address [@option{num_entries}]] Dump the MMU translation table from TTB0 or TTB1 register, or from physical memory location @var{address}. When dumping the table from @var{address}, print at most diff --git a/src/target/armv7a.c b/src/target/armv7a.c index c14155e013..fb8862611a 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -179,54 +179,6 @@ int armv7a_read_ttbcr(struct target *target) return retval; } -/* FIXME: remove it */ -static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) -{ - struct armv7a_l2x_cache *l2x_cache; - struct target_list *head; - - struct armv7a_common *armv7a = target_to_armv7a(target); - l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache)); - l2x_cache->base = base; - l2x_cache->way = way; - /*LOG_INFO("cache l2 initialized base %x way %d", - l2x_cache->base,l2x_cache->way);*/ - if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) - LOG_INFO("outer cache already initialized\n"); - armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; - /* initialize all target in this cluster (smp target) - * l2 cache must be configured after smp declaration */ - foreach_smp_target(head, target->smp_targets) { - struct target *curr = head->target; - if (curr != target) { - armv7a = target_to_armv7a(curr); - if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) - LOG_ERROR("smp target : outer cache already initialized\n"); - armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; - } - } - return JIM_OK; -} - -/* FIXME: remove it */ -COMMAND_HANDLER(handle_cache_l2x) -{ - struct target *target = get_current_target(CMD_CTX); - uint32_t base, way; - - if (CMD_ARGC != 2) - return ERROR_COMMAND_SYNTAX_ERROR; - - /* command_print(CMD, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */ - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way); - - /* AP address is in bits 31:24 of DP_SELECT */ - armv7a_l2x_cache_init(target, base, way); - - return ERROR_OK; -} - int armv7a_handle_cache_info_command(struct command_invocation *cmd, struct armv7a_cache_common *armv7a_cache) { @@ -561,33 +513,7 @@ int armv7a_arch_state(struct target *target) return ERROR_OK; } -static const struct command_registration l2_cache_commands[] = { - { - .name = "l2x", - .handler = handle_cache_l2x, - .mode = COMMAND_EXEC, - .help = "configure l2x cache", - .usage = "[base_addr] [number_of_way]", - }, - COMMAND_REGISTRATION_DONE - -}; - -static const struct command_registration l2x_cache_command_handlers[] = { - { - .name = "cache_config", - .mode = COMMAND_EXEC, - .help = "cache configuration for a target", - .usage = "", - .chain = l2_cache_commands, - }, - COMMAND_REGISTRATION_DONE -}; - const struct command_registration armv7a_command_handlers[] = { - { - .chain = l2x_cache_command_handlers, - }, { .chain = arm7a_cache_command_handlers, }, diff --git a/src/target/startup.tcl b/src/target/startup.tcl index e9646097f0..1cc9bb7fda 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -316,3 +316,9 @@ proc _post_init_target_cortex_a_cache_auto {} { } } lappend post_init_commands _post_init_target_cortex_a_cache_auto + +lappend _telnet_autocomplete_skip "cache_config l2x" +proc "cache_config l2x" {args} { + echo "DEPRECATED! use 'cache l2x conf' not 'cache_config l2x'" + eval cache_config l2x $args +} diff --git a/tcl/target/u8500.cfg b/tcl/target/u8500.cfg index 1fdc11fe34..ea3c7218ee 100644 --- a/tcl/target/u8500.cfg +++ b/tcl/target/u8500.cfg @@ -133,7 +133,7 @@ proc enable_apetap {} { set status [$_TARGETNAME_1 curstate] if {[string equal "unknown" $status]} { $_TARGETNAME_1 arp_examine - cache_config l2x 0xa0412000 8 + cache l2x conf 0xa0412000 8 } set status [$_TARGETNAME_2 curstate] From 06c827757b0c44bef5a15558a71ab666375cbb87 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 19 Apr 2025 17:05:16 +0200 Subject: [PATCH 1215/1312] target: armv7a: use proper type for struct armv7a_cache_common::outer_cache The field 'outer_cache' is always initialized and used as a pointer to 'struct armv7a_l2x_cache'. There is no reason for using type 'void *' for it. Change the type of 'outer_cache'. Drop the useless cast while reading 'outer_cache'. Change-Id: Iaea9d02e247da26e230f887c85fbf8e9d7be34d5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8858 Tested-by: jenkins --- src/target/armv7a.c | 3 +-- src/target/armv7a.h | 2 +- src/target/armv7a_cache_l2x.c | 23 +++++++++++------------ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/target/armv7a.c b/src/target/armv7a.c index fb8862611a..4d353dec65 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -182,8 +182,7 @@ int armv7a_read_ttbcr(struct target *target) int armv7a_handle_cache_info_command(struct command_invocation *cmd, struct armv7a_cache_common *armv7a_cache) { - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a_cache->outer_cache); + struct armv7a_l2x_cache *l2x_cache = armv7a_cache->outer_cache; int cl; diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 8943f1c697..2706c4629b 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -66,7 +66,7 @@ struct armv7a_cache_common { int i_cache_enabled; int d_u_cache_enabled; /* outer unified cache if some */ - void *outer_cache; + struct armv7a_l2x_cache *outer_cache; int (*flush_all_data_cache)(struct target *target); }; diff --git a/src/target/armv7a_cache_l2x.c b/src/target/armv7a_cache_l2x.c index 39c503f096..bc60e6d193 100644 --- a/src/target/armv7a_cache_l2x.c +++ b/src/target/armv7a_cache_l2x.c @@ -21,8 +21,8 @@ static int arm7a_l2x_sanity_check(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a->armv7a_mmu.armv7a_cache.outer_cache); + struct armv7a_l2x_cache *l2x_cache = + armv7a->armv7a_mmu.armv7a_cache.outer_cache; if (target->state != TARGET_HALTED) { LOG_ERROR("%s: target not halted", __func__); @@ -42,8 +42,8 @@ static int arm7a_l2x_sanity_check(struct target *target) int arm7a_l2x_flush_all_data(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a->armv7a_mmu.armv7a_cache.outer_cache); + struct armv7a_l2x_cache *l2x_cache = + armv7a->armv7a_mmu.armv7a_cache.outer_cache; uint32_t l2_way_val; int retval; @@ -62,8 +62,8 @@ int armv7a_l2x_cache_flush_virt(struct target *target, target_addr_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a->armv7a_mmu.armv7a_cache.outer_cache); + struct armv7a_l2x_cache *l2x_cache = + armv7a->armv7a_mmu.armv7a_cache.outer_cache; /* FIXME: different controllers have different linelen? */ uint32_t i, linelen = 32; int retval; @@ -97,8 +97,8 @@ static int armv7a_l2x_cache_inval_virt(struct target *target, target_addr_t virt uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a->armv7a_mmu.armv7a_cache.outer_cache); + struct armv7a_l2x_cache *l2x_cache = + armv7a->armv7a_mmu.armv7a_cache.outer_cache; /* FIXME: different controllers have different linelen */ uint32_t i, linelen = 32; int retval; @@ -132,8 +132,8 @@ static int armv7a_l2x_cache_clean_virt(struct target *target, target_addr_t virt unsigned int size) { struct armv7a_common *armv7a = target_to_armv7a(target); - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a->armv7a_mmu.armv7a_cache.outer_cache); + struct armv7a_l2x_cache *l2x_cache = + armv7a->armv7a_mmu.armv7a_cache.outer_cache; /* FIXME: different controllers have different linelen */ uint32_t i, linelen = 32; int retval; @@ -166,8 +166,7 @@ static int armv7a_l2x_cache_clean_virt(struct target *target, target_addr_t virt static int arm7a_handle_l2x_cache_info_command(struct command_invocation *cmd, struct armv7a_cache_common *armv7a_cache) { - struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *) - (armv7a_cache->outer_cache); + struct armv7a_l2x_cache *l2x_cache = armv7a_cache->outer_cache; if (armv7a_cache->info == -1) { command_print(cmd, "cache not yet identified"); From 00f5b7ece6f031ece824375007e825ffc113e72b Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 1 May 2025 19:38:42 +0200 Subject: [PATCH 1216/1312] transport: fix incorrect statement Commit 236208a5ff2d ("transport: use a bitmask for the transport") has an incorrect C statement in place of a return. The code is working thanks to the previous condition never true. The issue has been detected by clang scan-build in OpenOCD ACI since the missing return can make the following statement dereferencing a NULL pointer. Fix it! Change-Id: I3bbe04d99ad9b1288f55ba3c45e2e487aef9ae40 Signed-off-by: Antonio Borneo Fixes: 236208a5ff2d ("transport: use a bitmask for the transport") Reviewed-on: https://review.openocd.org/c/openocd/+/8868 Tested-by: jenkins --- src/transport/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport/transport.c b/src/transport/transport.c index ab5be490fb..5323a7ca0a 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -258,7 +258,7 @@ struct transport *get_current_transport(void) const char *get_current_transport_name(void) { if (!session || !is_transport_id_valid(session->id)) - NULL; + return NULL; return transport_full_name(session->id); } From 618e447278097e41daecf76f6a1e2005f9fc9450 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 1 May 2025 18:41:51 +0200 Subject: [PATCH 1217/1312] tcl: board: convert transport select dapdirect_swd to swd Two new boards were added after the commit ad53fe659b46 ("tcl: convert transport select to jtag and swd") Align them too. Change-Id: I53e36a3a1a7730822521f0239922682c7b2fcef6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8869 Tested-by: jenkins --- tcl/board/st/nucleo-u083rc.cfg | 2 +- tcl/board/st_nucleo_c0.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/board/st/nucleo-u083rc.cfg b/tcl/board/st/nucleo-u083rc.cfg index 7b878adbc0..03e9569305 100644 --- a/tcl/board/st/nucleo-u083rc.cfg +++ b/tcl/board/st/nucleo-u083rc.cfg @@ -5,7 +5,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32u0x.cfg] diff --git a/tcl/board/st_nucleo_c0.cfg b/tcl/board/st_nucleo_c0.cfg index 7d07675920..845b7b50e9 100644 --- a/tcl/board/st_nucleo_c0.cfg +++ b/tcl/board/st_nucleo_c0.cfg @@ -2,7 +2,7 @@ source [find interface/stlink.cfg] -transport select dapdirect_swd +transport select swd source [find target/stm32c0x.cfg] From d6c54b94941294628c5ebff5f9c776c4a7b2aebb Mon Sep 17 00:00:00 2001 From: Daniel Goehring Date: Wed, 30 Apr 2025 22:38:15 -0400 Subject: [PATCH 1218/1312] target: cget command fix for result output Function target_configure() when processing a "cget" command needs to print the result to the console. Currently the result is only printed when an error occurs. To fix this, move the command print statement from the error handling section to the common code section. The code was tested by executing a "$target_name cget -dap" command and reviewing the result. Change-Id: Iff1999de8c8e9a837055ba95714137aa03e68d4b Signed-off-by: Daniel Goehring Fixes: 61890e3dc320 ("target: rewrite function target_configure() as COMMAND_HELPER") Reviewed-on: https://review.openocd.org/c/openocd/+/8870 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/target.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 8ccab7e0ab..a85d3def85 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4889,16 +4889,18 @@ static COMMAND_HELPER(target_configure, struct target *target, unsigned int inde goi.is_configure = is_configure; int e = (*target->type->target_jim_configure)(target, &goi); index = CMD_ARGC - goi.argc; + + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + if (e == JIM_OK) { /* more? */ continue; } if (e == JIM_ERR) { /* An error */ - int reslen; - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); - if (reslen > 0) - command_print(CMD, "%s", result); return ERROR_FAIL; } /* otherwise we 'continue' below */ From 8c09cc2c17547dca9783b596d43b735520f2e936 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Mon, 28 Apr 2025 16:46:08 +0300 Subject: [PATCH 1219/1312] target: improve error messaging in `target create` There are a couple of issues with the usage string for `target create`, namely: * `-chain-position` is allowed to be not the first option. * `-chain-position` should be ommited alltogether on ARM targets when DAP is specified. Before the patch: ``` > openocd -c 'target create name testee' ... target create name type '-chain-position' name [options ...] ``` After the patch: ``` > openocd -c 'target create name testee' ... -chain-position ?name? required when creating target > openocd -c 'target create' ... target create name type [options ...] ``` Change-Id: Ia21a99ce6a4086e2e0676f5ef4685da3514a4f69 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8860 Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/target/target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index a85d3def85..6d2fc95060 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5706,7 +5706,7 @@ COMMAND_HANDLER(handle_target_create) int retval = ERROR_OK; int x; - if (CMD_ARGC < 4) + if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; /* check if the target name clashes with an existing command name */ @@ -6051,7 +6051,7 @@ static const struct command_registration target_subcommand_handlers[] = { .name = "create", .mode = COMMAND_CONFIG, .handler = handle_target_create, - .usage = "name type '-chain-position' name [options ...]", + .usage = "name type [options ...]", .help = "Creates and selects a new target", }, { From f42540cc90b874c7662c59b8e4ebef3f657717ad Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Mon, 28 Apr 2025 16:55:35 +0300 Subject: [PATCH 1220/1312] target: improve error reporting for `-event` option `target create` calls can get quite long and an indication what is the option that caused the error can be helpful. Also, there can be multiple `-event` options for different events, therefore indicating which one is it is also helpful. Change-Id: I5ea61437ca9705e790ed8343183883a3fdfebc80 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8861 Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/target.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 6d2fc95060..6653c381c0 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4926,7 +4926,8 @@ static COMMAND_HELPER(target_configure, struct target *target, unsigned int inde case TCFG_EVENT: if (index == CMD_ARGC) { - command_print(CMD, "missing event-name"); + command_print(CMD, "expecting %s event-name event-body", + CMD_ARGV[index - 1]); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -4939,7 +4940,8 @@ static COMMAND_HELPER(target_configure, struct target *target, unsigned int inde if (is_configure) { if (index == CMD_ARGC) { - command_print(CMD, "missing event-body"); + command_print(CMD, "expecting %s %s event-body", + CMD_ARGV[index - 2], CMD_ARGV[index - 1]); return ERROR_COMMAND_ARGUMENT_INVALID; } } From 1b2a2b818573269e9704e1e117424210941de3c3 Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Fri, 29 Nov 2024 17:44:50 +0300 Subject: [PATCH 1221/1312] testing/tcl_commands: test `target create`, `cget`, `configure` Introduce basic testing of error-handling in target configuration related commands. The tests can be run via `make check` when JTAG `dummy` adapter is enabled. Change-Id: Id0f382046dd70007d8e696d82d2396a7ccab7a33 Signed-off-by: Evgeniy Naydanov Reviewed-on: https://review.openocd.org/c/openocd/+/8644 Tested-by: jenkins Reviewed-by: Antonio Borneo --- Makefile.am | 5 +- configure.ac | 4 +- testing/Makefile.am | 4 + testing/tcl_commands/Makefile.am | 15 ++++ .../test-target-configure-cget-command.cfg | 31 +++++++ .../test-target-create-command.cfg | 54 +++++++++++++ testing/tcl_commands/utils.tcl | 80 +++++++++++++++++++ 7 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 testing/Makefile.am create mode 100644 testing/tcl_commands/Makefile.am create mode 100644 testing/tcl_commands/test-target-configure-cget-command.cfg create mode 100644 testing/tcl_commands/test-target-create-command.cfg create mode 100644 testing/tcl_commands/utils.tcl diff --git a/Makefile.am b/Makefile.am index 271a2c1654..7fe137583c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ AUTOMAKE_OPTIONS = gnu 1.6 AM_DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim # do not run Jim Tcl tests (esp. during distcheck) -check-recursive: SUBDIRS := +check-recursive: SUBDIRS := $(SUBDIRS:jimtcl=) nobase_dist_pkgdata_DATA = \ contrib/libdcc/dcc_stdio.c \ @@ -36,6 +36,9 @@ EXTRA_DIST += jimtcl/configure.gnu DISTCLEANFILES += jimtcl/jsmn/jsmn.o endif +SUBDIRS += testing +DIST_SUBDIRS += testing + # common flags used in openocd build AM_CFLAGS = $(GCC_WARNINGS) AM_LDFLAGS = diff --git a/configure.ac b/configure.ac index 9db378702e..e48653b215 100644 --- a/configure.ac +++ b/configure.ac @@ -835,7 +835,9 @@ AS_IF([test "x$gcc_warnings" = "xyes"], [ AC_SUBST(EXTRA_DIST_NEWS, ["$(echo $srcdir/NEWS-*)"]) AC_CONFIG_FILES([ - Makefile + Makefile \ + testing/Makefile \ + testing/tcl_commands/Makefile ]) AC_OUTPUT diff --git a/testing/Makefile.am b/testing/Makefile.am new file mode 100644 index 0000000000..22778a4c21 --- /dev/null +++ b/testing/Makefile.am @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +SUBDIRS = tcl_commands +DIST_SUBDIRS = tcl_commands diff --git a/testing/tcl_commands/Makefile.am b/testing/tcl_commands/Makefile.am new file mode 100644 index 0000000000..fe8d150707 --- /dev/null +++ b/testing/tcl_commands/Makefile.am @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +TESTS = + +if DUMMY +TESTS += \ + test-target-create-command.cfg \ + test-target-configure-cget-command.cfg +endif + +EXTRA_DIST = utils.tcl $(TESTS) + +TEST_EXTENSIONS = .cfg +CFG_LOG_COMPILER = $(top_builddir)/src/openocd +AM_CFG_LOG_FLAGS = -f $(abs_srcdir)/utils.tcl -f diff --git a/testing/tcl_commands/test-target-configure-cget-command.cfg b/testing/tcl_commands/test-target-configure-cget-command.cfg new file mode 100644 index 0000000000..2d546c83da --- /dev/null +++ b/testing/tcl_commands/test-target-configure-cget-command.cfg @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +namespace import testing_helpers::* +namespace import configure_testing::* + +adapter driver dummy +jtag newtap tap cpu -irlen 5 + +{*}[target_create_first_args] {*}[simple_configure_options] + +set target_name [lindex [target names] 0] + +check_matches testee {$target_name cget -type} + +foreach {opt arg} [simple_configure_options] { + check_syntax_err {$target_name cget $opt extra_arg} + check_matches [dict get [simple_configure_options] $opt] \ + {$target_name cget $opt} +} + +check_error_matches .*-event.* {$target_name cget -event} +$target_name cget -event examine-start +check_syntax_err {$target_name cget -event examine-start extra_arg} + +check_syntax_err {$target_name configure} + +foreach {opt arg} [simple_configure_options] { + $target_name configure $opt [$target_name cget $opt] +} + +shutdown diff --git a/testing/tcl_commands/test-target-create-command.cfg b/testing/tcl_commands/test-target-create-command.cfg new file mode 100644 index 0000000000..11264316c3 --- /dev/null +++ b/testing/tcl_commands/test-target-create-command.cfg @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +namespace import testing_helpers::* +namespace import configure_testing::* + +adapter driver dummy +jtag newtap tap cpu -irlen 5 + +check_syntax_err {target create} +check_syntax_err {target create} +check_syntax_err {target create test.target} +check_error_matches -chain-position {target create test.target testee} + +{*}[target_create_first_args] {*}[simple_configure_options] + +foreach {opt arg} [simple_configure_options] { + check_error_matches ".*${opt}.*" {{*}[target_create_first_args] $opt} +} + +foreach {opt1 arg1} [simple_configure_options] { + foreach {opt2 arg2} [simple_configure_options] { + check_error_matches ".*${opt2}.*" \ + {{*}[target_create_first_args] $opt1 $arg1 $opt2} + check_error_matches {} \ + {{*}[target_create_first_args] $opt1 $opt2 $arg2} + } +} + +check_error_matches ".*-type.*" \ + {{*}[target_create_first_args] -type} + +check_error_matches ".*-type.*" \ + {{*}[target_create_first_args] {*}[simple_configure_options] -type} + +check_error_matches {.*-event [^ ]+ .*} \ + {{*}[target_create_first_args] -event} + +check_error_matches {.*not-an-event.*} \ + {{*}[target_create_first_args] -event not-an-event} + +check_error_matches {.*-event examine-start [^ ]+.*} \ + {{*}[target_create_first_args] -event examine-start} + +{*}[target_create_first_args] {*}[simple_configure_options] \ + -event examine-start body +{*}[target_create_first_args] {*}[simple_configure_options] \ + -event examine-start body \ + -event examine-end another-body \ + -event examine-start new-body +{*}[target_create_first_args] -event examine-start body {*}[simple_configure_options] + +{*}[target_create_first_args] {*}[simple_configure_options] -defer-examine + +shutdown diff --git a/testing/tcl_commands/utils.tcl b/testing/tcl_commands/utils.tcl new file mode 100644 index 0000000000..dfc8966613 --- /dev/null +++ b/testing/tcl_commands/utils.tcl @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +namespace eval testing_helpers { + + proc test_failure message { + echo $message + shutdown error + } + + proc check_for_error {expctd_code msg_ptrn script} { + set code [catch {uplevel $script} msg] + set expanded_script [uplevel subst \"$script\"] + if {!$code} { + test_failure \ + "'$expanded_script' finished successfully. \ + Was expecting an error." + } + if {$expctd_code ne "" && $code != $expctd_code} { + test_failure \ + "'$expanded_script' returned unexpected error code $code. \ + Was expecting $expctd_code. Error message: '$msg'" + } + if {$msg_ptrn ne "" && ![regexp -- $msg_ptrn $msg]} { + test_failure \ + "'$expanded_script' returned unexpected error message '$msg'. \ + Was expecting '$msg_ptrn'. Error code: $code" + } + } + + proc check_error_matches {pattern script} { + tailcall check_for_error {} $pattern $script + } + + proc check_syntax_err script { + tailcall check_for_error -601 {} $script + } + + proc check_matches {pattern script} { + set result [uplevel $script] + if {[regexp $pattern $result]} {return} + test_failure \ + "'$script' produced unexpected result '$result'. \ + Was expecting '$pattern'." + } + + namespace export check_error_matches check_syntax_err check_matches +} + +namespace eval configure_testing { + + variable target_idx 0 + + proc unique_tgt_name {} { + variable target_idx + incr target_idx + return test_target$target_idx + } + + proc target_create_first_args {} { + return "target create [unique_tgt_name] testee" + } + + proc simple_configure_options {} { + return { + -work-area-virt 0 + -work-area-phys 0 + -work-area-size 1 + -work-area-backup 0 + -endian little + -coreid 1 + -chain-position tap.cpu + -dbgbase 0 + -rtos hwthread + -gdb-port 0 + -gdb-max-connections 1 + } + } + + namespace export target_create_first_args simple_configure_options +} From 744955e5b4f4f943c187622f4ae977bc4cd6fdb7 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 5 May 2025 10:00:10 +0200 Subject: [PATCH 1222/1312] LICENSES: add dual/CC-BY-4.0 The license CC-BY-4.0 is not compatible with GPLv2, but files can be dual licensed with a GPLv2 compatible license 'OR' CC-BY-4.0. This is the case for some file auto-generated by riscv project. Change-Id: I4313d85a569a5e6423392129a730d1e22ef17c51 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8894 Reviewed-by: Bernhard Rosenkraenzer Tested-by: jenkins --- LICENSES/dual/CC-BY-4.0 | 409 +++++++++++++++++++++++++++++++++++++ LICENSES/license-rules.txt | 18 +- Makefile.am | 1 + tools/scripts/spdxcheck.py | 2 +- 4 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 LICENSES/dual/CC-BY-4.0 diff --git a/LICENSES/dual/CC-BY-4.0 b/LICENSES/dual/CC-BY-4.0 new file mode 100644 index 0000000000..e20b7a455e --- /dev/null +++ b/LICENSES/dual/CC-BY-4.0 @@ -0,0 +1,409 @@ +Valid-License-Identifier: CC-BY-4.0 +SPDX-URL: https://spdx.org/licenses/CC-BY-4.0 +Usage-Guide: + Do NOT use on OpenOCD code. This license is not GPL2 compatible. It may only + be used for dual-licensed files where the other license is GPL2 compatible. + If you end up using this it MUST be used together with a GPL2 compatible + license using "OR". + To use the Creative Commons Attribution 4.0 International license put + the following SPDX tag/value pair into a comment according to the + placement guidelines in the licensing rules documentation: + SPDX-License-Identifier: CC-BY-4.0 +License-Text: + +Creative Commons Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the "Licensor." The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/LICENSES/license-rules.txt b/LICENSES/license-rules.txt index ecc8e4db16..66aaaa5b4d 100644 --- a/LICENSES/license-rules.txt +++ b/LICENSES/license-rules.txt @@ -187,7 +187,21 @@ OpenOCD, can be broken down into: License-Text: Full license text -2. Exceptions: +2. Dual Licensing Only: + + These licenses should only be used to dual license code with another + license in addition to a preferred license. These licenses are available + from the directory:: + + LICENSES/dual/ + + in the OpenOCD source tree. + + The files in this directory contain the full license text and + `Metatags`_. The file names are identical to the SPDX license + identifier which shall be used for the license in source files. + +3. Exceptions: Some licenses can be amended with exceptions which grant certain rights which the original license does not. These exceptions are available @@ -244,7 +258,7 @@ OpenOCD, can be broken down into: License-Text: Full license text -3. Stand-alone licenses: +4. Stand-alone licenses: These licenses should only be used for stand-alone applications that are distributed with OpenOCD but are not included in the OpenOCD binary. diff --git a/Makefile.am b/Makefile.am index 7fe137583c..b2b6cef006 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,7 @@ EXTRA_DIST += \ $(EXTRA_DIST_NEWS) \ Doxyfile.in \ LICENSES/license-rules.txt \ + LICENSES/dual/CC-BY-4.0 \ LICENSES/exceptions/eCos-exception-2.0 \ LICENSES/preferred/BSD-1-Clause \ LICENSES/preferred/BSD-2-Clause \ diff --git a/tools/scripts/spdxcheck.py b/tools/scripts/spdxcheck.py index f882943790..9180f61fa6 100755 --- a/tools/scripts/spdxcheck.py +++ b/tools/scripts/spdxcheck.py @@ -50,7 +50,7 @@ def read_spdxdata(repo): # The subdirectories of LICENSES in the kernel source # Note: exceptions needs to be parsed as last directory. # OpenOCD specific: Begin - license_dirs = [ "preferred", "stand-alone", "exceptions" ] + license_dirs = [ "preferred", "dual", "exceptions", "stand-alone" ] # OpenOCD specific: End lictree = repo.head.commit.tree['LICENSES'] From e30828a2769c294a9d2a36ed10f1f3516d82d1c1 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Mon, 4 Mar 2024 17:29:15 +0800 Subject: [PATCH 1223/1312] helper: add bitfield helper macros This patch ports FIELD_{GET,PREP,FIT} macros and related macro from FreeBSD, referenced file: - `src/tree/sys/compat/linuxkpi/common/include/linux/bitfield.h` Checkpatch-ignore: MACRO_ARG_REUSE Change-Id: I6fdf4514d3f95d62fadf7654409a4878d470a600 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/8171 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/Makefile.am | 1 + src/helper/bitfield.h | 60 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/helper/bitfield.h diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am index e0fa331ea2..a17ada97d6 100644 --- a/src/helper/Makefile.am +++ b/src/helper/Makefile.am @@ -19,6 +19,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la %D%/nvp.c \ %D%/align.h \ %D%/binarybuffer.h \ + %D%/bitfield.h \ %D%/bits.h \ %D%/configuration.h \ %D%/list.h \ diff --git a/src/helper/bitfield.h b/src/helper/bitfield.h new file mode 100644 index 0000000000..9f397282cf --- /dev/null +++ b/src/helper/bitfield.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* +* Copyright (c) 2020-2024 The FreeBSD Foundation +* +* This software was developed by Björn Zeeb under sponsorship from +* the FreeBSD Foundation. +*/ + +#ifndef OPENOCD_HELPER_BITFIELD_H +#define OPENOCD_HELPER_BITFIELD_H + +/** + * These macros come from FreeBSD, check source on + * https://cgit.freebsd.org/src/tree/sys/compat/linuxkpi/common/include/linux/bitfield.h + * Which does not include example usages of them. + */ + +#define __bf_shf(x) (__builtin_ffsll(x) - 1) + +/** + * FIELD_FIT(_mask, _value) - Check if a value fits in the specified bitfield mask + * @_mask: Bitfield mask + * @_value: Value to check + * + * This macro checks whether a given value fits within the range defined by the + * specified bitfield mask. It ensures that no bits outside the mask are set. + * + * Return: true if the value fits, false otherwise. + */ +#define FIELD_FIT(_mask, _value) \ + (!(((typeof(_mask))(_value) << __bf_shf(_mask)) & ~(_mask))) + +/** + * FIELD_PREP(_mask, _value) - Prepare a value for insertion into a bitfield + * @_mask: Bitfield mask + * @_value: Value to insert + * + * This macro prepares a value for insertion into a bitfield by shifting the + * value into the position defined by the mask and applying the mask. + * + * Return: The prepared bitfield value. + */ +#define FIELD_PREP(_mask, _value) \ + (((typeof(_mask))(_value) << __bf_shf(_mask)) & (_mask)) + +/** + * FIELD_GET(_mask, _value) - Extract a value from a bitfield + * @_mask: Bitfield mask + * @_value: Bitfield value to extract from + * + * This macro extracts a value from a bitfield by masking and shifting the + * relevant bits down to the least significant position. + * + * Return: The extracted value. + */ +#define FIELD_GET(_mask, _value) \ + ((typeof(_mask))(((_value) & (_mask)) >> __bf_shf(_mask))) + +#endif /* OPENOCD_HELPER_BITFIELD_H */ From 6a3abda0b46a777490a8ce5bc748e6fed6775354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Rosenkr=C3=A4nzer?= Date: Tue, 6 May 2025 01:07:06 +0200 Subject: [PATCH 1224/1312] helper: add base64 encoding/decoding helpers from FreeBSD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These helpers are needed by the updated RISC-V target files. Change-Id: I5aa9f4e58eb75e1c7a1e8e0e3961725e2a915ebb Signed-off-by: Bernhard Rosenkränzer Reviewed-on: https://review.openocd.org/c/openocd/+/8895 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/helper/Makefile.am | 2 + src/helper/base64.c | 160 +++++++++++++++++++++++++++++++++++++++++ src/helper/base64.h | 19 +++++ 3 files changed, 181 insertions(+) create mode 100644 src/helper/base64.c create mode 100644 src/helper/base64.h diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am index a17ada97d6..8072124784 100644 --- a/src/helper/Makefile.am +++ b/src/helper/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la %C%_libhelper_la_SOURCES = \ + %D%/base64.c \ %D%/binarybuffer.c \ %D%/options.c \ %D%/time_support_common.c \ @@ -18,6 +19,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la %D%/jim-nvp.c \ %D%/nvp.c \ %D%/align.h \ + %D%/base64.h \ %D%/binarybuffer.h \ %D%/bitfield.h \ %D%/bits.h \ diff --git a/src/helper/base64.c b/src/helper/base64.c new file mode 100644 index 0000000000..5e0ee0846e --- /dev/null +++ b/src/helper/base64.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/* + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005-2011, Jouni Malinen + * + * Original file from FreeBSD code + * https://cgit.freebsd.org/src/tree/contrib/wpa/src/utils/base64.c?id=f05cddf940db + */ + + +#include +#include +#include + +#include "base64.h" + +static const unsigned char base64_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * base64_encode - Base64 encode + * @src: Data to be encoded + * @len: Length of the data to be encoded + * @out_len: Pointer to output length variable, or %NULL if not used + * Returns: Allocated buffer of out_len bytes of encoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. Returned buffer is + * nul terminated to make it easier to use as a C string. The nul terminator is + * not included in out_len. + */ +unsigned char *base64_encode(const unsigned char *src, size_t len, + size_t *out_len) +{ + unsigned char *out, *pos; + const unsigned char *end, *in; + size_t olen; + int line_len; + + olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ + olen += olen / 72; /* line feeds */ + olen++; /* nul termination */ + if (olen < len) + return NULL; /* integer overflow */ + out = malloc(olen); + if (!out) + return NULL; + + end = src + len; + in = src; + pos = out; + line_len = 0; + while (end - in >= 3) { + *pos++ = base64_table[in[0] >> 2]; + *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; + *pos++ = base64_table[in[2] & 0x3f]; + in += 3; + line_len += 4; + if (line_len >= 72) { + *pos++ = '\n'; + line_len = 0; + } + } + + if (end - in) { + *pos++ = base64_table[in[0] >> 2]; + if (end - in == 1) { + *pos++ = base64_table[(in[0] & 0x03) << 4]; + *pos++ = '='; + } else { + *pos++ = base64_table[((in[0] & 0x03) << 4) | + (in[1] >> 4)]; + *pos++ = base64_table[(in[1] & 0x0f) << 2]; + } + *pos++ = '='; + line_len += 4; + } + + if (line_len) + *pos++ = '\n'; + + *pos = '\0'; + if (out_len) + *out_len = pos - out; + return out; +} + + +/** + * base64_decode - Base64 decode + * @src: Data to be decoded + * @len: Length of the data to be decoded + * @out_len: Pointer to output length variable + * Returns: Allocated buffer of out_len bytes of decoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. + */ +unsigned char *base64_decode(const unsigned char *src, size_t len, + size_t *out_len) +{ + unsigned char dtable[256], *out, *pos, block[4], tmp; + size_t i, count, olen; + int pad = 0; + + memset(dtable, 0x80, 256); + for (i = 0; i < sizeof(base64_table) - 1; i++) + dtable[base64_table[i]] = (unsigned char)i; + dtable['='] = 0; + + count = 0; + for (i = 0; i < len; i++) { + if (dtable[src[i]] != 0x80) + count++; + } + + if (count == 0 || count % 4) + return NULL; + + olen = count / 4 * 3; + out = malloc(olen); + if (!out) + return NULL; + pos = out; + + count = 0; + for (i = 0; i < len; i++) { + tmp = dtable[src[i]]; + if (tmp == 0x80) + continue; + + if (src[i] == '=') + pad++; + block[count] = tmp; + count++; + if (count == 4) { + *pos++ = (block[0] << 2) | (block[1] >> 4); + *pos++ = (block[1] << 4) | (block[2] >> 2); + *pos++ = (block[2] << 6) | block[3]; + count = 0; + if (pad) { + if (pad == 1) { + pos--; + } else if (pad == 2) { + pos -= 2; + } else { + /* Invalid padding */ + free(out); + return NULL; + } + break; + } + } + } + + *out_len = pos - out; + return out; +} diff --git a/src/helper/base64.h b/src/helper/base64.h new file mode 100644 index 0000000000..d3e0462131 --- /dev/null +++ b/src/helper/base64.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005, Jouni Malinen + * + * Original file from FreeBSD code + * https://cgit.freebsd.org/src/tree/contrib/wpa/src/utils/base64.h?id=f05cddf940db + */ + +#ifndef BASE64_H +#define BASE64_H + +unsigned char *base64_encode(const unsigned char *src, size_t len, + size_t *out_len); +unsigned char *base64_decode(const unsigned char *src, size_t len, + size_t *out_len); + +#endif /* BASE64_H */ From 532db01df29ab0636911f5cb0b40ed5747879c4e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 2 May 2025 16:10:39 +0200 Subject: [PATCH 1225/1312] cortex-a: fix single-step on infinite loop On ARMv7a/r the single-step is implemented through a HW breakpoint that hits instructions at any address except the address of the current instruction. The method above fails in case of an infinite loop coded by a single instruction that jumps on itself; in such case, the same instruction (at the same address) is executed over and over and the breakpoint never hits. In current code this case is wrongly considered as an error. Reduce the timeout while waiting for the HW breakpoint being hit, then halt. The jump on itself would be executed several times before the timeout and the halt, but this is not an issue. There are few "pathological" instructions in ARMv7a/r that jumps on itself and that can have side effects if executed more than once. They are listed in the code. We do not consider these as real use cases generated by a compiler. Document the method in the code. Report that the single-step function is not properly managing the HW breakpoints if it exits on error. To be fixed in the future. Change-Id: I9641a4a3e2f68b83897ccf3a12d3c34e98a7805c Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8871 Tested-by: jenkins --- src/target/cortex_a.c | 55 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index ee27e1b217..46362017af 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1169,6 +1169,29 @@ static int cortex_a_set_dscr_bits(struct target *target, return retval; } +/* + * Single-step on ARMv7a/r is implemented through a HW breakpoint that hits + * every instruction at any address except the address of the current + * instruction. + * Such HW breakpoint is never hit in case of a single instruction that jumps + * on itself (infinite loop), or a WFI or a WFE. In this case, halt the CPU + * after a timeout. + * The jump on itself would be executed several times before the timeout forces + * the halt, but this is not an issue. In ARMv7a/r there are few "pathological" + * instructions, listed below, that jumps on itself and that can have side + * effects if executed more than once; but they are not considered as real use + * cases generated by a compiler. + * Some example: + * - 'pop {pc}' or multi register 'pop' including PC, when the new PC value is + * the same value of current PC. The single step will not stop at the first + * 'pop' and will continue taking values from the stack, modifying SP at each + * iteration. + * - 'rfeda', 'rfedb', 'rfeia', 'rfeib', when the new PC value is the same + * value of current PC. The register provided to the instruction (usually SP) + * will be incremented or decremented at each iteration. + * + * TODO: fix exit in case of error, cleaning HW breakpoints. + */ static int cortex_a_step(struct target *target, bool current, target_addr_t address, bool handle_breakpoints) { @@ -1227,15 +1250,34 @@ static int cortex_a_step(struct target *target, bool current, target_addr_t addr if (retval != ERROR_OK) return retval; - int64_t then = timeval_ms(); + // poll at least once before starting the timeout + retval = cortex_a_poll(target); + if (retval != ERROR_OK) + return retval; + + int64_t then = timeval_ms() + 100; while (target->state != TARGET_HALTED) { + if (timeval_ms() > then) + break; + retval = cortex_a_poll(target); if (retval != ERROR_OK) return retval; - if (target->state == TARGET_HALTED) - break; - if (timeval_ms() > then + 1000) { - LOG_ERROR("timeout waiting for target halt"); + } + + if (target->state != TARGET_HALTED) { + LOG_TARGET_DEBUG(target, "timeout waiting for target halt, try halt"); + + retval = cortex_a_halt(target); + if (retval != ERROR_OK) + return retval; + + retval = cortex_a_poll(target); + if (retval != ERROR_OK) + return retval; + + if (target->state != TARGET_HALTED) { + LOG_TARGET_ERROR(target, "timeout waiting for target halt"); return ERROR_FAIL; } } @@ -1255,9 +1297,6 @@ static int cortex_a_step(struct target *target, bool current, target_addr_t addr if (breakpoint) cortex_a_set_breakpoint(target, breakpoint, 0); - if (target->state != TARGET_HALTED) - LOG_DEBUG("target stepped"); - return ERROR_OK; } From 1aef2ae18d709a141404777dc5bce3ec59b37909 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 5 Dec 2023 00:45:54 +0100 Subject: [PATCH 1226/1312] target: arm_dap: rewrite commands 'dap create' as COMMAND_HANDLER Rewrite only the command, but still use the old jimtcl specific code in dap_configure(). Change-Id: I3360884616367aae52f5b32247d9864000c53fdc Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8897 Tested-by: jenkins --- src/target/arm_dap.c | 92 ++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index c5bd6ccd4d..be5e63c7ca 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -333,61 +333,59 @@ static int dap_check_config(struct adiv5_dap *dap) return ERROR_OK; } -static int dap_create(struct jim_getopt_info *goi) +COMMAND_HANDLER(handle_dap_create) { - struct command_context *cmd_ctx; - static struct arm_dap_object *dap; - Jim_Obj *new_cmd; - Jim_Cmd *cmd; - const char *cp; - int e; + if (CMD_ARGC < 3) + return ERROR_COMMAND_SYNTAX_ERROR; - cmd_ctx = current_command_context(goi->interp); - assert(cmd_ctx); + int retval = ERROR_COMMAND_ARGUMENT_INVALID; - if (goi->argc < 3) { - Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options..."); - return JIM_ERR; - } - /* COMMAND */ - jim_getopt_obj(goi, &new_cmd); - /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); - if (cmd) { - cp = Jim_GetString(new_cmd, NULL); - Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp); - return JIM_ERR; + /* check if the dap name clashes with an existing command name */ + Jim_Cmd *jimcmd = Jim_GetCommand(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], JIM_NONE); + if (jimcmd) { + command_print(CMD, "Command/dap: %s Exists", CMD_ARGV[0]); + return ERROR_FAIL; } /* Create it */ - dap = calloc(1, sizeof(struct arm_dap_object)); - if (!dap) - return JIM_ERR; + struct arm_dap_object *dap = calloc(1, sizeof(struct arm_dap_object)); + if (!dap) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } dap_instance_init(&dap->dap); - cp = Jim_GetString(new_cmd, NULL); - dap->name = strdup(cp); + dap->name = strdup(CMD_ARGV[0]); + if (!dap->name) { + LOG_ERROR("Out of memory"); + free(dap); + return ERROR_FAIL; + } - e = dap_configure(goi, dap); - if (e != JIM_OK) + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 1, CMD_JIMTCL_ARGV + 1); + int e = dap_configure(&goi, dap); + if (e != JIM_OK) { + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); goto err; + } if (!dap->dap.tap) { - Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1); - e = JIM_ERR; + command_print(CMD, "-chain-position required when creating DAP"); goto err; } - e = dap_check_config(&dap->dap); - if (e != ERROR_OK) { - e = JIM_ERR; + retval = dap_check_config(&dap->dap); + if (retval != ERROR_OK) goto err; - } struct command_registration dap_create_commands[] = { { - .name = cp, + .name = CMD_ARGV[0], .mode = COMMAND_ANY, .help = "dap instance command group", .usage = "", @@ -400,32 +398,18 @@ static int dap_create(struct jim_getopt_info *goi) if (transport_is_hla()) dap_create_commands[0].chain = NULL; - e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap); - if (e != ERROR_OK) { - e = JIM_ERR; + retval = register_commands_with_data(CMD_CTX, NULL, dap_create_commands, dap); + if (retval != ERROR_OK) goto err; - } list_add_tail(&dap->lh, &all_dap); - return JIM_OK; + return ERROR_OK; err: free(dap->name); free(dap); - return e; -} - -static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 2) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - " [ ...]"); - return JIM_ERR; - } - return dap_create(&goi); + return retval; } COMMAND_HANDLER(handle_dap_names) @@ -496,7 +480,7 @@ static const struct command_registration dap_subcommand_handlers[] = { { .name = "create", .mode = COMMAND_ANY, - .jim_handler = jim_dap_create, + .handler = handle_dap_create, .usage = "name '-chain-position' name", .help = "Creates a new DAP instance", }, From c8979f6441eb62bb261827daa252c4e5596c4a39 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 5 Dec 2023 01:10:10 +0100 Subject: [PATCH 1227/1312] target: arm_cti: rewrite commands 'cti create' as COMMAND_HANDLER Rewrite only the command, but still use the old jimtcl specific code in cti_configure(). Change-Id: I29fb952a7c8148416b301cbf78b6e342979af7d3 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8898 Tested-by: jenkins --- src/target/arm_cti.c | 93 ++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index b2f78eef78..830956e5c5 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -434,49 +434,47 @@ static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti) return JIM_OK; } -static int cti_create(struct jim_getopt_info *goi) +COMMAND_HANDLER(handle_cti_create) { - struct command_context *cmd_ctx; - static struct arm_cti *cti; - Jim_Obj *new_cmd; - Jim_Cmd *cmd; - const char *cp; - int e; - - cmd_ctx = current_command_context(goi->interp); - assert(cmd_ctx); - - if (goi->argc < 3) { - Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options..."); - return JIM_ERR; - } - /* COMMAND */ - jim_getopt_obj(goi, &new_cmd); - /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE); - if (cmd) { - cp = Jim_GetString(new_cmd, NULL); - Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp); - return JIM_ERR; + if (CMD_ARGC < 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* check if the cti name clashes with an existing command name */ + Jim_Cmd *jimcmd = Jim_GetCommand(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], JIM_NONE); + if (jimcmd) { + command_print(CMD, "Command/cti: %s Exists", CMD_ARGV[0]); + return ERROR_FAIL; } /* Create it */ - cti = calloc(1, sizeof(*cti)); - if (!cti) - return JIM_ERR; + struct arm_cti *cti = calloc(1, sizeof(*cti)); + if (!cti) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } adiv5_mem_ap_spot_init(&cti->spot); /* Do the rest as "configure" options */ - goi->is_configure = true; - e = cti_configure(goi, cti); + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 1, CMD_JIMTCL_ARGV + 1); + goi.is_configure = 1; + int e = cti_configure(&goi, cti); if (e != JIM_OK) { + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); free(cti); - return e; + return ERROR_COMMAND_ARGUMENT_INVALID; } - cp = Jim_GetString(new_cmd, NULL); - cti->name = strdup(cp); + cti->name = strdup(CMD_ARGV[0]); + if (!cti->name) { + LOG_ERROR("Out of memory"); + free(cti); + return ERROR_FAIL; + } /* now - create the new cti name command */ const struct command_registration cti_subcommands[] = { @@ -487,7 +485,7 @@ static int cti_create(struct jim_getopt_info *goi) }; const struct command_registration cti_commands[] = { { - .name = cp, + .name = CMD_ARGV[0], .mode = COMMAND_ANY, .help = "cti instance command group", .usage = "", @@ -495,31 +493,24 @@ static int cti_create(struct jim_getopt_info *goi) }, COMMAND_REGISTRATION_DONE }; - e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti); - if (e != ERROR_OK) - return JIM_ERR; + int retval = register_commands_with_data(CMD_CTX, NULL, cti_commands, cti); + if (retval != ERROR_OK) { + free(cti->name); + free(cti); + return retval; + } 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; + command_print(CMD, "Cannot get AP"); + free(cti->name); + free(cti); + return ERROR_FAIL; } - return JIM_OK; -} - -static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 2) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - " [ ...]"); - return JIM_ERR; - } - return cti_create(&goi); + return ERROR_OK; } COMMAND_HANDLER(cti_handle_names) @@ -539,7 +530,7 @@ static const struct command_registration cti_subcommand_handlers[] = { { .name = "create", .mode = COMMAND_ANY, - .jim_handler = jim_cti_create, + .handler = handle_cti_create, .usage = "name '-chain-position' name [options ...]", .help = "Creates a new CTI object", }, From 114385280ae59fa0788b0077ba6d9596660cc714 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 26 May 2024 12:34:58 +0200 Subject: [PATCH 1228/1312] target/arm_tpiu_swo: rewrite command 'swo create' as COMMAND_HANDLER Rewrite only the command, but still use the old jimtcl specific code in arm_tpiu_swo_configure(), shared with commands 'configure' and 'cget'. Change-Id: I39c69b1cdc23f7b5f875df3e15be987c715b0bcf Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8899 Tested-by: jenkins --- src/target/arm_tpiu_swo.c | 90 +++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index e20cd59272..f2cb1a0fd1 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -907,56 +907,25 @@ static const struct command_registration arm_tpiu_swo_instance_command_handlers[ COMMAND_REGISTRATION_DONE }; -static int arm_tpiu_swo_create(Jim_Interp *interp, struct arm_tpiu_swo_object *obj) +COMMAND_HANDLER(handle_arm_tpiu_swo_create) { - struct command_context *cmd_ctx; - Jim_Cmd *cmd; - int e; + int retval = ERROR_FAIL; - cmd_ctx = current_command_context(interp); - assert(cmd_ctx); + if (!CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; /* does this command exist? */ - cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_NONE); - if (cmd) { - Jim_SetResultFormatted(interp, "cannot create TPIU object because a command with name '%s' already exists", - obj->name); - return JIM_ERR; - } - - /* now - create the new tpiu/swo name command */ - const struct command_registration obj_commands[] = { - { - .name = obj->name, - .mode = COMMAND_ANY, - .help = "tpiu/swo instance command group", - .usage = "", - .chain = arm_tpiu_swo_instance_command_handlers, - }, - COMMAND_REGISTRATION_DONE - }; - e = register_commands_with_data(cmd_ctx, NULL, obj_commands, obj); - if (e != ERROR_OK) - return JIM_ERR; - - list_add_tail(&obj->lh, &all_tpiu_swo); - - return JIM_OK; -} - -static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct jim_getopt_info goi; - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 1) { - Jim_WrongNumArgs(interp, 1, argv, "name ?option option ...?"); - return JIM_ERR; + Jim_Cmd *jimcmd = Jim_GetCommand(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], JIM_NONE); + if (jimcmd) { + command_print(CMD, "cannot create TPIU object because a command with name '%s' already exists", + CMD_ARGV[0]); + return ERROR_FAIL; } struct arm_tpiu_swo_object *obj = calloc(1, sizeof(struct arm_tpiu_swo_object)); if (!obj) { LOG_ERROR("Out of memory"); - return JIM_ERR; + return ERROR_FAIL; } INIT_LIST_HEAD(&obj->connections); adiv5_mem_ap_spot_init(&obj->spot); @@ -968,36 +937,55 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const goto err_exit; } - Jim_Obj *n; - jim_getopt_obj(&goi, &n); - obj->name = strdup(Jim_GetString(n, NULL)); + obj->name = strdup(CMD_ARGV[0]); if (!obj->name) { LOG_ERROR("Out of memory"); goto err_exit; } /* Do the rest as "configure" options */ - goi.is_configure = true; + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 1, CMD_JIMTCL_ARGV + 1); + goi.is_configure = 1; int e = arm_tpiu_swo_configure(&goi, obj); + + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + if (e != JIM_OK) goto err_exit; if (!obj->spot.dap || obj->spot.ap_num == DP_APSEL_INVALID) { - Jim_SetResultString(goi.interp, "-dap and -ap-num required when creating TPIU", -1); + command_print(CMD, "-dap and -ap-num required when creating TPIU"); goto err_exit; } - e = arm_tpiu_swo_create(goi.interp, obj); - if (e != JIM_OK) + /* now - create the new tpiu/swo name command */ + const struct command_registration obj_commands[] = { + { + .name = obj->name, + .mode = COMMAND_ANY, + .help = "tpiu/swo instance command group", + .usage = "", + .chain = arm_tpiu_swo_instance_command_handlers, + }, + COMMAND_REGISTRATION_DONE + }; + retval = register_commands_with_data(CMD_CTX, NULL, obj_commands, obj); + if (retval != ERROR_OK) goto err_exit; - return JIM_OK; + list_add_tail(&obj->lh, &all_tpiu_swo); + + return ERROR_OK; err_exit: free(obj->name); free(obj->out_filename); free(obj); - return JIM_ERR; + return retval; } COMMAND_HANDLER(handle_arm_tpiu_swo_names) @@ -1192,7 +1180,7 @@ static const struct command_registration arm_tpiu_swo_subcommand_handlers[] = { { .name = "create", .mode = COMMAND_ANY, - .jim_handler = jim_arm_tpiu_swo_create, + .handler = handle_arm_tpiu_swo_create, .usage = "name [-dap dap] [-ap-num num] [-baseaddr baseaddr]", .help = "Creates a new TPIU or SWO object", }, From e9c78512b30b13fc6a9714e3fad0074bc2387bb5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 16 Dec 2023 17:29:43 +0100 Subject: [PATCH 1229/1312] target/arm_tpiu_swo: rewrite commands 'configure' and 'cget' as COMMAND_HANDLER Rewrite only the command, but still use the old jimtcl specific code in arm_tpiu_swo_configure(), shared with command 'create'. Change-Id: If2258f048403f54faf229e602d9b395b71894f97 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8900 Tested-by: jenkins --- src/target/arm_tpiu_swo.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index f2cb1a0fd1..afdd8ce919 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -554,20 +554,28 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s return JIM_ERR; } -static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +COMMAND_HANDLER(handle_arm_tpiu_swo_configure) { - struct command *c = jim_to_command(interp); + struct arm_tpiu_swo_object *obj = CMD_DATA; + + if (!CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + struct jim_getopt_info goi; + jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC, CMD_JIMTCL_ARGV); + goi.is_configure = !strcmp(CMD_NAME, "configure"); - jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.is_configure = !strcmp(c->name, "configure"); - if (goi.argc < 1) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - "missing: -option ..."); - return JIM_ERR; - } - struct arm_tpiu_swo_object *obj = c->jim_handler_data; - return arm_tpiu_swo_configure(&goi, obj); + int e = arm_tpiu_swo_configure(&goi, obj); + + int reslen; + const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen); + if (reslen > 0) + command_print(CMD, "%s", result); + + if (e != JIM_OK) + return ERROR_FAIL; + + return ERROR_OK; } static int wrap_write_u32(struct target *target, struct adiv5_ap *tpiu_ap, @@ -872,14 +880,14 @@ static const struct command_registration arm_tpiu_swo_instance_command_handlers[ { .name = "configure", .mode = COMMAND_ANY, - .jim_handler = jim_arm_tpiu_swo_configure, + .handler = handle_arm_tpiu_swo_configure, .help = "configure a new TPIU/SWO for use", .usage = "[attribute value ...]", }, { .name = "cget", .mode = COMMAND_ANY, - .jim_handler = jim_arm_tpiu_swo_configure, + .handler = handle_arm_tpiu_swo_configure, .help = "returns the specified TPIU/SWO attribute", .usage = "attribute", }, From 6cec67251d29a4a62d330ff6289807babee04fda Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 16 Dec 2023 17:39:12 +0100 Subject: [PATCH 1230/1312] command: drop Jim Command handler, at last With all OpenOCD commands converted to COMMAND_HANDLER, we can drop the management of jim_handler commands. Drop also from documentation the subsection on Jim Command Registration. Change-Id: I4d13abc7e384e64ecb155cb40bbbd52bb79ec672 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8901 Tested-by: jenkins --- doc/manual/helper.txt | 12 ------------ src/helper/command.c | 10 +++------- src/helper/command.h | 2 -- src/server/telnet_server.c | 2 +- 4 files changed, 4 insertions(+), 22 deletions(-) diff --git a/doc/manual/helper.txt b/doc/manual/helper.txt index 6cf3c977bf..29e84e6f0b 100644 --- a/doc/manual/helper.txt +++ b/doc/manual/helper.txt @@ -97,18 +97,6 @@ registration, while the @c unregister_command() and These may be called at any time, allowing the command set to change in response to system actions. -@subsection helpercmdjim Jim Command Registration - -The command_registration structure provides support for registering -native Jim command handlers (@c jim_handler) too. For these handlers, -the module can provide help and usage support; however, this mechanism -allows Jim handlers to be called as sub-commands of other commands. -These commands may be registered with a private data value (@c -jim_handler_data) that will be available when called, as with low-level -Jim command registration. - -A command may have a normal @c handler or a @c jim_handler, but not both. - @subsection helpercmdregisterchains Command Chaining When using register_commands(), the array of commands may reference diff --git a/src/helper/command.c b/src/helper/command.c index 218f0581ef..b70081a4dd 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -130,13 +130,13 @@ static struct command *command_new(struct command_context *cmd_ctx, assert(cr->name); /* - * If it is a non-jim command with no .usage specified, + * If it is a command with no .usage specified, * log an error. * * strlen(.usage) == 0 means that the command takes no * arguments. */ - if (!cr->jim_handler && !cr->usage) + if (!cr->usage) LOG_ERROR("BUG: command '%s' does not have the " "'.usage' field filled out", full_name); @@ -152,7 +152,6 @@ static struct command *command_new(struct command_context *cmd_ctx, } c->handler = cr->handler; - c->jim_handler = cr->jim_handler; c->mode = cr->mode; if (cr->help || cr->usage) @@ -425,9 +424,6 @@ static bool command_can_run(struct command_context *cmd_ctx, struct command *c, static int exec_command(Jim_Interp *interp, struct command_context *context, struct command *c, int argc, Jim_Obj * const *argv) { - if (c->jim_handler) - return c->jim_handler(interp, argc, argv); - /* use c->handler */ const char **words = malloc(argc * sizeof(char *)); if (!words) { @@ -841,7 +837,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a script_debug(interp, argc, argv); struct command *c = jim_to_command(interp); - if (!c->jim_handler && !c->handler) { + if (!c->handler) { Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv); return JIM_ERR; } diff --git a/src/helper/command.h b/src/helper/command.h index 18fe561782..8bd2430e0b 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -197,7 +197,6 @@ typedef __COMMAND_HANDLER((*command_handler_t)); struct command { char *name; command_handler_t handler; - Jim_CmdProc *jim_handler; void *jim_handler_data; /* Command handlers can use it for any handler specific data */ struct target *jim_override_target; @@ -234,7 +233,6 @@ static inline struct command *jim_to_command(Jim_Interp *interp) struct command_registration { const char *name; command_handler_t handler; - Jim_CmdProc *jim_handler; enum command_mode mode; const char *help; /** a string listing the options and arguments, required or optional */ diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 2c3f769801..3634a2a592 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -671,7 +671,7 @@ static void telnet_auto_complete(struct connection *connection) } else if (jimcmd_is_oocd_command(jim_cmd)) { struct command *cmd = jimcmd_privdata(jim_cmd); - if (cmd && !cmd->handler && !cmd->jim_handler) { + if (cmd && !cmd->handler) { /* Initial part of a multi-word command. Ignore it! */ ignore_cmd = true; } else if (cmd && cmd->mode == COMMAND_CONFIG) { From 3c7725ea703e186c9d9ced3b0e03231982abdbfd Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 22 Dec 2022 12:34:41 +0100 Subject: [PATCH 1231/1312] checkpatch: drop camelcase symbols not used anymore With the rewrite of jim_handler commands as COMMAND_HANDLER, some camelcase symbol from jimtcl are not referenced anymore in OpenOCD code. Drop such symbols from the camelcase whitelist. Change-Id: I723be1820f13fe2cec7e4f0512a5e9da12889199 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8902 Tested-by: jenkins --- tools/scripts/camelcase.txt | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/tools/scripts/camelcase.txt b/tools/scripts/camelcase.txt index 6c6c28daa5..058df4d808 100644 --- a/tools/scripts/camelcase.txt +++ b/tools/scripts/camelcase.txt @@ -87,20 +87,14 @@ Jim_AppendString Jim_AppendStrings Jim_Cmd Jim_CmdPrivData -Jim_CmdProc -Jim_CompareStringImmediate -Jim_ConcatObj Jim_CreateCommand Jim_CreateInterp Jim_DecrRefCount -Jim_DelCmdProc Jim_DeleteAssocData Jim_DeleteCommand -Jim_DictAddElement Jim_DictPairs Jim_DuplicateObj Jim_Eval -Jim_EvalExpression Jim_EvalObj Jim_EvalObjPrefix Jim_EvalSource @@ -113,46 +107,31 @@ Jim_GetDouble Jim_GetEnum Jim_GetExitCode Jim_GetGlobalVariableStr -Jim_GetIntRepPtr -Jim_GetLong Jim_GetResult Jim_GetString -Jim_GetVariable Jim_GetWide Jim_IncrRefCount Jim_InitStaticExtensions Jim_Interp -Jim_Length -Jim_ListAppendElement Jim_ListGetIndex Jim_ListLength Jim_MakeErrorMessage -Jim_NewDictObj Jim_NewEmptyStringObj Jim_NewIntObj -Jim_NewListObj Jim_NewStringObj -Jim_NewWideObj Jim_Obj Jim_ProcessEvents Jim_RegisterCoreCommands Jim_SetAssocData Jim_SetEmptyResult Jim_SetResult -Jim_SetResultBool Jim_SetResultFormatted -Jim_SetResultInt Jim_SetResultString -Jim_SetVariable Jim_String Jim_WrongNumArgs cmdProc -currentScriptObj -delProc -emptyObj privData returnCode -typePtr # from elf.h Elf32_Addr From 4c1e2105c4e5ad3188dae6e62ce019df15c7e52a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 10 May 2025 14:14:05 +0200 Subject: [PATCH 1232/1312] target: drop struct target_type::target_jim_commands() The API was introduced in 2008 by commit 8d73c2a9b0c0 ("duan ellis target tcl work in progress") and never used. Drop it! Change-Id: Icbc5789f59696bd28f9d1151bc3e29f4adb74670 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8903 Tested-by: jenkins --- src/target/target_type.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/target/target_type.h b/src/target/target_type.h index eddedbf34f..5b0dc5a6c0 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -201,10 +201,6 @@ struct target_type { /* otherwise: JIM_OK, or JIM_ERR, */ int (*target_jim_configure)(struct target *target, struct jim_getopt_info *goi); - /* target commands specifically handled by the target */ - /* returns JIM_OK, or JIM_ERR, or JIM_CONTINUE - if option not understood */ - int (*target_jim_commands)(struct target *target, struct jim_getopt_info *goi); - /** * This method is used to perform target setup that requires * JTAG access. From 8b47a0736b249e0c2574578a184d962294e03b90 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 10 May 2025 23:52:30 +0200 Subject: [PATCH 1233/1312] target: arm_cti: fix return values in handle_cti_dump() Since the initial commit f444c57bf2d6 ("arm_cti: add cti command group") the helper handle_cti_dump() return JIM error codes. Fix it by returning standard OpenOCD error codes. Change-Id: Ia36b82083d213aff90fe22fcfe7fbe26172806a3 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8904 Tested-by: jenkins --- src/target/arm_cti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 830956e5c5..032e5ac379 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -232,13 +232,13 @@ COMMAND_HANDLER(handle_cti_dump) retval = dap_run(ap->dap); if (retval != ERROR_OK) - return JIM_ERR; + return retval; for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32, cti_names[i].label, cti_names[i].offset, values[i]); - return JIM_OK; + return ERROR_OK; } COMMAND_HANDLER(handle_cti_enable) From 9b30e051379bffaec0928c3e6447b1d54becdb45 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 18 May 2025 11:49:31 +0200 Subject: [PATCH 1234/1312] flash, target: avoid logging of numeric target state Replace it by target_state_name() helper. Change-Id: I720f2bf121e6fd2c6987a7e8fa9e52593888ee6c Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8918 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/ambiqmicro.c | 4 ++-- src/target/espressif/esp32.c | 4 ++-- src/target/espressif/esp32s2.c | 4 ++-- src/target/espressif/esp32s3.c | 4 ++-- src/target/stm8.c | 2 +- src/target/xtensa/xtensa.c | 3 ++- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c index bb893778ce..67cc6b68a7 100644 --- a/src/flash/nor/ambiqmicro.c +++ b/src/flash/nor/ambiqmicro.c @@ -309,9 +309,9 @@ static int ambiqmicro_exec_command(struct target *target, */ target_poll(target); alive_sleep(100); - LOG_DEBUG("state = %d", target->state); } else { - LOG_ERROR("Target not halted or running %d", target->state); + LOG_ERROR("Target not halted or running (state is %s)", + target_state_name(target)); break; } } diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 399ba8e7cd..5e2490a229 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -192,8 +192,8 @@ static int esp32_soc_reset(struct target *target) alive_sleep(10); xtensa_poll(target); if (timeval_ms() >= timeout) { - LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be reset, target state=%d", - target->state); + LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be reset, target state %s", + target_state_name(target)); get_timeout = true; break; } diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index b86e43e626..e32893a6b2 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -272,8 +272,8 @@ static int esp32s2_soc_reset(struct target *target) alive_sleep(10); xtensa_poll(target); if (timeval_ms() >= timeout) { - LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be reset, target state=%d", - target->state); + LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be reset, target state %s", + target_state_name(target)); return ERROR_TARGET_TIMEOUT; } } diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 82413f77fb..14f7a7bb64 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -193,8 +193,8 @@ static int esp32s3_soc_reset(struct target *target) xtensa_poll(target); if (timeval_ms() >= timeout) { LOG_TARGET_ERROR(target, - "Timed out waiting for CPU to be reset, target state=%d", - target->state); + "Timed out waiting for CPU to be reset, target state %s", + target_state_name(target)); get_timeout = true; break; } diff --git a/src/target/stm8.c b/src/target/stm8.c index 81c41f2b2a..7785d40ef0 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -870,7 +870,7 @@ static int stm8_poll(struct target *target) uint8_t csr1, csr2; #ifdef LOG_STM8 - LOG_DEBUG("target->state=%d", target->state); + LOG_DEBUG("target->state %s", target_state_name(target)); #endif /* read dm_csrx control regs */ diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 3a877edfa6..3366623d64 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -949,7 +949,8 @@ int xtensa_smpbreak_set(struct target *target, uint32_t set) xtensa->smp_break = set; if (target_was_examined(target)) res = xtensa_smpbreak_write(xtensa, xtensa->smp_break); - LOG_TARGET_DEBUG(target, "set smpbreak=%" PRIx32 ", state=%i", set, target->state); + LOG_TARGET_DEBUG(target, "set smpbreak=%" PRIx32 ", state %s", set, + target_state_name(target)); return res; } From bde7e86e8eb74097880af2cab81444b250712b18 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 18 May 2025 21:25:35 +0200 Subject: [PATCH 1235/1312] server/gdb_server: do not discard Ctrl-C if _DEBUG_GDB_IO_ GDB server debug logging eat Ctrl-C when gdb user issues interrupt in time of communication between OpenOCD and gdb. E.g. Ctrl-C after `next` gdb command taking many gdb remote protocol $vCont;s (steps) Change-Id: I4a65446a9bb25a28e50566607b3dec116fa7d2cd Suggested-by: Tim Newsome Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8920 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 71b7c7764a..bd00feb490 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -434,6 +434,10 @@ static int gdb_put_packet_inner(struct connection *connection, gdb_putback_char(connection, reply); LOG_DEBUG("Unexpected start of new packet"); break; + } else if (reply == 0x3) { + /* do not discard Ctrl-C */ + gdb_putback_char(connection, reply); + break; } LOG_WARNING("Discard unexpected char %c", reply); From 4fe57a0c197158958c7cc295002504d6434d4777 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Mon, 19 May 2025 15:23:23 +0200 Subject: [PATCH 1236/1312] server: gdb_server: use a macro for CTRL-C value The numeric value '3' for the ASCII character CTRL-C is not immediately readable, even if the lines that follow explicitly mention CTRL-C. Use the same macro present in `telnet_server.c` to replace the numeric value. Change-Id: Iaf4296b1f0e384f8122d8a4875cad17e8ddaf66a Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8922 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/server/gdb_server.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index bd00feb490..085058f4f3 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -50,6 +50,8 @@ * found in most modern embedded processors. */ +#define CTRL(c) ((c) - '@') + enum gdb_output_flag { /* GDB doesn't accept 'O' packets */ GDB_OUTPUT_NO, @@ -434,7 +436,7 @@ static int gdb_put_packet_inner(struct connection *connection, gdb_putback_char(connection, reply); LOG_DEBUG("Unexpected start of new packet"); break; - } else if (reply == 0x3) { + } else if (reply == CTRL('C')) { /* do not discard Ctrl-C */ gdb_putback_char(connection, reply); break; @@ -486,7 +488,7 @@ static int gdb_put_packet_inner(struct connection *connection, gdb_con->output_flag = GDB_OUTPUT_NO; gdb_log_incoming_packet(connection, "-"); LOG_WARNING("negative reply, retrying"); - } else if (reply == 0x3) { + } else if (reply == CTRL('C')) { gdb_con->ctrl_c = true; gdb_log_incoming_packet(connection, ""); retval = gdb_get_char(connection, &reply); @@ -696,7 +698,7 @@ static int gdb_get_packet_inner(struct connection *connection, gdb_log_incoming_packet(connection, "-"); LOG_WARNING("negative acknowledgment, but no packet pending"); break; - case 0x3: + case CTRL('C'): gdb_log_incoming_packet(connection, ""); gdb_con->ctrl_c = true; *len = 0; From 92287c1a2afa93f2f20d2249827a57ffac6760c6 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 27 Oct 2022 15:21:31 -0700 Subject: [PATCH 1237/1312] target: Add TARGET_UNAVAILABLE state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is added for future RISC-V changes. The RISC-V debug interface can explicitly tell a debugger when a hart is unavailable. This is used for instance when that hart is powered down (or yet to be powered up out of reset). Imported from https://github.com/riscv-collab/riscv-openocd/pull/752 Change-Id: I8a062d59eea1e5b3c788281a75159592db024683 Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/8911 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Bernhard Rosenkränzer --- src/target/target.c | 1 + src/target/target.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/target/target.c b/src/target/target.c index 6653c381c0..fd0e0116b5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -220,6 +220,7 @@ static const struct nvp nvp_target_state[] = { { .name = "halted", .value = TARGET_HALTED }, { .name = "reset", .value = TARGET_RESET }, { .name = "debug-running", .value = TARGET_DEBUG_RUNNING }, + { .name = "unavailable", .value = TARGET_UNAVAILABLE }, { .name = NULL, .value = -1 }, }; diff --git a/src/target/target.h b/src/target/target.h index b698f250ce..b850b49cf3 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -46,6 +46,8 @@ struct gdb_fileio_info; * not sure how this is used with all the recent changes) * TARGET_DEBUG_RUNNING = 4: the target is running, but it is executing code on * behalf of the debugger (e.g. algorithm for flashing) + * TARGET_UNAVAILABLE = 5: The target is unavailable for some reason. It might + * be powered down, for instance. * * also see: target_state_name(); */ @@ -56,6 +58,7 @@ enum target_state { TARGET_HALTED = 2, TARGET_RESET = 3, TARGET_DEBUG_RUNNING = 4, + TARGET_UNAVAILABLE = 5 }; enum target_reset_mode { From 98ed83e2782bfd242b653bd3190c34d091b3d7b6 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 7 Sep 2022 11:55:52 -0700 Subject: [PATCH 1238/1312] rtos/hwthread: Hide unavailable targets from thread list. Imported from https://github.com/riscv-collab/riscv-openocd/pull/767 Change-Id: I53c6e2876d9bab70800a0f080e72a2abe0499120 Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/8919 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtos/hwthread.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 76571c6b60..cc43a07b42 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -105,7 +105,8 @@ static int hwthread_update_threads(struct rtos *rtos) foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - if (!target_was_examined(curr)) + if (!target_was_examined(curr) || + curr->state == TARGET_UNAVAILABLE) continue; ++thread_list_size; @@ -130,7 +131,8 @@ static int hwthread_update_threads(struct rtos *rtos) foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; - if (!target_was_examined(curr)) + if (!target_was_examined(curr) || + curr->state == TARGET_UNAVAILABLE) continue; threadid_t tid = threadid_from_target(curr); From 7f57e72afec76fcbc6210ddbd85ad4ecd5062ab5 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 27 Oct 2022 14:42:23 -0700 Subject: [PATCH 1239/1312] gdb_server: Operate on available targets. When SMP is enabled, gdb will always use the first target in the SMP group. That doesn't work when that first target is unavailable, but others in the SMP group are still available. For cases where gdb expects an operation to affect the entire group (run control, memory access), find the first available target in an SMP group and use that. Imported from https://github.com/riscv-collab/riscv-openocd/pull/767 Change-Id: I4bed600da3ac0fdfe4287d8fdd090a58452db501 Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/8912 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 56 +++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 085058f4f3..b5007d9278 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -151,6 +151,29 @@ static bool gdb_use_target_description = true; /* current processing free-run type, used by file-I/O */ static char gdb_running_type; +/* Find an available target in the SMP group that gdb is connected to. For + * commands that affect an entire SMP group (like memory access and run control) + * this will give better results than returning the unavailable target and having + * the command fail. If gdb was aware that targets can be unavailable we + * wouldn't need this logic. + */ +struct target *get_available_target_from_connection(struct connection *connection) +{ + struct gdb_service *gdb_service = connection->service->priv; + struct target *target = gdb_service->target; + if (target->state == TARGET_UNAVAILABLE && target->smp) { + struct target_list *tlist; + foreach_smp_target(tlist, target->smp_targets) { + struct target *t = tlist->target; + if (t->state != TARGET_UNAVAILABLE) + return t; + } + /* If we can't find an available target, just return the + * original. */ + } + return target; +} + static int gdb_last_signal(struct target *target) { LOG_TARGET_DEBUG(target, "Debug reason is: %s", @@ -961,9 +984,9 @@ static int gdb_target_callback_event_handler(struct target *target, enum target_event event, void *priv) { struct connection *connection = priv; - struct gdb_service *gdb_service = connection->service->priv; + struct target *gdb_target = get_available_target_from_connection(connection); - if (gdb_service->target != target) + if (gdb_target != target) return ERROR_OK; switch (event) { @@ -1504,7 +1527,7 @@ static int gdb_error(struct connection *connection, int retval) static int gdb_read_memory_packet(struct connection *connection, char const *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); char *separator; uint64_t addr = 0; uint32_t len = 0; @@ -1579,7 +1602,7 @@ static int gdb_read_memory_packet(struct connection *connection, static int gdb_write_memory_packet(struct connection *connection, char const *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); char *separator; uint64_t addr = 0; uint32_t len = 0; @@ -1630,7 +1653,7 @@ static int gdb_write_memory_packet(struct connection *connection, static int gdb_write_memory_binary_packet(struct connection *connection, char const *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); char *separator; uint64_t addr = 0; uint32_t len = 0; @@ -1709,7 +1732,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, static int gdb_step_continue_packet(struct connection *connection, char const *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); bool current = false; uint64_t address = 0x0; int retval = ERROR_OK; @@ -1737,7 +1760,7 @@ static int gdb_step_continue_packet(struct connection *connection, static int gdb_breakpoint_watchpoint_packet(struct connection *connection, char const *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); int type; enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */; enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */; @@ -1910,7 +1933,7 @@ static int gdb_memory_map(struct connection *connection, * have to regenerate it a couple of times. */ - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); struct flash_bank *p; char *xml = NULL; int size = 0; @@ -2986,7 +3009,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p __attribute__((unused)) int packet_size) { struct gdb_connection *gdb_connection = connection->priv; - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); const char *parse = packet; int retval; @@ -3208,7 +3231,7 @@ static void gdb_restart_inferior(struct connection *connection, const char *pack static bool gdb_handle_vrun_packet(struct connection *connection, const char *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); const char *parse = packet; /* Skip "vRun" */ @@ -3254,7 +3277,7 @@ static int gdb_v_packet(struct connection *connection, struct gdb_connection *gdb_connection = connection->priv; int result; - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); if (strncmp(packet, "vCont", 5) == 0) { bool handled; @@ -3433,7 +3456,7 @@ static int gdb_detach(struct connection *connection) static int gdb_fileio_response_packet(struct connection *connection, char const *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); + struct target *target = get_available_target_from_connection(connection); char *separator; char *parsing_point; int fileio_retcode = strtoul(packet + 1, &separator, 16); @@ -3726,10 +3749,11 @@ static int gdb_input_inner(struct connection *connection) } if (gdb_con->ctrl_c) { - if (target->state == TARGET_RUNNING) { - struct target *t = target; - if (target->rtos) - target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &t); + struct target *available_target = get_available_target_from_connection(connection); + if (available_target->state == TARGET_RUNNING) { + struct target *t = available_target; + if (available_target->rtos) + available_target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &t); retval = target_halt(t); if (retval == ERROR_OK) retval = target_poll(t); From 6975baa88be60505e60d1bc76176b2344e966c3f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 19 May 2025 16:00:52 +0200 Subject: [PATCH 1240/1312] doc: list target unavailable state Fixes: 8911: target: Add TARGET_UNAVAILABLE state | https://review.openocd.org/c/openocd/+/8911 Change-Id: I6d152aea5bb449f79fd0f829252442b8b9f8ed9c Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8923 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index ca357c7802..27ed46b920 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5439,7 +5439,8 @@ Displays the current target state: @code{debug-running}, @code{halted}, @code{reset}, -@code{running}, or @code{unknown}. +@code{running}, +@code{unavailable} or @code{unknown}. (Also, @pxref{eventpolling,,Event Polling}.) @end deffn From 330b06b440aafff1150e00f396ac8d44a8cd82a9 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sun, 18 May 2025 11:11:07 +0200 Subject: [PATCH 1241/1312] rtos/hwthread: Nicer debug message in hwthread_update_threads() Imported from https://github.com/riscv-collab/riscv-openocd/pull/763 Change-Id: Ia5931a772476a2ae186ed87cd70d7e4be2f196fb Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/8917 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/rtos/hwthread.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index cc43a07b42..5c6c45f78f 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -206,8 +206,8 @@ static int hwthread_update_threads(struct rtos *rtos) else rtos->current_thread = threadid_from_target(target); - LOG_TARGET_DEBUG(target, "%s current_thread=%i", __func__, - (int)rtos->current_thread); + LOG_TARGET_DEBUG(target, "current_thread=%i, threads_found=%d", + (int)rtos->current_thread, threads_found); return 0; } From c545b9c4ab32c5566091dfe05e7f1765c39ed069 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 19 May 2025 17:10:00 +0200 Subject: [PATCH 1242/1312] rtos/hwthread: use printf format specifier instead of typecast. Change-Id: I62e3a0faebd915615f6b72a456667c49970a4091 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8926 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/rtos/hwthread.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 5c6c45f78f..b2a45ade9f 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -206,8 +206,8 @@ static int hwthread_update_threads(struct rtos *rtos) else rtos->current_thread = threadid_from_target(target); - LOG_TARGET_DEBUG(target, "current_thread=%i, threads_found=%d", - (int)rtos->current_thread, threads_found); + LOG_TARGET_DEBUG(target, "current_thread=%" PRId64 ", threads_found=%d", + rtos->current_thread, threads_found); return 0; } From 25b99ae456971d5522c4e836e80bfa8e40e5a512 Mon Sep 17 00:00:00 2001 From: Lucien Dufour Date: Thu, 15 May 2025 14:31:25 +0200 Subject: [PATCH 1243/1312] cortex_a: Use endianness for soft breakpoints Fix endianness for cortex_r4 and cortex_r5 when inserting software breakpoints. Because the cortex_a target is used by the cortex_r architecture and some chips start in BE by default (e.g. TMS570) Change-Id: I68b7fe7c4604de67fee2e64fff0fad2691659a58 Signed-off-by: Lucien Dufour Reviewed-on: https://review.openocd.org/c/openocd/+/8909 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/cortex_a.c | 13 +++++++++++++ src/target/cortex_a.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 46362017af..2ebbf65774 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1380,6 +1380,19 @@ static int cortex_a_set_breakpoint(struct target *target, buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); } + /* + * ARMv7-A/R fetches instructions in little-endian on both LE and BE CPUs. + * But Cortex-R4 and Cortex-R5 big-endian require BE instructions. + * https://developer.arm.com/documentation/den0042/a/Coding-for-Cortex-R-Processors/Endianness + * https://developer.arm.com/documentation/den0013/d/Porting/Endianness + */ + if ((((cortex_a->cpuid & CPUDBG_CPUID_MASK) == CPUDBG_CPUID_CORTEX_R4) || + ((cortex_a->cpuid & CPUDBG_CPUID_MASK) == CPUDBG_CPUID_CORTEX_R5)) && + target->endianness == TARGET_BIG_ENDIAN) { + // In place swapping is allowed + buf_bswap32(code, code, 4); + } + retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index 37fba1a885..8e438fd958 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -30,6 +30,9 @@ #define CORTEX_A_MIDR_PARTNUM_SHIFT 4 #define CPUDBG_CPUID 0xD00 +#define CPUDBG_CPUID_MASK 0xff00fff0 +#define CPUDBG_CPUID_CORTEX_R4 0x4100c140 +#define CPUDBG_CPUID_CORTEX_R5 0x4100c150 #define CPUDBG_CTYPR 0xD04 #define CPUDBG_TTYPR 0xD0C #define CPUDBG_LOCKACCESS 0xFB0 From b1c1dd1ec4b014d3b17be7598b7ecfebe97edcb5 Mon Sep 17 00:00:00 2001 From: Lucien Dufour Date: Tue, 20 May 2025 17:39:19 +0200 Subject: [PATCH 1244/1312] tcl/target: Add support for TMS570LS1xxx Added support for TMS570LS1xxx series parts. This uses the existing ti_tms570.cfg as parent. Change-Id: I40567bfb8dc052532807df68ef3d42f8e7a8ecf4 Signed-off-by: Lucien Dufour Reviewed-on: https://review.openocd.org/c/openocd/+/8928 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: zapb --- tcl/target/ti_tms570ls1x.cfg | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tcl/target/ti_tms570ls1x.cfg diff --git a/tcl/target/ti_tms570ls1x.cfg b/tcl/target/ti_tms570ls1x.cfg new file mode 100644 index 0000000000..3c25777578 --- /dev/null +++ b/tcl/target/ti_tms570ls1x.cfg @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# TMS570LS1114, TMS570LS1115 +# TMS570LS1224, TMS570LS1225, TMS570LS1227 +set DAP_TAPID 0x0B95502F +set JRC_TAPID 0x0B95502F + +source [find target/ti_tms570.cfg] From b06212b5a2fc5b9bff72327bc7d5a7ec1c7ef613 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 21 May 2025 15:19:28 +0200 Subject: [PATCH 1245/1312] startup.tcl: extend the file search in vendor folders The TCL configuration files are going to be dispatched in vendor specific folders. Old user configuration files will fail to find the new files to include, so a set of fallback files reporting the deprecation should replace the renamed files. To prevent such enormous proliferation of fallback files, extend the search of files in the vendor folders too. For non-trivial renames, a dedicated table is added in the file tcl/file_renaming.cfg to track old --> new file names. The deprecated message is then part of the extended search. E.g.: old file names: - path/to/a/certain/vendor_config_file - path/to/a/certain/vendor-config_file trigger search of: - path/to/a/certain/vendor/config_file and - path/to/a/certain/config_file trigger search of: - path/to/a/certain/${vendor}/config_file among a possible vendors list. This is a temporarily feature that should be removed as soon as possible to prevent clashing on files with the same name. The names in tcl/file_renaming.cfg are for demonstration purpose only and should be dropped when the first real entries are added. Change-Id: If4793fef27dc570d5df4ff4d77a5e36004f394f6 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8929 Tested-by: jenkins --- src/helper/startup.tcl | 46 +++++++++++++++++++++++++++++++++++++++++- tcl/file_renaming.cfg | 19 +++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tcl/file_renaming.cfg diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl index e6e76e68fd..e328cbe07f 100644 --- a/src/helper/startup.tcl +++ b/src/helper/startup.tcl @@ -7,7 +7,8 @@ # Try flipping / and \ to find file if the filename does not # match the precise spelling -proc find {filename} { +# lappend _telnet_autocomplete_skip _find_internal +proc _find_internal {filename} { if {[catch {ocd_find $filename} t]==0} { return $t } @@ -20,6 +21,49 @@ proc find {filename} { # make sure error message matches original input string return -code error "Can't find $filename" } + +proc find {filename} { + if {[catch {_find_internal $filename} t]==0} { + return $t + } + + # Check in vendor specific folder: + + # - path/to/a/certain/vendor_config_file + # - path/to/a/certain/vendor-config_file + # replaced with + # - path/to/a/certain/vendor/config_file + regsub {([/\\])([^/\\_-]*)[_-]([^/\\]*$)} $filename "\\1\\2\\1\\3" f + if {[catch {_find_internal $f} t]==0} { + echo "WARNING: '$filename' is deprecated, use '$f' instead" + return $t + } + + foreach vendor {nordic ti st} { + # - path/to/a/certain/config_file + # replaced with + # - path/to/a/certain/${vendor}/config_file + regsub {([/\\])([^/\\]*$)} $filename "\\1$vendor\\1\\2" f + if {[catch {_find_internal $f} t]==0} { + echo "WARNING: '$filename' is deprecated, use '$f' instead" + return $t + } + } + + # at last, check for explicit renaming + if {[catch { + source [_find_internal file_renaming.cfg] + set unixname [string map {\\ /} $filename] + regsub {^(.*/|)((board|chip|cpld|cpu|fpga|interface|target|test|tools)/.*.cfg$)} $unixname {{\1} {\2}} split + set newname [lindex $split 0][dict get $_file_renaming [lindex $split 1]] + _find_internal $newname + } t]==0} { + echo "WARNING: '$filename' is deprecated, use '$newname' instead" + return $t + } + + return -code error "Can't find $filename" +} add_usage_text find "" add_help_text find "print full path to file according to OpenOCD search rules" diff --git a/tcl/file_renaming.cfg b/tcl/file_renaming.cfg new file mode 100644 index 0000000000..81e54823f0 --- /dev/null +++ b/tcl/file_renaming.cfg @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This file is used to remap configuration files that has been +# renamed, except simple renames that are taken care automatically +# like: +# .../file.cfg ==> .../${vendor}/file.cfg +# .../vendor-file.cfg ==> .../vendor/file.cfg +# .../vendor_file.cfg ==> .../vendor/file.cfg +# +# The formatting below is a TCL dict, so pairs of key-value +# in a simple TCL list, using for each line +# old_name new_name +# including in each name one of the prefix folder between +# board, chip, cpld, cpu, fpga, interface, target, test, tools + +set _file_renaming { + board/hello.cfg board/st/nucleo-u083rc.cfg + board/my-funny-pcb.cfg board/st_nucleo_f0.cfg +} From 152becc4607e97aa692e41cb281753121d9ee75d Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 12 May 2025 06:47:22 +0200 Subject: [PATCH 1246/1312] tcl/target: Move nordic configuration files Move target configuration files into a dedicated vendor directory as required by the new guideline for configuration files. Note that the moved files are still accessible via the old path to ensure backwards compatibility. This works because of the extended file search in vendor folders. Change-Id: If3935985769dc543e8c7d72cda590c9d79303abb Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8905 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/{nrf_common.cfg => nordic/common.cfg} | 0 tcl/target/{ => nordic}/nrf51.cfg | 0 tcl/target/{ => nordic}/nrf52.cfg | 0 tcl/target/{ => nordic}/nrf53.cfg | 2 +- tcl/target/{ => nordic}/nrf91.cfg | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename tcl/target/{nrf_common.cfg => nordic/common.cfg} (100%) rename tcl/target/{ => nordic}/nrf51.cfg (100%) rename tcl/target/{ => nordic}/nrf52.cfg (100%) rename tcl/target/{ => nordic}/nrf53.cfg (99%) rename tcl/target/{ => nordic}/nrf91.cfg (97%) diff --git a/tcl/target/nrf_common.cfg b/tcl/target/nordic/common.cfg similarity index 100% rename from tcl/target/nrf_common.cfg rename to tcl/target/nordic/common.cfg diff --git a/tcl/target/nrf51.cfg b/tcl/target/nordic/nrf51.cfg similarity index 100% rename from tcl/target/nrf51.cfg rename to tcl/target/nordic/nrf51.cfg diff --git a/tcl/target/nrf52.cfg b/tcl/target/nordic/nrf52.cfg similarity index 100% rename from tcl/target/nrf52.cfg rename to tcl/target/nordic/nrf52.cfg diff --git a/tcl/target/nrf53.cfg b/tcl/target/nordic/nrf53.cfg similarity index 99% rename from tcl/target/nrf53.cfg rename to tcl/target/nordic/nrf53.cfg index 307df902c2..0dcfd55eca 100644 --- a/tcl/target/nrf53.cfg +++ b/tcl/target/nordic/nrf53.cfg @@ -60,7 +60,7 @@ if { ![using_hla] } { # Keep adapter speed less or equal 2000 kHz or flash programming fails! adapter speed 1000 -source [find target/nrf_common.cfg] +source [find target/nordic/common.cfg] flash bank $_CHIPNAME.app.flash nrf5 0x00000000 0 0 0 $_TARGETNAME_APP flash bank $_CHIPNAME.app.uicr nrf5 0x00FF8000 0 0 0 $_TARGETNAME_APP diff --git a/tcl/target/nrf91.cfg b/tcl/target/nordic/nrf91.cfg similarity index 97% rename from tcl/target/nrf91.cfg rename to tcl/target/nordic/nrf91.cfg index e0ff4e5460..64ed864e75 100644 --- a/tcl/target/nrf91.cfg +++ b/tcl/target/nordic/nrf91.cfg @@ -45,7 +45,7 @@ adapter speed 1000 $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -source [find target/nrf_common.cfg] +source [find target/nordic/common.cfg] flash bank $_CHIPNAME.flash nrf5 0x00000000 0 0 0 $_TARGETNAME flash bank $_CHIPNAME.uicr nrf5 0x00FF8000 0 0 0 $_TARGETNAME From 83c1546e77b7683508fd17decf66763cd72393bf Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 12 May 2025 06:53:16 +0200 Subject: [PATCH 1247/1312] tcl/target: Deprecate old nordic configuration files Keep the old configuration files to ensure backwards compatibility. Change-Id: Ia1d06b5a8a646d65f2cdc5a9415df3014a93b7d7 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8863 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/file_renaming.cfg | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tcl/file_renaming.cfg b/tcl/file_renaming.cfg index 81e54823f0..d7937f6e2f 100644 --- a/tcl/file_renaming.cfg +++ b/tcl/file_renaming.cfg @@ -14,6 +14,8 @@ # board, chip, cpld, cpu, fpga, interface, target, test, tools set _file_renaming { - board/hello.cfg board/st/nucleo-u083rc.cfg - board/my-funny-pcb.cfg board/st_nucleo_f0.cfg + target/nrf51.cfg target/nordic/nrf51.cfg + target/nrf52.cfg target/nordic/nrf52.cfg + target/nrf53.cfg target/nordic/nrf53.cfg + target/nrf91.cfg target/nordic/nrf91.cfg } From fbdb86adbd897337de6ee5b1b25a6f4ee7b5e4e4 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 12 May 2025 10:54:49 +0200 Subject: [PATCH 1248/1312] tcl/board: Use moved nordic target files Use the moved nordic target configuration files. Change-Id: Ie0e2eb7f9514eedb1ae6678eeee59291856c2674 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8906 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/nordic_nrf51822_mkit.cfg | 2 +- tcl/board/nordic_nrf51_dk.cfg | 2 +- tcl/board/nordic_nrf52_dk.cfg | 2 +- tcl/board/nordic_nrf52_ftx232.cfg | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tcl/board/nordic_nrf51822_mkit.cfg b/tcl/board/nordic_nrf51822_mkit.cfg index 266d710704..fd32271789 100644 --- a/tcl/board/nordic_nrf51822_mkit.cfg +++ b/tcl/board/nordic_nrf51822_mkit.cfg @@ -5,4 +5,4 @@ # source [find interface/cmsis-dap.cfg] -source [find target/nrf51.cfg] +source [find target/nordic/nrf51.cfg] diff --git a/tcl/board/nordic_nrf51_dk.cfg b/tcl/board/nordic_nrf51_dk.cfg index 7ddae2d438..4ccd3272e5 100644 --- a/tcl/board/nordic_nrf51_dk.cfg +++ b/tcl/board/nordic_nrf51_dk.cfg @@ -8,4 +8,4 @@ source [find interface/jlink.cfg] transport select swd -source [find target/nrf51.cfg] +source [find target/nordic/nrf51.cfg] diff --git a/tcl/board/nordic_nrf52_dk.cfg b/tcl/board/nordic_nrf52_dk.cfg index 7366bf94af..9b2390a624 100644 --- a/tcl/board/nordic_nrf52_dk.cfg +++ b/tcl/board/nordic_nrf52_dk.cfg @@ -8,4 +8,4 @@ source [find interface/jlink.cfg] transport select swd -source [find target/nrf52.cfg] +source [find target/nordic/nrf52.cfg] diff --git a/tcl/board/nordic_nrf52_ftx232.cfg b/tcl/board/nordic_nrf52_ftx232.cfg index c3c69a89a5..848d5dcd32 100644 --- a/tcl/board/nordic_nrf52_ftx232.cfg +++ b/tcl/board/nordic_nrf52_ftx232.cfg @@ -10,4 +10,4 @@ source [find interface/ftdi/ft232h-module-swd.cfg] transport select swd -source [find target/nrf52.cfg] +source [find target/nordic/nrf52.cfg] From 1ee7c09d9513e17bf37b0286ddec3a7f0a2ffbdc Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 12 May 2025 10:42:11 +0200 Subject: [PATCH 1249/1312] tcl/board: Move nordic configuration files Move board configuration files into a dedicated vendor directory as required by the new guideline for configuration files. Change-Id: Icbf368d7a453c82813e685d2935b186eb738c3ea Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8864 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/{nordic_nrf51_dk.cfg => nordic/nrf51-dk.cfg} | 0 tcl/board/{nordic_nrf51822_mkit.cfg => nordic/nrf51822-mkit.cfg} | 0 tcl/board/{nordic_nrf52_dk.cfg => nordic/nrf52-dk.cfg} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tcl/board/{nordic_nrf51_dk.cfg => nordic/nrf51-dk.cfg} (100%) rename tcl/board/{nordic_nrf51822_mkit.cfg => nordic/nrf51822-mkit.cfg} (100%) rename tcl/board/{nordic_nrf52_dk.cfg => nordic/nrf52-dk.cfg} (100%) diff --git a/tcl/board/nordic_nrf51_dk.cfg b/tcl/board/nordic/nrf51-dk.cfg similarity index 100% rename from tcl/board/nordic_nrf51_dk.cfg rename to tcl/board/nordic/nrf51-dk.cfg diff --git a/tcl/board/nordic_nrf51822_mkit.cfg b/tcl/board/nordic/nrf51822-mkit.cfg similarity index 100% rename from tcl/board/nordic_nrf51822_mkit.cfg rename to tcl/board/nordic/nrf51822-mkit.cfg diff --git a/tcl/board/nordic_nrf52_dk.cfg b/tcl/board/nordic/nrf52-dk.cfg similarity index 100% rename from tcl/board/nordic_nrf52_dk.cfg rename to tcl/board/nordic/nrf52-dk.cfg From 84f6c561f35fe4fec3c810c0c0c5e4090cb85fe1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 12 May 2025 10:43:19 +0200 Subject: [PATCH 1250/1312] tcl/board: Deprecate old nordic configuration files Add the old configuration files to the 'file_renaming' list in order to ensure backwards compatibility. Change-Id: Ia61df8e5cd8c19cee19a494635c8025e36f3f4a7 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8907 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/file_renaming.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tcl/file_renaming.cfg b/tcl/file_renaming.cfg index d7937f6e2f..0a3c7ba65b 100644 --- a/tcl/file_renaming.cfg +++ b/tcl/file_renaming.cfg @@ -14,6 +14,9 @@ # board, chip, cpld, cpu, fpga, interface, target, test, tools set _file_renaming { + board/nordic_nrf51822_mkit.cfg board/nordic/nrf51822-mkit.cfg + board/nordic_nrf51_dk.cfg board/nordic/nrf51-dk.cfg + board/nordic_nrf52_dk.cfg board/nordic/nrf52-dk.cfg target/nrf51.cfg target/nordic/nrf51.cfg target/nrf52.cfg target/nordic/nrf52.cfg target/nrf53.cfg target/nordic/nrf53.cfg From 895dfb5d87f9af18004c654163f48d3a5c9e92b6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 21 Apr 2025 18:10:20 +0000 Subject: [PATCH 1251/1312] tcl/board: Deprecate nordic_nrf52_ftx232.cfg Board configuration files for specific external debug adapters are not / no longer supported. Checkpatch-ignore: LONG_LINE_STRING Change-Id: I0f391dfb1a2d7ceb92c2ad3e34eaeb8a85b2cdc5 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8865 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/nordic_nrf52_ftx232.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcl/board/nordic_nrf52_ftx232.cfg b/tcl/board/nordic_nrf52_ftx232.cfg index 848d5dcd32..772d176d6f 100644 --- a/tcl/board/nordic_nrf52_ftx232.cfg +++ b/tcl/board/nordic_nrf52_ftx232.cfg @@ -5,6 +5,8 @@ # or any FT232H/FT2232H/FT4232H based board/module # +echo "WARNING: 'board/nordic_nrf52_ftx232.cfg' is deprecated, use '-f interface/ftdi/ft232h-module-swd.cfg -f target/nordic/nrf52.cfg' instead" + source [find interface/ftdi/ft232h-module-swd.cfg] #source [find interface/ftdi/minimodule-swd.cfg] From 20d7e83576e9f7ef23cd569a6b60f0ab2d702b36 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 24 Apr 2025 06:24:24 +0000 Subject: [PATCH 1252/1312] tcl/board: Add config for nRF9160 development kit Tested with nRF9160 development kit. Change-Id: I367b869b9707bef0547b5d3575b24e19db74cd21 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8866 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/nordic/nrf9160-dk.cfg | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tcl/board/nordic/nrf9160-dk.cfg diff --git a/tcl/board/nordic/nrf9160-dk.cfg b/tcl/board/nordic/nrf9160-dk.cfg new file mode 100644 index 0000000000..dc456202c1 --- /dev/null +++ b/tcl/board/nordic/nrf9160-dk.cfg @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic Semiconductor nRF9160 Development Kit +# https://www.nordicsemi.com/Products/Development-hardware/nRF9160-DK +# + +source [find interface/jlink.cfg] + +transport select swd + +source [find target/nordic/nrf91.cfg] From 3fbca95ae13b8caea3194a85bc4b2a29ebe31a66 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 24 Apr 2025 07:51:42 +0000 Subject: [PATCH 1253/1312] tcl/board: Add config for nRF5340 development kit Tested with nRF5340 development kit. Change-Id: I44f1ba176dd4ac491b5dccea4c4d6d6d9bfaf479 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8867 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/nordic/nrf5340-dk.cfg | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tcl/board/nordic/nrf5340-dk.cfg diff --git a/tcl/board/nordic/nrf5340-dk.cfg b/tcl/board/nordic/nrf5340-dk.cfg new file mode 100644 index 0000000000..fd7a40d666 --- /dev/null +++ b/tcl/board/nordic/nrf5340-dk.cfg @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Nordic Semiconductor nRF5340 Development Kit +# https://www.nordicsemi.com/Products/Development-hardware/nRF5340-DK +# + +source [find interface/jlink.cfg] + +transport select swd + +source [find target/nordic/nrf53.cfg] From 40e6c98dfc46a7ce7bf5e029c7c69491f8d8c58f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 22 May 2025 02:02:19 +0200 Subject: [PATCH 1254/1312] helper: configuration: check for empty search dirs The function find_file() is supposed to be called when the search dirs in 'script_search_dirs' has already been populated. This is not the case when the command 'ocd_find' is used in one of the embedded scripts 'startup.tcl'. It then triggers SIGSEGV. Check for 'script_search_dirs' and eventually skip searching in the dirs. Change-Id: I9e75a8739c94de72041fb64487910d60dffcb2bd Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8931 Tested-by: jenkins --- src/helper/configuration.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/helper/configuration.c b/src/helper/configuration.c index 16732eb3dd..447b0dfefa 100644 --- a/src/helper/configuration.c +++ b/src/helper/configuration.c @@ -71,17 +71,18 @@ char *find_file(const char *file) full_path = alloc_printf("%s", file); fp = fopen(full_path, mode); - while (!fp) { - free(full_path); - full_path = NULL; - dir = *search_dirs++; + if (script_search_dirs) + while (!fp) { + free(full_path); + full_path = NULL; + dir = *search_dirs++; - if (!dir) - break; + if (!dir) + break; - full_path = alloc_printf("%s/%s", dir, file); - fp = fopen(full_path, mode); - } + full_path = alloc_printf("%s/%s", dir, file); + fp = fopen(full_path, mode); + } if (fp) { fclose(fp); From 125d4f106dcde07340394aebc6754245e455ff1b Mon Sep 17 00:00:00 2001 From: Matthias Breithaupt Date: Thu, 25 Apr 2024 16:36:20 +0200 Subject: [PATCH 1255/1312] flash/nor/spi: add puya p25q flash devices P25Q16 can be found in the Efinix T13/20Q100F3, so that one is necessary for jtagspi on those chips. The other ones were added for completeness. Change-Id: Ifb6f3c6fbd23938d6fd26bce7742c3484ece130c Signed-off-by: Matthias Breithaupt Reviewed-on: https://review.openocd.org/c/openocd/+/8223 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/spi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c index bf654f9f6b..7f03f1fead 100644 --- a/src/flash/nor/spi.c +++ b/src/flash/nor/spi.c @@ -184,6 +184,16 @@ const struct flash_device flash_devices[] = { FLASH_ID("xtx xt25q64b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017600b, 0x100, 0x10000, 0x800000), FLASH_ID("xtx xt25q128b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018600b, 0x100, 0x10000, 0x1000000), FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000), + FLASH_ID("puya p25q05", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00106085, 0x100, 0x1000, 0x10000), + FLASH_ID("puya p25q10", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00116085, 0x100, 0x1000, 0x20000), + FLASH_ID("puya p25q20", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00126085, 0x100, 0x1000, 0x40000), + FLASH_ID("puya p25q40", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00136085, 0x100, 0x1000, 0x80000), + FLASH_ID("puya p25q80", 0x03, 0x6b, 0x02, 0x52, 0xc7, 0x00146085, 0x100, 0x8000, 0x100000), + FLASH_ID("puya p25q16", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00156085, 0x100, 0x10000, 0x200000), + FLASH_ID("puya p25q32", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00166085, 0x100, 0x10000, 0x400000), + FLASH_ID("puya p25q64", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00176085, 0x100, 0x10000, 0x800000), + FLASH_ID("puya p25q128", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00186085, 0x100, 0x10000, 0x1000000), + /* FRAM, no erase commands, no write page or sectors */ From db8db903338d1f99eda6ad533168885c9e21178f Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 1 Apr 2025 04:34:27 +0000 Subject: [PATCH 1256/1312] tcl/target/stm32f4x: Enable the trace port clock Enable the trace port (GPIOE) clock, otherwise the following pin configurations have no effect. Change-Id: I3942d2527c64340463c3b6c607addb4214f83081 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8823 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/stm32f4x.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tcl/target/stm32f4x.cfg b/tcl/target/stm32f4x.cfg index 35d8275b55..a77527c46d 100644 --- a/tcl/target/stm32f4x.cfg +++ b/tcl/target/stm32f4x.cfg @@ -98,6 +98,9 @@ proc _proc_pre_enable_$_CHIPNAME.tpiu {_chipname} { targets $_chipname.cpu if { [$_chipname.tpiu cget -protocol] eq "sync" } { + # Enable the GPIOE clock. + mmw 0x40023830 0x00000010 0x00000010 + switch [$_chipname.tpiu cget -port-width] { 1 { # Set TRACE_IOEN; TRACE_MODE to sync 1 bit; GPIOE[2-3] to AF0 From 2065bac3805102a37a2d10d374298b875d750392 Mon Sep 17 00:00:00 2001 From: Jacek Wuwer Date: Wed, 24 Apr 2024 10:15:38 +0200 Subject: [PATCH 1257/1312] jtag/vdebug: implement a polling mechanism This change adds a polling mechanism to the driver. When not busy the driver issues a wait, allowing the target to advance time. The wait period gets adjusted to match the polling setting. Change-Id: I67f481d05d7c5ce5352b5cb97de78dbaa97d82ae Signed-off-by: Jacek Wuwer Reviewed-on: https://review.openocd.org/c/openocd/+/8221 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/jtag/drivers/vdebug.c | 48 ++++++++++++++++++++++++++++---- tcl/board/vd_a75x4_jtag.cfg | 2 +- tcl/board/vd_pulpissimo_jtag.cfg | 8 +++--- tcl/interface/vdebug.cfg | 2 +- tcl/target/vd_riscv.cfg | 12 ++++---- 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index 38685950a8..29bfa8360d 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -47,19 +47,20 @@ #include "jtag/interface.h" #include "jtag/commands.h" #include "transport/transport.h" +#include "target/target.h" #include "target/arm_adi_v5.h" #include "helper/time_support.h" #include "helper/replacements.h" #include "helper/log.h" #include "helper/list.h" -#define VD_VERSION 48 +#define VD_VERSION 50 #define VD_BUFFER_LEN 4024 #define VD_CHEADER_LEN 24 #define VD_SHEADER_LEN 16 #define VD_MAX_MEMORIES 20 -#define VD_POLL_INTERVAL 500 +#define VD_POLL_INTERVAL 1000 #define VD_SCALE_PSTOMS 1000000000 /** @@ -205,6 +206,7 @@ struct vd_client { uint32_t poll_max; uint32_t targ_time; int hsocket; + int64_t poll_ts; char server_name[32]; char bfm_path[128]; char mem_path[VD_MAX_MEMORIES][128]; @@ -839,6 +841,35 @@ static void vdebug_mem_close(int hsock, struct vd_shm *pm, uint8_t ndx) } +/* function gets invoked through a callback every VD_POLL_INTERVAL ms + * if the idle time, measured by VD_POLL_INTERVAL - targ_time is more than poll_min + * the wait function is called and its time measured and wait cycles adjusted. + * The wait allows hardware to advance, when no data activity from the vdebug occurs + */ +static int vdebug_poll(void *priv) +{ + int64_t ts, te; + + ts = timeval_ms(); + if (ts - vdc.poll_ts - vdc.targ_time >= vdc.poll_min) { + vdebug_wait(vdc.hsocket, pbuf, vdc.poll_cycles); + te = timeval_ms(); + LOG_DEBUG("poll after %" PRId64 "ms, busy %" PRIu32 "ms; wait %" PRIu32 " %" PRId64 "ms", + ts - vdc.poll_ts, vdc.targ_time, vdc.poll_cycles, te - ts); + + if (te - ts + vdc.targ_time < vdc.poll_max / 2) + vdc.poll_cycles *= 2; + else if (te - ts + vdc.targ_time > vdc.poll_max) + vdc.poll_cycles /= 2; + } else { + LOG_DEBUG("poll after %" PRId64 "ms, busy %" PRIu32 "ms", ts - vdc.poll_ts, vdc.targ_time); + } + vdc.poll_ts = ts; + vdc.targ_time = 0; /* reset target time counter */ + + return ERROR_OK; +} + static int vdebug_init(void) { vdc.hsocket = vdebug_socket_open(vdc.server_name, vdc.server_port); @@ -858,6 +889,7 @@ static int vdebug_init(void) } vdc.trans_first = 1; vdc.poll_cycles = vdc.poll_max; + vdc.poll_ts = timeval_ms(); uint32_t sig_mask = VD_SIG_RESET; if (transport_is_jtag()) sig_mask |= VD_SIG_TRST | VD_SIG_TCKDIV; @@ -876,6 +908,8 @@ static int vdebug_init(void) LOG_ERROR("0x%x cannot connect to %s", rc, vdc.mem_path[i]); } + target_register_timer_callback(vdebug_poll, VD_POLL_INTERVAL, + TARGET_TIMER_TYPE_PERIODIC, &vdc); LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16, VD_VERSION, vdc.bfm_path, vdc.server_name, vdc.server_port); } @@ -885,6 +919,8 @@ static int vdebug_init(void) static int vdebug_quit(void) { + target_unregister_timer_callback(vdebug_poll, &vdc); + for (uint8_t i = 0; i < vdc.mem_ndx; i++) if (vdc.mem_width[i]) vdebug_mem_close(vdc.hsocket, pbuf, i); @@ -1299,16 +1335,16 @@ static const struct command_registration vdebug_command_handlers[] = { { .name = "batching", .handler = &vdebug_set_batching, - .mode = COMMAND_CONFIG, + .mode = COMMAND_ANY, .help = "set the transaction batching no|wr|rd [0|1|2]", .usage = "", }, { .name = "polling", .handler = &vdebug_set_polling, - .mode = COMMAND_CONFIG, - .help = "set the polling pause, executing hardware cycles between min and max", - .usage = " ", + .mode = COMMAND_ANY, + .help = "set the min idle time and max wait time in ms", + .usage = " ", }, COMMAND_REGISTRATION_DONE }; diff --git a/tcl/board/vd_a75x4_jtag.cfg b/tcl/board/vd_a75x4_jtag.cfg index c94a71972d..a91f8b8cfc 100644 --- a/tcl/board/vd_a75x4_jtag.cfg +++ b/tcl/board/vd_a75x4_jtag.cfg @@ -17,7 +17,7 @@ set CPUTAPID 0x4ba06477 transport select jtag # JTAG reset config, frequency and reset delay -reset_config trst_and_srst +reset_config trst_only adapter speed 1500000 adapter srst delay 5 diff --git a/tcl/board/vd_pulpissimo_jtag.cfg b/tcl/board/vd_pulpissimo_jtag.cfg index a3f5a84886..5a6725fd62 100644 --- a/tcl/board/vd_pulpissimo_jtag.cfg +++ b/tcl/board/vd_pulpissimo_jtag.cfg @@ -4,9 +4,9 @@ source [find interface/vdebug.cfg] -set _CHIPNAME ibex -set _HARTID 0x20 -set _CPUTAPID 0x249511c3 +set CHIPNAME ibex +set HARTID 0x20 +set CPUTAPID 0x249511c3 # vdebug select transport transport select jtag @@ -25,7 +25,7 @@ vdebug mem_path tbench.soc_domain_i.pulp_soc_i.gen_mem_l2_pri\[1\].sram_i.mem_ar vdebug mem_path tbench.soc_domain_i.pulp_soc_i.gen_mem_l2\[0\].sram_i.mem_array 0x1c010000 0x80000 # need to explicitly define riscv tap, autoprobing does not work for icapture != 0x01 -jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x05 -irmask 0x1f -expected-id $_CPUTAPID +jtag newtap $CHIPNAME cpu -irlen 5 -ircapture 0x05 -irmask 0x1f -expected-id $CPUTAPID jtag arp_init-reset diff --git a/tcl/interface/vdebug.cfg b/tcl/interface/vdebug.cfg index 63a5955067..27a8aafd7b 100644 --- a/tcl/interface/vdebug.cfg +++ b/tcl/interface/vdebug.cfg @@ -30,4 +30,4 @@ tcl port disabled vdebug batching 1 # Polling values -vdebug polling 100 1000 +vdebug polling 100 500 diff --git a/tcl/target/vd_riscv.cfg b/tcl/target/vd_riscv.cfg index f08cb1ac8b..44a80524a6 100644 --- a/tcl/target/vd_riscv.cfg +++ b/tcl/target/vd_riscv.cfg @@ -2,15 +2,15 @@ # Cadence virtual debug interface # RISCV core -if {![info exists _HARTID]} { - set _HARTID 0x00 +if {![info exists HARTID]} { + set HARTID 0x00 } -if {![info exists _CHIPNAME]} { - set _CHIPNAME riscv +if {![info exists CHIPNAME]} { + set CHIPNAME riscv } -set _TARGETNAME $_CHIPNAME.cpu +set _TARGETNAME $CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid $_HARTID +target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid $HARTID riscv set_reset_timeout_sec 120 riscv set_command_timeout_sec 120 From 6a40fe64d63568d307fdfbb4666784a848222787 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 23 Nov 2024 14:43:51 +0000 Subject: [PATCH 1258/1312] flash/nor/tcl: Add 'read_memory' command This command allows to read non-memory mapped flash content directly via Tcl script. The API is the same as for the 'read_memory' command for targets. Change-Id: I4a8d0d7ea2f778ac8f1501227b60b964c881cb84 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8634 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 18 +++++++ src/flash/nor/tcl.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 27ed46b920..c7d8c7d0d5 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5870,6 +5870,24 @@ The flash bank to use is inferred from the @var{address} of each block, and the specified length must stay within that bank. @end deffn +@deffn {Command} {flash read_memory} address width count +This function provides an efficient way to read flash memory from a Tcl script. +A Tcl list containing the requested memory elements is returned by this function. + +@itemize +@item @var{address} ... flash memory address +@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64 +@item @var{count} ... number of elements to read +@end itemize + +For example, the following command reads two 32 bit words from the flash +memory at address 0x08000000: + +@example +flash read_memory 0x08000000 32 2 +@end example +@end deffn + @deffn {Command} {flash write_bank} num filename [offset] Write the binary @file{filename} to flash bank @var{num}, starting at @var{offset} bytes from the beginning of the bank. If @var{offset} diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index e21620934a..0d41e49c8e 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -727,6 +727,124 @@ COMMAND_HANDLER(handle_flash_md_command) return retval; } +COMMAND_HANDLER(handle_flash_read_memory_command) +{ + /* + * CMD_ARGV[0] = memory address + * CMD_ARGV[1] = desired element width in bits + * CMD_ARGV[2] = number of elements to read + */ + + if (CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* Arg 1: Memory address. */ + target_addr_t addr; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr); + + /* Arg 2: Bit width of one element. */ + unsigned int width_bits; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits); + + /* Arg 3: Number of elements to read. */ + unsigned int count; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); + + switch (width_bits) { + case 8: + case 16: + case 32: + case 64: + break; + default: + command_print(CMD, "invalid width, must be 8, 16, 32 or 64"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + if (count > 65536) { + command_print(CMD, "too large read request, exceeds 64K elements"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + const unsigned int width = width_bits / 8; + /* -1 is needed to handle cases when (addr + count * width) results in zero + * due to overflow. + */ + if ((addr + count * width - 1) < addr) { + command_print(CMD, "memory region wraps over address zero"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + struct target *target = get_current_target(CMD_CTX); + struct flash_bank *bank; + int retval = get_flash_bank_by_addr(target, addr, true, &bank); + if (retval != ERROR_OK) + return retval; + + uint32_t offset = addr - bank->base; + uint32_t sizebytes = count * width_bits; + if (offset + sizebytes > bank->size) { + command_print(CMD, "cannot cross flash bank borders"); + return ERROR_FAIL; + } + + const size_t buffer_size = 4096; + uint8_t *buffer = malloc(buffer_size); + + if (!buffer) { + command_print(CMD, "failed to allocate memory"); + return ERROR_FAIL; + } + + char *separator = ""; + while (count > 0) { + const unsigned int max_chunk_len = buffer_size / width; + const size_t chunk_len = MIN(count, max_chunk_len); + + retval = flash_driver_read(bank, buffer, offset, chunk_len * width); + + if (retval != ERROR_OK) { + LOG_DEBUG("read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + addr, width_bits, chunk_len); + /* + * FIXME: we append the errmsg to the list of value already read. + * Add a way to flush and replace old output, but LOG_DEBUG() it + */ + command_print(CMD, "failed to read memory"); + free(buffer); + return retval; + } + + for (size_t i = 0; i < chunk_len ; i++) { + uint64_t v = 0; + + switch (width) { + case 8: + v = target_buffer_get_u64(target, &buffer[i * width]); + break; + case 4: + v = target_buffer_get_u32(target, &buffer[i * width]); + break; + case 2: + v = target_buffer_get_u16(target, &buffer[i * width]); + break; + case 1: + v = buffer[i]; + break; + } + + command_print_sameline(CMD, "%s0x%" PRIx64, separator, v); + separator = " "; + } + + count -= chunk_len; + offset += chunk_len * width; + } + + free(buffer); + + return ERROR_OK; +} COMMAND_HANDLER(handle_flash_write_bank_command) { @@ -1170,6 +1288,13 @@ static const struct command_registration flash_exec_command_handlers[] = { .usage = "address [count]", .help = "Display words from flash.", }, + { + .name = "read_memory", + .mode = COMMAND_EXEC, + .handler = handle_flash_read_memory_command, + .help = "Read Tcl list of 8/16/32/64 bit numbers from flash memory", + .usage = "address width count", + }, { .name = "write_bank", .handler = handle_flash_write_bank_command, From 7abc0f9e6593694059db56bf6f4ad64972b45ad7 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 21 May 2025 15:26:20 +0100 Subject: [PATCH 1259/1312] doc: bcm2835gpio: remove broken link and clarify usage The peripheral address details have been removed from the documentation part of the website (instead presented in the SoC datasheets). Pi 5 GPIOs are provided by the RP1 southbridge, which requires the use of libgpiod. The associated Linux driver for the GPIO interface must be used when bitbashing on Pi 5, as the timing of pin state changes is not guaranteed across the PCIe link without special treatment. Using libgpiod, the typical maximum swclk speed is 1MHz. Signed-off-by: Jonathan Bell Change-Id: I8b2c44ec5edd71abaa0a763ba4d4f4603a211348 Reviewed-on: https://review.openocd.org/c/openocd/+/8884 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- doc/openocd.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index c7d8c7d0d5..bd6b3704a8 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3346,8 +3346,10 @@ The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1". @end deffn @deffn {Interface Driver} {bcm2835gpio} -This SoC is present in Raspberry Pi which is a cheap single-board computer -exposing some GPIOs on its expansion header. +This GPIO interface is present in Raspberry Pi 0-4 which is a cheap +single-board computer exposing some GPIOs on its expansion header. + +@emph{Note:} for Raspberry Pi 5, use @b{linuxgpiod} not this driver. The driver accesses memory-mapped GPIO peripheral registers directly for maximum performance, but the only possible race condition is for @@ -3386,9 +3388,7 @@ and drive strength is reduced to 4 mA (2 mA on RPi 4). @deffn {Config Command} {bcm2835gpio peripheral_base} @var{base} Set the peripheral base register address to access GPIOs. Ignored if @file{/dev/gpiomem} is used. For the RPi1, use -0x20000000. For RPi2 and RPi3, use 0x3F000000. For RPi4, use 0xFE000000. A full -list can be found in the -@uref{https://www.raspberrypi.org/documentation/hardware/raspberrypi/peripheral_addresses.md, official guide}. +0x20000000. For RPi2 and RPi3, use 0x3F000000. For RPi4, use 0xFE000000. @end deffn @end deffn From e23a6bbc635aa426668c040abda8c2d38628e8d4 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 21 May 2025 15:37:25 +0100 Subject: [PATCH 1260/1312] tcl: fix broken Raspberry Pi website links raspberrypi.com is the home for technical information, raspberrypi.org is the Foundation's site (though there are intelligent redirects). Several pages have moved around, fix these. Also tweak a few comments for style and correctness. Signed-off-by: Jonathan Bell Change-Id: I7f52bcc362fb213b50987e3a42866fe4a6fec883 Reviewed-on: https://review.openocd.org/c/openocd/+/8885 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- tcl/board/rpi3.cfg | 4 ++-- tcl/board/rpi4b.cfg | 4 ++-- tcl/target/bcm2711.cfg | 4 ++-- tcl/target/bcm2835.cfg | 4 ++-- tcl/target/bcm2836.cfg | 6 +++--- tcl/target/bcm2837.cfg | 6 +++--- tcl/target/rp2040.cfg | 2 +- tcl/target/rp2350.cfg | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tcl/board/rpi3.cfg b/tcl/board/rpi3.cfg index fd93a9d9d8..a08bfeb12e 100644 --- a/tcl/board/rpi3.cfg +++ b/tcl/board/rpi3.cfg @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later # This is the Raspberry Pi 3 board with BCM2837 chip -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2837/README.md +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2837 # # Enable JTAG GPIO on Raspberry Pi boards -# https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md +# https://www.raspberrypi.com/documentation/computers/legacy_config_txt.html#enable_jtag_gpio source [find target/bcm2837.cfg] transport select jtag diff --git a/tcl/board/rpi4b.cfg b/tcl/board/rpi4b.cfg index 5b046af7b5..7d937e8c05 100644 --- a/tcl/board/rpi4b.cfg +++ b/tcl/board/rpi4b.cfg @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later # This is the Raspberry Pi 4 model B board with BCM2711 chip -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/README.md +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711 # # Enable JTAG GPIO on Raspberry Pi boards -# https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md +# https://www.raspberrypi.com/documentation/computers/legacy_config_txt.html#enable_jtag_gpio source [find target/bcm2711.cfg] transport select jtag diff --git a/tcl/target/bcm2711.cfg b/tcl/target/bcm2711.cfg index f8d2b3a65b..9704daf812 100644 --- a/tcl/target/bcm2711.cfg +++ b/tcl/target/bcm2711.cfg @@ -3,8 +3,8 @@ # The Broadcom BCM2711 used in Raspberry Pi 4 # No documentation was found on Broadcom website -# Partial information is available in raspberry pi website: -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/ +# Partial information is available on the Raspberry Pi website: +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME diff --git a/tcl/target/bcm2835.cfg b/tcl/target/bcm2835.cfg index 32a03666c4..645588730d 100644 --- a/tcl/target/bcm2835.cfg +++ b/tcl/target/bcm2835.cfg @@ -3,8 +3,8 @@ # This is the Broadcom chip used in the Raspberry Pi Model A, B, B+, # the Compute Module, and the Raspberry Pi Zero. -# Partial information is available in raspberry pi website: -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835 +# Partial information is available on the Raspberry Pi website: +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME diff --git a/tcl/target/bcm2836.cfg b/tcl/target/bcm2836.cfg index 04921315ed..695426e7a8 100644 --- a/tcl/target/bcm2836.cfg +++ b/tcl/target/bcm2836.cfg @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-or-later -# The Broadcom chip used in the Raspberry Pi 2 Model B +# The Broadcom chip used in the Raspberry Pi 2 Model B v1.1 -# Partial information is available in raspberry pi website: -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836 +# Partial information is available on the Raspberry Pi website: +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2836 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME diff --git a/tcl/target/bcm2837.cfg b/tcl/target/bcm2837.cfg index 749de31037..d41892c431 100644 --- a/tcl/target/bcm2837.cfg +++ b/tcl/target/bcm2837.cfg @@ -3,9 +3,9 @@ # This is the Broadcom chip used in the Raspberry Pi 3, # and in later models of the Raspberry Pi 2. -# Partial information is available in raspberry pi website: -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2837 -# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2837b0 +# Partial information is available on the Raspberry Pi website: +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2837 +# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2837b0 if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME diff --git a/tcl/target/rp2040.cfg b/tcl/target/rp2040.cfg index f64d4322b1..da88a3125b 100644 --- a/tcl/target/rp2040.cfg +++ b/tcl/target/rp2040.cfg @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later # RP2040 is a microcontroller with dual Cortex-M0+ core. -# https://www.raspberrypi.com/documentation/microcontrollers/rp2040.html +# https://www.raspberrypi.com/documentation/microcontrollers/silicon.html#rp2040 # The device requires multidrop SWD for debug. transport select swd diff --git a/tcl/target/rp2350.cfg b/tcl/target/rp2350.cfg index b7617acd4c..96bb9298fb 100644 --- a/tcl/target/rp2350.cfg +++ b/tcl/target/rp2350.cfg @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later # RP2350 is a microcontroller with dual Cortex-M33 cores or dual Hazard3 RISC-V cores. -# https://www.raspberrypi.com/documentation/microcontrollers/rp2350.html +# https://www.raspberrypi.com/documentation/microcontrollers/silicon.html#rp2350 transport select swd From d9b614a56db9ff08b349dc29f4b257c16a442013 Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Mon, 12 Oct 2020 13:22:47 -0700 Subject: [PATCH 1261/1312] target/armv8: Handle modeswitch for aarch32 secure EL3 For aarch32 secure EL3 - Change target_el to 3 for SVC/ABT/IRQ/FIQ/UND/SYS for aarch32 secure EL3 - Do not update SPSR for SYS, behavior is UNPREDICTABLE (ARMv8-A F5.1.121) - Do not execute DRPS for SYS, behavior is UNPREDICTABLE (ARMv8-A F5.1.51) Change-Id: Ic1484665cd53afcccb5c20b152993a3f0407f8a2 Signed-off-by: Kevin Yang Reviewed-on: https://review.openocd.org/c/openocd/+/5854 Tested-by: jenkins Reviewed-by: Matthias Welwarsky Reviewed-by: Plamena Marinova Reviewed-by: Antonio Borneo --- src/target/armv8_dpm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index d1cee8a10c..3384e82ea5 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -542,6 +542,8 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) unsigned int target_el; enum arm_state core_state; uint32_t cpsr; + uint32_t rw = (dpm->dscr >> 10) & 0xF; + uint32_t ns = (dpm->dscr >> 18) & 0x1; /* restore previous mode */ if (mode == ARM_MODE_ANY) { @@ -564,7 +566,11 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) case ARM_MODE_IRQ: case ARM_MODE_FIQ: case ARM_MODE_SYS: - target_el = 1; + /* For Secure, EL1 if EL3 is aarch64, EL3 if EL3 is aarch32 */ + if (ns || (rw & (1 << 3))) + target_el = 1; + else + target_el = 3; break; /* * TODO: handle ARM_MODE_HYP @@ -598,8 +604,8 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) } else { core_state = armv8_dpm_get_core_state(dpm); if (core_state != ARM_STATE_AARCH64) { - /* cannot do DRPS/ERET when already in EL0 */ - if (dpm->last_el != 0) { + /* cannot do DRPS/ERET when in EL0 or in SYS mode */ + if (dpm->last_el != 0 && dpm->arm->core_mode != ARM_MODE_SYS) { /* load SPSR with the desired mode and execute DRPS */ LOG_DEBUG("SPSR = 0x%08"PRIx32, cpsr); retval = dpm->instr_write_data_r0(dpm, From 1347b693a508179db5b19279cd6a37753fe0dfd5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 28 May 2025 16:58:44 +0200 Subject: [PATCH 1262/1312] configure: fix for missing include files on Linux By merging [1] and [2], the drivers 'xlnx-pcie-xvc' and 'linuxspidev' are now build by default on Linux. This highlights the dependency of some include files under subfolder 'linux' that are not installed by default in all Linux boxes. Add the check in 'configure' for the presence of the include file and conditionally enable the build of the driver. Change-Id: Ie88645c3455ab07622f069a0cc7bf09d1a5a2c75 Signed-off-by: Antonio Borneo Link: [1] 7214c8be46f7 ("configure: show adapter Xilinx XVC/PCIe in the configuration summary") Link: [2] 83e0293f7ba3 ("Add Linux SPI device SWD adapter support") Reviewed-on: https://review.openocd.org/c/openocd/+/8935 Tested-by: jenkins --- configure.ac | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e48653b215..c44d902d2c 100644 --- a/configure.ac +++ b/configure.ac @@ -63,6 +63,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int v = __GLIBC_ AC_MSG_RESULT($have_glibc) AC_CHECK_HEADERS([fcntl.h]) +AC_CHECK_HEADERS([linux/pci.h]) +AC_CHECK_HEADERS([linux/spi/spidev.h]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) AC_CHECK_HEADERS([poll.h]) @@ -694,10 +696,11 @@ PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpi PROCESS_ADAPTERS([SYSFSGPIO_ADAPTER], ["x$is_linux" = "xyes"], [Linux sysfs]) PROCESS_ADAPTERS([REMOTE_BITBANG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) -PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build]) +PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_pci_h" = "xyes"], [Linux build]) PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"], [internal error: validation should happen beforehand]) -PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev]) +PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_spi_spidev_h" = "xyes"], + [Linux spidev]) PROCESS_ADAPTERS([VDEBUG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([JTAG_DPI_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([JTAG_VPI_ADAPTER], [true], [unused]) From 4732e40637682a805956fd99832c151a9d4a691e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 3 Jun 2025 10:34:29 +0200 Subject: [PATCH 1263/1312] configure: hide build issue of amt_jtagaccel driver by disabling it With commit d8a2f6dbcf5f ("configure.ac: show the Amontec JTAG-Accelerator driver in the config summary") the driver amt_jtagaccel is now build by default on Linux. This highlights the dependency of some include files, dependency that is not properly managed and that can cause build failure. The driver is queued to be dropped soon, so there is no real interest to fix the dependencies. Change the default so the driver is not built if the user does not require it at configure time. Change-Id: Ifb74e2c802abda290efbf59ca4ce02048c94e6f8 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8939 Reviewed-by: R. Diez Tested-by: jenkins --- configure.ac | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c44d902d2c..3e1d9a2baa 100644 --- a/configure.ac +++ b/configure.ac @@ -329,11 +329,14 @@ AC_ARG_ADAPTERS([ JTAG_DPI_ADAPTER, JTAG_VPI_ADAPTER, RSHIM_ADAPTER, - AMTJTAGACCEL_ADAPTER, PCIE_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) +AC_ARG_ADAPTERS([ + AMTJTAGACCEL_ADAPTER + ],[no]) + AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), [build_parport=$enableval], [build_parport=no]) From 990ee1be73bcc0e901282c4898ee14c663c781c6 Mon Sep 17 00:00:00 2001 From: HAOUES Ahmed Date: Tue, 27 May 2025 11:22:09 +0100 Subject: [PATCH 1264/1312] flash/bluenrg-x: Add blueNRG alternate names BlueNRG-LP -> STM32WB07 BlueNRG-LPS -> STM32WB05 Change-Id: I8e05ea29e84d3a7842e145fb66f448d0c82bd004 Signed-off-by: HAOUES Ahmed Reviewed-on: https://review.openocd.org/c/openocd/+/8880 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/bluenrg-x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index 9ced2e9718..d019c1165e 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -63,7 +63,7 @@ static const struct flash_ctrl_priv_data flash_priv_data_lp = { .flash_regs_base = 0x40001000, .flash_page_size = 2048, .jtag_idcode = 0x0201E041, - .part_name = "BLUENRG-LP", + .part_name = "STM32WB07 (BLUENRG-LP)", }; static const struct flash_ctrl_priv_data flash_priv_data_lps = { @@ -73,7 +73,7 @@ static const struct flash_ctrl_priv_data flash_priv_data_lps = { .flash_regs_base = 0x40001000, .flash_page_size = 2048, .jtag_idcode = 0x02028041, - .part_name = "BLUENRG-LPS", + .part_name = "STM32WB05 (BLUENRG-LPS)", }; struct bluenrgx_flash_bank { From 0644a88a1ba60ccc2730a10954d255342a276309 Mon Sep 17 00:00:00 2001 From: HAOUES Ahmed Date: Tue, 27 May 2025 11:34:24 +0100 Subject: [PATCH 1265/1312] flash/bluenrg-x: Support STM32WB09 AKA BlueNRG-LPF device The BlueNRG-LPF has a flash size up to 512 Kb Change-Id: I4c71b716330351004f4f2ab8bf8eac7d5bb694eb Signed-off-by: HAOUES Ahmed Reviewed-on: https://review.openocd.org/c/openocd/+/8881 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/bluenrg-x.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index d019c1165e..cde4af5e3b 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -19,6 +19,7 @@ #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg) #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg) +#define BLUENRGLPF_JTAG_REG (flash_priv_data_lpf.jtag_idcode_reg) #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg) #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg) @@ -76,6 +77,16 @@ static const struct flash_ctrl_priv_data flash_priv_data_lps = { .part_name = "STM32WB05 (BLUENRG-LPS)", }; +static const struct flash_ctrl_priv_data flash_priv_data_lpf = { + .die_id_reg = 0x40000000, + .jtag_idcode_reg = 0x40000004, + .flash_base = 0x10040000, + .flash_regs_base = 0x40001000, + .flash_page_size = 2048, + .jtag_idcode = 0x02032041, + .part_name = "STM32WB09 (BLUENRG-LPF)", +}; + struct bluenrgx_flash_bank { bool probed; uint32_t die_id; @@ -86,7 +97,9 @@ static const struct flash_ctrl_priv_data *flash_ctrl[] = { &flash_priv_data_1, &flash_priv_data_2, &flash_priv_data_lp, - &flash_priv_data_lps}; + &flash_priv_data_lps, + &flash_priv_data_lpf +}; /* flash_bank bluenrg-x 0 0 0 0 */ FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command) @@ -387,7 +400,8 @@ static int bluenrgx_probe(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - if ((idcode != flash_priv_data_lp.jtag_idcode) && (idcode != flash_priv_data_lps.jtag_idcode)) { + if (idcode != flash_priv_data_lp.jtag_idcode && idcode != flash_priv_data_lps.jtag_idcode + && idcode != flash_priv_data_lpf.jtag_idcode) { retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode); if (retval != ERROR_OK) return retval; From 37a0f013f8893ae5041136900a2198ef16d38226 Mon Sep 17 00:00:00 2001 From: HAOUES Ahmed Date: Thu, 29 May 2025 10:01:20 +0100 Subject: [PATCH 1266/1312] flash/bluenrg-x: fix programming for devices with 512k flash flash ADDRESS register is encoded in 17 bits (was 16), so fix the cast to uint32_t Change-Id: I13384ee8967e65890577b12a42a0eb4f1e2a7467 Signed-off-by: HAOUES Ahmed Reviewed-on: https://review.openocd.org/c/openocd/+/8882 Tested-by: jenkins Reviewed-by: Antonio Borneo --- .../loaders/flash/bluenrg-x/bluenrg-x_write.c | 2 +- .../flash/bluenrg-x/bluenrg-x_write.inc | 34 ++++++++++--------- src/flash/nor/bluenrg-x.c | 4 +-- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c index 1bc72d5921..3c1988f112 100644 --- a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c +++ b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c @@ -52,7 +52,7 @@ static inline __attribute__((always_inline)) uint32_t flashWrite(uint32_t addres /* Clear the IRQ flags */ *((volatile uint32_t *)(flash_regs_base + FLASH_REG_IRQRAW)) = 0x0000003F; /* Load the flash address to write */ - *((volatile uint32_t *)(flash_regs_base + FLASH_REG_ADDRESS)) = (uint16_t)((address + index - MFB_BOTTOM) >> 2); + *((volatile uint32_t *)(flash_regs_base + FLASH_REG_ADDRESS)) = (uint32_t)((address + index - MFB_BOTTOM) >> 2); /* Prepare and load the data to flash */ *((volatile uint32_t *)(flash_regs_base + FLASH_REG_DATA0)) = flash_word[0]; *((volatile uint32_t *)(flash_regs_base + FLASH_REG_DATA1)) = flash_word[1]; diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc index ff05634bb2..146a6bedeb 100644 --- a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc +++ b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc @@ -1,17 +1,19 @@ /* Autogenerated with ../../../../src/helper/bin2char.sh */ -0x05,0x93,0x43,0x68,0x14,0x9e,0x09,0x93,0x05,0x9b,0x05,0x00,0x07,0x91,0x06,0x92, -0x01,0x24,0xb1,0x46,0x00,0x2b,0x68,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0xfb,0xd0, -0x2b,0x68,0x00,0x2b,0x61,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0x5e,0xd9,0x6b,0x68, -0x07,0x9a,0xd3,0x1a,0x0f,0x2b,0xef,0xdd,0x4a,0x46,0x00,0x21,0x03,0x93,0xd1,0x60, -0x00,0x2b,0x42,0xd0,0x40,0x22,0x4a,0x44,0x90,0x46,0x44,0x22,0x4a,0x44,0x00,0x92, -0x48,0x22,0x4a,0x44,0x93,0x46,0x4c,0x22,0x27,0x4f,0x4a,0x44,0xbc,0x46,0x4e,0x46, -0x92,0x46,0x06,0x99,0x4b,0x46,0x61,0x44,0x08,0x00,0x00,0x99,0x18,0x36,0x6a,0x68, -0x08,0x95,0x8c,0x46,0x55,0x46,0xda,0x46,0xb3,0x46,0x10,0x33,0x04,0x92,0x11,0x68, -0x5e,0x46,0x00,0x91,0x51,0x68,0x97,0x68,0x01,0x91,0xd1,0x68,0x02,0x91,0x3f,0x21, -0x19,0x60,0x81,0x03,0x09,0x0c,0x31,0x60,0x46,0x46,0x00,0x99,0x31,0x60,0x66,0x46, -0x01,0x99,0x31,0x60,0x56,0x46,0x02,0x99,0x37,0x60,0x29,0x60,0xcc,0x26,0x49,0x46, -0x0e,0x60,0x19,0x68,0x0c,0x42,0xfc,0xd0,0x04,0x99,0x03,0x9e,0x10,0x32,0x10,0x30, -0x51,0x1a,0x8e,0x42,0xdb,0xd8,0x08,0x9d,0x6a,0x60,0x03,0x9a,0x06,0x9b,0x94,0x46, -0x63,0x44,0x06,0x93,0x07,0x9a,0x6b,0x68,0x9a,0x42,0x01,0xd8,0x09,0x9b,0x6b,0x60, -0x05,0x9b,0x03,0x9a,0x9b,0x1a,0x05,0x93,0x96,0xd1,0x00,0xbe,0x2b,0x68,0x6a,0x68, -0x9b,0x1a,0x9f,0xd5,0x90,0xe7,0xc0,0x46,0x00,0x00,0xfc,0xef, +0x16,0x9e,0x05,0x00,0x01,0x24,0xb1,0x46,0x06,0x93,0x43,0x68,0x08,0x91,0x07,0x92, +0x09,0x93,0x06,0x9b,0x00,0x2b,0x6f,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0xfb,0xd0, +0x2b,0x68,0x00,0x2b,0x68,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0x65,0xd9,0x6b,0x68, +0x08,0x9a,0xd3,0x1a,0x0b,0x93,0x0b,0x9b,0x0f,0x2b,0xea,0xdd,0x4a,0x46,0x00,0x21, +0x0b,0x9b,0xd1,0x60,0x04,0x93,0x00,0x2b,0x43,0xd0,0x31,0x4a,0x07,0x9b,0x94,0x46, +0x40,0x22,0x4a,0x44,0x90,0x46,0x44,0x22,0x4a,0x44,0x63,0x44,0x94,0x46,0x48,0x22, +0x4a,0x44,0x93,0x46,0x05,0x93,0x4c,0x22,0x4b,0x46,0x4a,0x44,0x10,0x33,0x4e,0x46, +0x92,0x46,0x00,0x93,0x2b,0x00,0x18,0x36,0x6a,0x68,0x55,0x46,0xb2,0x46,0x5e,0x46, +0x9b,0x46,0x10,0x68,0x57,0x68,0x01,0x90,0x3f,0x20,0x00,0x9b,0x02,0x97,0x97,0x68, +0x03,0x97,0xd7,0x68,0x18,0x60,0x53,0x46,0x05,0x98,0x40,0x18,0x80,0x08,0x18,0x60, +0x43,0x46,0x01,0x98,0x18,0x60,0x63,0x46,0x02,0x98,0x18,0x60,0x03,0x98,0x4b,0x46, +0x30,0x60,0xcc,0x20,0x2f,0x60,0x18,0x60,0x00,0x9b,0x18,0x68,0x04,0x42,0xfc,0xd0, +0x58,0x46,0x10,0x32,0x42,0x60,0x04,0x98,0x10,0x31,0x00,0x93,0x88,0x42,0xd8,0xd8, +0x5d,0x46,0x07,0x9a,0x0b,0x9b,0x94,0x46,0x9c,0x44,0x63,0x46,0x08,0x9a,0x07,0x93, +0x6b,0x68,0x93,0x42,0x01,0xd3,0x09,0x9b,0x6b,0x60,0x06,0x9a,0x0b,0x9b,0xd3,0x1a, +0x06,0x93,0x06,0x9b,0x00,0x2b,0x8f,0xd1,0x00,0xbe,0x2b,0x68,0x6a,0x68,0x9b,0x1a, +0x0b,0x93,0x0b,0x9b,0x00,0x2b,0x00,0xdb,0x95,0xe7,0x00,0x23,0x0b,0x93,0x92,0xe7, +0x00,0x00,0xfc,0xef, diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index cde4af5e3b..a953e9b283 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -315,10 +315,10 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, init_reg_param(®_params[4], "sp", 32, PARAM_OUT); /* Put the 4th parameter at the location in the stack frame of target write() function. * See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.lst - * 34 ldr r6, [sp, #80] + * 34 ldr r6, [sp, #88] * ^^^ offset */ - init_mem_param(&mem_params[0], write_algorithm_stack->address + 80, 32, PARAM_OUT); + init_mem_param(&mem_params[0], write_algorithm_stack->address + 88, 32, PARAM_OUT); /* Stack for target write algorithm - target write() function has * __attribute__((naked)) so it does not setup the new stack frame. * Therefore the stack frame uses the area from SP upwards! From 2da332fa83b1aa55a61a44e6fe4d2089a9bb34b9 Mon Sep 17 00:00:00 2001 From: HAOUES Ahmed Date: Tue, 27 May 2025 11:42:42 +0100 Subject: [PATCH 1267/1312] flash/bluenrg-x: support programming without loader fallback programming without loader when resources are not available while at there refactor reused code (wait for interrupt and command execution) Change-Id: I2cba0f53d3470bc324f4a72614c236cebf196f64 Signed-off-by: BOCHKATI Tarek Signed-off-by: HAOUES Ahmed Reviewed-on: https://review.openocd.org/c/openocd/+/8883 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/bluenrg-x.c | 167 +++++++++++++++++++++++++++----------- src/flash/nor/bluenrg-x.h | 5 ++ 2 files changed, 126 insertions(+), 46 deletions(-) diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index a953e9b283..ccbbcc66eb 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -143,8 +143,45 @@ static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value); } -static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, - unsigned int last) +static int bluenrgx_wait_for_interrupt(struct flash_bank *bank, uint32_t interrupt_flag) +{ + bool flag_raised = false; + for (unsigned int j = 0; j < 100; j++) { + uint32_t value; + if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value) != ERROR_OK) { + LOG_ERROR("Register read failed"); + return ERROR_FAIL; + } + + if (value & interrupt_flag) { + flag_raised = true; + break; + } + } + + /* clear the interrupt */ + if (flag_raised) { + if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, interrupt_flag) != ERROR_OK) { + LOG_ERROR("Cannot clear interrupt flag"); + return ERROR_FAIL; + } + + return ERROR_OK; + } + + LOG_ERROR("Erase command failed (timeout)"); + return ERROR_TIMEOUT_REACHED; +} + +static inline int bluenrgx_wait_for_command(struct flash_bank *bank) +{ + if (bluenrgx_wait_for_interrupt(bank, FLASH_INT_CMDSTART) == ERROR_OK) + return bluenrgx_wait_for_interrupt(bank, FLASH_INT_CMDDONE); + + return ERROR_FAIL; +} + +static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, unsigned int last) { int retval = ERROR_OK; struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; @@ -186,19 +223,8 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, return ERROR_FAIL; } - for (unsigned int i = 0; i < 100; i++) { - uint32_t value; - if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) { - LOG_ERROR("Register write failed"); - return ERROR_FAIL; - } - if (value & FLASH_INT_CMDDONE) - break; - if (i == 99) { - LOG_ERROR("Mass erase command failed (timeout)"); - retval = ERROR_FAIL; - } - } + if (bluenrgx_wait_for_command(bank) != ERROR_OK) + return ERROR_FAIL; } else { command = FLASH_CMD_ERASE_PAGE; @@ -222,19 +248,8 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, return ERROR_FAIL; } - for (unsigned int j = 0; j < 100; j++) { - uint32_t value; - if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) { - LOG_ERROR("Register write failed"); - return ERROR_FAIL; - } - if (value & FLASH_INT_CMDDONE) - break; - if (j == 99) { - LOG_ERROR("Erase command failed (timeout)"); - retval = ERROR_FAIL; - } - } + if (bluenrgx_wait_for_command(bank) != ERROR_OK) + return ERROR_FAIL; } } @@ -242,7 +257,7 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, } -static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, +static int bluenrgx_write_with_loader(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; @@ -264,22 +279,6 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc" }; - /* check preconditions */ - if (!bluenrgx_info->probed) - return ERROR_FLASH_BANK_NOT_PROBED; - - if ((offset + count) > bank->size) { - LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32, - (offset + count), - bank->size); - return ERROR_FLASH_DST_OUT_OF_BANK; - } - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); @@ -366,6 +365,7 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, if (error != 0) LOG_ERROR("flash write failed = %08" PRIx32, error); } + if (retval == ERROR_OK) { uint32_t rp; /* Read back rp and check that is valid */ @@ -377,6 +377,7 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, } } } + target_free_working_area(target, source); target_free_working_area(target, write_algorithm); target_free_working_area(target, write_algorithm_stack); @@ -391,6 +392,80 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, return retval; } +static int bluenrgx_write_without_loader(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + unsigned int data_count = count / FLASH_DATA_WIDTH; + + while (data_count--) { + /* clear flags */ + if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) { + LOG_ERROR("Register write failed"); + return ERROR_FAIL; + } + + if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS, offset >> 2) != ERROR_OK) { + LOG_ERROR("Register write failed"); + return ERROR_FAIL; + } + + if (target_write_memory(target, bluenrgx_get_flash_reg(bank, FLASH_REG_DATA0), + FLASH_WORD_LEN, FLASH_DATA_WIDTH_W, buffer) != ERROR_OK) { + LOG_ERROR("Failed to write data"); + return ERROR_FAIL; + } + + if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, FLASH_CMD_BURSTWRITE) != ERROR_OK) { + LOG_ERROR("Failed"); + return ERROR_FAIL; + } + + if (bluenrgx_wait_for_command(bank) != ERROR_OK) + return ERROR_FAIL; + + /* increment offset, and buffer */ + offset += FLASH_DATA_WIDTH; + buffer += FLASH_DATA_WIDTH; + } + + return ERROR_OK; +} + +static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; + int retval = ERROR_OK; + + /* check preconditions */ + if (!bluenrgx_info->probed) + return ERROR_FLASH_BANK_NOT_PROBED; + + if ((offset + count) > bank->size) { + LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32, + (offset + count), + bank->size); + return ERROR_FLASH_DST_OUT_OF_BANK; + } + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + assert(offset % FLASH_WORD_LEN == 0); + assert(count % FLASH_WORD_LEN == 0); + + retval = bluenrgx_write_with_loader(bank, buffer, offset, count); + /* if resources are not available write without a loader */ + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + LOG_WARNING("falling back to programming without a flash loader (slower)"); + retval = bluenrgx_write_without_loader(bank, buffer, offset, count); + } + return retval; +} + static int bluenrgx_probe(struct flash_bank *bank) { struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; @@ -428,7 +503,7 @@ static int bluenrgx_probe(struct flash_bank *bank) return retval; bank->size = (size_info + 1) * FLASH_WORD_LEN; - bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info); + bank->num_sectors = bank->size / FLASH_PAGE_SIZE(bluenrgx_info); bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors); for (unsigned int i = 0; i < bank->num_sectors; i++) { diff --git a/src/flash/nor/bluenrg-x.h b/src/flash/nor/bluenrg-x.h index 720cb6e618..03c66cd81a 100644 --- a/src/flash/nor/bluenrg-x.h +++ b/src/flash/nor/bluenrg-x.h @@ -28,7 +28,12 @@ #define FLASH_CMD_WRITE 0x33 #define FLASH_CMD_BURSTWRITE 0xCC #define FLASH_INT_CMDDONE 0x01 +#define FLASH_INT_CMDSTART 0x02 +/* Flash Controller constants */ #define FLASH_WORD_LEN 4 +#define FLASH_DATA_WIDTH_W 4 +#define FLASH_DATA_WIDTH 16 + #endif /* OPENOCD_FLASH_NOR_BLUENRGX_H */ From e171959edec1275fd417617f69cec7ede529ec14 Mon Sep 17 00:00:00 2001 From: Electric Worry Date: Thu, 29 May 2025 10:51:59 +0100 Subject: [PATCH 1268/1312] target: add support for Allwinner H618 SoC The Allwinner H618 is an updated H616 but appears functionally equivalent. It is used in small boards such as Orange Pi Zero 3. Change-Id: I299a42be746189f3e8e31070aa26b83ab7d806a4 Signed-off-by: Electric Worry Reviewed-on: https://review.openocd.org/c/openocd/+/8936 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/target/allwinner_h618.cfg | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tcl/target/allwinner_h618.cfg diff --git a/tcl/target/allwinner_h618.cfg b/tcl/target/allwinner_h618.cfg new file mode 100644 index 0000000000..98d3ace0de --- /dev/null +++ b/tcl/target/allwinner_h618.cfg @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This is the Allwinner H618 chip. It is an updated version of the Allwinner H616. + +# Information is available on linux-sunxi.org: +# Datasheet: https://linux-sunxi.org/images/b/b9/H616_Datasheet_V1.0_cleaned.pdf +# Manual: https://linux-sunxi.org/images/2/24/H616_User_Manual_V1.0_cleaned.pdf + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME h618 +} + +if { [info exists USE_SMP] } { + set _USE_SMP $USE_SMP +} else { + set _USE_SMP 0 +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x5ba00477 +} + +set _cores 4 +jtag newtap $_CHIPNAME cpu -expected-id $_DAP_TAPID -irlen 4 +adapter speed 4000 + +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +# MEM-AP for direct access +target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 1 + +# these addresses are obtained from the ROM table via 'dap info 1' command +set _DBGBASE {0x81410000 0x81510000 0x81610000 0x81710000} +set _CTIBASE {0x81420000 0x81520000 0x81620000 0x81720000} + +set _smp_command "target smp" + +for { set _core 0 } { $_core < $_cores } { incr _core } { + set _CTINAME $_CHIPNAME.cti$_core + set _TARGETNAME $_CHIPNAME.cpu$_core + + cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 1 -baseaddr [lindex $_CTIBASE $_core] + target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 1 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME + + set _smp_command "$_smp_command $_TARGETNAME" +} + +if {$_USE_SMP} { + eval $_smp_command +} + +# default target is cpu0 +targets $_CHIPNAME.cpu0 From fa83ca0bea5532afa1cb7b994b77cc3b6d77f7db Mon Sep 17 00:00:00 2001 From: Electric Worry Date: Thu, 29 May 2025 11:31:59 +0100 Subject: [PATCH 1269/1312] tcl/board/orange_pi_zero_3: Add Orange Pi Zero 3 board The Orange Pi Zero 3 is an SBC that uses an Allwinner H618 SoC. As such, JTAG support is fully available, however the SoC multiplexes JTAG function with UART1 and microSD. Unfortunately Xunlong has used UART1 for the Wifi-BT chip, leaving JTAG accessible only via the microSD using a microSD breakout board (for example). Change-Id: I0dc078cd2f3176815271917eb5e948cc8ef94525 Signed-off-by: Electric Worry Reviewed-on: https://review.openocd.org/c/openocd/+/8938 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- tcl/board/orange_pi_zero_3.cfg | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tcl/board/orange_pi_zero_3.cfg diff --git a/tcl/board/orange_pi_zero_3.cfg b/tcl/board/orange_pi_zero_3.cfg new file mode 100644 index 0000000000..2af983c650 --- /dev/null +++ b/tcl/board/orange_pi_zero_3.cfg @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This is the Orange Pi Zero 3 board with Allwinner H618 chip +# http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-Zero-3.html +# +# Accessing JTAG signals on Orange Pi Zero 3 board requires connection to pins +# on the microSD card slot. +# 1 - DAT2 - TCK +# 2 - CD/DAT3 - NC +# 3 - CMD - TDO +# 4 - VDD - NC +# 5 - CLK - NC +# 6 - VSS - NC +# 7 - DAT0 - TDI +# 8 - DAT1 - TMS +# +# PF Configure Register 0 at address 0x0300b0b4 must be set 0x07373733 to set +# the JTAG function on these pins (which is what the factory installed image on +# the SPI flash does when the board is powered without a microSD inserted). + +source [find target/allwinner_h618.cfg] + +# To this contributor's knowledge, the board neither exposes TRST nor SRST. +reset_config none From c77ba0cf57f0632ecbdca500516f449853e017f4 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 3 Jun 2025 11:52:59 +0200 Subject: [PATCH 1270/1312] HACKING: describe keeping the 'Change-Id' on new patch versions We often get on Gerrit a new version of an old patch with a new 'Change-Id' value. This breaks the history of the review, adding more work to the review process. Describe in HACKING why the hook 'commit-msg' is required and how to handle the 'Change-Id' on new patch versions. Change-Id: I5c060b19f966add7422704912b38e1ab2f788e5f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8940 Tested-by: jenkins --- HACKING | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/HACKING b/HACKING index 8988b1617d..785179efe9 100644 --- a/HACKING +++ b/HACKING @@ -169,7 +169,9 @@ git remote add review https://USERNAME:PASSWORD@review.openocd.org/p/openocd.git Gerrit server, even if you plan to use several local branches for different topics. It is possible because @c for/master is not a traditional Git branch. - -# You will need to install this hook, we will look into a better solution: + -# You will need to install this hook to automatically add the + field "Change-Id:" in the commit message, as required by Gerrit. + We will look into a better solution: @code wget https://review.openocd.org/tools/hooks/commit-msg mv commit-msg .git/hooks @@ -246,6 +248,12 @@ doc: fix typos @code git pull --rebase origin master @endcode + +-# When you create a new version of an old patch, check that the new patch + keeps the same 'Change-Id:' field of the old patch. + This allows the Gerrit server to recognize the patch as a new version of + the older one and keeps track of the history and the review process. + -# Send the patches to the Gerrit server for review: @code git push review From 88aec4b49939a3f29fd3d9d5e8954e5bffeda8c9 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 9 Oct 2024 11:13:42 +0200 Subject: [PATCH 1271/1312] adapter: Deprecate Amontec JTAG Accelerator driver The adapter is not available for years now and Amontec is not even a company anymore. The poor hardware availability and the lack of users prevents testing, maintenance and adaptations to future changes. Mark the adapter as deprecated as a first step to give potential users the opportunity to upgrade the hardware until the next OpenOCD release. Change-Id: Idd9fb75588246bc39e12ea17a71435ed77f0f50b Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8349 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 6 ++++++ doc/openocd.texi | 2 ++ src/jtag/drivers/amt_jtagaccel.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/configure.ac b/configure.ac index 3e1d9a2baa..9561f2ba06 100644 --- a/configure.ac +++ b/configure.ac @@ -857,6 +857,12 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ AC_MSG_WARN([Using the internal jimtcl is deprecated and will not be possible in the future.]) ]) +AS_IF([test "x$enable_amtjtagaccel" != "xno"], [ + echo + echo + AC_MSG_WARN([Amontec JTAG-Accelerator adapter is deprecated and support will be removed in the next release!]) +]) + echo echo echo OpenOCD configuration summary diff --git a/doc/openocd.texi b/doc/openocd.texi index bd6b3704a8..04fa77bd40 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2508,6 +2508,8 @@ enabled when OpenOCD is configured, in order to be made available at run time. @deffn {Interface Driver} {amt_jtagaccel} +@b{Note: This adapter is deprecated and support will be removed in the next release!} + Amontec Chameleon in its JTAG Accelerator configuration, connected to a PC's EPP mode parallel port. This defines some driver-specific commands: diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index 633c20413a..d3f8bb61eb 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -419,6 +419,8 @@ static int amt_jtagaccel_init(void) #endif uint8_t ar_status; + LOG_WARNING("This adapter is deprecated and support will be removed in the next release!"); + #if PARPORT_USE_PPDEV == 1 if (device_handle > 0) { LOG_ERROR("device is already opened"); From 207ecaab33b985b16a067fc2c054a4f2cc161dc3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 9 Oct 2024 11:14:21 +0200 Subject: [PATCH 1272/1312] adapter: Deprecate Gateworks GW16012 driver The adapter is not available for years now. There is also no information about this device from Gateworks. The poor hardware availability and the lack of users prevents testing, maintenance and adaptations to future changes. Mark the adapter as deprecated as a first step to give potential users the opportunity to upgrade the hardware until the next OpenOCD release. Change-Id: I037325a6b018b26608733a36bef30db2785858f8 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8651 Tested-by: jenkins Reviewed-by: Antonio Borneo --- configure.ac | 5 +++++ doc/openocd.texi | 2 ++ src/jtag/drivers/gw16012.c | 2 ++ 3 files changed, 9 insertions(+) diff --git a/configure.ac b/configure.ac index 9561f2ba06..0bac37e5de 100644 --- a/configure.ac +++ b/configure.ac @@ -862,6 +862,11 @@ AS_IF([test "x$enable_amtjtagaccel" != "xno"], [ echo AC_MSG_WARN([Amontec JTAG-Accelerator adapter is deprecated and support will be removed in the next release!]) ]) +AS_IF([test "x$build_gw16012" = "xyes"], [ + echo + echo + AC_MSG_WARN([Gateworks GW16012 JTAG adapter is deprecated and support will be removed in the next release!]) +]) echo echo diff --git a/doc/openocd.texi b/doc/openocd.texi index 04fa77bd40..4ad66ee5f4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2929,6 +2929,8 @@ image. To be used with USB-Blaster II only. @end deffn @deffn {Interface Driver} {gw16012} +@b{Note: This adapter is deprecated and support will be removed in the next release!} + Gateworks GW16012 JTAG programmer. This has one driver-specific command: diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index 805065f1f4..98f7754223 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -461,6 +461,8 @@ static int gw16012_init(void) { uint8_t status_port; + LOG_WARNING("This adapter is deprecated and support will be removed in the next release!"); + if (gw16012_init_device() != ERROR_OK) return ERROR_JTAG_INIT_FAILED; From 8046f2a38f8af0048c0d2d0842b8a708b79c0c57 Mon Sep 17 00:00:00 2001 From: kryvosheiaivan Date: Wed, 28 May 2025 16:52:42 +0300 Subject: [PATCH 1273/1312] cmsis-dap: Fix freeing pending transfers on close Freeing pending transfers on shutdown is done in openOCD and on libusb side. This created concurrency in freeing memory and segmentation faults: https://github.com/libusb/libusb/issues/1627 Bug is reproduced better if many targets are laucnhed. Bug was reproduced with CMSIS-DAP on targets: cyw20829, psoc4, stm32l5 if launching multiple times. Proposed working fix: if some transfers pending/in-flight on 'shutdown' then apply libusb_handle_events_timeout_completed() to make transfer complete. In all cases transfer completed due to tests. Change-Id: I44621ac6096791714910220d04614d0a19ce47bd Signed-off-by: kryvosheiaivan Reviewed-on: https://review.openocd.org/c/openocd/+/8876 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/cmsis_dap_usb_bulk.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 8fbcb029dd..0dd6b2bbce 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -414,7 +414,19 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p static void cmsis_dap_usb_close(struct cmsis_dap *dap) { for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - libusb_free_transfer(dap->bdata->command_transfers[i].transfer); + if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) { + LOG_DEBUG("busy command USB transfer at %u", dap->pending_fifo_put_idx); + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 1000 + }; + /* Complete pending commands */ + int res = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, NULL); + if (res == 0) + libusb_free_transfer(dap->bdata->command_transfers[i].transfer); + } else { + libusb_free_transfer(dap->bdata->command_transfers[i].transfer); + } libusb_free_transfer(dap->bdata->response_transfers[i].transfer); } cmsis_dap_usb_free(dap); From 9a7c85b163d409ff48e9d445afe4cefbc6c28394 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 8 Jun 2025 11:22:39 +0200 Subject: [PATCH 1274/1312] configure.ac: remove usage of obsolete Automake macro AM_PROG_CC_C_O Macro AM_PROG_CC_C_O has been obsolete since Automake 1.14, released in June 2013 (12 years ago). It used to check whether the C compiler supports the -c and -o options, but that is now included in AC_PROG_CC. Increase the minimum required Automake version to 1.14 accordingly. Also remove the "not a GNU package" comment, which does not really make sense. Change-Id: I987ba8686721c7f36fba81e100f1c3ddf77f636d Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8942 Reviewed-by: Antonio Borneo Tested-by: jenkins --- Makefile.am | 4 +--- configure.ac | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index b2b6cef006..845543721d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,8 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later -# not a GNU package. You can remove this line, if -# have all needed files, that a GNU package needs -AUTOMAKE_OPTIONS = gnu 1.6 +AUTOMAKE_OPTIONS = gnu 1.14 .DELETE_ON_ERROR: diff --git a/configure.ac b/configure.ac index 0bac37e5de..b13af86d85 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,6 @@ AC_LANG([C]) AC_PROG_CC # autoconf 2.70 obsoletes AC_PROG_CC_C99 and includes it in AC_PROG_CC m4_version_prereq([2.70],[],[AC_PROG_CC_C99]) -AM_PROG_CC_C_O AC_PROG_RANLIB # If macro PKG_PROG_PKG_CONFIG is not available, Autoconf generates a misleading error message, From 1ebff3ab33c77e3f8fb4e1ddda262b606b572af1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 09:52:57 +0200 Subject: [PATCH 1275/1312] jep106: update to revision JEP106BM Jun 2025 Update to latest available document. Change-Id: Ic1c892b42d3efbb35ad4a6c85deb17ab31ad9997 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8944 Tested-by: jenkins --- src/helper/jep106.inc | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 8bbaf4ca5c..5e50e19550 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -8,7 +8,7 @@ * identification code list, please visit the JEDEC website at www.jedec.org . */ -/* This file is aligned to revision JEP106BL February 2025. */ +/* This file is aligned to revision JEP106BM June 2025. */ [0][0x01 - 1] = "AMD", [0][0x02 - 1] = "AMI", @@ -78,7 +78,7 @@ [0][0x42 - 1] = "Macronix", [0][0x43 - 1] = "Xerox", [0][0x44 - 1] = "Plus Logic", -[0][0x45 - 1] = "Western Digital Technologies Inc", +[0][0x45 - 1] = "SanDisk Technologies Inc", [0][0x46 - 1] = "Elan Circuit Tech.", [0][0x47 - 1] = "European Silicon Str.", [0][0x48 - 1] = "Apple Computer", @@ -1798,7 +1798,7 @@ [14][0x16 - 1] = "Chiplego Technology (Shanghai) Co Ltd", [14][0x17 - 1] = "StoreSkill", [14][0x18 - 1] = "Shenzhen Astou Technology Company", -[14][0x19 - 1] = "Guangdong LeafFive Technology Limited", +[14][0x19 - 1] = "Guangdong LeapFive Technology Limited", [14][0x1a - 1] = "Jin JuQuan", [14][0x1b - 1] = "Huaxuan Technology (Shenzhen) Co Ltd", [14][0x1c - 1] = "Gigastone Corporation", @@ -2049,4 +2049,39 @@ [16][0x15 - 1] = "Hangzhou Lishu Technology Co Ltd", [16][0x16 - 1] = "Tier IV Inc", [16][0x17 - 1] = "Wuhan Xuanluzhe Network Technology Co", +[16][0x18 - 1] = "EA Semi (Shanghai) Limited", +[16][0x19 - 1] = "Tech Vision Information Technology Co", +[16][0x1a - 1] = "Zhihe Computing Technology", +[16][0x1b - 1] = "Beijing Apexichips Tech", +[16][0x1c - 1] = "Yemas Holdingsl Limited", +[16][0x1d - 1] = "Eluktronics", +[16][0x1e - 1] = "Walton Digi-Tech Industries Ltd", +[16][0x1f - 1] = "Beijing Qixin Gongli Technology Co Ltd", +[16][0x20 - 1] = "M.RED", +[16][0x21 - 1] = "Shenzhen Damay Semiconductor Co Ltd", +[16][0x22 - 1] = "Corelab Tech Singapore Holding PTE LTD", +[16][0x23 - 1] = "EmBestor Technology Inc", +[16][0x24 - 1] = "XConn Technologies", +[16][0x25 - 1] = "Flagchip", +[16][0x26 - 1] = "CUNNUC", +[16][0x27 - 1] = "SGMicro", +[16][0x28 - 1] = "Lanxin Computing (Shenzhen) Technology", +[16][0x29 - 1] = "FuturePlus Systems LLC", +[16][0x2a - 1] = "Shenzhen Jielong Storage Technology Co", +[16][0x2b - 1] = "Precision Planting LLC", +[16][0x2c - 1] = "Sichuan ZeroneStor Microelectronics Tech", +[16][0x2d - 1] = "The University of Tokyo", +[16][0x2e - 1] = "Aodu (Fujian) Information Technology Co", +[16][0x2f - 1] = "Bytera Memory Inc", +[16][0x30 - 1] = "XSemitron Technology Inc", +[16][0x31 - 1] = "Cloud Ridge Ltd", +[16][0x32 - 1] = "Shenzhen XinChiTai Technology Co Ltd", +[16][0x33 - 1] = "Shenzhen Xinxin Semiconductor Co Ltd", +[16][0x34 - 1] = "Shenzhen ShineKing Electronics Co Ltd.", +[16][0x35 - 1] = "Shenzhen Shande Semiconductor Co. Ltd.", +[16][0x36 - 1] = "AheadComputing", +[16][0x37 - 1] = "Beijing Ronghua Kangweiye Technology", +[16][0x38 - 1] = "Shanghai Yunsilicon Technology Co Ltd", +[16][0x39 - 1] = "Shenzhen Wolongtai Technology Co Ltd.", +[16][0x3a - 1] = "Vervesemi Microelectronics", /* EOF */ From 33ebae9abde0b67ad33bb527cf5a2c2f761ab2c4 Mon Sep 17 00:00:00 2001 From: Daniel Goehring Date: Tue, 18 Jan 2022 12:34:25 -0500 Subject: [PATCH 1276/1312] target/armv8: update MPIDR decoding Update MPIDR decode to support the multithreading (MT) bit. If detected, socket, cluster, core and multithread affinity levels are decoded and displayed. Change-Id: I43569141fa0eef8ee8fc16c187a4af3c23e97db8 Signed-off-by: Daniel Goehring Reviewed-on: https://review.openocd.org/c/openocd/+/7190 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv8.c | 55 ++++++++++++++++++++++++++++++++++++++-------- src/target/armv8.h | 5 ----- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 40390731e8..ece49c2a26 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -883,12 +883,27 @@ int armv8_read_mpidr(struct armv8_common *armv8) int retval = ERROR_FAIL; struct arm *arm = &armv8->arm; struct arm_dpm *dpm = armv8->arm.dpm; - uint32_t mpidr; + uint64_t mpidr; + uint8_t multi_processor_system; + uint8_t aff3; + uint8_t aff2; + uint8_t aff1; + uint8_t aff0; + uint8_t mt; retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; + /* + * TODO: BUG - routine armv8_dpm_modeswitch() doesn't re-evaluate 'arm->dpm->core_state'. + * If the core is halted in EL0 AArch32 while EL1 is in AArch64, the modeswitch moves the core + * to EL1, but there is no re-evaluation of dpm->arm->core_state. As a result, while the core + * is in AArch64, the code considers the system still in AArch32. The read of MPIDR would + * select the instruction based on the old core_state. The call to 'armv8_dpm_get_core_state()' + * below could also potentially return the incorrect execution state for the current EL. + */ + /* check if we're in an unprivileged mode */ if (armv8_curel_from_core_mode(arm->core_mode) < SYSTEM_CUREL_EL1) { retval = armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H); @@ -896,17 +911,39 @@ int armv8_read_mpidr(struct armv8_common *armv8) return retval; } - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); + retval = dpm->instr_read_data_r0_64(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); if (retval != ERROR_OK) goto done; if (mpidr & 1U<<31) { - armv8->multi_processor_system = (mpidr >> 30) & 1; - armv8->cluster_id = (mpidr >> 8) & 0xf; - armv8->cpu_id = mpidr & 0x3; - LOG_INFO("%s cluster %x core %x %s", target_name(armv8->arm.target), - armv8->cluster_id, - armv8->cpu_id, - armv8->multi_processor_system == 0 ? "multi core" : "single core"); + multi_processor_system = (mpidr >> 30) & 1; + aff3 = (mpidr >> 32) & 0xff; + aff2 = (mpidr >> 16) & 0xff; + aff1 = (mpidr >> 8) & 0xff; + aff0 = mpidr & 0xff; + mt = (mpidr >> 24) & 0x1; + if (armv8_dpm_get_core_state(&armv8->dpm) == ARM_STATE_AARCH64) { + if (mt) + LOG_INFO("%s socket %" PRIu32 " cluster %" PRIu32 " core %" PRIu32 " thread %" PRIu32 " %s", + target_name(armv8->arm.target), + aff3, aff2, aff1, aff0, + multi_processor_system == 0 ? "multi core" : "single core"); + else + LOG_INFO("%s socket %" PRIu32 " cluster %" PRIu32 " core %" PRIu32 " %s", + target_name(armv8->arm.target), + aff3, aff1, aff0, + multi_processor_system == 0 ? "multi core" : "single core"); + } else { + if (mt) + LOG_INFO("%s cluster %" PRIu32 " core %" PRIu32 " thread %" PRIu32 " %s", + target_name(armv8->arm.target), + aff2, aff1, aff0, + multi_processor_system == 0 ? "multi core" : "single core"); + else + LOG_INFO("%s cluster %" PRIu32 " core %" PRIu32 " %s", + target_name(armv8->arm.target), + aff1, aff0, + multi_processor_system == 0 ? "multi core" : "single core"); + } } else LOG_ERROR("mpidr not in multiprocessor format"); diff --git a/src/target/armv8.h b/src/target/armv8.h index dba12f9666..64ca5ec9d4 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -195,11 +195,6 @@ struct armv8_common { const uint32_t *opcodes; - /* mdir */ - uint8_t multi_processor_system; - uint8_t cluster_id; - uint8_t cpu_id; - /* armv8 aarch64 need below information for page translation */ uint8_t va_size; uint8_t pa_size; From 9e4b6b90c960b769bf87cf233e638198d96da647 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sun, 8 Jun 2025 10:37:21 +0200 Subject: [PATCH 1277/1312] configure.ac: show 5 ARM adapters in config summary Adapters: bcm2835gpio, imx_gpio, am335xgpio, ep93xx and at91rm9200 Allow the user to enable them regardless of the target architecture. Change-Id: I9fbc7cbefe770ea2e2239b95a3305fd29127fa85 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8892 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 118 +++++++++++++++++++-------------------------------- 1 file changed, 44 insertions(+), 74 deletions(-) diff --git a/configure.ac b/configure.ac index b13af86d85..4b94716299 100644 --- a/configure.ac +++ b/configure.ac @@ -197,6 +197,15 @@ m4_define([RSHIM_ADAPTER], m4_define([AMTJTAGACCEL_ADAPTER], [[[amtjtagaccel], [Amontec JTAG-Accelerator driver], [AMTJTAGACCEL]]]) +m4_define([HOST_ARM_BITBANG_ADAPTERS], + [[[ep93xx], [Bitbanging on EP93xx-based SBCs], [EP93XX]], + [[at91rm9200], [Bitbanging on AT91RM9200-based SBCs], [AT91RM9200]]]) + +m4_define([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS], + [[[bcm2835gpio], [Bitbanging on BCM2835 (as found in Raspberry Pi)], [BCM2835GPIO]], + [[imx_gpio], [Bitbanging on NXP IMX processors], [IMX_GPIO]], + [[am335xgpio], [Bitbanging on AM335x (as found in Beaglebones)], [AM335XGPIO]]]) + # The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter # because there is an M4 macro called 'adapter'. m4_define([DUMMY_ADAPTER], @@ -336,6 +345,16 @@ AC_ARG_ADAPTERS([ AMTJTAGACCEL_ADAPTER ],[no]) +# The following adapters use bitbanging and can actually be built on all architectures, +# which is useful to verify that they still build fine. +# We could enable them automatically only on the architectures where they actually occur: +# HOST_ARM_BITBANG_ADAPTERS: when ${host_cpu} matches arm* +# HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS: when ${host_cpu} matches arm*|aarch64 +# However, conditionally changing the meaning of 'auto' requires +# a more flexible logic around. +AC_ARG_ADAPTERS([HOST_ARM_BITBANG_ADAPTERS],[no]) +AC_ARG_ADAPTERS([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS],[no]) + AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), [build_parport=$enableval], [build_parport=no]) @@ -350,39 +369,6 @@ AC_ARG_ENABLE([parport_giveio], [Enable use of giveio for parport (for CygWin only)]), [parport_use_giveio=$enableval], [parport_use_giveio=]) -AS_CASE(["${host_cpu}"], - [arm*|aarch64], [ - AC_ARG_ENABLE([bcm2835gpio], - AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]), - [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no]) - AC_ARG_ENABLE([imx_gpio], - AS_HELP_STRING([--enable-imx_gpio], [Enable building support for bitbanging on NXP IMX processors]), - [build_imx_gpio=$enableval], [build_imx_gpio=no]) - AC_ARG_ENABLE([am335xgpio], - AS_HELP_STRING([--enable-am335xgpio], [Enable building support for bitbanging on AM335x (as found in Beaglebones)]), - [build_am335xgpio=$enableval], [build_am335xgpio=no]) - ], - [ - build_bcm2835gpio=no - build_imx_gpio=no - build_am335xgpio=no -]) - -AS_CASE(["${host_cpu}"], - [arm*], [ - AC_ARG_ENABLE([ep93xx], - AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]), - [build_ep93xx=$enableval], [build_ep93xx=no]) - - AC_ARG_ENABLE([at91rm9200], - AS_HELP_STRING([--enable-at91rm9200], [Enable building support for AT91RM9200 based SBCs]), - [build_at91rm9200=$enableval], [build_at91rm9200=no]) - ], - [ - build_ep93xx=no - build_at91rm9200=no -]) - AC_ARG_ENABLE([gw16012], AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]), [build_gw16012=$enableval], [build_gw16012=no]) @@ -529,41 +515,6 @@ AS_IF([test "x$ADAPTER_VAR([dummy])" != "xno"], [ build_bitbang=yes ]) -AS_IF([test "x$build_ep93xx" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_EP93XX], [1], [1 if you want ep93xx.]) -], [ - AC_DEFINE([BUILD_EP93XX], [0], [0 if you don't want ep93xx.]) -]) - -AS_IF([test "x$build_at91rm9200" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.]) -], [ - AC_DEFINE([BUILD_AT91RM9200], [0], [0 if you don't want at91rm9200.]) -]) - -AS_IF([test "x$build_bcm2835gpio" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_BCM2835GPIO], [1], [1 if you want bcm2835gpio.]) -], [ - AC_DEFINE([BUILD_BCM2835GPIO], [0], [0 if you don't want bcm2835gpio.]) -]) - -AS_IF([test "x$build_imx_gpio" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_IMX_GPIO], [1], [1 if you want imx_gpio.]) -], [ - AC_DEFINE([BUILD_IMX_GPIO], [0], [0 if you don't want imx_gpio.]) -]) - -AS_IF([test "x$build_am335xgpio" = "xyes"], [ - build_bitbang=yes - AC_DEFINE([BUILD_AM335XGPIO], [1], [1 if you want am335xgpio.]) -], [ - AC_DEFINE([BUILD_AM335XGPIO], [0], [0 if you don't want am335xgpio.]) -]) - AS_IF([test "x$parport_use_ppdev" = "xyes"], [ AC_DEFINE([PARPORT_USE_PPDEV], [1], [1 if you want parport to use ppdev.]) ], [ @@ -709,6 +660,8 @@ PROCESS_ADAPTERS([JTAG_VPI_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([RSHIM_ADAPTER], ["x$can_build_rshim" = "xyes"], [internal error: validation should happen beforehand]) PROCESS_ADAPTERS([AMTJTAGACCEL_ADAPTER], [true], [unused]) +PROCESS_ADAPTERS([HOST_ARM_BITBANG_ADAPTERS], [true], [unused]) +PROCESS_ADAPTERS([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS], [true], [unused]) PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused]) AS_IF([test "x$enable_linuxgpiod" != "xno"], [ @@ -723,6 +676,26 @@ AS_IF([test "x$enable_remote_bitbang" != "xno"], [ build_bitbang=yes ]) +AS_IF([test "x$enable_bcm2835gpio" != "xno"], [ + build_bitbang=yes +]) + +AS_IF([test "x$enable_imx_gpio" != "xno"], [ + build_bitbang=yes +]) + +AS_IF([test "x$enable_am335xgpio" != "xno"], [ + build_bitbang=yes +]) + +AS_IF([test "x$enable_ep93xx" != "xno"], [ + build_bitbang=yes +]) + +AS_IF([test "x$enable_at91rm9200" != "xno"], [ + build_bitbang=yes +]) + AS_IF([test "x$enable_stlink" != "xno" -o "x$enable_ti_icdi" != "xno" -o "x$enable_nulink" != "xno"], [ AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.]) AM_CONDITIONAL([HLADAPTER], [true]) @@ -758,11 +731,6 @@ AS_IF([test "x$enable_esp_usb_jtag" != "xno"], [ AM_CONDITIONAL([RELEASE], [test "x$build_release" = "xyes"]) AM_CONDITIONAL([PARPORT], [test "x$build_parport" = "xyes"]) AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"]) -AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "xyes"]) -AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"]) -AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"]) -AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"]) -AM_CONDITIONAL([AM335XGPIO], [test "x$build_am335xgpio" = "xyes"]) AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) @@ -884,10 +852,12 @@ m4_foreach([adapter], [USB1_ADAPTERS, JTAG_VPI_ADAPTER, RSHIM_ADAPTER, AMTJTAGACCEL_ADAPTER, + HOST_ARM_BITBANG_ADAPTERS, + HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], - [s=m4_format(["%-41s"], ADAPTER_DESC([adapter])) + [s=m4_format(["%-49s"], ADAPTER_DESC([adapter])) AS_CASE([$ADAPTER_VAR([adapter])], [auto], [ echo "$s"yes '(auto)' From 82dc399e5e73495c0464283cff331854271706be Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 14 Jun 2025 12:18:53 +0200 Subject: [PATCH 1278/1312] target/cortex_m: fix debug reason after reset halt [1] removed target_halt() from cortex_m_assert_reset() It broke debug_reason tracking and the previous reason was shown after reset halt. Set debug_reason to DBG_REASON_DBGRQ during reset halt preparation. Fixes: [1] commit 226085065bdf ("target/cortex_m: drop useless target_halt() call") Reported-by: Marc Schink Change-Id: I685618ed158abde11f6e00eeeee1dfa8ed90952d Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8945 Tested-by: jenkins Reviewed-by: zapb --- src/target/cortex_m.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index ba9d83d79f..8eaf70f60a 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1779,6 +1779,7 @@ static int cortex_m_assert_reset(struct target *target) int retval2; retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); + target->debug_reason = DBG_REASON_DBGRQ; if (retval != ERROR_OK || retval2 != ERROR_OK) LOG_TARGET_INFO(target, "AP write error, reset will not halt"); } From 1afa12005ca84d549bddf31cc8a39308b7bdd197 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 15 Jun 2025 22:44:53 +0200 Subject: [PATCH 1279/1312] doc: Fix 'add_script_search_dir' usage The 'directory' parameter is not optional. Change-Id: Ifbc7b311692157dae0621dfa6d35a24b8fe8cbb2 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8954 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 4ad66ee5f4..ec856757d4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9335,7 +9335,7 @@ Redirect logging to @var{filename}. If used without an argument or stderr. @end deffn -@deffn {Command} {add_script_search_dir} [directory] +@deffn {Command} {add_script_search_dir} directory Add @var{directory} to the file/script search path. @end deffn From 06a0b8451fd7bb81e463abcaa79a9dcaaa8c0e84 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 16 Jun 2025 10:04:44 +0200 Subject: [PATCH 1280/1312] doc: Fix 'find' and 'ocd_find' usage Remove the quotation marks as they are used for strings and not parameter names. Change-Id: Ib0629e1465f821f91cd1e837f4ef8c752013b6b7 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8955 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index ec856757d4..df1d8d0bee 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -1382,11 +1382,11 @@ Read the OpenOCD source code (and Developer's Guide) if you have a new kind of hardware interface and need to provide a driver for it. -@deffn {Command} {find} 'filename' +@deffn {Command} {find} filename Prints full path to @var{filename} according to OpenOCD search rules. @end deffn -@deffn {Command} {ocd_find} 'filename' +@deffn {Command} {ocd_find} filename Prints full path to @var{filename} according to OpenOCD search rules. This is a low level function used by the @command{find}. Usually you want to use @command{find}, instead. From 99d642ca5b9c6c56c14325d6128a661cedae41a3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 19 Jun 2025 23:44:23 +0200 Subject: [PATCH 1281/1312] doc: Fix 'add_help_text' and 'add_usage_text' usage Remove the quotation marks as they are used for strings and not parameter names. Change-Id: I7bb25eb251427e89256b73cf697d8ec5c1b401dc Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8963 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index df1d8d0bee..948372c7c9 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9870,11 +9870,11 @@ Requests the current target to map the specified @var{virtual_address} to its corresponding physical address, and displays the result. @end deffn -@deffn {Command} {add_help_text} 'command_name' 'help-string' +@deffn {Command} {add_help_text} command_name help_string Add or replace help text on the given @var{command_name}. @end deffn -@deffn {Command} {add_usage_text} 'command_name' 'help-string' +@deffn {Command} {add_usage_text} command_name help_string Add or replace usage text on the given @var{command_name}. @end deffn From 1040bdec79d430440a31e77585547eb15c39966a Mon Sep 17 00:00:00 2001 From: Vitaly Cheptsov Date: Sun, 18 May 2025 08:49:30 +0300 Subject: [PATCH 1282/1312] jlink: add nickname support Using nicknames provides a human-readable alternative to serial numbers for convenience purposes. Allow matching adapter serial with device nickname. Change-Id: I03b8d28a6c89412a825d42f4f66b3b528f217d9c Signed-off-by: Vitaly Cheptsov Reviewed-on: https://review.openocd.org/c/openocd/+/8886 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: zapb --- doc/openocd.texi | 3 ++ src/jtag/drivers/jlink.c | 73 ++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 948372c7c9..494042530d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2499,6 +2499,9 @@ If this command is not specified, serial strings are not checked. Only the following adapter drivers use the serial string from this command: arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus, openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110. + +For jlink adapters, the @var{serial_string} is also compared +against the adapter's nickname. @end deffn @section Interface Drivers diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 9caf37f6f0..f6bb3099d6 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -40,8 +41,6 @@ static struct jaylink_connection connlist[JAYLINK_MAX_CONNECTIONS]; static enum jaylink_jtag_version jtag_command_version; static uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE]; -static uint32_t serial_number; -static bool use_serial_number; static bool use_usb_location; static enum jaylink_usb_address usb_address; static bool use_usb_address; @@ -561,8 +560,9 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) } use_usb_location = !!adapter_usb_get_location(); + const char *adapter_serial = adapter_get_required_serial(); - if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { + if (!adapter_serial && !use_usb_address && !use_usb_location && num_devices > 1) { LOG_ERROR("Multiple devices found, specify the desired device"); LOG_INFO("Found devices:"); for (size_t i = 0; devs[i]; i++) { @@ -575,7 +575,12 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) jaylink_strerror(ret)); continue; } - LOG_INFO("Device %zu serial: %" PRIu32, i, serial); + char name[JAYLINK_NICKNAME_MAX_LENGTH]; + int name_ret = jaylink_device_get_nickname(devs[i], name); + if (name_ret == JAYLINK_OK) + LOG_INFO("Device %zu serial: %" PRIu32 ", nickname %s", i, serial, name); + else + LOG_INFO("Device %zu serial: %" PRIu32, i, serial); } jaylink_free_devices(devs, true); @@ -585,23 +590,39 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) *found_device = false; + uint32_t serial_number; + ret = jaylink_parse_serial_number(adapter_serial, &serial_number); + if (ret != JAYLINK_OK) + serial_number = 0; + for (size_t i = 0; devs[i]; i++) { struct jaylink_device *dev = devs[i]; - if (use_serial_number) { - uint32_t tmp; - ret = jaylink_device_get_serial_number(dev, &tmp); - - if (ret == JAYLINK_ERR_NOT_AVAILABLE) { - continue; - } else if (ret != JAYLINK_OK) { - LOG_WARNING("jaylink_device_get_serial_number() failed: %s", - jaylink_strerror(ret)); - continue; + if (adapter_serial) { + /* + * Treat adapter serial as a nickname first as it can also be numeric. + * If it fails to match (optional) device nickname try to compare + * adapter serial with the actual device serial number. + */ + char nickname[JAYLINK_NICKNAME_MAX_LENGTH]; + ret = jaylink_device_get_nickname(dev, nickname); + if (ret != JAYLINK_OK || strcmp(nickname, adapter_serial) != 0) { + if (!serial_number) + continue; + + uint32_t tmp; + ret = jaylink_device_get_serial_number(dev, &tmp); + if (ret == JAYLINK_ERR_NOT_AVAILABLE) { + continue; + } else if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_serial_number() failed: %s", + jaylink_strerror(ret)); + continue; + } + + if (serial_number != tmp) + continue; } - - if (serial_number != tmp) - continue; } if (use_usb_address) { @@ -670,29 +691,15 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } - const char *serial = adapter_get_required_serial(); - if (serial) { - ret = jaylink_parse_serial_number(serial, &serial_number); - if (ret == JAYLINK_ERR) { - LOG_ERROR("Invalid serial number: %s", serial); - jaylink_exit(jayctx); - return ERROR_JTAG_INIT_FAILED; - } - if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_parse_serial_number() failed: %s", jaylink_strerror(ret)); - jaylink_exit(jayctx); - return ERROR_JTAG_INIT_FAILED; - } - use_serial_number = true; + if (adapter_get_required_serial()) use_usb_address = false; - } bool found_device; ret = jlink_open_device(JAYLINK_HIF_USB, &found_device); if (ret != ERROR_OK) return ret; - if (!found_device && use_serial_number) { + if (!found_device && adapter_get_required_serial()) { ret = jlink_open_device(JAYLINK_HIF_TCP, &found_device); if (ret != ERROR_OK) return ret; From a9015ba79d73fcc68fac7b98e679e6d4818472ee Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 19 Jun 2025 10:28:36 +0200 Subject: [PATCH 1283/1312] tcl/target/lsch3_common: Remove 'mem2array' The 'mem2array' function is deprecated and replaced by 'read_memory'. Change-Id: Iea54a390d67978d20dbb99ab6f7f4178dda481c2 Reported-by: Paul Fertser Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8962 Reviewed-by: Paul Fertser Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/target/lsch3_common.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcl/target/lsch3_common.cfg b/tcl/target/lsch3_common.cfg index f48d59b9d8..ad88b2e1b3 100644 --- a/tcl/target/lsch3_common.cfg +++ b/tcl/target/lsch3_common.cfg @@ -51,8 +51,8 @@ proc release_cpu {cpu} { } # Release the cpu; it will start executing something bogus - mem2array regs 32 $RST_BRRL 1 - mww $RST_BRRL [expr {$regs(0) | 1 << $cpu}] + set reg [read_memory $RST_BRRL 32 1] + mww $RST_BRRL [expr {$reg | 1 << $cpu}] if {$not_halted} { resume From a64ae963be55a3a7e12d8f7a91c9787bf4047778 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 12:36:07 +0200 Subject: [PATCH 1284/1312] flash: nor: sort the drivers by alphabetic order Add comments to require the list of drivers to be kept sorted. Change-Id: I57382605edc6a38d6c1ac18393421b18ae72215b Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8946 Tested-by: jenkins --- src/flash/nor/driver.h | 1 + src/flash/nor/drivers.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 3b57ef9ff0..da649e7831 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -237,6 +237,7 @@ struct flash_driver { */ const struct flash_driver *flash_driver_find_by_name(const char *name); +// Keep in alphabetic order this list of drivers extern const struct flash_driver aduc702x_flash; extern const struct flash_driver aducm360_flash; extern const struct flash_driver ambiqmicro_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 3770bfbd3c..4f468848bc 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -14,6 +14,7 @@ * @todo Make this dynamically extendable with loadable modules. */ static const struct flash_driver * const flash_drivers[] = { + // Keep in alphabetic order the list of drivers &aduc702x_flash, &aducm360_flash, &ambiqmicro_flash, @@ -27,8 +28,8 @@ static const struct flash_driver * const flash_drivers[] = { &atsamv_flash, &avr_flash, &bluenrgx_flash, - &cc3220sf_flash, &cc26xx_flash, + &cc3220sf_flash, &cfi_flash, &dsp5680xx_flash, &dw_spi_flash, @@ -37,9 +38,9 @@ static const struct flash_driver * const flash_drivers[] = { &eneispif_flash, &esirisc_flash, &faux_flash, + &fespi_flash, &fm3_flash, &fm4_flash, - &fespi_flash, &jtagspi_flash, &kinetis_flash, &kinetis_ke_flash, @@ -54,40 +55,40 @@ static const struct flash_driver * const flash_drivers[] = { &mspm0_flash, &niietcm4_flash, &npcx_flash, - &nrf5_flash, &nrf51_flash, + &nrf5_flash, &numicro_flash, &ocl_flash, &pic32mx_flash, &psoc4_flash, - &psoc5lp_flash, &psoc5lp_eeprom_flash, + &psoc5lp_flash, &psoc5lp_nvl_flash, &psoc6_flash, &qn908x_flash, &renesas_rpchf_flash, &rp2xxx_flash, + &rsl10_flash, &sh_qspi_flash, &sim3x_flash, &stellaris_flash, &stm32f1x_flash, &stm32f2x_flash, - &stm32lx_flash, - &stm32l4x_flash, &stm32h7x_flash, - &stmsmi_flash, + &stm32l4x_flash, + &stm32lx_flash, &stmqspi_flash, + &stmsmi_flash, &str7x_flash, &str9x_flash, &str9xpec_flash, &swm050_flash, &tms470_flash, &virtual_flash, + &w600_flash, &xcf_flash, &xmc1xxx_flash, &xmc4xxx_flash, - &w600_flash, - &rsl10_flash, NULL, }; From fa0fa25764b4737b42fbceab9f56a467263e12b0 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 14:02:25 +0200 Subject: [PATCH 1285/1312] flash: nor: use array size to constraint the loop Instead of using NULL terminated arrays to determine the last element of the array, use the size of the array. Change-Id: Ia3d739b0a9f201ba2e7b1d1244d60c8e5546c9c1 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8947 Reviewed-by: Brandon Martin Tested-by: jenkins --- src/flash/nor/drivers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 4f468848bc..cb807ec625 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -7,6 +7,8 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif + +#include #include "imp.h" /** @@ -89,12 +91,11 @@ static const struct flash_driver * const flash_drivers[] = { &xcf_flash, &xmc1xxx_flash, &xmc4xxx_flash, - NULL, }; const struct flash_driver *flash_driver_find_by_name(const char *name) { - for (unsigned int i = 0; flash_drivers[i]; i++) { + for (size_t i = 0; i < ARRAY_SIZE(flash_drivers); i++) { if (strcmp(name, flash_drivers[i]->name) == 0) return flash_drivers[i]; } From 6ab6d3475fb3758b60ad670b1b0d2cf3b2d10768 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 13:53:50 +0200 Subject: [PATCH 1286/1312] flash: nand: sort the drivers by alphabetic order Add comments to require the list of drivers to be kept sorted. Change-Id: I21b52cc1f5e679b0ebf7797e204248507f53557b Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8948 Tested-by: jenkins --- src/flash/nand/driver.c | 11 ++++++----- src/flash/nand/driver.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c index 5d99102c85..69b3ba9618 100644 --- a/src/flash/nand/driver.c +++ b/src/flash/nand/driver.c @@ -14,20 +14,21 @@ #include "driver.h" static struct nand_flash_controller *nand_flash_controllers[] = { - &nonce_nand_controller, + // Keep in alphabetic order the list of drivers + &at91sam9_nand_controller, &davinci_nand_controller, + &imx31_nand_flash_controller, &lpc3180_nand_controller, &lpc32xx_nand_controller, + &mxc_nand_flash_controller, + &nonce_nand_controller, + &nuc910_nand_controller, &orion_nand_controller, &s3c2410_nand_controller, &s3c2412_nand_controller, &s3c2440_nand_controller, &s3c2443_nand_controller, &s3c6400_nand_controller, - &mxc_nand_flash_controller, - &imx31_nand_flash_controller, - &at91sam9_nand_controller, - &nuc910_nand_controller, NULL }; diff --git a/src/flash/nand/driver.h b/src/flash/nand/driver.h index 4e84f10fbd..d26e77c75b 100644 --- a/src/flash/nand/driver.h +++ b/src/flash/nand/driver.h @@ -89,6 +89,7 @@ typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *); */ int nand_driver_walk(nand_driver_walker_t f, void *x); +// Keep in alphabetic order the list of drivers extern struct nand_flash_controller at91sam9_nand_controller; extern struct nand_flash_controller davinci_nand_controller; extern struct nand_flash_controller imx31_nand_flash_controller; From 5d192a9f70a706f8639721a636156547875e9fa8 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 13:58:38 +0200 Subject: [PATCH 1287/1312] flash: nand: use array size to constraint the loop Instead of using NULL terminated arrays to determine the last element of the array, use the size of the array. Change-Id: I532a51a223061348e57bae3bd66ee6b346c1b070 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8949 Tested-by: jenkins Reviewed-by: Brandon Martin --- src/flash/nand/driver.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c index 69b3ba9618..eda033b5b7 100644 --- a/src/flash/nand/driver.c +++ b/src/flash/nand/driver.c @@ -10,6 +10,8 @@ #ifdef HAVE_CONFIG_H #include #endif + +#include #include "core.h" #include "driver.h" @@ -29,12 +31,11 @@ static struct nand_flash_controller *nand_flash_controllers[] = { &s3c2440_nand_controller, &s3c2443_nand_controller, &s3c6400_nand_controller, - NULL }; struct nand_flash_controller *nand_driver_find_by_name(const char *name) { - for (unsigned int i = 0; nand_flash_controllers[i]; i++) { + for (size_t i = 0; i < ARRAY_SIZE(nand_flash_controllers); i++) { struct nand_flash_controller *controller = nand_flash_controllers[i]; if (strcmp(name, controller->name) == 0) return controller; @@ -43,7 +44,7 @@ struct nand_flash_controller *nand_driver_find_by_name(const char *name) } int nand_driver_walk(nand_driver_walker_t f, void *x) { - for (unsigned int i = 0; nand_flash_controllers[i]; i++) { + for (size_t i = 0; i < ARRAY_SIZE(nand_flash_controllers); i++) { int retval = (*f)(nand_flash_controllers[i], x); if (retval != ERROR_OK) return retval; From c92cf66c6714ebf367d1ccb1ba59010491924063 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 14:39:37 +0200 Subject: [PATCH 1288/1312] jtag: interfaces: sort the drivers by alphabetic order Add comments to require the list of drivers to be kept sorted. While there: - align the check on BUILD_PRESTO and BUILD_USB_BLASTER; - fix indentation of the closing parenthesis. Change-Id: Ic78281b1cdfb5bf72ea41427233e76516001b429 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8950 Tested-by: jenkins --- src/jtag/interface.h | 1 + src/jtag/interfaces.c | 153 +++++++++++++++++++++--------------------- 2 files changed, 79 insertions(+), 75 deletions(-) diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 475dbed36e..8349973613 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -371,6 +371,7 @@ int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, unsigned int traceclkin_freq, uint16_t *prescaler); int adapter_poll_trace(uint8_t *buf, size_t *size); +// Keep in alphabetic order this list of drivers extern struct adapter_driver am335xgpio_adapter_driver; extern struct adapter_driver amt_jtagaccel_adapter_driver; extern struct adapter_driver angie_adapter_driver; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index e49bd9e0f3..834247245b 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -36,125 +36,128 @@ * drivers that were enabled by the @c configure script. */ struct adapter_driver *adapter_drivers[] = { -#if BUILD_PARPORT == 1 - &parport_adapter_driver, + // Keep in alphabetic order this list of drivers + +#if BUILD_AM335XGPIO == 1 + &am335xgpio_adapter_driver, #endif -#if BUILD_DUMMY == 1 - &dummy_adapter_driver, +#if BUILD_AMTJTAGACCEL == 1 + &amt_jtagaccel_adapter_driver, #endif -#if BUILD_FTDI == 1 - &ftdi_adapter_driver, +#if BUILD_ANGIE == 1 + &angie_adapter_driver, #endif -#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1 - &usb_blaster_adapter_driver, +#if BUILD_ARMJTAGEW == 1 + &armjtagew_adapter_driver, #endif -#if BUILD_ESP_USB_JTAG == 1 - &esp_usb_adapter_driver, +#if BUILD_AT91RM9200 == 1 + &at91rm9200_adapter_driver, #endif -#if BUILD_JTAG_VPI == 1 - &jtag_vpi_adapter_driver, +#if BUILD_BCM2835GPIO == 1 + &bcm2835gpio_adapter_driver, #endif -#if BUILD_VDEBUG == 1 - &vdebug_adapter_driver, +#if BUILD_BUS_PIRATE == 1 + &buspirate_adapter_driver, #endif -#if BUILD_JTAG_DPI == 1 - &jtag_dpi_adapter_driver, +#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1 + &cmsis_dap_adapter_driver, #endif -#if BUILD_FT232R == 1 - &ft232r_adapter_driver, +#if BUILD_DMEM == 1 + &dmem_dap_adapter_driver, #endif -#if BUILD_AMTJTAGACCEL == 1 - &amt_jtagaccel_adapter_driver, +#if BUILD_DUMMY == 1 + &dummy_adapter_driver, #endif #if BUILD_EP93XX == 1 &ep93xx_adapter_driver, #endif -#if BUILD_AT91RM9200 == 1 - &at91rm9200_adapter_driver, +#if BUILD_ESP_USB_JTAG == 1 + &esp_usb_adapter_driver, +#endif +#if BUILD_FT232R == 1 + &ft232r_adapter_driver, +#endif +#if BUILD_FTDI == 1 + &ftdi_adapter_driver, #endif #if BUILD_GW16012 == 1 &gw16012_adapter_driver, #endif -#if BUILD_PRESTO - &presto_adapter_driver, -#endif -#if BUILD_USBPROG == 1 - &usbprog_adapter_driver, +#if BUILD_HLADAPTER == 1 + &hl_adapter_driver, #endif -#if BUILD_OPENJTAG == 1 - &openjtag_adapter_driver, +#if BUILD_IMX_GPIO == 1 + &imx_gpio_adapter_driver, #endif #if BUILD_JLINK == 1 &jlink_adapter_driver, #endif -#if BUILD_VSLLINK == 1 - &vsllink_adapter_driver, -#endif -#if BUILD_RLINK == 1 - &rlink_adapter_driver, +#if BUILD_JTAG_DPI == 1 + &jtag_dpi_adapter_driver, #endif -#if BUILD_ULINK == 1 - &ulink_adapter_driver, +#if BUILD_JTAG_VPI == 1 + &jtag_vpi_adapter_driver, #endif -#if BUILD_ANGIE == 1 - &angie_adapter_driver, +#if BUILD_KITPROG == 1 + &kitprog_adapter_driver, #endif -#if BUILD_ARMJTAGEW == 1 - &armjtagew_adapter_driver, +#if BUILD_LINUXGPIOD == 1 + &linuxgpiod_adapter_driver, #endif -#if BUILD_BUS_PIRATE == 1 - &buspirate_adapter_driver, +#if BUILD_LINUXSPIDEV == 1 + &linuxspidev_adapter_driver, #endif -#if BUILD_REMOTE_BITBANG == 1 - &remote_bitbang_adapter_driver, +#if BUILD_OPENDOUS == 1 + &opendous_adapter_driver, #endif -#if BUILD_HLADAPTER == 1 - &hl_adapter_driver, +#if BUILD_OPENJTAG == 1 + &openjtag_adapter_driver, #endif #if BUILD_OSBDM == 1 &osbdm_adapter_driver, #endif -#if BUILD_OPENDOUS == 1 - &opendous_adapter_driver, +#if BUILD_PARPORT == 1 + &parport_adapter_driver, #endif -#if BUILD_SYSFSGPIO == 1 - &sysfsgpio_adapter_driver, +#if BUILD_PRESTO == 1 + &presto_adapter_driver, #endif -#if BUILD_LINUXGPIOD == 1 - &linuxgpiod_adapter_driver, +#if BUILD_REMOTE_BITBANG == 1 + &remote_bitbang_adapter_driver, #endif -#if BUILD_LINUXSPIDEV == 1 - &linuxspidev_adapter_driver, +#if BUILD_RLINK == 1 + &rlink_adapter_driver, #endif -#if BUILD_XLNX_PCIE_XVC == 1 - &xlnx_pcie_xvc_adapter_driver, +#if BUILD_RSHIM == 1 + &rshim_dap_adapter_driver, #endif -#if BUILD_BCM2835GPIO == 1 - &bcm2835gpio_adapter_driver, +#if BUILD_HLADAPTER_STLINK == 1 + &stlink_dap_adapter_driver, #endif -#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1 - &cmsis_dap_adapter_driver, +#if BUILD_SYSFSGPIO == 1 + &sysfsgpio_adapter_driver, #endif -#if BUILD_KITPROG == 1 - &kitprog_adapter_driver, +#if BUILD_ULINK == 1 + &ulink_adapter_driver, #endif -#if BUILD_IMX_GPIO == 1 - &imx_gpio_adapter_driver, +#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1 + &usb_blaster_adapter_driver, #endif -#if BUILD_XDS110 == 1 - &xds110_adapter_driver, +#if BUILD_USBPROG == 1 + &usbprog_adapter_driver, #endif -#if BUILD_HLADAPTER_STLINK == 1 - &stlink_dap_adapter_driver, +#if BUILD_VDEBUG == 1 + &vdebug_adapter_driver, #endif -#if BUILD_RSHIM == 1 - &rshim_dap_adapter_driver, +#if BUILD_VSLLINK == 1 + &vsllink_adapter_driver, #endif -#if BUILD_DMEM == 1 - &dmem_dap_adapter_driver, +#if BUILD_XDS110 == 1 + &xds110_adapter_driver, #endif -#if BUILD_AM335XGPIO == 1 - &am335xgpio_adapter_driver, +#if BUILD_XLNX_PCIE_XVC == 1 + &xlnx_pcie_xvc_adapter_driver, #endif + NULL, - }; +}; From cd749419caae4f083daa2e0717fb2c6747ba033a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 14:51:43 +0200 Subject: [PATCH 1289/1312] target: sort the targets by alphabetic order Add comments to require the list of targets to be kept sorted. Change-Id: Ie3d7e3f5d55a9f9214dc179c5c986b6682f59412 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8951 Tested-by: jenkins --- src/target/target.c | 53 ++++++++++++++++++++-------------------- src/target/target_type.h | 1 + 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index fd0e0116b5..8bf654a272 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -71,44 +71,45 @@ static int target_gdb_fileio_end_default(struct target *target, int retcode, int fileio_errno, bool ctrl_c); static struct target_type *target_types[] = { + // Keep in alphabetic order this list of targets + &aarch64_target, + &arcv2_target, + &arm11_target, + &arm720t_target, &arm7tdmi_target, - &arm9tdmi_target, &arm920t_target, - &arm720t_target, - &arm966e_target, - &arm946e_target, &arm926ejs_target, - &fa526_target, - &feroceon_target, - &dragonite_target, - &xscale_target, - &xtensa_chip_target, - &cortexm_target, + &arm946e_target, + &arm966e_target, + &arm9tdmi_target, + &armv8r_target, + &avr32_ap7k_target, + &avr_target, &cortexa_target, + &cortexm_target, &cortexr4_target, - &arm11_target, - &ls1_sap_target, - &mips_m4k_target, - &avr_target, + &dragonite_target, &dsp563xx_target, &dsp5680xx_target, - &testee_target, - &avr32_ap7k_target, - &hla_target, - &esp32_target, + &esirisc_target, &esp32s2_target, &esp32s3_target, + &esp32_target, + &fa526_target, + &feroceon_target, + &hla_target, + &ls1_sap_target, + &mem_ap_target, + &mips_m4k_target, + &mips_mips64_target, &or1k_target, - &quark_x10xx_target, &quark_d20xx_target, - &stm8_target, + &quark_x10xx_target, &riscv_target, - &mem_ap_target, - &esirisc_target, - &arcv2_target, - &aarch64_target, - &armv8r_target, - &mips_mips64_target, + &stm8_target, + &testee_target, + &xscale_target, + &xtensa_chip_target, NULL, }; diff --git a/src/target/target_type.h b/src/target/target_type.h index 5b0dc5a6c0..a146fab763 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -307,6 +307,7 @@ struct target_type { unsigned int (*data_bits)(struct target *target); }; +// Keep in alphabetic order this list of targets extern struct target_type aarch64_target; extern struct target_type arcv2_target; extern struct target_type arm11_target; From df525290cb11ab40968253b7d4c5588b1aab7d82 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 15:02:04 +0200 Subject: [PATCH 1290/1312] target: use array size to constraint the loop Instead of using NULL terminated arrays to determine the last element of the array, use the size of the array. Change-Id: I3cdc0f6aef8a5110073aeef333c439e61fc54032 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8952 Tested-by: jenkins Reviewed-by: Brandon Martin --- src/target/target.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 8bf654a272..995adbc9d3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -110,7 +110,6 @@ static struct target_type *target_types[] = { &testee_target, &xscale_target, &xtensa_chip_target, - NULL, }; struct target *all_targets; @@ -5708,7 +5707,6 @@ static const struct command_registration target_instance_command_handlers[] = { COMMAND_HANDLER(handle_target_create) { int retval = ERROR_OK; - int x; if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -5732,15 +5730,16 @@ COMMAND_HANDLER(handle_target_create) LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD"); } /* now does target type exist */ - for (x = 0 ; target_types[x] ; x++) { + size_t x; + for (x = 0 ; x < ARRAY_SIZE(target_types) ; x++) { if (strcmp(cp, target_types[x]->name) == 0) { /* found */ break; } } - if (!target_types[x]) { + if (x == ARRAY_SIZE(target_types)) { char *all = NULL; - for (x = 0 ; target_types[x] ; x++) { + for (x = 0 ; x < ARRAY_SIZE(target_types) ; x++) { char *prev = all; if (all) all = alloc_printf("%s, %s", all, target_types[x]->name); @@ -5942,7 +5941,7 @@ COMMAND_HANDLER(handle_target_types) if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned int x = 0; target_types[x]; x++) + for (size_t x = 0; x < ARRAY_SIZE(target_types); x++) command_print(CMD, "%s", target_types[x]->name); return ERROR_OK; From 9b660bbd1957ffc1fd86485ceef5200f8968aeb6 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Jun 2025 15:07:50 +0200 Subject: [PATCH 1291/1312] rtos: sort the rtos by alphabetic order Add comments to require the list of rtos to be kept sorted. Change-Id: Iecf9250a14f6593d0a24a9f9b8930c0ec8d74bd2 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8953 Tested-by: jenkins --- src/rtos/rtos.c | 16 +++++++++------- src/rtos/rtos.h | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 216129b971..2ccccf1b0d 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -17,20 +17,22 @@ #include "server/gdb_server.h" static const struct rtos_type *rtos_types[] = { - &threadx_rtos, - &freertos_rtos, - &ecos_rtos, - &linux_rtos, + // Keep in alphabetic order this list of rtos, except hwthread &chibios_rtos, &chromium_ec_rtos, + &ecos_rtos, &embkernel_rtos, + &freertos_rtos, + &linux_rtos, &mqx_rtos, - &ucos_iii_rtos, &nuttx_rtos, &riot_rtos, - &zephyr_rtos, &rtkernel_rtos, - /* keep this as last, as it always matches with rtos auto */ + &threadx_rtos, + &ucos_iii_rtos, + &zephyr_rtos, + + // keep this as last, as it always matches with rtos auto &hwthread_rtos, }; diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 05beab1459..dbaa7e8ce8 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -136,6 +136,7 @@ int rtos_read_buffer(struct target *target, target_addr_t address, int rtos_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer); +// Keep in alphabetic order this list of rtos extern const struct rtos_type chibios_rtos; extern const struct rtos_type chromium_ec_rtos; extern const struct rtos_type ecos_rtos; From 46aa9c0e526f39c61b2c08ac1d21c998ad34259e Mon Sep 17 00:00:00 2001 From: Jan Matyas Date: Tue, 17 Jun 2025 13:17:23 +0200 Subject: [PATCH 1292/1312] openocd.c: 'init' should fail if GDB service cannot be created If it is not possible to create a GDB service for a certain target (for example the given TCP port is already occupied), the "init" command should fail, but it currently does not. Fix this by checking the return code of gdb_target_add_all(). Steps to reproduce: 1) Make the port 3333/tcp occupied. For example by: nc -l 3333 2) In another terminal, launch OpenOCD. Use the gdb_port 3333 (which is the default). For example: path/to/your/openocd \ -c "adapter driver ..." \ -c "jtag newtap ..." -c "target create ..." 3) Observe the outcome: Before this patch: Error "couldn't bind gdb to socket on port 3333: Address already in use" is displayed but OpenOCD keeps running. After this patch: The error message is displayed and OpenOCD exits - as expected. Change-Id: I63c283a9a1095167b78e69e9ee879c378a6b9f2a Signed-off-by: Jan Matyas Reviewed-on: https://review.openocd.org/c/openocd/+/8957 Tested-by: jenkins Reviewed-by: zapb Reviewed-by: Antonio Borneo --- src/openocd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openocd.c b/src/openocd.c index 3fbece3955..e63a9661a3 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -170,7 +170,8 @@ COMMAND_HANDLER(handle_init_command) jtag_poll_unmask(save_poll_mask); /* initialize telnet subsystem */ - gdb_target_add_all(all_targets); + if (gdb_target_add_all(all_targets) != ERROR_OK) + return ERROR_FAIL; target_register_event_callback(log_target_callback_event_handler, CMD_CTX); From 4d56d580ce9e2f10e8659bd0d0c4e1b333efa45c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 20 Jun 2025 10:17:12 +0200 Subject: [PATCH 1293/1312] target/arm_dpm: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() to indicate which target the message belongs to. While at it, rework the log messages. For example, using correct format specifiers. Change-Id: I05031e0ae25fe9e7bc38dfb781b6623a967fd533 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8964 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_dpm.c | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 0b2db77c5c..8ab464d0ab 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -50,9 +50,8 @@ static int dpm_mrc(struct target *target, int cpnum, if (retval != ERROR_OK) return retval; - LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum, - (int) op1, (int) crn, - (int) crm, (int) op2); + LOG_TARGET_DEBUG(target, "MRC p%d, %" PRId32 ", r0, c%" PRId32 ", c%" PRId32 ", %" PRId32, + cpnum, op1, crn, crm, op2); /* read coprocessor register into R0; return via DCC */ retval = dpm->instr_read_data_r0(dpm, @@ -74,8 +73,8 @@ static int dpm_mrrc(struct target *target, int cpnum, if (retval != ERROR_OK) return retval; - LOG_DEBUG("MRRC p%d, %d, r0, r1, c%d", cpnum, - (int)op, (int)crm); + LOG_TARGET_DEBUG(target, "MRRC p%d, %" PRId32 ", r0, r1, c%" PRId32, + cpnum, op, crm); /* read coprocessor register into R0, R1; return via DCC */ retval = dpm->instr_read_data_r0_r1(dpm, @@ -98,9 +97,8 @@ static int dpm_mcr(struct target *target, int cpnum, if (retval != ERROR_OK) return retval; - LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum, - (int) op1, (int) crn, - (int) crm, (int) op2); + LOG_TARGET_DEBUG(target, "MCR p%d, %" PRId32 ", r0, c%" PRId32 ", c%" PRId32 ", %" PRId32, + cpnum, op1, crn, crm, op2); /* read DCC into r0; then write coprocessor register from R0 */ retval = dpm->instr_write_data_r0(dpm, @@ -122,8 +120,8 @@ static int dpm_mcrr(struct target *target, int cpnum, if (retval != ERROR_OK) return retval; - LOG_DEBUG("MCRR p%d, %d, r0, r1, c%d", cpnum, - (int)op, (int)crm); + LOG_TARGET_DEBUG(target, "MCRR p%d, %" PRId32 ", r0, r1, c%" PRId32, + cpnum, op, crm); /* read DCC into r0, r1; then write coprocessor register from R0, R1 */ retval = dpm->instr_write_data_r0_r1(dpm, @@ -198,7 +196,8 @@ static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned int reg buf_set_u32(r->value + 4, 0, 32, value_r1); r->valid = true; r->dirty = false; - LOG_DEBUG("READ: %s, %8.8" PRIx32 ", %8.8" PRIx32, r->name, value_r0, value_r1); + LOG_TARGET_DEBUG(dpm->arm->target, "READ: %s, %8.8" PRIx32 ", %8.8" PRIx32, + r->name, value_r0, value_r1); } return retval; @@ -237,10 +236,10 @@ int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) break; case ARM_STATE_JAZELLE: /* core-specific ... ? */ - LOG_WARNING("Jazelle PC adjustment unknown"); + LOG_TARGET_WARNING(dpm->arm->target, "Jazelle PC adjustment unknown"); break; default: - LOG_WARNING("unknown core state"); + LOG_TARGET_WARNING(dpm->arm->target, "unknown core state"); break; } break; @@ -265,7 +264,8 @@ int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) buf_set_u32(r->value, 0, 32, value); r->valid = true; r->dirty = false; - LOG_DEBUG("READ: %s, %8.8" PRIx32, r->name, value); + LOG_TARGET_DEBUG(dpm->arm->target, "READ: %s, %8.8" PRIx32, r->name, + value); } return retval; @@ -301,7 +301,8 @@ static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned int re if (retval == ERROR_OK) { r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8" PRIx32 ", %8.8" PRIx32, r->name, value_r0, value_r1); + LOG_TARGET_DEBUG(dpm->arm->target, "WRITE: %s, %8.8" PRIx32 ", %8.8" PRIx32, + r->name, value_r0, value_r1); } return retval; @@ -349,7 +350,8 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum if (retval == ERROR_OK) { r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8" PRIx32, r->name, value); + LOG_TARGET_DEBUG(dpm->arm->target, "WRITE: %s, %8.8" PRIx32, r->name, + value); } return retval; @@ -463,9 +465,8 @@ static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, xp->address, xp->control); if (retval != ERROR_OK) - LOG_ERROR("%s: can't %s HW %spoint %d", + LOG_TARGET_ERROR(dpm->arm->target, "can't %s HW %spoint %d", disable ? "disable" : "enable", - target_name(dpm->arm->target), (xp->number < 16) ? "break" : "watch", xp->number & 0xf); done: @@ -670,7 +671,7 @@ static enum arm_mode dpm_mapmode(struct arm *arm, case ARM_VFP_V3_D0 ... ARM_VFP_V3_FPSCR: return mode; default: - LOG_WARNING("invalid register #%u", num); + LOG_TARGET_WARNING(arm->target, "invalid register #%u", num); break; } return ARM_MODE_ANY; @@ -885,7 +886,7 @@ static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp, } /* FALL THROUGH */ default: - LOG_ERROR("unsupported {break,watch}point length/alignment"); + LOG_TARGET_ERROR(dpm->arm->target, "unsupported {break,watch}point length/alignment"); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -899,7 +900,7 @@ static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp, xp->control = control; xp->dirty = true; - LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d", + LOG_TARGET_DEBUG(dpm->arm->target, "BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d", xp->address, control, xp->number); /* hardware is updated in write_dirty_registers() */ @@ -919,7 +920,7 @@ static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp) /* FIXME we need a generic solution for software breakpoints. */ if (bp->type == BKPT_SOFT) - LOG_DEBUG("using HW bkpt, not SW..."); + LOG_TARGET_DEBUG(dpm->arm->target, "using HW breakpoint instead of SW"); for (unsigned int i = 0; i < dpm->nbp; i++) { if (!dpm->dbp[i].bp) { @@ -963,7 +964,7 @@ static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned int index_t, /* this hardware doesn't support data value matching or masking */ if (wp->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) { - LOG_DEBUG("watchpoint values and masking not supported"); + LOG_TARGET_ERROR(dpm->arm->target, "watchpoint values and masking not supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1143,8 +1144,8 @@ int arm_dpm_setup(struct arm_dpm *dpm) return ERROR_FAIL; } - LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", - target_name(target), dpm->nbp, dpm->nwp); + LOG_TARGET_INFO(target, "hardware has %d breakpoints, %d watchpoints", + dpm->nbp, dpm->nwp); /* REVISIT ... and some of those breakpoints could match * execution context IDs... @@ -1172,8 +1173,7 @@ int arm_dpm_initialize(struct arm_dpm *dpm) (void) dpm->bpwp_disable(dpm, 16 + i); } } else - LOG_WARNING("%s: can't disable breakpoints and watchpoints", - target_name(dpm->arm->target)); + LOG_TARGET_WARNING(dpm->arm->target, "can't disable breakpoints and watchpoints"); return ERROR_OK; } From d008a02a74cb4edf18d99b0a6d7d1a698ccc4890 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 20 Jun 2025 10:53:09 +0200 Subject: [PATCH 1294/1312] target/armv7a: Hide multiprocessing support message Print a debug message about missing multiprocessing support rather than an error message. Change-Id: Ia1581f7284747d8a92096d6f5515f891c8069f71 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8965 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv7a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 4d353dec65..651241b772 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -263,7 +263,7 @@ static int armv7a_read_mpidr(struct target *target) armv7a->multi_threading_processor == 1 ? "SMT" : "no SMT"); } else - LOG_ERROR("MPIDR not in multiprocessor format"); + LOG_DEBUG("MPIDR not in multiprocessor format"); done: dpm->finish(dpm); From 7fa8a5c257dcf3dbf072103f69959448e57dfa2c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 20 Jun 2025 10:30:03 +0200 Subject: [PATCH 1295/1312] target/armv7a: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() to indicate which target the message belongs to. Change-Id: Ic40c61a779c1a1ebdc96ebc56b27541fff5e6205 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8966 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv7a.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 651241b772..2bbafd420f 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -68,9 +68,9 @@ static void armv7a_show_fault_registers(struct target *target) if (retval != ERROR_OK) goto done; - LOG_USER("Data fault registers DFSR: %8.8" PRIx32 + LOG_TARGET_USER(target, "Data fault registers DFSR: %8.8" PRIx32 ", DFAR: %8.8" PRIx32, dfsr, dfar); - LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32 + LOG_TARGET_USER(target, "Instruction fault registers IFSR: %8.8" PRIx32 ", IFAR: %8.8" PRIx32, ifsr, ifar); done: @@ -134,7 +134,7 @@ int armv7a_read_ttbcr(struct target *target) if (retval != ERROR_OK) goto done; - LOG_DEBUG("ttbcr %" PRIx32, ttbcr); + LOG_TARGET_DEBUG(target, "ttbcr %" PRIx32, ttbcr); ttbcr_n = ttbcr & 0x7; armv7a->armv7a_mmu.ttbcr = ttbcr; @@ -169,7 +169,7 @@ int armv7a_read_ttbcr(struct target *target) armv7a->armv7a_mmu.ttbr_mask[0] = 7 << (32 - ttbcr_n); } - LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32, + LOG_TARGET_DEBUG(target, "ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32, (ttbcr_n != 0) ? "used" : "not used", armv7a->armv7a_mmu.ttbr_mask[0], armv7a->armv7a_mmu.ttbr_mask[1]); @@ -248,14 +248,13 @@ static int armv7a_read_mpidr(struct target *target) /* Is register in Multiprocessing Extensions register format? */ if (mpidr & MPIDR_MP_EXT) { - LOG_DEBUG("%s: MPIDR 0x%" PRIx32, target_name(target), mpidr); + LOG_TARGET_DEBUG(target, "%s: MPIDR 0x%" PRIx32, target_name(target), mpidr); armv7a->multi_processor_system = (mpidr >> 30) & 1; armv7a->multi_threading_processor = (mpidr >> 24) & 1; armv7a->level2_id = (mpidr >> 16) & 0xf; armv7a->cluster_id = (mpidr >> 8) & 0xf; armv7a->cpu_id = mpidr & 0xf; - LOG_INFO("%s: MPIDR level2 %x, cluster %x, core %x, %s, %s", - target_name(target), + LOG_TARGET_INFO(target, "MPIDR level2 %x, cluster %x, core %x, %s, %s", armv7a->level2_id, armv7a->cluster_id, armv7a->cpu_id, @@ -263,7 +262,7 @@ static int armv7a_read_mpidr(struct target *target) armv7a->multi_threading_processor == 1 ? "SMT" : "no SMT"); } else - LOG_DEBUG("MPIDR not in multiprocessor format"); + LOG_TARGET_DEBUG(target, "MPIDR not in multiprocessor format"); done: dpm->finish(dpm); @@ -338,7 +337,7 @@ int armv7a_identify_cache(struct target *target) cache->iminline = 4UL << (ctr & 0xf); cache->dminline = 4UL << ((ctr & 0xf0000) >> 16); - LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRIu32 " ctr.dminline %" PRIu32, + LOG_TARGET_DEBUG(target, "ctr %" PRIx32 " ctr.iminline %" PRIu32 " ctr.dminline %" PRIu32, ctr, cache->iminline, cache->dminline); /* retrieve CLIDR @@ -350,7 +349,7 @@ int armv7a_identify_cache(struct target *target) goto done; cache->loc = (clidr & 0x7000000) >> 24; - LOG_DEBUG("Number of cache levels to PoC %" PRId32, cache->loc); + LOG_TARGET_DEBUG(target, "Number of cache levels to PoC %" PRId32, cache->loc); /* retrieve selected cache for later restore * MRC p15, 2,, c0, c0, 0; Read CSSELR */ @@ -378,13 +377,13 @@ int armv7a_identify_cache(struct target *target) goto done; cache->arch[cl].d_u_size = decode_cache_reg(cache_reg); - LOG_DEBUG("data/unified cache index %" PRIu32 " << %" PRIu32 ", way %" PRIu32 " << %" PRIu32, + LOG_TARGET_DEBUG(target, "data/unified cache index %" PRIu32 " << %" PRIu32 ", way %" PRIu32 " << %" PRIu32, cache->arch[cl].d_u_size.index, cache->arch[cl].d_u_size.index_shift, cache->arch[cl].d_u_size.way, cache->arch[cl].d_u_size.way_shift); - LOG_DEBUG("cacheline %" PRIu32 " bytes %" PRIu32 " KBytes asso %" PRIu32 " ways", + LOG_TARGET_DEBUG(target, "cacheline %" PRIu32 " bytes %" PRIu32 " KBytes asso %" PRIu32 " ways", cache->arch[cl].d_u_size.linelen, cache->arch[cl].d_u_size.cachesize, cache->arch[cl].d_u_size.associativity); @@ -398,13 +397,13 @@ int armv7a_identify_cache(struct target *target) goto done; cache->arch[cl].i_size = decode_cache_reg(cache_reg); - LOG_DEBUG("instruction cache index %" PRIu32 " << %" PRIu32 ", way %" PRIu32 " << %" PRIu32, + LOG_TARGET_DEBUG(target, "instruction cache index %" PRIu32 " << %" PRIu32 ", way %" PRIu32 " << %" PRIu32, cache->arch[cl].i_size.index, cache->arch[cl].i_size.index_shift, cache->arch[cl].i_size.way, cache->arch[cl].i_size.way_shift); - LOG_DEBUG("cacheline %" PRIu32 " bytes %" PRIu32 " KBytes asso %" PRIu32 " ways", + LOG_TARGET_DEBUG(target, "cacheline %" PRIu32 " bytes %" PRIu32 " KBytes asso %" PRIu32 " ways", cache->arch[cl].i_size.linelen, cache->arch[cl].i_size.cachesize, cache->arch[cl].i_size.associativity); @@ -445,7 +444,7 @@ static int armv7a_setup_semihosting(struct target *target, int enable) armv7a->debug_base + CPUDBG_VCR, &vcr); if (ret < 0) { - LOG_ERROR("Failed to read VCR register\n"); + LOG_TARGET_ERROR(target, "Failed to read VCR register"); return ret; } @@ -458,7 +457,7 @@ static int armv7a_setup_semihosting(struct target *target, int enable) armv7a->debug_base + CPUDBG_VCR, vcr); if (ret < 0) - LOG_ERROR("Failed to write VCR register\n"); + LOG_TARGET_ERROR(target, "Failed to write VCR register"); return ret; } @@ -489,18 +488,18 @@ int armv7a_arch_state(struct target *target) struct arm *arm = &armv7a->arm; if (armv7a->common_magic != ARMV7_COMMON_MAGIC) { - LOG_ERROR("BUG: called for a non-ARMv7A target"); + LOG_TARGET_ERROR(target, "BUG: called for a non-ARMv7A target"); return ERROR_COMMAND_SYNTAX_ERROR; } arm_arch_state(target); if (armv7a->is_armv7r) { - LOG_USER("D-Cache: %s, I-Cache: %s", + LOG_TARGET_USER(target, "D-Cache: %s, I-Cache: %s", state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]); } else { - LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", + LOG_TARGET_USER(target, "MMU: %s, D-Cache: %s, I-Cache: %s", state[armv7a->armv7a_mmu.mmu_enabled], state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]); From 56c24b9eb22c690f62fc173fe2fbd649070ae3d6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 20 Jun 2025 10:44:21 +0200 Subject: [PATCH 1296/1312] target/armv4: Use LOG_TARGET_xxx() Use LOG_TARGET_xxx() for log messages as it is used for other targets. While at it, rework the log messages. For example by removing spaces or punctuation marks at the end of the message. Change-Id: I295001876d40527ec8f35c2aec8d562a29e57b26 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8967 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv4_5.c | 59 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 597dc8990c..22cdba8ced 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -437,7 +437,7 @@ const int armv4_5_core_reg_map[9][17] = { static const char *arm_core_state_string(struct arm *arm) { if (arm->core_state > ARRAY_SIZE(arm_state_strings)) { - LOG_ERROR("core_state exceeds table size"); + LOG_TARGET_ERROR(arm->target, "core_state exceeds table size"); return "Unknown"; } @@ -483,20 +483,20 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) if (cpsr & (1 << 5)) { /* T */ if (cpsr & (1 << 24)) { /* J */ - LOG_WARNING("ThumbEE -- incomplete support"); + LOG_TARGET_WARNING(arm->target, "ThumbEE -- incomplete support"); state = ARM_STATE_THUMB_EE; } else state = ARM_STATE_THUMB; } else { if (cpsr & (1 << 24)) { /* J */ - LOG_ERROR("Jazelle state handling is BROKEN!"); + LOG_TARGET_ERROR(arm->target, "Jazelle state handling is broken"); state = ARM_STATE_JAZELLE; } else state = ARM_STATE_ARM; } arm->core_state = state; - LOG_DEBUG("set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, + LOG_TARGET_DEBUG(arm->target, "set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, arm_mode_name(mode), arm_core_state_string(arm)); } @@ -521,7 +521,7 @@ struct reg *arm_reg_current(struct arm *arm, unsigned int regnum) return NULL; if (!arm->map) { - LOG_ERROR("Register map is not available yet, the target is not fully initialised"); + LOG_TARGET_ERROR(arm->target, "Register map is not available yet, the target is not fully initialised"); r = arm->core_cache->reg_list + regnum; } else r = arm->core_cache->reg_list + arm->map[regnum]; @@ -530,7 +530,7 @@ struct reg *arm_reg_current(struct arm *arm, unsigned int regnum) * that doesn't support it... */ if (!r) { - LOG_ERROR("Invalid CPSR mode"); + LOG_TARGET_ERROR(arm->target, "Invalid CPSR mode"); r = arm->core_cache->reg_list + regnum; } @@ -631,7 +631,7 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) */ if (armv4_5_target->core_mode != (enum arm_mode)(value & 0x1f)) { - LOG_DEBUG("changing ARM core mode to '%s'", + LOG_TARGET_DEBUG(target, "changing ARM core mode to '%s'", arm_mode_name(value & 0x1f)); value &= ~((1 << 24) | (1 << 5)); uint8_t t[4]; @@ -798,7 +798,7 @@ int arm_arch_state(struct target *target) struct arm *arm = target_to_arm(target); if (arm->common_magic != ARM_COMMON_MAGIC) { - LOG_ERROR("BUG: called for a non-ARM target"); + LOG_TARGET_ERROR(target, "BUG: called for a non-ARM target"); return ERROR_FAIL; } @@ -806,7 +806,7 @@ int arm_arch_state(struct target *target) if (target->semihosting && target->semihosting->hit_fileio) return ERROR_OK; - LOG_USER("target halted in %s state due to %s, current mode: %s\n" + LOG_TARGET_USER(target, "target halted in %s state due to %s, current mode: %s\n" "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s%s", arm_core_state_string(arm), debug_reason_name(target), @@ -1291,7 +1291,7 @@ int arm_get_gdb_reg_list(struct target *target, unsigned int i; if (!is_arm_mode(arm->core_mode)) { - LOG_ERROR("not a valid arm core mode - communication failure?"); + LOG_TARGET_ERROR(target, "not a valid arm core mode - communication failure?"); return ERROR_FAIL; } @@ -1362,7 +1362,7 @@ int arm_get_gdb_reg_list(struct target *target, return ERROR_OK; default: - LOG_ERROR("not a valid register class type in query."); + LOG_TARGET_ERROR(target, "not a valid register class type in query"); return ERROR_FAIL; } } @@ -1391,8 +1391,7 @@ static int armv4_5_run_algorithm_completion(struct target *target, /* fast exit: ARMv5+ code can use BKPT */ if (exit_point && buf_get_u32(arm->pc->value, 0, 32) != exit_point) { - LOG_WARNING( - "target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "", + LOG_TARGET_ERROR(target, "reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); return ERROR_TARGET_TIMEOUT; } @@ -1417,10 +1416,10 @@ int armv4_5_run_algorithm_inner(struct target *target, int i; int retval = ERROR_OK; - LOG_DEBUG("Running algorithm"); + LOG_TARGET_DEBUG(target, "Running algorithm"); if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC) { - LOG_ERROR("current target isn't an ARMV4/5 target"); + LOG_TARGET_ERROR(target, "current target isn't an ARMV4/5 target"); return ERROR_TARGET_INVALID; } @@ -1430,13 +1429,13 @@ int armv4_5_run_algorithm_inner(struct target *target, } if (!is_arm_mode(arm->core_mode)) { - LOG_ERROR("not a valid arm core mode - communication failure?"); + LOG_TARGET_ERROR(target, "not a valid arm core mode - communication failure?"); return ERROR_FAIL; } /* armv5 and later can terminate with BKPT instruction; less overhead */ if (!exit_point && arm->arch == ARM_ARCH_V4) { - LOG_ERROR("ARMv4 target needs HW breakpoint location"); + LOG_TARGET_ERROR(target, "ARMv4 target needs HW breakpoint location"); return ERROR_FAIL; } @@ -1470,12 +1469,12 @@ int armv4_5_run_algorithm_inner(struct target *target, struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, false); if (!reg) { - LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + LOG_TARGET_ERROR(target, "BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { - LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", + LOG_TARGET_ERROR(target, "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1491,12 +1490,12 @@ int armv4_5_run_algorithm_inner(struct target *target, else if (arm->core_state == ARM_STATE_THUMB) exit_breakpoint_size = 2; else { - LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state"); + LOG_TARGET_ERROR(target, "BUG: can't execute algorithms when not in ARM or Thumb state"); return ERROR_COMMAND_SYNTAX_ERROR; } if (arm_algorithm_info->core_mode != ARM_MODE_ANY) { - LOG_DEBUG("setting core_mode: 0x%2.2x", + LOG_TARGET_DEBUG(target, "setting core_mode: 0x%2.2x", arm_algorithm_info->core_mode); buf_set_u32(arm->cpsr->value, 0, 5, arm_algorithm_info->core_mode); @@ -1509,7 +1508,7 @@ int armv4_5_run_algorithm_inner(struct target *target, retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD); if (retval != ERROR_OK) { - LOG_ERROR("can't add HW breakpoint to terminate algorithm"); + LOG_TARGET_ERROR(target, "can't add HW breakpoint to terminate algorithm"); return ERROR_TARGET_FAILURE; } } @@ -1542,13 +1541,13 @@ int armv4_5_run_algorithm_inner(struct target *target, reg_params[i].reg_name, false); if (!reg) { - LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + LOG_TARGET_ERROR(target, "BUG: register '%s' not found", reg_params[i].reg_name); retval = ERROR_COMMAND_SYNTAX_ERROR; continue; } if (reg->size != reg_params[i].size) { - LOG_ERROR( + LOG_TARGET_ERROR(target, "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); retval = ERROR_COMMAND_SYNTAX_ERROR; @@ -1667,7 +1666,7 @@ int arm_checksum_memory(struct target *target, if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); else - LOG_ERROR("error executing ARM crc algorithm"); + LOG_TARGET_ERROR(target, "error executing ARM CRC algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -1702,7 +1701,7 @@ int arm_blank_check_memory(struct target *target, assert(sizeof(check_code_le) % 4 == 0); if (erased_value != 0xff) { - LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for ARMv4/v5 targets", + LOG_TARGET_ERROR(target, "Erase value 0x%02" PRIx8 " not yet supported for ARMv4/v5 targets", erased_value); return ERROR_FAIL; } @@ -1781,7 +1780,7 @@ static int arm_default_mrc(struct target *target, int cpnum, uint32_t crn, uint32_t crm, uint32_t *value) { - LOG_ERROR("%s doesn't implement MRC", target_type_name(target)); + LOG_TARGET_ERROR(target, "%s doesn't implement MRC", target_type_name(target)); return ERROR_FAIL; } @@ -1789,7 +1788,7 @@ static int arm_default_mrrc(struct target *target, int cpnum, uint32_t op, uint32_t crm, uint64_t *value) { - LOG_ERROR("%s doesn't implement MRRC", target_type_name(target)); + LOG_TARGET_ERROR(target, "%s doesn't implement MRRC", target_type_name(target)); return ERROR_FAIL; } @@ -1798,7 +1797,7 @@ static int arm_default_mcr(struct target *target, int cpnum, uint32_t crn, uint32_t crm, uint32_t value) { - LOG_ERROR("%s doesn't implement MCR", target_type_name(target)); + LOG_TARGET_ERROR(target, "%s doesn't implement MCR", target_type_name(target)); return ERROR_FAIL; } @@ -1806,7 +1805,7 @@ static int arm_default_mcrr(struct target *target, int cpnum, uint32_t op, uint32_t crm, uint64_t value) { - LOG_ERROR("%s doesn't implement MCRR", target_type_name(target)); + LOG_TARGET_ERROR(target, "%s doesn't implement MCRR", target_type_name(target)); return ERROR_FAIL; } From c6f18633522e8cbc80e2abb5cf5e87da13440b92 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 20 Jun 2025 10:47:23 +0200 Subject: [PATCH 1297/1312] target/armv4: Use command_print() instead of LOG_ERROR() Use command_print() in order to provide an error message to the caller. Change-Id: I9f1a2ef07a102e1d6e755f3680bed0f7183b5c9c Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8968 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv4_5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 22cdba8ced..d907615691 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -842,7 +842,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) } if (!is_arm_mode(arm->core_mode)) { - LOG_ERROR("not a valid arm core mode - communication failure?"); + command_print(CMD, "not a valid arm core mode - communication failure?"); return ERROR_FAIL; } @@ -954,7 +954,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) struct target *target = get_current_target(CMD_CTX); if (!target) { - LOG_ERROR("No target selected"); + command_print(CMD, "No target selected"); return ERROR_FAIL; } From 8194fc48bd3f06071a9068e385a122499447340a Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 20 Jun 2025 11:18:03 +0200 Subject: [PATCH 1298/1312] tcl/board: Add config for TMS570LS12x development kit Tested on the corresponding hardware. Change-Id: Ic98141c450bb981cc7853c93b38195c7930bc7d3 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/8969 Tested-by: jenkins Reviewed-by: Antonio Borneo --- tcl/board/ti/launchxl2-tms57012.cfg | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tcl/board/ti/launchxl2-tms57012.cfg diff --git a/tcl/board/ti/launchxl2-tms57012.cfg b/tcl/board/ti/launchxl2-tms57012.cfg new file mode 100644 index 0000000000..99cb26e204 --- /dev/null +++ b/tcl/board/ti/launchxl2-tms57012.cfg @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Hercules TMS570LS12x LaunchPad Development Kit +# https://www.ti.com/tool/LAUNCHXL2-TMS57012 + +source [find interface/xds110.cfg] + +transport select jtag + +source [find target/ti_tms570ls1x.cfg] From 6631419beba62893075eae5e1e13ddba9062d4f5 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 11 Dec 2024 09:34:57 +0100 Subject: [PATCH 1299/1312] jtag: drivers: xlnx-pcie-xvc: use correct TMS polarity during pathmove The xlnx_pcie_xvc_execute_pathmove() function checks whether TMS should be high or low for transitioning from the current state to the next state, but then calls xlnx_pcie_xvc_transact() with the opposite level, leading to invalid state transitions. Fix the polarity of TMS in the calls to xlnx_pcie_xvc_transact() to match the required TMS level. Change-Id: I2383e41fb70063e26aa69fabcf728df597607934 Signed-off-by: Henrik Brix Andersen Reviewed-on: https://review.openocd.org/c/openocd/+/8613 Reviewed-by: Moritz Fischer Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Nicolas Derumigny --- src/jtag/drivers/xlnx-pcie-xvc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index 3baa183d95..5208e2b871 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -210,9 +210,9 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) { - err = xlnx_pcie_xvc_transact(1, 1, 0, NULL); - } else if (path[i] == tap_state_transition(tap_get_state(), true)) { err = xlnx_pcie_xvc_transact(1, 0, 0, NULL); + } else if (path[i] == tap_state_transition(tap_get_state(), true)) { + err = xlnx_pcie_xvc_transact(1, 1, 0, NULL); } else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.", tap_state_name(tap_get_state()), From 13b74c3fc7718d3ac639d6c382b2a4e3ec70a6d1 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 21 Jun 2025 12:11:24 +0200 Subject: [PATCH 1300/1312] helper: types: fix proper return type in example of ARRAY_SIZE() The example in the comment above the declaration of the macro ARRAY_SIZE() assigns the value to a variable of type 'unsigned' that is not allowed by the coding style (should be 'unsigned int') and is not correct since the macro uses 'sizeof()' and the type returned is 'size_t'. Fix the comment. Change-Id: I18c32b5328a229ab74b56dafab46a064ce5d23c5 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8970 Reviewed-by: zapb Tested-by: jenkins --- src/helper/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/types.h b/src/helper/types.h index 53249e5b79..b3edd21184 100644 --- a/src/helper/types.h +++ b/src/helper/types.h @@ -51,7 +51,7 @@ * Compute the number of elements of a variable length array. * * const char *strs[] = { "a", "b", "c" }; - * unsigned num_strs = ARRAY_SIZE(strs); + * size_t num_strs = ARRAY_SIZE(strs); * */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) From ce3bf664c81569b2eb457f676814eade9d464141 Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 21 Jun 2025 22:05:17 +0200 Subject: [PATCH 1301/1312] configure.ac: rename M4 macro 'adapter' to prevent accidental conflicts Also remove a comment about such a conflict which had been already noticed. Change-Id: I6f301ccbd1261ea1c15c44a02d3f34f0cf5cb9f4 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8972 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 4b94716299..5a05f3171c 100644 --- a/configure.ac +++ b/configure.ac @@ -206,8 +206,6 @@ m4_define([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS], [[imx_gpio], [Bitbanging on NXP IMX processors], [IMX_GPIO]], [[am335xgpio], [Bitbanging on AM335x (as found in Beaglebones)], [AM335XGPIO]]]) -# The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter -# because there is an M4 macro called 'adapter'. m4_define([DUMMY_ADAPTER], [[[dummy], [Dummy Adapter], [DUMMY]]]) @@ -309,15 +307,15 @@ AC_ARG_ENABLE([dmem], [build_dmem=$enableval], [build_dmem=no]) m4_define([AC_ARG_ADAPTERS], [ - m4_foreach([adapter], [$1], - [AC_ARG_ENABLE(ADAPTER_OPT([adapter]), - AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])[[[=yes/no/auto]]]], - [Enable building support for the ]ADAPTER_DESC([adapter])[ (default is $2)]), + m4_foreach([adapterTuple], [$1], + [AC_ARG_ENABLE(ADAPTER_OPT([adapterTuple]), + AS_HELP_STRING([--enable-ADAPTER_OPT([adapterTuple])[[[=yes/no/auto]]]], + [Enable building support for the ]ADAPTER_DESC([adapterTuple])[ (default is $2)]), [case "${enableval}" in yes|no|auto) ;; - *) AC_MSG_ERROR([Option --enable-ADAPTER_OPT([adapter]) has invalid value "${enableval}".]) ;; + *) AC_MSG_ERROR([Option --enable-ADAPTER_OPT([adapterTuple]) has invalid value "${enableval}".]) ;; esac], - [ADAPTER_VAR([adapter])=$2]) + [ADAPTER_VAR([adapterTuple])=$2]) ]) ]) @@ -622,21 +620,23 @@ PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], # Arg $3: What prerequisites are missing, to be shown in an error message # if an adapter was requested but cannot be enabled. m4_define([PROCESS_ADAPTERS], [ - m4_foreach([adapter], [$1], [ + m4_foreach([adapterTuple], [$1], [ AS_IF([test $2], [ - AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [ - AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).) + AS_IF([test "x$ADAPTER_VAR([adapterTuple])" != "xno"], [ + AC_DEFINE([BUILD_]ADAPTER_SYM([adapterTuple]), [1], + [1 if you want the ]ADAPTER_DESC([adapterTuple]).) ], [ - AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).) + AC_DEFINE([BUILD_]ADAPTER_SYM([adapterTuple]), [0], + [0 if you do not want the ]ADAPTER_DESC([adapterTuple]).) ]) ], [ - AS_IF([test "x$ADAPTER_VAR([adapter])" = "xyes"], [ - AC_MSG_ERROR([$3 is required for [adapter] "ADAPTER_DESC([adapter])".]) + AS_IF([test "x$ADAPTER_VAR([adapterTuple])" = "xyes"], [ + AC_MSG_ERROR([$3 is required for [adapterTuple] "ADAPTER_DESC([adapterTuple])".]) ]) - ADAPTER_VAR([adapter])=no - AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).) + ADAPTER_VAR([adapterTuple])=no + AC_DEFINE([BUILD_]ADAPTER_SYM([adapterTuple]), [0], [0 if you do not want the ]ADAPTER_DESC([adapterTuple]).) ]) - AM_CONDITIONAL(ADAPTER_SYM([adapter]), [test "x$ADAPTER_VAR([adapter])" != "xno"]) + AM_CONDITIONAL(ADAPTER_SYM([adapterTuple]), [test "x$ADAPTER_VAR([adapterTuple])" != "xno"]) ]) ]) @@ -839,7 +839,7 @@ echo echo echo OpenOCD configuration summary echo --------------------------------------------------- -m4_foreach([adapter], [USB1_ADAPTERS, +m4_foreach([adapterTuple], [USB1_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, @@ -857,8 +857,8 @@ m4_foreach([adapter], [USB1_ADAPTERS, DUMMY_ADAPTER, OPTIONAL_LIBRARIES, COVERAGE], - [s=m4_format(["%-49s"], ADAPTER_DESC([adapter])) - AS_CASE([$ADAPTER_VAR([adapter])], + [s=m4_format(["%-49s"], ADAPTER_DESC([adapterTuple])) + AS_CASE([$ADAPTER_VAR([adapterTuple])], [auto], [ echo "$s"yes '(auto)' ], @@ -870,8 +870,8 @@ m4_foreach([adapter], [USB1_ADAPTERS, ], [ AC_MSG_ERROR(m4_normalize([ - Error in [adapter] "ADAPTER_ARG([adapter])": Variable "ADAPTER_VAR([adapter])" - has invalid value "$ADAPTER_VAR([adapter])".])) + Error in [adapterTuple] "ADAPTER_ARG([adapterTuple])": Variable "ADAPTER_VAR([adapterTuple])" + has invalid value "$ADAPTER_VAR([adapterTuple])".])) ]) ]) echo From f547e55076e847889387904c6a0803e742aeb36d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 17 Jun 2025 16:23:12 +0200 Subject: [PATCH 1302/1312] target/cortex_m: introduce security manipulation routines Running target algorithms on ARMv8M may require core in secure mode with SAU and MPU off (as set after reset). cortex_m_set_secure() forces this mode with optional save of the previous state. cortex_m_security_restore() restores previously saved state. Change-Id: Ia71826db47ee7b0557eaffd55244ce13eacbcb4b Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8959 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 106 ++++++++++++++++++++++++++++++++++++++++++ src/target/cortex_m.h | 27 +++++++++++ 2 files changed, 133 insertions(+) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 8eaf70f60a..0501a5b2f5 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2563,6 +2563,112 @@ static bool cortex_m_has_tz(struct target *target) return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0; } +int cortex_m_set_secure(struct target *target, struct cortex_m_saved_security *ssec) +{ + if (ssec) { + ssec->dscsr_dirty = false; + ssec->sau_ctrl_dirty = false; + ssec->mpu_ctrl_dirty = false; + } + + if (!cortex_m_has_tz(target)) + return ERROR_OK; + + uint32_t dscsr; + int retval = target_read_u32(target, DCB_DSCSR, &dscsr); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: DSCSR read failed"); + return retval; + } + if (!(dscsr & DSCSR_CDS)) { + if (ssec) { + ssec->dscsr_dirty = true; + ssec->dscsr = dscsr; + } + LOG_TARGET_DEBUG(target, "Setting Current Domain Secure in DSCSR"); + retval = target_write_u32(target, DCB_DSCSR, DSCSR_CDS); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: DSCSR write failed"); + return retval; + } + } + + uint32_t sau_ctrl; + retval = target_read_u32(target, SAU_CTRL, &sau_ctrl); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: SAU_CTRL read failed"); + return retval; + } + if (sau_ctrl & SAU_CTRL_ENABLE) { + if (ssec) { + ssec->sau_ctrl_dirty = true; + ssec->sau_ctrl = sau_ctrl; + } + retval = target_write_u32(target, SAU_CTRL, sau_ctrl & ~SAU_CTRL_ENABLE); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: SAU_CTRL write failed"); + return retval; + } + } + + uint32_t mpu_ctrl; + retval = target_read_u32(target, MPU_CTRL, &mpu_ctrl); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: MPU_CTRL read failed"); + return retval; + } + if (mpu_ctrl & MPU_CTRL_ENABLE) { + if (ssec) { + ssec->mpu_ctrl_dirty = true; + ssec->mpu_ctrl = mpu_ctrl; + } + retval = target_write_u32(target, MPU_CTRL, mpu_ctrl & ~MPU_CTRL_ENABLE); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: MPU_CTRL write failed"); + return retval; + } + } + return ERROR_OK; +} + +int cortex_m_security_restore(struct target *target, struct cortex_m_saved_security *ssec) +{ + int retval; + if (!cortex_m_has_tz(target)) + return ERROR_OK; + + if (!ssec) + return ERROR_OK; + + if (ssec->mpu_ctrl_dirty) { + retval = target_write_u32(target, MPU_CTRL, ssec->mpu_ctrl); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M security restore: MPU_CTRL write failed"); + return retval; + } + ssec->mpu_ctrl_dirty = false; + } + + if (ssec->sau_ctrl_dirty) { + retval = target_write_u32(target, SAU_CTRL, ssec->sau_ctrl); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M security restore: SAU_CTRL write failed"); + return retval; + } + ssec->sau_ctrl_dirty = false; + } + + if (ssec->dscsr_dirty) { + LOG_TARGET_DEBUG(target, "Restoring Current Domain Security in DSCSR"); + retval = target_write_u32(target, DCB_DSCSR, ssec->dscsr & ~DSCSR_CDSKEY); + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "ARMv8M set secure: DSCSR write failed"); + return retval; + } + ssec->dscsr_dirty = false; + } + return ERROR_OK; +} #define MVFR0 0xE000EF40 #define MVFR0_SP_MASK 0x000000F0 diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 144f24560c..82b2c1ecde 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -167,6 +167,8 @@ struct cortex_m_part_info { #define NVIC_DFSR 0xE000ED30 #define NVIC_MMFAR 0xE000ED34 #define NVIC_BFAR 0xE000ED38 +#define MPU_CTRL 0xE000ED94 +#define SAU_CTRL 0xE000EDD0 #define NVIC_SFSR 0xE000EDE4 #define NVIC_SFAR 0xE000EDE8 @@ -184,6 +186,9 @@ struct cortex_m_part_info { #define DFSR_VCATCH 8 #define DFSR_EXTERNAL 16 +#define MPU_CTRL_ENABLE BIT(0) +#define SAU_CTRL_ENABLE BIT(0) + #define FPCR_CODE 0 #define FPCR_LITERAL 1 #define FPCR_REPLACE_REMAP (0ul << 30) @@ -264,6 +269,15 @@ struct cortex_m_common { bool incorrect_halt_erratum; }; +struct cortex_m_saved_security { + bool dscsr_dirty; + uint32_t dscsr; + bool sau_ctrl_dirty; + uint32_t sau_ctrl; + bool mpu_ctrl_dirty; + uint32_t mpu_ctrl; +}; + static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m) { return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC; @@ -341,4 +355,17 @@ void cortex_m_deinit_target(struct target *target); int cortex_m_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); +/** + * Forces Cortex-M core to the basic secure context with SAU and MPU off + * @param ssec pointer to save previous security state or NULL + * @returns error code or ERROR_OK if secure mode was set or is not applicable + * (not ARMv8M with security extension) + */ +int cortex_m_set_secure(struct target *target, struct cortex_m_saved_security *ssec); + +/** + * Restores saved security context to MPU_CTRL, SAU_CTRL and DSCSR + */ +int cortex_m_security_restore(struct target *target, struct cortex_m_saved_security *ssec); + #endif /* OPENOCD_TARGET_CORTEX_M_H */ From c4fb64e76c526799fc43f72fe2cdd4606c8b9b52 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 18 Jun 2025 09:44:03 +0200 Subject: [PATCH 1303/1312] flash/nor/rp2xxx: save security state over target algo RP2040 and RP2350 flash driver runs a ROM API target algorithm in probe to setup QSPI command interface. The Cortex-M33 core of RP2350 has to be in secure mode with SAU and MPU switched off to ensure ROM API call working properly. Especially after the flash probe (used in gdb-attach event) we need to completely restore the original security state to allow 'resume' or gdb 'continue' without injecting strange errors to application code. Use cortex_m support to set secure mode and to restore it back. Fixes: commit ea775d49fc71 ("flash/nor/rp2040: add RP2350 support") Change-Id: I72096bfecbb45a8aa4d3a7a37ad140532b3b00b2 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8960 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/rp2xxx.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index 85c5911041..fa13ec527f 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -209,6 +209,8 @@ struct rp2xxx_flash_bank { bool size_override; struct flash_device spi_dev; /* detected model of SPI flash */ unsigned int sfdp_dummy, sfdp_dummy_detect; + + struct cortex_m_saved_security saved_security; }; #ifndef LOG_ROM_SYMBOL_DEBUG @@ -630,23 +632,12 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank // run in the Secure state, so flip the state now before attempting to // execute any code on the core. int retval; - uint32_t dscsr; - retval = target_read_u32(target, DCB_DSCSR, &dscsr); + retval = cortex_m_set_secure(target, &priv->saved_security); if (retval != ERROR_OK) { - LOG_ERROR("RP2350 init ARM core: DSCSR read failed"); + LOG_ERROR("RP2350 init ARM core: set secure mode failed"); return retval; } - LOG_DEBUG("DSCSR: 0x%08" PRIx32, dscsr); - if (!(dscsr & DSCSR_CDS)) { - LOG_DEBUG("Setting Current Domain Secure in DSCSR"); - retval = target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS); - if (retval != ERROR_OK) { - LOG_ERROR("RP2350 init ARM core: DSCSR read failed"); - return retval; - } - } - if (!priv->stack) { LOG_ERROR("No stack for flash programming code"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -840,6 +831,15 @@ static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2xxx_fla driver state. Best to clean up our allocations manually after completing each flash call, so we know to make fresh ones next time. */ LOG_DEBUG("Cleaning up after flash operations"); + + if (IS_RP2350(priv->id)) { + /* TODO: restore ACCESSCTRL */ + if (is_arm(target_to_arm(target))) { + int retval = cortex_m_security_restore(target, &priv->saved_security); + if (retval != ERROR_OK) + LOG_WARNING("RP2xxx: security state was not restored properly. Debug 'resume' will probably fail, use 'reset' instead"); + } + } if (priv->stack) { target_free_working_area(target, priv->stack); priv->stack = 0; From f9077f302658eaf5d114d3f84f838a45481af0ac Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 18 Jun 2025 12:01:08 +0200 Subject: [PATCH 1304/1312] flash/nor/rp2xxx: save ACCESSCTRL over ROM API calls Especially after the flash probe (used in gdb-attach event) we need to completely restore the original security state to allow 'resume' or gdb 'continue' without injecting strange errors to application code. Save all ACCESSCTRL registers potentially changed by triggering CFGRESET. Restore them at cleanup. Fixes: commit ea775d49fc71 ("flash/nor/rp2040: add RP2350 support") Change-Id: I964886d5b1d0269497c343811ee4dcd5c31953db Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8961 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/flash/nor/rp2xxx.c | 66 +++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c index fa13ec527f..30c6e99141 100644 --- a/src/flash/nor/rp2xxx.c +++ b/src/flash/nor/rp2xxx.c @@ -41,10 +41,18 @@ #define BOOTROM_STATE_RESET_OTHER_CORE 0x02 #define BOOTROM_STATE_RESET_GLOBAL_STATE 0x04 -#define ACCESSCTRL_LOCK_OFFSET 0x40060000u -#define ACCESSCTRL_LOCK_DEBUG_BITS 0x00000008u -#define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u -#define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u +#define ACCESSCTRL_LOCK_OFFSET 0x40060000u +#define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u +#define ACCESSCTRL_GPIO_NSMASK0_OFFSET 0x4006000cu +#define ACCESSCTRL_GPIO_ROM_OFFSET 0x40060014u +#define ACCESSCTRL_GPIO_XIP_AUX_OFFSET 0x400600e8u + +#define ACCESSCTRL_SAVE_BASE ACCESSCTRL_GPIO_NSMASK0_OFFSET +#define ACCESSCTRL_SAVE_SIZE \ + (ACCESSCTRL_GPIO_XIP_AUX_OFFSET + 4 - ACCESSCTRL_SAVE_BASE) + +#define ACCESSCTRL_LOCK_DEBUG_BITS 0x00000008u +#define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u #define RP2040_SSI_DR0 0x18000060 #define RP2040_QSPI_CTRL 0x4001800c @@ -211,6 +219,8 @@ struct rp2xxx_flash_bank { unsigned int sfdp_dummy, sfdp_dummy_detect; struct cortex_m_saved_security saved_security; + bool accessctrl_dirty; + uint8_t saved_accessctrl[ACCESSCTRL_SAVE_SIZE]; /* in target byte order */ }; #ifndef LOG_ROM_SYMBOL_DEBUG @@ -601,8 +611,28 @@ static int rp2xxx_call_rom_func(struct target *target, struct rp2xxx_flash_bank return rp2xxx_call_rom_func_batch(target, priv, &call, 1); } -static int rp2350_init_accessctrl(struct target *target) +static int rp2350_save_accessctrl(struct target *target, struct rp2xxx_flash_bank *priv) { + return target_read_memory(target, ACCESSCTRL_SAVE_BASE, 4, ACCESSCTRL_SAVE_SIZE / 4, + priv->saved_accessctrl); +} + +static int rp2350_restore_accessctrl(struct target *target, struct rp2xxx_flash_bank *priv) +{ + // Add write passwords to all ACCESSCTRL regs from ACCESSCTRL_GPIO_ROM to the end + // (exclude not keyed ACCESSCTRL_GPIO_NSMASK0 and ACCESSCTRL_GPIO_NSMASK1 + for (unsigned int i = ACCESSCTRL_GPIO_ROM_OFFSET - ACCESSCTRL_SAVE_BASE; + i < ACCESSCTRL_SAVE_SIZE; i += 4) + target_buffer_set_u32(target, priv->saved_accessctrl + i, + target_buffer_get_u32(target, priv->saved_accessctrl + i) | ACCESSCTRL_WRITE_PASSWORD); + + return target_write_memory(target, ACCESSCTRL_SAVE_BASE, 4, ACCESSCTRL_SAVE_SIZE / 4, + priv->saved_accessctrl); +} + +static int rp2350_init_accessctrl(struct target *target, struct rp2xxx_flash_bank *priv) +{ + priv->accessctrl_dirty = false; // Attempt to reset ACCESSCTRL, in case Secure access to SRAM has been // blocked, which will stop us from loading/running algorithms such as RCP // init. (Also ROM, QMI regs are needed later) @@ -620,6 +650,13 @@ static int rp2350_init_accessctrl(struct target *target) if (accessctrl_lock_reg & ACCESSCTRL_LOCK_DEBUG_BITS) { LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail"); } else { + int retval = rp2350_save_accessctrl(target, priv); + if (retval == ERROR_OK) + priv->accessctrl_dirty = true; + // If the ACCESSCTRL backup copy is valid, mark it dirty + // as we immediately proceed to ACCESSCTRL config reset. + // Don't fail on save ACCESSCTRL error, not vital for ROM API call + LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET"); return target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u); } @@ -704,7 +741,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba } if (IS_RP2350(priv->id)) { - err = rp2350_init_accessctrl(target); + err = rp2350_init_accessctrl(target, priv); if (err != ERROR_OK) { LOG_ERROR("Failed to init ACCESSCTRL before ROM call"); return err; @@ -833,12 +870,19 @@ static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2xxx_fla LOG_DEBUG("Cleaning up after flash operations"); if (IS_RP2350(priv->id)) { - /* TODO: restore ACCESSCTRL */ - if (is_arm(target_to_arm(target))) { - int retval = cortex_m_security_restore(target, &priv->saved_security); - if (retval != ERROR_OK) - LOG_WARNING("RP2xxx: security state was not restored properly. Debug 'resume' will probably fail, use 'reset' instead"); + int retval1 = ERROR_OK; + if (priv->accessctrl_dirty) { + retval1 = rp2350_restore_accessctrl(target, priv); + priv->accessctrl_dirty = false; } + + int retval2 = ERROR_OK; + if (is_arm(target_to_arm(target))) + retval2 = cortex_m_security_restore(target, &priv->saved_security); + + if (retval1 != ERROR_OK || retval2 != ERROR_OK) + LOG_WARNING("RP2xxx: security state was not restored properly. Debug 'resume' will probably fail, use 'reset' instead"); + /* Don't fail on security restore error, not vital for flash operation */ } if (priv->stack) { target_free_working_area(target, priv->stack); From e8dca112453ae01bdfa04e1a1da8d20d5eb08d8f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 26 May 2025 07:54:05 +0200 Subject: [PATCH 1305/1312] doc: fix bp usage Commit c8926d14579528bfcead1e179baf7cb846513db4 ("cortex_a hybrid & context breakpoints") missed doc update. Add info about settig hybrid & context breakpoints to chapter 15.5 Breakpoint and Watchpoint commands Change-Id: I4a6fdc83a4c30ad8437c49796de8e6d8c6375c0c Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8934 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 494042530d..6d607d697f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9731,12 +9731,14 @@ hardware support for a handful of code breakpoints and data watchpoints. In addition, CPUs almost always support software breakpoints. -@deffn {Command} {bp} [address len [@option{hw}]] +@deffn {Command} {bp} [address [asid] len [@option{hw} | @option{hw_ctx}]] With no parameters, lists all active breakpoints. Else sets a breakpoint on code execution starting at @var{address} for @var{length} bytes. -This is a software breakpoint, unless @option{hw} is specified -in which case it will be a hardware breakpoint. +This is a software breakpoint, unless @option{hw} or @option{hw_ctx} +is specified in which case it will be a hardware, context or hybrid breakpoint. +The context and hybrid breakpoints require an additional parameter @var{asid}: +address space identifier. (@xref{arm9vectorcatch,,arm9 vector_catch}, or @pxref{xscalevectorcatch,,xscale vector_catch}, for similar mechanisms that do not consume hardware breakpoints.) From ff274122dc2fbf509b24480e97a98291db53a338 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 10 Nov 2022 10:32:23 -0800 Subject: [PATCH 1306/1312] gdb_server: Improve info message. Add target name and state to "Not running when halt was requested" message. Imported from https://github.com/riscv-collab/riscv-openocd/pull/763 Change-Id: Ic84e9a884b57caa270cfee0ca6fa6a0dd8e5d2bd Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/8916 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov Reviewed-by: Antonio Borneo --- src/server/gdb_server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index b5007d9278..3eba15070e 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3761,7 +3761,8 @@ static int gdb_input_inner(struct connection *connection) target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); gdb_con->ctrl_c = false; } else { - LOG_INFO("The target is not running when halt was requested, stopping GDB."); + LOG_TARGET_INFO(target, "Not running when halt was requested, stopping GDB. (state=%d)", + target->state); target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } } From 7f1f18399ce626e30d5176fb9740ed5fcd312c43 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 22 Jun 2025 11:03:41 +0200 Subject: [PATCH 1307/1312] jtag/drivers: dmem: fix build on Linux 32 bits On 32 bits machine both 'uintptr_t' and pointers are 32 bit. The cast (volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr) fails with error error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] in lines 100 and 109 because: - 'addr' is a 'uint64_t'; - adding 'uintptr_t' and 'uint64_t' returns a 64 bit value; - cast the 64 bit to 'uint32_t *' is an error. In the code the value passed to 'addr' is always 32 bit wide, so there is no need to pass it as 'uint64_t'. Change the type of 'addr' to 'uint32_t'. Fix also some format string to fit both 32 and 64 bits machines. Change-Id: I90ff7cd3731cb24a0fc91fe7b69c532b5c698ba0 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/8974 Reviewed-by: Nishanth Menon Tested-by: jenkins Reviewed-by: R. Diez --- src/jtag/drivers/dmem.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c index e50e84aeeb..c1eb5b80dd 100644 --- a/src/jtag/drivers/dmem.c +++ b/src/jtag/drivers/dmem.c @@ -93,14 +93,14 @@ static bool dmem_is_emulated_ap(struct adiv5_ap *ap, unsigned int *idx) return false; } -static void dmem_emu_set_ap_reg(uint64_t addr, uint32_t val) +static void dmem_emu_set_ap_reg(uint32_t addr, uint32_t val) { addr &= ~ARM_APB_PADDR31; *(volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr) = val; } -static uint32_t dmem_emu_get_ap_reg(uint64_t addr) +static uint32_t dmem_emu_get_ap_reg(uint32_t addr) { uint32_t val; @@ -113,7 +113,7 @@ static uint32_t dmem_emu_get_ap_reg(uint64_t addr) static int dmem_emu_ap_q_read(unsigned int ap_idx, unsigned int reg, uint32_t *data) { - uint64_t addr; + uint32_t addr; int ret = ERROR_OK; struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx]; @@ -164,7 +164,7 @@ static int dmem_emu_ap_q_read(unsigned int ap_idx, unsigned int reg, uint32_t *d static int dmem_emu_ap_q_write(unsigned int ap_idx, unsigned int reg, uint32_t data) { - uint64_t addr; + uint32_t addr; int ret = ERROR_OK; struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx]; @@ -519,7 +519,7 @@ static int dmem_dap_init(void) MAP_SHARED, dmem_fd, dmem_mapped_start); if (dmem_map_base == MAP_FAILED) { - LOG_ERROR("Mapping address 0x%lx for 0x%lx bytes failed!", + LOG_ERROR("Mapping address 0x%zx for 0x%zx bytes failed!", dmem_mapped_start, dmem_mapped_size); goto error_fail; } @@ -543,7 +543,7 @@ static int dmem_dap_init(void) MAP_SHARED, dmem_fd, dmem_mapped_start); if (dmem_emu_map_base == MAP_FAILED) { - LOG_ERROR("Mapping EMU address 0x%lx for 0x%lx bytes failed!", + LOG_ERROR("Mapping EMU address 0x%" PRIx64 " for 0x%" PRIx64 " bytes failed!", dmem_emu_base_address, dmem_emu_size); goto error_fail; } From 04d51723d042f87057a012086003c19144732f3d Mon Sep 17 00:00:00 2001 From: "R. Diez" Date: Sat, 21 Jun 2025 21:41:38 +0200 Subject: [PATCH 1308/1312] configure.ac: show the dmem adapter in the config summary Also enable this adapter by default (auto). Change-Id: I61597c8572115f838ab0c92021163436eb7b0d59 Signed-off-by: R. Diez Reviewed-on: https://review.openocd.org/c/openocd/+/8971 Reviewed-by: Antonio Borneo Tested-by: jenkins --- configure.ac | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 5a05f3171c..453cbcfb5a 100644 --- a/configure.ac +++ b/configure.ac @@ -165,6 +165,9 @@ m4_define([LIBFTDI_USB1_ADAPTERS], m4_define([LIBGPIOD_ADAPTERS], [[[linuxgpiod], [Linux GPIO bitbang through libgpiod], [LINUXGPIOD]]]) +m4_define([DMEM_ADAPTER], + [[[dmem], [CoreSight Direct Memory], [DMEM]]]) + m4_define([SYSFSGPIO_ADAPTER], [[[sysfsgpio], [Linux GPIO bitbang through sysfs], [SYSFSGPIO]]]) @@ -302,10 +305,6 @@ AS_IF([test "x$debug_malloc" = "xyes" -a "x$have_glibc" = "xyes"], [ AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging]) ]) -AC_ARG_ENABLE([dmem], - AS_HELP_STRING([--enable-dmem], [Enable building the dmem driver]), - [build_dmem=$enableval], [build_dmem=no]) - m4_define([AC_ARG_ADAPTERS], [ m4_foreach([adapterTuple], [$1], [AC_ARG_ENABLE(ADAPTER_OPT([adapterTuple]), @@ -326,6 +325,7 @@ AC_ARG_ADAPTERS([ LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + DMEM_ADAPTER, SYSFSGPIO_ADAPTER, REMOTE_BITBANG_ADAPTER, LINUXSPIDEV_ADAPTER, @@ -503,12 +503,6 @@ AS_IF([test "x$build_parport" = "xyes"], [ AC_DEFINE([BUILD_PARPORT], [0], [0 if you don't want parport.]) ]) -AS_IF([test "x$build_dmem" = "xyes"], [ - AC_DEFINE([BUILD_DMEM], [1], [1 if you want to debug via Direct Mem.]) -], [ - AC_DEFINE([BUILD_DMEM], [0], [0 if you don't want to debug via Direct Mem.]) -]) - AS_IF([test "x$ADAPTER_VAR([dummy])" != "xno"], [ build_bitbang=yes ]) @@ -646,6 +640,7 @@ PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libu PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x]) PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpiod]) +PROCESS_ADAPTERS([DMEM_ADAPTER], ["x$is_linux" = "xyes"], [Linux /dev/mem]) PROCESS_ADAPTERS([SYSFSGPIO_ADAPTER], ["x$is_linux" = "xyes"], [Linux sysfs]) PROCESS_ADAPTERS([REMOTE_BITBANG_ADAPTER], [true], [unused]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) @@ -744,7 +739,6 @@ AM_CONDITIONAL([USE_LIBFTDI], [test "x$use_libftdi" = "xyes"]) AM_CONDITIONAL([USE_LIBGPIOD], [test "x$use_libgpiod" = "xyes"]) AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"]) AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"]) -AM_CONDITIONAL([DMEM], [test "x$build_dmem" = "xyes"]) AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"]) AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"]) @@ -843,6 +837,7 @@ m4_foreach([adapterTuple], [USB1_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, LIBFTDI_USB1_ADAPTERS, LIBGPIOD_ADAPTERS, + DMEM_ADAPTER, SYSFSGPIO_ADAPTER, REMOTE_BITBANG_ADAPTER, LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS, From 537d907555ddd5137a6fecfc6d0d74b404b3445a Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 23 Jun 2025 12:41:04 -0500 Subject: [PATCH 1309/1312] tcl/board/ti_*_swd_native.cfg: Add explicit transport info We use swd emulation in direct memory operations. Instead of relying on deprecated autoselect of transport, explicitly state swd as transport scheme. Change-Id: Iec7e2ad18edd365992cd7ba88558494bccf49fd2 Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8975 Reviewed-by: Antonio Borneo Tested-by: jenkins --- tcl/board/ti_am625_swd_native.cfg | 1 + tcl/board/ti_am62a7_swd_native.cfg | 1 + tcl/board/ti_am62p_swd_native.cfg | 1 + tcl/board/ti_j721e_swd_native.cfg | 1 + tcl/board/ti_j722s_swd_native.cfg | 1 + 5 files changed, 5 insertions(+) diff --git a/tcl/board/ti_am625_swd_native.cfg b/tcl/board/ti_am625_swd_native.cfg index dc4b20579d..65314fe5dc 100644 --- a/tcl/board/ti_am625_swd_native.cfg +++ b/tcl/board/ti_am625_swd_native.cfg @@ -14,6 +14,7 @@ # We are using dmem, which uses dapdirect_swd transport adapter driver dmem +transport select swd if { ![info exists SOC] } { set SOC am625 diff --git a/tcl/board/ti_am62a7_swd_native.cfg b/tcl/board/ti_am62a7_swd_native.cfg index 99fc0b0b38..3d5e892289 100644 --- a/tcl/board/ti_am62a7_swd_native.cfg +++ b/tcl/board/ti_am62a7_swd_native.cfg @@ -14,6 +14,7 @@ # We are using dmem, which uses dapdirect_swd transport adapter driver dmem +transport select swd if { ![info exists SOC] } { set SOC am62a7 diff --git a/tcl/board/ti_am62p_swd_native.cfg b/tcl/board/ti_am62p_swd_native.cfg index fa549f3585..a8c6bd1204 100644 --- a/tcl/board/ti_am62p_swd_native.cfg +++ b/tcl/board/ti_am62p_swd_native.cfg @@ -14,6 +14,7 @@ # We are using dmem, which uses dapdirect_swd transport adapter driver dmem +transport select swd if { ![info exists SOC] } { set SOC am62p diff --git a/tcl/board/ti_j721e_swd_native.cfg b/tcl/board/ti_j721e_swd_native.cfg index 3041c3c345..38316387af 100644 --- a/tcl/board/ti_j721e_swd_native.cfg +++ b/tcl/board/ti_j721e_swd_native.cfg @@ -14,6 +14,7 @@ # We are using dmem, which uses dapdirect_swd transport adapter driver dmem +transport select swd if { ![info exists SOC] } { set SOC j721e diff --git a/tcl/board/ti_j722s_swd_native.cfg b/tcl/board/ti_j722s_swd_native.cfg index bbe0d508c8..a171ec3586 100644 --- a/tcl/board/ti_j722s_swd_native.cfg +++ b/tcl/board/ti_j722s_swd_native.cfg @@ -15,6 +15,7 @@ # We are using dmem, which uses dapdirect_swd transport adapter driver dmem +transport select swd if { ![info exists SOC] } { set SOC j722s From f71b0bbd7b31627dfdfb87741cf207d83335357c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 3 Jan 2025 15:04:43 +0100 Subject: [PATCH 1310/1312] jtag/swd: extend ap_delay_hint parameter comments Assure that zero is passed in ap_delay_hint in case of DP r/w. Change-Id: I5cd53b99950a7f1398b88f7394b3e66530803479 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8689 Tested-by: jenkins --- src/jtag/swd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jtag/swd.h b/src/jtag/swd.h index 3fe1365b58..c4b6215abd 100644 --- a/src/jtag/swd.h +++ b/src/jtag/swd.h @@ -270,6 +270,7 @@ struct swd_driver { * @param Where to store value to read from register * @param ap_delay_hint Number of idle cycles that may be * needed after an AP access to avoid WAITs + * or zero in case of DP read. */ void (*read_reg)(uint8_t cmd, uint32_t *value, uint32_t ap_delay_hint); @@ -280,6 +281,7 @@ struct swd_driver { * @param Value to be written to the register * @param ap_delay_hint Number of idle cycles that may be * needed after an AP access to avoid WAITs + * or zero in case of DP write. */ void (*write_reg)(uint8_t cmd, uint32_t value, uint32_t ap_delay_hint); From 09a54c3a89af563329adf757990e0c6dd83a1095 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 3 Jan 2025 18:23:07 +0100 Subject: [PATCH 1311/1312] target/arm_adi: add URLs of latest ARM ADI spec While on it warn about screwed SWD diagrams in ADI spec and add reference to a SWD timing diagram. Change-Id: I628d707ebf8ce7c22ba19bdcfd06028d4eaa60f8 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/8690 Tested-by: jenkins --- src/target/arm_adi_v5.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index df897b80ed..67a3fcc577 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -50,8 +50,16 @@ /* * Relevant specifications from ARM include: * - * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031F + * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031G + * https://developer.arm.com/documentation/ihi0031/latest/ + * * ARM(tm) Debug Interface v6 Architecture Specification ARM IHI 0074C + * https://developer.arm.com/documentation/ihi0074/latest/ + * + * Note that diagrams B4-1 to B4-7 in both ADI specifications show + * SWCLK signal mostly in wrong polarity. See detailed SWD timing + * https://developer.arm.com/documentation/dui0499/b/arm-dstream-target-interface-connections/swd-timing-requirements + * * CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B * * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D From 4ab72110f081e4b10ad5207b0ee74cd8d9423792 Mon Sep 17 00:00:00 2001 From: Dave Brand Date: Thu, 3 Jul 2025 18:04:02 -0400 Subject: [PATCH 1312/1312] Fix compiler warning --- src/flash/nor/at32qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/at32qspi.c b/src/flash/nor/at32qspi.c index 1a39e3dc05..cd5dae22a0 100644 --- a/src/flash/nor/at32qspi.c +++ b/src/flash/nor/at32qspi.c @@ -200,7 +200,7 @@ QSPI_OPERATE_MODE_114, 8, 0x32, QSPI_XIP_ADDRLEN_3_BYTE, -QSPI_XIP_ADDRLEN_3_BYTE, +QSPI_OPERATE_MODE_111, 0, QSPI_XIPW_SEL_MODED, 0x7F,