diff --git a/doc/openocd.texi b/doc/openocd.texi index 967c637ae..1243438a4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4070,6 +4070,7 @@ defaulting to the currently selected AP. Displays ID register from AP @var{num}, defaulting to the currently selected AP. @end deffn +@anchor{DAP subcommand apreg} @deffn Command {$dap_name apreg} ap_num reg [value] Displays content of a register @var{reg} from AP @var{ap_num} or set a new value @var{value}. @@ -4091,9 +4092,47 @@ memory bus access [0-255], giving additional time to respond to reads. If @var{value} is defined, first assigns that. @end deffn -@deffn Command {$dap_name apcsw} [0 / 1] -fix CSW_SPROT from register AP_REG_CSW on selected dap. -Defaulting to 0. +@deffn Command {$dap_name apcsw} [value [mask]] +Displays or changes CSW bit pattern for MEM-AP transfers. + +At the begin of each memory access the CSW pattern is extended (bitwise or-ed) +by @dfn{Size} and @dfn{AddrInc} bit-fields according to transfer requirements +and the result is written to the real CSW register. All bits except dynamically +updated fields @dfn{Size} and @dfn{AddrInc} can be changed by changing +the CSW pattern. Refer to ARM ADI v5 manual chapter 7.6.4 and appendix A +for details. + +Use @var{value} only syntax if you want to set the new CSW pattern as a whole. +The example sets HPROT1 bit (required by Cortex-M) and clears the rest of +the pattern: +@example +kx.dap apcsw 0x2000000 +@end example + +If @var{mask} is also used, the CSW pattern is changed only on bit positions +where the mask bit is 1. The following example sets HPROT3 (cacheable) +and leaves the rest of the pattern intact. It configures memory access through +DCache on Cortex-M7. +@example +set CSW_HPROT3_CACHEABLE [expr 1 << 27] +samv.dap apcsw $CSW_HPROT3_CACHEABLE $CSW_HPROT3_CACHEABLE +@end example + +Another example clears SPROT bit and leaves the rest of pattern intact: +@example +set CSW_SPROT [expr 1 << 30] +samv.dap apcsw 0 $CSW_SPROT +@end example + +@emph{Note:} If you want to check the real value of CSW, not CSW pattern, use +@code{xxx.dap apreg 0}. @xref{DAP subcommand apreg,,}. + +@emph{Warning:} Some of the CSW bits are vital for working memory transfer. +If you set a wrong CSW pattern and MEM-AP stopped working, use the following +example with a proper dap name: +@example +xxx.dap apcsw default +@end example @end deffn @deffn Command {$dap_name ti_be_32_quirks} [@option{enable}] diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index f9b51cdec..e2d9b5e66 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -97,8 +97,7 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) { - csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT | - ap->csw_default; + csw |= ap->csw_default; if (csw != ap->csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ @@ -1647,22 +1646,33 @@ COMMAND_HANDLER(dap_apcsw_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); uint32_t apcsw = dap->ap[dap->apsel].csw_default; - uint32_t sprot = 0; + uint32_t csw_val, csw_mask; switch (CMD_ARGC) { case 0: - command_print(CMD_CTX, "apsel %" PRIi32 " selected, csw 0x%8.8" PRIx32, - (dap->apsel), apcsw); - break; + command_print(CMD_CTX, "ap %" PRIi32 " selected, csw 0x%8.8" PRIx32, + dap->apsel, apcsw); + return ERROR_OK; case 1: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], sprot); - /* AP address is in bits 31:24 of DP_SELECT */ - if (sprot > 1) - return ERROR_COMMAND_SYNTAX_ERROR; - if (sprot) - apcsw |= CSW_SPROT; + if (strcmp(CMD_ARGV[0], "default") == 0) + csw_val = CSW_DEFAULT; else - apcsw &= ~CSW_SPROT; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], csw_val); + + if (csw_val & (CSW_SIZE_MASK | CSW_ADDRINC_MASK)) { + LOG_ERROR("CSW value cannot include 'Size' and 'AddrInc' bit-fields"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + apcsw = csw_val; + break; + case 2: + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], csw_val); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], csw_mask); + if (csw_mask & (CSW_SIZE_MASK | CSW_ADDRINC_MASK)) { + LOG_ERROR("CSW mask cannot include 'Size' and 'AddrInc' bit-fields"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + apcsw = (apcsw & ~csw_mask) | (csw_val & csw_mask); break; default: return ERROR_COMMAND_SYNTAX_ERROR; @@ -1786,8 +1796,8 @@ const struct command_registration dap_instance_commands[] = { .name = "apcsw", .handler = dap_apcsw_command, .mode = COMMAND_EXEC, - .help = "Set csw access bit ", - .usage = "[sprot]", + .help = "Set CSW default bits", + .usage = "[value [mask]]", }, { diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index bc5611650..22c316630 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -112,13 +112,16 @@ #define CSW_ADDRINC_PACKED (2UL << 4) #define CSW_DEVICE_EN (1UL << 6) #define CSW_TRIN_PROG (1UL << 7) +/* all fields in bits 12 and above are implementation-defined! */ #define CSW_SPIDEN (1UL << 23) -/* 30:24 - implementation-defined! */ -#define CSW_HPROT (1UL << 25) /* ? */ -#define CSW_MASTER_DEBUG (1UL << 29) /* ? */ +#define CSW_HPROT1 (1UL << 25) /* AHB: Privileged */ +#define CSW_MASTER_DEBUG (1UL << 29) /* AHB: set HMASTER signals to AHB-AP ID */ #define CSW_SPROT (1UL << 30) #define CSW_DBGSWENABLE (1UL << 31) +/* initial value of csw_default used for MEM-AP transfers */ +#define CSW_DEFAULT (CSW_HPROT1 | CSW_MASTER_DEBUG | CSW_DBGSWENABLE) + /* Fields of the MEM-AP's IDR register */ #define IDR_REV (0xFUL << 28) #define IDR_JEP106 (0x7FFUL << 17) diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 797feb5ba..8c081800f 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -55,6 +55,8 @@ static void dap_instance_init(struct adiv5_dap *dap) dap->ap[i].memaccess_tck = 255; /* Number of bits for tar autoincrement, impl. dep. at least 10 */ dap->ap[i].tar_autoincr_block = (1<<10); + /* default CSW value */ + dap->ap[i].csw_default = CSW_DEFAULT; } INIT_LIST_HEAD(&dap->cmd_journal); }