From 289d963ba544dc9be67c3f76af9f270ecc0b302d Mon Sep 17 00:00:00 2001 From: Mikaela Szekely Date: Thu, 2 Jun 2022 18:18:34 -0600 Subject: [PATCH 01/32] Complete the version string migration from 5e3cade, fixing HOSTED_BMP_ONLY --- src/platforms/hosted/bmp_serial.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c index 03ef66e2..1922ec07 100644 --- a/src/platforms/hosted/bmp_serial.c +++ b/src/platforms/hosted/bmp_serial.c @@ -233,7 +233,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) struct dirent *dp; int i = 0; while ((dp = readdir(dir)) != NULL) { - if ((strstr(dp->d_name, BMP_IDSTRING)) && + if ((strstr(dp->d_name, BMP_IDSTRING_BLACKMAGIC) || + strstr(dp->d_name, BMP_IDSTRING_BLACKSPHERE) || + strstr(dp->d_name, BMP_IDSTRING_1BITSQUARED)) && (strstr(dp->d_name, "-if00"))) { i++; char type[256], version[256], serial[256]; @@ -266,7 +268,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) dir = opendir(DEVICE_BY_ID); i = 0; while ((dp = readdir(dir)) != NULL) { - if ((strstr(dp->d_name, BMP_IDSTRING)) && + if ((strstr(dp->d_name, BMP_IDSTRING_BLACKMAGIC) || + strstr(dp->d_name, BMP_IDSTRING_BLACKSPHERE) || + strstr(dp->d_name, BMP_IDSTRING_1BITSQUARED)) && (strstr(dp->d_name, "-if00"))) { i++; char type[256], version[256], serial[256]; From 08956eb4fb5344302e45f86aceaa732d0938b4eb Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 24 Jun 2022 21:21:33 -0400 Subject: [PATCH 02/32] gdb_main: Fix a formatting bug that breaks, among other things, breakpoints --- src/gdb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index 7e84d24c..38f909c5 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -592,7 +592,7 @@ handle_z_packet(char *packet, int plen) uint32_t addr; int ret; - sscanf(packet, "%*[zZ]%d,%08" PRIX32 ",%d", &type, &addr, &len); + sscanf(packet, "%*[zZ]%d,%08" PRIx32 ",%d", &type, &addr, &len); if(set) ret = target_breakwatch_set(cur_target, type, addr, len); else From 54790f032e579941731e98f006781082c0b3a386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Musia=C5=82?= Date: Sun, 26 Jun 2022 12:17:51 +0200 Subject: [PATCH 03/32] cortexm: fixed an issue with watchpoint handling and a register sanity check --- src/target/cortexm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 0c25509d..7502f1ab 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -502,7 +502,7 @@ bool cortexm_attach(target *t) priv->flash_patch_revision = (r >> 28); priv->hw_watchpoint_max = CORTEXM_MAX_WATCHPOINTS; r = target_mem_read32(t, CORTEXM_DWT_CTRL); - if ((r >> 28) > priv->hw_watchpoint_max) + if ((r >> 28) < priv->hw_watchpoint_max) priv->hw_watchpoint_max = r >> 28; /* Clear any stale breakpoints */ @@ -675,7 +675,7 @@ static int dcrsr_regnum(target *t, unsigned reg) return regnum_cortex_m[reg]; } else if ((t->target_options & TOPT_FLAVOUR_V7MF) && (reg < (sizeof(regnum_cortex_m) + - sizeof(regnum_cortex_mf) / 4))) { + sizeof(regnum_cortex_mf)) / 4)) { return regnum_cortex_mf[reg - sizeof(regnum_cortex_m)/4]; } else { return -1; From 7e91c401d3bda54b7caeab67dbb74cbf4854666a Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 14:14:59 -0400 Subject: [PATCH 04/32] ch32f1: formatting cleanup to bring things closer to inline with the rest of the codebase --- src/target/ch32f1.c | 172 ++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 95 deletions(-) diff --git a/src/target/ch32f1.c b/src/target/ch32f1.c index 8da38951..31dda8e7 100644 --- a/src/target/ch32f1.c +++ b/src/target/ch32f1.c @@ -18,12 +18,12 @@ * along with this program. If not, see . */ -/* This file implements CH32F1xx target specific functions. +/* This file implements CH32F1xx target specific functions. The ch32 flash is rather slow so this code is using the so called fast mode (ch32 specific). 128 bytes are copied to a write buffer, then the write buffer is committed to flash /!\ There is some sort of bus stall/bus arbitration going on that does NOT work when programmed through SWD/jtag - The workaround is to wait a few cycles before filling the write buffer. This is performed by reading the flash a few times + The workaround is to wait a few cycles before filling the write buffer. This is performed by reading the flash a few times */ @@ -32,21 +32,12 @@ #include "target_internal.h" #include "cortexm.h" -#if PC_HOSTED == 1 - #define DEBUG_CH DEBUG_INFO - #define ERROR_CH DEBUG_WARN -#else - #define DEBUG_CH(...) {} //DEBUG_WARN //(...) {} - #define ERROR_CH DEBUG_WARN //DEBUG_WARN -#endif - extern const struct command_s stm32f1_cmd_list[]; // Reuse stm32f1 stuff - static int ch32f1_flash_erase(struct target_flash *f, - target_addr addr, size_t len); - static int ch32f1_flash_write(struct target_flash *f, - target_addr dest, const void *src, size_t len); - +static int ch32f1_flash_erase(struct target_flash *f, + target_addr addr, size_t len); +static int ch32f1_flash_write(struct target_flash *f, + target_addr dest, const void *src, size_t len); // these are common with stm32f1/gd32f1/... #define FPEC_BASE 0x40022000 @@ -76,9 +67,6 @@ extern const struct command_s stm32f1_cmd_list[]; // Reuse stm32f1 stuff #define FLASH_SR_EOP (1<<5) // End of programming #define FLASH_BEGIN_ADDRESS_CH32 0x8000000 - - - /** \fn ch32f1_add_flash \brief "fast" flash driver for CH32F10x chips @@ -104,7 +92,7 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era #define WAIT_BUSY() do { \ sr = target_mem_read32(t, FLASH_SR); \ if(target_check_error(t)) { \ - ERROR_CH("ch32f1 flash write: comm error\n"); \ + DEBUG_WARN("ch32f1 flash write: comm error\n"); \ return -1; \ } \ } while (sr & FLASH_SR_BSY); @@ -112,7 +100,7 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era #define WAIT_EOP() do { \ sr = target_mem_read32(t, FLASH_SR); \ if(target_check_error(t)) { \ - ERROR_CH("ch32f1 flash write: comm error\n"); \ + DEBUG_WARN("ch32f1 flash write: comm error\n"); \ return -1; \ } \ } while (!(sr & FLASH_SR_EOP)); @@ -120,18 +108,18 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era #define CLEAR_EOP() target_mem_write32(t, FLASH_SR,FLASH_SR_EOP) #define SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \ - ct|=(bit); \ + ct |= (bit); \ target_mem_write32(t, FLASH_CR, ct);} #define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \ - ct&=~(bit); \ + ct &= ~(bit); \ target_mem_write32(t, FLASH_CR, ct);} // Which one is the right value ? #define MAGIC_WORD 0x100 // #define MAGIC_WORD 0x1000 -#define MAGIC(adr) { magic=target_mem_read32(t,(adr) ^ MAGIC_WORD); \ +#define MAGIC(adr) { magic = target_mem_read32(t,(adr) ^ MAGIC_WORD); \ target_mem_write32(t, FLASH_MAGIC , magic); } /** @@ -140,7 +128,7 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era */ static int ch32f1_flash_unlock(target *t) { - DEBUG_CH("CH32: flash unlock \n"); + DEBUG_INFO("CH32: flash unlock \n"); target_mem_write32(t, FLASH_KEYR , KEY1); target_mem_write32(t, FLASH_KEYR , KEY2); @@ -148,16 +136,17 @@ static int ch32f1_flash_unlock(target *t) target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY1); target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY2); uint32_t cr = target_mem_read32(t, FLASH_CR); - if (cr & FLASH_CR_FLOCK_CH32){ - ERROR_CH("Fast unlock failed, cr: 0x%08" PRIx32 "\n", cr); + if (cr & FLASH_CR_FLOCK_CH32) { + DEBUG_WARN("Fast unlock failed, cr: 0x%08" PRIx32 "\n", cr); return -1; } return 0; } + static int ch32f1_flash_lock(target *t) { volatile uint32_t ct; - DEBUG_CH("CH32: flash lock \n"); + DEBUG_INFO("CH32: flash lock \n"); SET_CR(FLASH_CR_LOCK); return 0; } @@ -166,28 +155,24 @@ static int ch32f1_flash_lock(target *t) \brief identify the ch32f1 chip Actually grab all cortex m3 with designer = arm not caught earlier... */ - bool ch32f1_probe(target *t) { t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; - if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3) + + if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3 || t->idcode != 0x410) // only ch32f103 return false; - if(t->idcode !=0x410) { // only ch32f103 - return false; - } // try to flock ch32f1_flash_lock(t); // if this fails it is not a CH32 chip - if(ch32f1_flash_unlock(t)) { + if (ch32f1_flash_unlock(t)) return false; - } uint32_t signature = target_mem_read32(t, FLASHSIZE); uint32_t flashSize = signature & 0xFFFF; target_add_ram(t, 0x20000000, 0x5000); - ch32f1_add_flash(t, FLASH_BEGIN_ADDRESS_CH32, flashSize*1024, 128); + ch32f1_add_flash(t, FLASH_BEGIN_ADDRESS_CH32, flashSize * 1024, 128); target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD/VL-LD/VL-MD"); t->driver = "CH32F1 medium density (stm32f1 clone)"; return true; @@ -196,26 +181,26 @@ bool ch32f1_probe(target *t) \fn ch32f1_flash_erase \brief fast erase of CH32 */ -int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len) +int ch32f1_flash_erase(struct target_flash *f, target_addr addr, size_t len) { volatile uint32_t ct, sr, magic; target *t = f->t; - DEBUG_CH("CH32: flash erase \n"); + DEBUG_INFO("CH32: flash erase \n"); if (ch32f1_flash_unlock(t)) { - ERROR_CH("CH32: Unlock failed\n"); + DEBUG_WARN("CH32: Unlock failed\n"); return -1; } // Fast Erase 128 bytes pages (ch32 mode) - while(len) { + while (len) { SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER /* write address to FMA */ - target_mem_write32(t, FLASH_AR , addr); + target_mem_write32(t, FLASH_AR, addr); /* Flash page erase start instruction */ - SET_CR( FLASH_CR_STRT ); + SET_CR(FLASH_CR_STRT); WAIT_EOP(); CLEAR_EOP(); - CLEAR_CR( FLASH_CR_STRT ); + CLEAR_CR(FLASH_CR_STRT); // Magic MAGIC(addr); if (len > 128) @@ -226,8 +211,8 @@ int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len) } sr = target_mem_read32(t, FLASH_SR); ch32f1_flash_lock(t); - if ((sr & SR_ERROR_MASK)) { - ERROR_CH("ch32f1 flash erase error 0x%" PRIx32 "\n", sr); + if (sr & SR_ERROR_MASK) { + DEBUG_WARN("ch32f1 flash erase error 0x%" PRIx32 "\n", sr); return -1; } return 0; @@ -241,39 +226,38 @@ int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len) NB: Just reading fff is not enough as it could be a transient previous operation value */ -static bool ch32f1_wait_flash_ready(target *t,uint32_t adr) +static bool ch32f1_wait_flash_ready(target *t, uint32_t addr) { - uint32_t ff; - for(int i = 0; i < 32; i++) { - ff = target_mem_read32(t,adr); - } - if(ff != 0xffffffffUL) { - ERROR_CH("ch32f1 Not erased properly at %x or flash access issue\n",adr); - return false; - } - return true; + uint32_t ff = 0; + for (size_t i = 0; i < 32; i++) + ff = target_mem_read32(t, addr); + if (ff != 0xffffffffUL) { + DEBUG_WARN("ch32f1 Not erased properly at %" PRIx32 " or flash access issue\n", addr); + return false; + } + return true; } /** \fn ch32f1_flash_write \brief fast flash for ch32. Load 128 bytes chunk and then flash them */ -static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t offset) +static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t offset) { volatile uint32_t ct, sr, magic; const uint32_t *ss = (const uint32_t *)(src+offset); - uint32_t dd = dest+offset; + uint32_t dd = dest + offset; SET_CR(FLASH_CR_FTPG_CH32); - target_mem_write32(t, dd+0,ss[0]); - target_mem_write32(t, dd+4,ss[1]); - target_mem_write32(t, dd+8,ss[2]); - target_mem_write32(t, dd+12,ss[3]); + target_mem_write32(t, dd + 0, ss[0]); + target_mem_write32(t, dd + 4, ss[1]); + target_mem_write32(t, dd + 8, ss[2]); + target_mem_write32(t, dd + 12, ss[3]); SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */ WAIT_EOP(); CLEAR_EOP(); CLEAR_CR(FLASH_CR_FTPG_CH32); - MAGIC((dest+offset)); + MAGIC(dest + offset); return 0; } /** @@ -282,12 +266,12 @@ static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t of */ int ch32f1_buffer_clear(target *t) { - volatile uint32_t ct,sr; - SET_CR(FLASH_CR_FTPG_CH32); // Fast page program 4- - SET_CR(FLASH_CR_BUF_RESET_CH32); // BUF_RESET 5- - WAIT_BUSY(); // 6- - CLEAR_CR(FLASH_CR_FTPG_CH32); // Fast page program 4- - return 0; + volatile uint32_t ct, sr; + SET_CR(FLASH_CR_FTPG_CH32); // Fast page program 4- + SET_CR(FLASH_CR_BUF_RESET_CH32); // BUF_RESET 5- + WAIT_BUSY(); // 6- + CLEAR_CR(FLASH_CR_FTPG_CH32); // Fast page program 4- + return 0; } //#define CH32_VERIFY @@ -295,21 +279,21 @@ int ch32f1_buffer_clear(target *t) */ static int ch32f1_flash_write(struct target_flash *f, - target_addr dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { volatile uint32_t ct, sr, magic; target *t = f->t; size_t length = len; #ifdef CH32_VERIFY - target_addr orgDest=dest; - const void *orgSrc=src; + target_addr org_dest = dest; + const void *org_src = src; #endif - DEBUG_CH("CH32: flash write 0x%x ,size=%d\n",dest,len); + DEBUG_INFO("CH32: flash write 0x%x ,size=%d\n", dest, len); - while(length > 0) + while (length > 0) { - if(ch32f1_flash_unlock(t)) { - ERROR_CH("ch32f1 cannot fast unlock\n"); + if (ch32f1_flash_unlock(t)) { + DEBUG_WARN("ch32f1 cannot fast unlock\n"); return -1; } WAIT_BUSY(); @@ -317,12 +301,12 @@ static int ch32f1_flash_write(struct target_flash *f, // Buffer reset... ch32f1_buffer_clear(t); // Load 128 bytes to buffer - if(!ch32f1_wait_flash_ready(t,dest)) { + if (!ch32f1_wait_flash_ready(t,dest)) return -1; - } - for(int i = 0; i < 8; i++) { - if(ch32f1_upload(t,dest,src, 16*i)) { - ERROR_CH("Cannot upload to buffer\n"); + + for (size_t i = 0; i < 8; i++) { + if (ch32f1_upload(t, dest, src, i * 16U)) { + DEBUG_WARN("Cannot upload to buffer\n"); return -1; } } @@ -334,11 +318,11 @@ static int ch32f1_flash_write(struct target_flash *f, CLEAR_EOP(); CLEAR_CR(FLASH_CR_FTPG_CH32); - MAGIC((dest)); + MAGIC(dest); // next - if(length > 128) - length -=128; + if (length > 128) + length -=128; else length = 0; dest += 128; @@ -346,24 +330,23 @@ static int ch32f1_flash_write(struct target_flash *f, sr = target_mem_read32(t, FLASH_SR); // 13 ch32f1_flash_lock(t); - if ((sr & SR_ERROR_MASK) ) { - ERROR_CH("ch32f1 flash write error 0x%" PRIx32 "\n", sr); + if (sr & SR_ERROR_MASK) { + DEBUG_WARN("ch32f1 flash write error 0x%" PRIx32 "\n", sr); return -1; } - } + #ifdef CH32_VERIFY - DEBUG_CH("Verifying\n"); - size_t i = 0; - for(i = 0; i < len; i+= 4) + DEBUG_INFO("Verifying\n"); + for (size_t i = 0; i < len; i += 4) { - uint32_t mem=target_mem_read32(t, orgDest+i); - uint32_t mem2=*(uint32_t *)(orgSrc+i); - if(mem!=mem2) + const uint32_t expected = *(uint32_t *)(org_src + i); + const uint32_t actual = target_mem_read32(t, org_dest + i); + if (expected != actual) { - ERROR_CH(">>>>write mistmatch at address 0x%x\n",orgDest+i); - ERROR_CH(">>>>expected 0x%x\n",mem2); - ERROR_CH(">>>>flash 0x%x\n",mem); + DEBUG_WARN(">>>>write mistmatch at address 0x%x\n", org_dest + i); + DEBUG_WARN(">>>>expected: 0x%x\n", expected); + DEBUG_WARN(">>>> actual: 0x%x\n", actual); return -1; } } @@ -371,4 +354,3 @@ static int ch32f1_flash_write(struct target_flash *f, return 0; } -// EOF From eb8bb01c57bf627270a800dda8605b5c208de9d0 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 14:26:04 -0400 Subject: [PATCH 05/32] ch32f1: Fixed the probe routine distrubing state for other parts wrt `t->idcode` The CH32F1 routine now reads the IDCode into a local. If the part number matches and appears to be the chip (based on Flash locking), it only then writes the IDCode into `t->idcode`, which is at the point we can only `return true` from the probe routine anyway. --- src/target/ch32f1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/ch32f1.c b/src/target/ch32f1.c index 31dda8e7..3874cb92 100644 --- a/src/target/ch32f1.c +++ b/src/target/ch32f1.c @@ -157,9 +157,8 @@ static int ch32f1_flash_lock(target *t) */ bool ch32f1_probe(target *t) { - t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; - - if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3 || t->idcode != 0x410) // only ch32f103 + const uint32_t idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; + if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3 || idcode != 0x410) // only ch32f103 return false; // try to flock @@ -168,6 +167,7 @@ bool ch32f1_probe(target *t) if (ch32f1_flash_unlock(t)) return false; + t->idcode = idcode; uint32_t signature = target_mem_read32(t, FLASHSIZE); uint32_t flashSize = signature & 0xFFFF; From d9f4d069e6a4aef5d8ebf9a1ad5207f1cc41457e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 16:49:06 -0400 Subject: [PATCH 06/32] ch32f1: Further formatting and layout cleanup --- src/target/ch32f1.c | 95 +++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/src/target/ch32f1.c b/src/target/ch32f1.c index 3874cb92..8feaa403 100644 --- a/src/target/ch32f1.c +++ b/src/target/ch32f1.c @@ -41,11 +41,11 @@ static int ch32f1_flash_write(struct target_flash *f, // these are common with stm32f1/gd32f1/... #define FPEC_BASE 0x40022000 -#define FLASH_ACR (FPEC_BASE+0x00) -#define FLASH_KEYR (FPEC_BASE+0x04) -#define FLASH_SR (FPEC_BASE+0x0C) -#define FLASH_CR (FPEC_BASE+0x10) -#define FLASH_AR (FPEC_BASE+0x14) +#define FLASH_ACR (FPEC_BASE + 0x00) +#define FLASH_KEYR (FPEC_BASE + 0x04) +#define FLASH_SR (FPEC_BASE + 0x0C) +#define FLASH_CR (FPEC_BASE + 0x10) +#define FLASH_AR (FPEC_BASE + 0x14) #define FLASH_CR_LOCK (1 << 7) #define FLASH_CR_STRT (1 << 6) #define FLASH_SR_BSY (1 << 0) @@ -57,14 +57,14 @@ static int ch32f1_flash_write(struct target_flash *f, #define FLASHSIZE 0x1FFFF7E0 // these are specific to ch32f1 -#define FLASH_MAGIC (FPEC_BASE+0x34) -#define FLASH_MODEKEYR_CH32 (FPEC_BASE+0x24) // Fast mode for CH32F10x -#define FLASH_CR_FLOCK_CH32 (1<<15) // fast unlock -#define FLASH_CR_FTPG_CH32 (1<<16) // fast page program -#define FLASH_CR_FTER_CH32 (1<<17) // fast page erase -#define FLASH_CR_BUF_LOAD_CH32 (1<<18) // Buffer load -#define FLASH_CR_BUF_RESET_CH32 (1<<19) // Buffer reset -#define FLASH_SR_EOP (1<<5) // End of programming +#define FLASH_MAGIC (FPEC_BASE + 0x34) +#define FLASH_MODEKEYR_CH32 (FPEC_BASE + 0x24) // Fast mode for CH32F10x +#define FLASH_CR_FLOCK_CH32 (1 << 15) // fast unlock +#define FLASH_CR_FTPG_CH32 (1 << 16) // fast page program +#define FLASH_CR_FTER_CH32 (1 << 17) // fast page erase +#define FLASH_CR_BUF_LOAD_CH32 (1 << 18) // Buffer load +#define FLASH_CR_BUF_RESET_CH32 (1 << 19) // Buffer reset +#define FLASH_SR_EOP (1 << 5) // End of programming #define FLASH_BEGIN_ADDRESS_CH32 0x8000000 /** @@ -89,38 +89,41 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era target_add_flash(t, f); } -#define WAIT_BUSY() do { \ - sr = target_mem_read32(t, FLASH_SR); \ - if(target_check_error(t)) { \ - DEBUG_WARN("ch32f1 flash write: comm error\n"); \ - return -1; \ - } \ - } while (sr & FLASH_SR_BSY); +#define WAIT_BUSY() do { \ + sr = target_mem_read32(t, FLASH_SR); \ + if (target_check_error(t)) { \ + DEBUG_WARN("ch32f1 flash write: comm error\n"); \ + return -1; \ + } \ +} while (sr & FLASH_SR_BSY); -#define WAIT_EOP() do { \ - sr = target_mem_read32(t, FLASH_SR); \ - if(target_check_error(t)) { \ - DEBUG_WARN("ch32f1 flash write: comm error\n"); \ - return -1; \ - } \ - } while (!(sr & FLASH_SR_EOP)); +#define WAIT_EOP() do { \ + sr = target_mem_read32(t, FLASH_SR); \ + if (target_check_error(t)) { \ + DEBUG_WARN("ch32f1 flash write: comm error\n"); \ + return -1; \ + } \ +} while (!(sr & FLASH_SR_EOP)); -#define CLEAR_EOP() target_mem_write32(t, FLASH_SR,FLASH_SR_EOP) +#define CLEAR_EOP() target_mem_write32(t, FLASH_SR,FLASH_SR_EOP) -#define SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \ - ct |= (bit); \ - target_mem_write32(t, FLASH_CR, ct);} +#define SET_CR(bit) do { \ + const uint32_t cr = target_mem_read32(t, FLASH_CR) | (bit); \ + target_mem_write32(t, FLASH_CR, cr); \ +} while(0) - -#define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \ - ct &= ~(bit); \ - target_mem_write32(t, FLASH_CR, ct);} +#define CLEAR_CR(bit) do { \ + const uint32_t cr = target_mem_read32(t, FLASH_CR) & (~(bit)); \ + target_mem_write32(t, FLASH_CR, cr); \ +} while(0) // Which one is the right value ? #define MAGIC_WORD 0x100 // #define MAGIC_WORD 0x1000 -#define MAGIC(adr) { magic = target_mem_read32(t,(adr) ^ MAGIC_WORD); \ - target_mem_write32(t, FLASH_MAGIC , magic); } +#define MAGIC(addr) do { \ + magic = target_mem_read32(t, (addr) ^ MAGIC_WORD); \ + target_mem_write32(t, FLASH_MAGIC , magic); \ +} while(0) /** \fn ch32f1_flash_unlock @@ -130,11 +133,11 @@ static int ch32f1_flash_unlock(target *t) { DEBUG_INFO("CH32: flash unlock \n"); - target_mem_write32(t, FLASH_KEYR , KEY1); - target_mem_write32(t, FLASH_KEYR , KEY2); + target_mem_write32(t, FLASH_KEYR, KEY1); + target_mem_write32(t, FLASH_KEYR, KEY2); // fast mode - target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY1); - target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY2); + target_mem_write32(t, FLASH_MODEKEYR_CH32, KEY1); + target_mem_write32(t, FLASH_MODEKEYR_CH32, KEY2); uint32_t cr = target_mem_read32(t, FLASH_CR); if (cr & FLASH_CR_FLOCK_CH32) { DEBUG_WARN("Fast unlock failed, cr: 0x%08" PRIx32 "\n", cr); @@ -145,7 +148,6 @@ static int ch32f1_flash_unlock(target *t) static int ch32f1_flash_lock(target *t) { - volatile uint32_t ct; DEBUG_INFO("CH32: flash lock \n"); SET_CR(FLASH_CR_LOCK); return 0; @@ -177,13 +179,14 @@ bool ch32f1_probe(target *t) t->driver = "CH32F1 medium density (stm32f1 clone)"; return true; } + /** \fn ch32f1_flash_erase \brief fast erase of CH32 */ int ch32f1_flash_erase(struct target_flash *f, target_addr addr, size_t len) { - volatile uint32_t ct, sr, magic; + volatile uint32_t sr, magic; target *t = f->t; DEBUG_INFO("CH32: flash erase \n"); @@ -244,7 +247,7 @@ static bool ch32f1_wait_flash_ready(target *t, uint32_t addr) static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t offset) { - volatile uint32_t ct, sr, magic; + volatile uint32_t sr, magic; const uint32_t *ss = (const uint32_t *)(src+offset); uint32_t dd = dest + offset; @@ -266,7 +269,7 @@ static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t off */ int ch32f1_buffer_clear(target *t) { - volatile uint32_t ct, sr; + volatile uint32_t sr; SET_CR(FLASH_CR_FTPG_CH32); // Fast page program 4- SET_CR(FLASH_CR_BUF_RESET_CH32); // BUF_RESET 5- WAIT_BUSY(); // 6- @@ -281,7 +284,7 @@ int ch32f1_buffer_clear(target *t) static int ch32f1_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { - volatile uint32_t ct, sr, magic; + volatile uint32_t sr, magic; target *t = f->t; size_t length = len; #ifdef CH32_VERIFY From c7c5f68a84ed34cf3b5e4a118d11d7108b54b21b Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 16:49:32 -0400 Subject: [PATCH 07/32] ch32f1: Re-ordered a couple of the operation in ch32f1_probe so it plays nicer with the STM32 parts --- src/target/ch32f1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/target/ch32f1.c b/src/target/ch32f1.c index 8feaa403..f79c02e5 100644 --- a/src/target/ch32f1.c +++ b/src/target/ch32f1.c @@ -159,8 +159,10 @@ static int ch32f1_flash_lock(target *t) */ bool ch32f1_probe(target *t) { - const uint32_t idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; - if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3 || idcode != 0x410) // only ch32f103 + if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3) + return false; + const uint32_t idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0x00000fffU; + if (idcode != 0x410) // only ch32f103 return false; // try to flock From d613d2983991c477420e3bd2a84fc0212e04d90e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 16:50:04 -0400 Subject: [PATCH 08/32] cortexm: Added additional debug information for part probing --- src/target/cortexm.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 7502f1ab..7452b29b 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -378,8 +378,25 @@ bool cortexm_probe(ADIv5_AP_t *ap) } else { target_check_error(t); } +#if PC_HOSTED +#define STRINGIFY(x) #x #define PROBE(x) \ - do { if ((x)(t)) {return true;} else target_check_error(t); } while (0) + do { \ + DEBUG_INFO("Calling " STRINGIFY(x) "\n"); \ + if ((x)(t)) \ + return true; \ + else \ + target_check_error(t); \ + } while (0) +#else +#define PROBE(x) \ + do { \ + if ((x)(t)) \ + return true; \ + else \ + target_check_error(t); \ + } while (0) +#endif switch (ap->ap_designer) { case AP_DESIGNER_FREESCALE: From 77a83f4ffc28ce9d763569bbf26bce969d50ea25 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 17:26:47 -0400 Subject: [PATCH 09/32] ch32f1: Fixed another broken debug print that made assumptions about %x and %d that are wrong --- src/target/ch32f1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/ch32f1.c b/src/target/ch32f1.c index f79c02e5..b9b2588d 100644 --- a/src/target/ch32f1.c +++ b/src/target/ch32f1.c @@ -293,7 +293,7 @@ static int ch32f1_flash_write(struct target_flash *f, target_addr org_dest = dest; const void *org_src = src; #endif - DEBUG_INFO("CH32: flash write 0x%x ,size=%d\n", dest, len); + DEBUG_INFO("CH32: flash write 0x%" PRIx32 " ,size=%zu\n", dest, len); while (length > 0) { From 4de54fbee69f34bcd63595931ba216b4d54cc4cc Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 00:22:14 -0400 Subject: [PATCH 10/32] kinetis: General formatting and readability cleanup --- src/target/kinetis.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 5e44bfe8..bcce4108 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -436,19 +436,18 @@ static int kl_gen_flash_write(struct target_flash *f, /* Ensure we don't write something horrible over the security byte */ if (!f->t->unsafe_enabled && - (dest <= FLASH_SECURITY_BYTE_ADDRESS) && - ((dest + len) > FLASH_SECURITY_BYTE_ADDRESS)) { + dest <= FLASH_SECURITY_BYTE_ADDRESS && + dest + len > FLASH_SECURITY_BYTE_ADDRESS) { ((uint8_t*)src)[FLASH_SECURITY_BYTE_ADDRESS - dest] = FLASH_SECURITY_BYTE_UNSECURED; } /* Determine write command based on the alignment. */ uint8_t write_cmd; - if (kf->write_len == K64_WRITE_LEN) { + if (kf->write_len == K64_WRITE_LEN) write_cmd = FTFE_CMD_PROGRAM_PHRASE; - } else { + else write_cmd = FTFA_CMD_PROGRAM_LONGWORD; - } while (len) { if (kl_gen_command(f->t, write_cmd, dest, src, 1)) { @@ -458,9 +457,8 @@ static int kl_gen_flash_write(struct target_flash *f, len = 0; dest += kf->write_len; src += kf->write_len; - } else { + } else return 1; - } } return 0; } @@ -472,14 +470,13 @@ static int kl_gen_flash_done(struct target_flash *f) if (f->t->unsafe_enabled) return 0; - if (target_mem_read8(f->t, FLASH_SECURITY_BYTE_ADDRESS) == - FLASH_SECURITY_BYTE_UNSECURED) + if (target_mem_read8(f->t, FLASH_SECURITY_BYTE_ADDRESS) == FLASH_SECURITY_BYTE_UNSECURED) return 0; /* Load the security byte based on the alignment (determine 8 byte phrases * vs 4 byte phrases). */ - if (kf->write_len == 8) { + if (kf->write_len == K64_WRITE_LEN) { uint32_t vals[2]; vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS-4); vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); From e9abd83412aa576ebd2fc3d4488ed051c2d23ea5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 29 Jun 2022 00:10:12 -0400 Subject: [PATCH 11/32] kinetis: Refactored out some common code from kinetis_probe for the S32K14 lineup --- src/target/kinetis.c | 79 +++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index bcce4108..563b88f8 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -124,6 +124,17 @@ static void kl_gen_add_flash(target *t, uint32_t addr, size_t length, target_add_flash(t, f); } +static void kl_s32k14_setup( + target *const t, const uint32_t sram_l, const uint32_t sram_h, const size_t flash_size, const size_t flexmem_size) +{ + t->driver = "S32K14x"; + target_add_ram(t, sram_l, 0x20000000 - sram_l); + target_add_ram(t, 0x20000000, sram_h); + + kl_gen_add_flash(t, 0x00000000, flash_size, 0x1000, K64_WRITE_LEN); /* P-Flash, 4 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, flexmem_size, 0x1000, K64_WRITE_LEN); /* FlexNVM, 4 KB Sectors */ +} + bool kinetis_probe(target *t) { uint32_t sdid = target_mem_read32(t, SIM_SDID); @@ -325,45 +336,37 @@ bool kinetis_probe(target *t) kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, K64_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ kl_gen_add_flash(t, 0x10000000, 0x00008000, 0x800, K64_WRITE_LEN); /* FlexNVM, 32 KB, 2 KB Sectors */ break; - /* gen1 s32k14x */ - { - uint32_t sram_l, sram_h; - uint32_t flash, flexmem; - case 0x142: /* s32k142 */ - case 0x143: /* s32k142w */ - sram_l = 0x1FFFC000; /* SRAM_L, 16k */ - sram_h = 0x03000; /* SRAM_H, 12k */ - flash = 0x00040000; /* flash 256 KB */ - flexmem = 0x10000; /* FlexNVM 64 KB */ - goto do_common_s32k14x; - case 0x144: /* s32k144 */ - case 0x145: /* s32k144w */ - sram_l = 0x1FFF8000; /* SRAM_L, 32k */ - sram_h = 0x07000; /* SRAM_H, 28k */ - flash = 0x00080000; /* flash 512 KB */ - flexmem = 0x10000; /* FlexNVM 64 KB */ - goto do_common_s32k14x; - case 0x146: /* s32k146 */ - sram_l = 0x1fff0000; /* SRAM_L, 64k */ - sram_h = 0x0f000; /* SRAM_H, 60k */ - flash = 0x00100000; /* flash 1024 KB */ - flexmem = 0x10000; /* FlexNVM 64 KB */ - goto do_common_s32k14x; - case 0x148: /* S32K148 */ - sram_l = 0x1ffe0000; /* SRAM_L, 128 KB */ - sram_h = 0x1f000; /* SRAM_H, 124 KB */ - flash = 0x00180000; /* flash 1536 KB */ - flexmem = 0x80000; /* FlexNVM 512 KB */ - goto do_common_s32k14x; -do_common_s32k14x: - t->driver = "S32K14x"; - target_add_ram(t, sram_l, 0x20000000 - sram_l); - target_add_ram(t, 0x20000000, sram_h); - - kl_gen_add_flash(t, 0x00000000, flash, 0x1000, K64_WRITE_LEN); /* P-Flash, 4 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, flexmem, 0x1000, K64_WRITE_LEN); /* FlexNVM, 4 KB Sectors */ + /* gen1 s32k14x */ + case 0x142: /* S32K142 */ + case 0x143: /* S32K142W */ + /* SRAM_L = 16KiB */ + /* SRAM_H = 12KiB */ + /* Flash = 256 KiB */ + /* FlexNVM = 64 KiB */ + kl_s32k14_setup(t, 0x1FFFC000, 0x03000, 0x00040000, 0x10000); + break; + case 0x144: /* S32K144 */ + case 0x145: /* S32K144W */ + /* SRAM_L = 32KiB */ + /* SRAM_H = 28KiB */ + /* Flash = 512 KiB */ + /* FlexNVM = 64 KiB */ + kl_s32k14_setup(t, 0x1FFF8000, 0x07000, 0x00080000, 0x10000); + break; + case 0x146: /* S32K146 */ + /* SRAM_L = 64KiB */ + /* SRAM_H = 60KiB */ + /* Flash = 1024 KiB */ + /* FlexNVM = 64 KiB */ + kl_s32k14_setup(t, 0x1fff0000, 0x0f000, 0x00100000, 0x10000); + break; + case 0x148: /* S32K148 */ + /* SRAM_L = 128 KiB */ + /* SRAM_H = 124 KiB */ + /* Flash = 1536 KiB */ + /* FlexNVM = 512 KiB */ + kl_s32k14_setup(t, 0x1ffe0000, 0x1f000, 0x00180000, 0x80000); break; - } default: return false; } From 9591649ec61092c31aa49cefd9d96db749cff43a Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 29 Jun 2022 00:10:36 -0400 Subject: [PATCH 12/32] kinetis: Run clang-format on the code --- src/target/kinetis.c | 383 +++++++++++++++++++++---------------------- 1 file changed, 186 insertions(+), 197 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 563b88f8..cf8527bf 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -37,15 +37,16 @@ #include "general.h" #include "target.h" #include "target_internal.h" +#include "adiv5.h" -#define SIM_SDID 0x40048024 -#define SIM_FCFG1 0x4004804C +#define SIM_SDID 0x40048024 +#define SIM_FCFG1 0x4004804C -#define FTFA_BASE 0x40020000 -#define FTFA_FSTAT (FTFA_BASE + 0x00) -#define FTFA_FCNFG (FTFA_BASE + 0x01) -#define FTFA_FSEC (FTFA_BASE + 0x02) -#define FTFA_FOPT (FTFA_BASE + 0x03) +#define FTFA_BASE 0x40020000 +#define FTFA_FSTAT (FTFA_BASE + 0x00) +#define FTFA_FCNFG (FTFA_BASE + 0x01) +#define FTFA_FSEC (FTFA_BASE + 0x02) +#define FTFA_FOPT (FTFA_BASE + 0x03) #define FTFA_FCCOB_0 (FTFA_BASE + 0x04) #define FTFA_FCCOB_1 (FTFA_BASE + 0x08) #define FTFA_FCCOB_2 (FTFA_BASE + 0x0C) @@ -56,35 +57,33 @@ #define FTFA_FSTAT_FPVIOL (1 << 4) #define FTFA_FSTAT_MGSTAT0 (1 << 0) -#define FTFA_CMD_CHECK_ERASE 0x01 -#define FTFA_CMD_PROGRAM_CHECK 0x02 -#define FTFA_CMD_READ_RESOURCE 0x03 -#define FTFA_CMD_PROGRAM_LONGWORD 0x06 +#define FTFA_CMD_CHECK_ERASE 0x01 +#define FTFA_CMD_PROGRAM_CHECK 0x02 +#define FTFA_CMD_READ_RESOURCE 0x03 +#define FTFA_CMD_PROGRAM_LONGWORD 0x06 /* Part of the FTFE module for K64 */ -#define FTFE_CMD_PROGRAM_PHRASE 0x07 -#define FTFA_CMD_ERASE_SECTOR 0x09 -#define FTFA_CMD_CHECK_ERASE_ALL 0x40 -#define FTFA_CMD_READ_ONCE 0x41 -#define FTFA_CMD_PROGRAM_ONCE 0x43 -#define FTFA_CMD_ERASE_ALL 0x44 -#define FTFA_CMD_BACKDOOR_ACCESS 0x45 +#define FTFE_CMD_PROGRAM_PHRASE 0x07 +#define FTFA_CMD_ERASE_SECTOR 0x09 +#define FTFA_CMD_CHECK_ERASE_ALL 0x40 +#define FTFA_CMD_READ_ONCE 0x41 +#define FTFA_CMD_PROGRAM_ONCE 0x43 +#define FTFA_CMD_ERASE_ALL 0x44 +#define FTFA_CMD_BACKDOOR_ACCESS 0x45 #define KL_WRITE_LEN 4 /* 8 byte phrases need to be written to the k64 flash */ #define K64_WRITE_LEN 8 -static bool kinetis_cmd_unsafe(target *t, int argc, char *argv[]); +static bool kinetis_cmd_unsafe(target *t, int argc, char **argv); const struct command_s kinetis_cmd_list[] = { {"unsafe", (cmd_handler)kinetis_cmd_unsafe, "Allow programming security byte (enable|disable)"}, - {NULL, NULL, NULL} -}; + {NULL, NULL, NULL}}; -static bool kinetis_cmd_unsafe(target *t, int argc, char *argv[]) +static bool kinetis_cmd_unsafe(target *t, int argc, char **argv) { if (argc == 1) { - tc_printf(t, "Allow programming security byte: %s\n", - t->unsafe_enabled ? "enabled" : "disabled"); + tc_printf(t, "Allow programming security byte: %s\n", t->unsafe_enabled ? "enabled" : "disabled"); } else { parse_enable_or_disable(argv[1], &t->unsafe_enabled); } @@ -92,8 +91,7 @@ static bool kinetis_cmd_unsafe(target *t, int argc, char *argv[]) } static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len); -static int kl_gen_flash_write(struct target_flash *f, - target_addr dest, const void *src, size_t len); +static int kl_gen_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len); static int kl_gen_flash_done(struct target_flash *f); struct kinetis_flash { @@ -101,13 +99,13 @@ struct kinetis_flash { uint8_t write_len; }; -static void kl_gen_add_flash(target *t, uint32_t addr, size_t length, - size_t erasesize, size_t write_len) +static void kl_gen_add_flash( + target *const t, const uint32_t addr, const size_t length, const size_t erasesize, const size_t write_len) { struct kinetis_flash *kf = calloc(1, sizeof(*kf)); struct target_flash *f; - if (!kf) { /* calloc failed: heap exhaustion */ + if (!kf) { /* calloc failed: heap exhaustion */ DEBUG_WARN("calloc: failed in %s\n", __func__); return; } @@ -135,7 +133,7 @@ static void kl_s32k14_setup( kl_gen_add_flash(t, 0x10000000, flexmem_size, 0x1000, K64_WRITE_LEN); /* FlexNVM, 4 KB Sectors */ } -bool kinetis_probe(target *t) +bool kinetis_probe(target *const t) { uint32_t sdid = target_mem_read32(t, SIM_SDID); uint32_t fcfg1 = target_mem_read32(t, SIM_FCFG1); @@ -143,52 +141,52 @@ bool kinetis_probe(target *t) switch (sdid >> 20) { case 0x161: /* sram memory size */ - switch((sdid >> 16) & 0x0f) { - case 0x03:/* 4 KB */ - target_add_ram(t, 0x1ffffc00, 0x0400); - target_add_ram(t, 0x20000000, 0x0C00); - break; - case 0x04:/* 8 KB */ - target_add_ram(t, 0x1ffff800, 0x0800); - target_add_ram(t, 0x20000000, 0x1800); - break; - case 0x05:/* 16 KB */ - target_add_ram(t, 0x1ffff000, 0x1000); - target_add_ram(t, 0x20000000, 0x3000); - break; - case 0x06:/* 32 KB */ - target_add_ram(t, 0x1fffe000, 0x2000); - target_add_ram(t, 0x20000000, 0x6000); - break; - default: - return false; - break; + switch ((sdid >> 16) & 0x0f) { + case 0x03: /* 4 KB */ + target_add_ram(t, 0x1ffffc00, 0x0400); + target_add_ram(t, 0x20000000, 0x0C00); + break; + case 0x04: /* 8 KB */ + target_add_ram(t, 0x1ffff800, 0x0800); + target_add_ram(t, 0x20000000, 0x1800); + break; + case 0x05: /* 16 KB */ + target_add_ram(t, 0x1ffff000, 0x1000); + target_add_ram(t, 0x20000000, 0x3000); + break; + case 0x06: /* 32 KB */ + target_add_ram(t, 0x1fffe000, 0x2000); + target_add_ram(t, 0x20000000, 0x6000); + break; + default: + return false; + break; } /* flash memory size */ - switch((fcfg1 >> 24) & 0x0f) { - case 0x03: /* 32 KB */ - t->driver = "KL16Z32Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x08000, 0x400, KL_WRITE_LEN); - break; + switch ((fcfg1 >> 24) & 0x0f) { + case 0x03: /* 32 KB */ + t->driver = "KL16Z32Vxxx"; + kl_gen_add_flash(t, 0x00000000, 0x08000, 0x400, KL_WRITE_LEN); + break; - case 0x05: /* 64 KB */ - t->driver = "KL16Z64Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); - break; + case 0x05: /* 64 KB */ + t->driver = "KL16Z64Vxxx"; + kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); + break; - case 0x07: /* 128 KB */ - t->driver = "KL16Z128Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); - break; + case 0x07: /* 128 KB */ + t->driver = "KL16Z128Vxxx"; + kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); + break; - case 0x09: /* 256 KB */ - t->driver = "KL16Z256Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); - break; - default: - return false; - break; + case 0x09: /* 256 KB */ + t->driver = "KL16Z256Vxxx"; + kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); + break; + default: + return false; + break; } break; @@ -206,45 +204,45 @@ bool kinetis_probe(target *t) kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); break; case 0x271: - switch((sdid >> 16) & 0x0f) { - case 4: - t->driver = "KL27x32"; - target_add_ram(t, 0x1ffff800, 0x0800); - target_add_ram(t, 0x20000000, 0x1800); - kl_gen_add_flash(t, 0x00000000, 0x8000, 0x400, KL_WRITE_LEN); - break; - case 5: - t->driver = "KL27x64"; - target_add_ram(t, 0x1ffff000, 0x1000); - target_add_ram(t, 0x20000000, 0x3000); - kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); - break; - default: - return false; + switch ((sdid >> 16) & 0x0f) { + case 4: + t->driver = "KL27x32"; + target_add_ram(t, 0x1ffff800, 0x0800); + target_add_ram(t, 0x20000000, 0x1800); + kl_gen_add_flash(t, 0x00000000, 0x8000, 0x400, KL_WRITE_LEN); + break; + case 5: + t->driver = "KL27x64"; + target_add_ram(t, 0x1ffff000, 0x1000); + target_add_ram(t, 0x20000000, 0x3000); + kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); + break; + default: + return false; } break; case 0x021: /* KL02 family */ - switch((sdid >> 16) & 0x0f) { - case 3: - t->driver = "KL02x32"; - target_add_ram(t, 0x1FFFFC00, 0x400); - target_add_ram(t, 0x20000000, 0xc00); - kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400, KL_WRITE_LEN); - break; - case 2: - t->driver = "KL02x16"; - target_add_ram(t, 0x1FFFFE00, 0x200); - target_add_ram(t, 0x20000000, 0x600); - kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400, KL_WRITE_LEN); - break; - case 1: - t->driver = "KL02x8"; - target_add_ram(t, 0x1FFFFF00, 0x100); - target_add_ram(t, 0x20000000, 0x300); - kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN); - break; - default: - return false; + switch ((sdid >> 16) & 0x0f) { + case 3: + t->driver = "KL02x32"; + target_add_ram(t, 0x1FFFFC00, 0x400); + target_add_ram(t, 0x20000000, 0xc00); + kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400, KL_WRITE_LEN); + break; + case 2: + t->driver = "KL02x16"; + target_add_ram(t, 0x1FFFFE00, 0x200); + target_add_ram(t, 0x20000000, 0x600); + kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400, KL_WRITE_LEN); + break; + case 1: + t->driver = "KL02x8"; + target_add_ram(t, 0x1FFFFF00, 0x100); + target_add_ram(t, 0x20000000, 0x300); + kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN); + break; + default: + return false; } break; case 0x031: /* KL03 family */ @@ -266,73 +264,73 @@ bool kinetis_probe(target *t) * subfamily nibble as 2 */ t->driver = "K64"; - target_add_ram(t, 0x1FFF0000, 0x10000); - target_add_ram(t, 0x20000000, 0x30000); + target_add_ram(t, 0x1FFF0000, 0x10000); + target_add_ram(t, 0x20000000, 0x30000); kl_gen_add_flash(t, 0, 0x80000, 0x1000, K64_WRITE_LEN); kl_gen_add_flash(t, 0x80000, 0x80000, 0x1000, K64_WRITE_LEN); break; case 0x000: /* Older K-series */ - switch(sdid & 0xff0) { - case 0x000: /* K10 Family, DIEID=0x0 */ - case 0x080: /* K10 Family, DIEID=0x1 */ - case 0x100: /* K10 Family, DIEID=0x2 */ - case 0x180: /* K10 Family, DIEID=0x3 */ - case 0x220: /* K11 Family, DIEID=0x4 */ - return false; - case 0x200: /* K12 Family, DIEID=0x4 */ - switch((fcfg1 >> 24) & 0x0f) { - /* K12 Sub-Family Reference Manual, K12P80M50SF4RM, Rev. 4, February 2013 */ - case 0x7: - t->driver = "MK12DX128Vxx5"; - target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ - target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00020000, 0x800, KL_WRITE_LEN); /* P-Flash, 128 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ - break; - case 0x9: - t->driver = "MK12DX256Vxx5"; - target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ - target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ - break; - case 0xb: - t->driver = "MK12DN512Vxx5"; - target_add_ram(t, 0x1fff8000, 0x00008000); /* SRAM_L, 32 KB */ - target_add_ram(t, 0x20000000, 0x00008000); /* SRAM_H, 32 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x00040000, 0x00040000, 0x800, KL_WRITE_LEN); /* FlexNVM, 256 KB, 2 KB Sectors */ - break; - default: - return false; - } + switch (sdid & 0xff0) { + case 0x000: /* K10 Family, DIEID=0x0 */ + case 0x080: /* K10 Family, DIEID=0x1 */ + case 0x100: /* K10 Family, DIEID=0x2 */ + case 0x180: /* K10 Family, DIEID=0x3 */ + case 0x220: /* K11 Family, DIEID=0x4 */ + return false; + case 0x200: /* K12 Family, DIEID=0x4 */ + switch ((fcfg1 >> 24) & 0x0f) { + /* K12 Sub-Family Reference Manual, K12P80M50SF4RM, Rev. 4, February 2013 */ + case 0x7: + t->driver = "MK12DX128Vxx5"; + target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ + target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00020000, 0x800, KL_WRITE_LEN); /* P-Flash, 128 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ + break; + case 0x9: + t->driver = "MK12DX256Vxx5"; + target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ + target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ + break; + case 0xb: + t->driver = "MK12DN512Vxx5"; + target_add_ram(t, 0x1fff8000, 0x00008000); /* SRAM_L, 32 KB */ + target_add_ram(t, 0x20000000, 0x00008000); /* SRAM_H, 32 KB */ + kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kl_gen_add_flash(t, 0x00040000, 0x00040000, 0x800, KL_WRITE_LEN); /* FlexNVM, 256 KB, 2 KB Sectors */ break; - case 0x010: /* K20 Family, DIEID=0x0 */ - case 0x090: /* K20 Family, DIEID=0x1 */ - case 0x110: /* K20 Family, DIEID=0x2 */ - case 0x190: /* K20 Family, DIEID=0x3 */ - case 0x230: /* K21 Family, DIEID=0x4 */ - case 0x330: /* K21 Family, DIEID=0x6 */ - case 0x210: /* K22 Family, DIEID=0x4 */ - case 0x310: /* K22 Family, DIEID=0x6 */ - case 0x0a0: /* K30 Family, DIEID=0x1 */ - case 0x120: /* K30 Family, DIEID=0x2 */ - case 0x0b0: /* K40 Family, DIEID=0x1 */ - case 0x130: /* K40 Family, DIEID=0x2 */ - case 0x0e0: /* K50 Family, DIEID=0x1 */ - case 0x0f0: /* K51 Family, DIEID=0x1 */ - case 0x170: /* K53 Family, DIEID=0x2 */ - case 0x140: /* K60 Family, DIEID=0x2 */ - case 0x1c0: /* K60 Family, DIEID=0x3 */ - case 0x1d0: /* K70 Family, DIEID=0x3 */ default: return false; + } + break; + case 0x010: /* K20 Family, DIEID=0x0 */ + case 0x090: /* K20 Family, DIEID=0x1 */ + case 0x110: /* K20 Family, DIEID=0x2 */ + case 0x190: /* K20 Family, DIEID=0x3 */ + case 0x230: /* K21 Family, DIEID=0x4 */ + case 0x330: /* K21 Family, DIEID=0x6 */ + case 0x210: /* K22 Family, DIEID=0x4 */ + case 0x310: /* K22 Family, DIEID=0x6 */ + case 0x0a0: /* K30 Family, DIEID=0x1 */ + case 0x120: /* K30 Family, DIEID=0x2 */ + case 0x0b0: /* K40 Family, DIEID=0x1 */ + case 0x130: /* K40 Family, DIEID=0x2 */ + case 0x0e0: /* K50 Family, DIEID=0x1 */ + case 0x0f0: /* K51 Family, DIEID=0x1 */ + case 0x170: /* K53 Family, DIEID=0x2 */ + case 0x140: /* K60 Family, DIEID=0x2 */ + case 0x1c0: /* K60 Family, DIEID=0x3 */ + case 0x1d0: /* K70 Family, DIEID=0x3 */ + default: + return false; } break; case 0x118: /* S32K118 */ t->driver = "S32K118"; - target_add_ram(t, 0x1ffffc00, 0x00000400); /* SRAM_L, 1 KB */ - target_add_ram(t, 0x20000000, 0x00005800); /* SRAM_H, 22 KB */ + target_add_ram(t, 0x1ffffc00, 0x00000400); /* SRAM_L, 1 KB */ + target_add_ram(t, 0x20000000, 0x00005800); /* SRAM_H, 22 KB */ kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, K64_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ kl_gen_add_flash(t, 0x10000000, 0x00008000, 0x800, K64_WRITE_LEN); /* FlexNVM, 32 KB, 2 KB Sectors */ break; @@ -375,13 +373,12 @@ bool kinetis_probe(target *t) return true; } -static bool -kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint32_t *data, int n_items) +static bool kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint32_t *data, int n_items) { uint8_t fstat; /* clear errors unconditionally, so we can start a new operation */ - target_mem_write8(t,FTFA_FSTAT,(FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)); + target_mem_write8(t, FTFA_FSTAT, (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)); /* Wait for CCIF to be high */ do { @@ -412,7 +409,7 @@ kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint32_t *data, int return true; } -static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len) +static int kl_gen_flash_erase(struct target_flash *const f, target_addr addr, size_t len) { while (len) { if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL, 0)) { @@ -429,20 +426,16 @@ static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t l return 0; } -#define FLASH_SECURITY_BYTE_ADDRESS 0x40C +#define FLASH_SECURITY_BYTE_ADDRESS 0x40C #define FLASH_SECURITY_BYTE_UNSECURED 0xFE -static int kl_gen_flash_write(struct target_flash *f, - target_addr dest, const void *src, size_t len) +static int kl_gen_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { - struct kinetis_flash *kf = (struct kinetis_flash *)f; + struct kinetis_flash *const kf = (struct kinetis_flash *)f; /* Ensure we don't write something horrible over the security byte */ - if (!f->t->unsafe_enabled && - dest <= FLASH_SECURITY_BYTE_ADDRESS && - dest + len > FLASH_SECURITY_BYTE_ADDRESS) { - ((uint8_t*)src)[FLASH_SECURITY_BYTE_ADDRESS - dest] = - FLASH_SECURITY_BYTE_UNSECURED; + if (!f->t->unsafe_enabled && dest <= FLASH_SECURITY_BYTE_ADDRESS && dest + len > FLASH_SECURITY_BYTE_ADDRESS) { + ((uint8_t *)src)[FLASH_SECURITY_BYTE_ADDRESS - dest] = FLASH_SECURITY_BYTE_UNSECURED; } /* Determine write command based on the alignment. */ @@ -466,9 +459,9 @@ static int kl_gen_flash_write(struct target_flash *f, return 0; } -static int kl_gen_flash_done(struct target_flash *f) +static int kl_gen_flash_done(struct target_flash *const f) { - struct kinetis_flash *kf = (struct kinetis_flash *)f; + struct kinetis_flash *const kf = (struct kinetis_flash *)f; if (f->t->unsafe_enabled) return 0; @@ -481,17 +474,15 @@ static int kl_gen_flash_done(struct target_flash *f) */ if (kf->write_len == K64_WRITE_LEN) { uint32_t vals[2]; - vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS-4); + vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS - 4); vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; - kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, - FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2); + kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2); } else { uint32_t vals[1]; vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); vals[0] = (vals[0] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; - kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, - FLASH_SECURITY_BYTE_ADDRESS, vals, 1); + kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, FLASH_SECURITY_BYTE_ADDRESS, vals, 1); } return 0; @@ -504,7 +495,6 @@ static int kl_gen_flash_done(struct target_flash *f) * a backdoor AP is provided which may allow a mass erase to recover the * device. This provides a fake target to allow a monitor command interface */ -#include "adiv5.h" #define KINETIS_MDM_IDR_K22F 0x1c0000 #define KINETIS_MDM_IDR_KZ03 0x1c0020 @@ -514,19 +504,18 @@ static bool kinetis_mdm_cmd_ke04_mode(target *t, int argc, const char **argv); const struct command_s kinetis_mdm_cmd_list[] = { {"erase_mass", (cmd_handler)kinetis_mdm_cmd_erase_mass, "Erase entire flash memory"}, - {"ke04_mode", (cmd_handler)kinetis_mdm_cmd_ke04_mode, "Allow erase for KE04"}, - {NULL, NULL, NULL} -}; + {"ke04_mode", (cmd_handler)kinetis_mdm_cmd_ke04_mode, "Allow erase for KE04"}, {NULL, NULL, NULL}}; -enum target_halt_reason mdm_halt_poll(target *t, target_addr *watch) +enum target_halt_reason mdm_halt_poll(target *t, const target_addr *const watch) { - (void)t; (void)watch; + (void)t; + (void)watch; return TARGET_HALT_REQUEST; } void kinetis_mdm_probe(ADIv5_AP_t *ap) { - switch(ap->idr) { + switch (ap->idr) { case KINETIS_MDM_IDR_KZ03: /* Also valid for KE04, no way to check! */ case KINETIS_MDM_IDR_K22F: break; @@ -541,7 +530,7 @@ void kinetis_mdm_probe(ADIv5_AP_t *ap) adiv5_ap_ref(ap); t->priv = ap; - t->priv_free = (void*)adiv5_ap_unref; + t->priv_free = (void *)adiv5_ap_unref; t->driver = "Kinetis Recovery (MDM-AP)"; t->regs_size = 4; @@ -551,8 +540,8 @@ void kinetis_mdm_probe(ADIv5_AP_t *ap) #define MDM_STATUS ADIV5_AP_REG(0x00) #define MDM_CONTROL ADIV5_AP_REG(0x04) -#define MDM_STATUS_MASS_ERASE_ACK (1 << 0) -#define MDM_STATUS_FLASH_READY (1 << 1) +#define MDM_STATUS_MASS_ERASE_ACK (1 << 0) +#define MDM_STATUS_FLASH_READY (1 << 1) #define MDM_STATUS_MASS_ERASE_ENABLED (1 << 5) #define MDM_CONTROL_MASS_ERASE (1 << 0) @@ -569,6 +558,7 @@ static bool kinetis_mdm_cmd_ke04_mode(target *t, int argc, const char **argv) tc_printf(t, "Mass erase for KE04 now allowed\n"); return true; } + static bool kinetis_mdm_cmd_erase_mass(target *t, int argc, const char **argv) { (void)argc; @@ -576,13 +566,12 @@ static bool kinetis_mdm_cmd_erase_mass(target *t, int argc, const char **argv) ADIv5_AP_t *ap = t->priv; /* Keep the MCU in reset as stated in KL25PxxM48SF0RM */ - if(t->ke04_mode) + if (t->ke04_mode) adiv5_ap_write(ap, MDM_CONTROL, MDM_CONTROL_SYS_RESET); - uint32_t status, control; - status = adiv5_ap_read(ap, MDM_STATUS); - control = adiv5_ap_read(ap, MDM_CONTROL); - tc_printf(t, "Requesting mass erase (status = 0x%"PRIx32")\n", status); + uint32_t status = adiv5_ap_read(ap, MDM_STATUS); + uint32_t control = adiv5_ap_read(ap, MDM_CONTROL); + tc_printf(t, "Requesting mass erase (status = 0x%" PRIx32 ")\n", status); /* This flag does not exist on KE04 */ if (!(status & MDM_STATUS_MASS_ERASE_ENABLED) && !t->ke04_mode) { From f69ed07ba77b25162240e9b7ae50cca5440db00e Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 2 Jul 2022 03:11:55 +0100 Subject: [PATCH 13/32] kinetis: macro organization and clearer function naming Signed-off-by: Rafael Silva --- src/target/kinetis.c | 213 ++++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 103 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index cf8527bf..3c075bdf 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -39,36 +39,56 @@ #include "target_internal.h" #include "adiv5.h" +#define KINETIS_MDM_IDR_K22F 0x1c0000 +#define KINETIS_MDM_IDR_KZ03 0x1c0020 + +#define MDM_STATUS ADIV5_AP_REG(0x00) +#define MDM_CONTROL ADIV5_AP_REG(0x04) + +#define MDM_STATUS_MASS_ERASE_ACK (1 << 0) +#define MDM_STATUS_FLASH_READY (1 << 1) +#define MDM_STATUS_MASS_ERASE_ENABLED (1 << 5) +#define MDM_STATUS_BACK_KEY_ENABLED (1 << 6) + +#define MDM_CONTROL_MASS_ERASE (1 << 0) +#define MDM_CONTROL_SYS_RESET (1 << 3) + #define SIM_SDID 0x40048024 #define SIM_FCFG1 0x4004804C -#define FTFA_BASE 0x40020000 -#define FTFA_FSTAT (FTFA_BASE + 0x00) -#define FTFA_FCNFG (FTFA_BASE + 0x01) -#define FTFA_FSEC (FTFA_BASE + 0x02) -#define FTFA_FOPT (FTFA_BASE + 0x03) -#define FTFA_FCCOB_0 (FTFA_BASE + 0x04) -#define FTFA_FCCOB_1 (FTFA_BASE + 0x08) -#define FTFA_FCCOB_2 (FTFA_BASE + 0x0C) +#define FLASH_SECURITY_BYTE_ADDRESS 0x40C +#define FLASH_SECURITY_BYTE_UNSECURED 0xFE -#define FTFA_FSTAT_CCIF (1 << 7) -#define FTFA_FSTAT_RDCOLERR (1 << 6) -#define FTFA_FSTAT_ACCERR (1 << 5) -#define FTFA_FSTAT_FPVIOL (1 << 4) -#define FTFA_FSTAT_MGSTAT0 (1 << 0) +#define FTFx_BASE 0x40020000 +#define FTFx_FSTAT (FTFx_BASE + 0x00) +#define FTFx_FCNFG (FTFx_BASE + 0x01) +#define FTFx_FSEC (FTFx_BASE + 0x02) +#define FTFx_FOPT (FTFx_BASE + 0x03) +#define FTFx_FCCOB0 (FTFx_BASE + 0x04) +#define FTFx_FCCOB4 (FTFx_BASE + 0x08) +#define FTFx_FCCOB8 (FTFx_BASE + 0x0C) -#define FTFA_CMD_CHECK_ERASE 0x01 -#define FTFA_CMD_PROGRAM_CHECK 0x02 -#define FTFA_CMD_READ_RESOURCE 0x03 -#define FTFA_CMD_PROGRAM_LONGWORD 0x06 +#define FTFx_FSTAT_CCIF (1 << 7) +#define FTFx_FSTAT_RDCOLERR (1 << 6) +#define FTFx_FSTAT_ACCERR (1 << 5) +#define FTFx_FSTAT_FPVIOL (1 << 4) +#define FTFx_FSTAT_MGSTAT0 (1 << 0) + +#define FTFx_FSEC_KEYEN_MSK (0b11 << 6) +#define FTFx_FSEC_KEYEN (0b10 << 6) + +#define FTFx_CMD_CHECK_ERASE 0x01 +#define FTFx_CMD_PROGRAM_CHECK 0x02 +#define FTFx_CMD_READ_RESOURCE 0x03 +#define FTFx_CMD_PROGRAM_LONGWORD 0x06 /* Part of the FTFE module for K64 */ -#define FTFE_CMD_PROGRAM_PHRASE 0x07 -#define FTFA_CMD_ERASE_SECTOR 0x09 -#define FTFA_CMD_CHECK_ERASE_ALL 0x40 -#define FTFA_CMD_READ_ONCE 0x41 -#define FTFA_CMD_PROGRAM_ONCE 0x43 -#define FTFA_CMD_ERASE_ALL 0x44 -#define FTFA_CMD_BACKDOOR_ACCESS 0x45 +#define FTFx_CMD_PROGRAM_PHRASE 0x07 +#define FTFx_CMD_ERASE_SECTOR 0x09 +#define FTFx_CMD_CHECK_ERASE_ALL 0x40 +#define FTFx_CMD_READ_ONCE 0x41 +#define FTFx_CMD_PROGRAM_ONCE 0x43 +#define FTFx_CMD_ERASE_ALL 0x44 +#define FTFx_CMD_BACKDOOR_ACCESS 0x45 #define KL_WRITE_LEN 4 /* 8 byte phrases need to be written to the k64 flash */ @@ -78,7 +98,8 @@ static bool kinetis_cmd_unsafe(target *t, int argc, char **argv); const struct command_s kinetis_cmd_list[] = { {"unsafe", (cmd_handler)kinetis_cmd_unsafe, "Allow programming security byte (enable|disable)"}, - {NULL, NULL, NULL}}; + {NULL, NULL, NULL}, +}; static bool kinetis_cmd_unsafe(target *t, int argc, char **argv) { @@ -90,16 +111,16 @@ static bool kinetis_cmd_unsafe(target *t, int argc, char **argv) return true; } -static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len); -static int kl_gen_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len); -static int kl_gen_flash_done(struct target_flash *f); +static int kinetis_flash_cmd_erase(struct target_flash *f, target_addr addr, size_t len); +static int kinetis_flash_cmd_write(struct target_flash *f, target_addr dest, const void *src, size_t len); +static int kinetis_flash_done(struct target_flash *f); struct kinetis_flash { struct target_flash f; uint8_t write_len; }; -static void kl_gen_add_flash( +static void kinetis_add_flash( target *const t, const uint32_t addr, const size_t length, const size_t erasesize, const size_t write_len) { struct kinetis_flash *kf = calloc(1, sizeof(*kf)); @@ -114,9 +135,9 @@ static void kl_gen_add_flash( f->start = addr; f->length = length; f->blocksize = erasesize; - f->erase = kl_gen_flash_erase; - f->write = kl_gen_flash_write; - f->done = kl_gen_flash_done; + f->erase = kinetis_flash_cmd_erase; + f->write = kinetis_flash_cmd_write; + f->done = kinetis_flash_done; f->erased = 0xff; kf->write_len = write_len; target_add_flash(t, f); @@ -129,8 +150,8 @@ static void kl_s32k14_setup( target_add_ram(t, sram_l, 0x20000000 - sram_l); target_add_ram(t, 0x20000000, sram_h); - kl_gen_add_flash(t, 0x00000000, flash_size, 0x1000, K64_WRITE_LEN); /* P-Flash, 4 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, flexmem_size, 0x1000, K64_WRITE_LEN); /* FlexNVM, 4 KB Sectors */ + kinetis_add_flash(t, 0x00000000, flash_size, 0x1000, K64_WRITE_LEN); /* P-Flash, 4 KB Sectors */ + kinetis_add_flash(t, 0x10000000, flexmem_size, 0x1000, K64_WRITE_LEN); /* FlexNVM, 4 KB Sectors */ } bool kinetis_probe(target *const t) @@ -167,22 +188,22 @@ bool kinetis_probe(target *const t) switch ((fcfg1 >> 24) & 0x0f) { case 0x03: /* 32 KB */ t->driver = "KL16Z32Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x08000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x08000, 0x400, KL_WRITE_LEN); break; case 0x05: /* 64 KB */ t->driver = "KL16Z64Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); break; case 0x07: /* 128 KB */ t->driver = "KL16Z128Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); break; case 0x09: /* 256 KB */ t->driver = "KL16Z256Vxxx"; - kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); break; default: return false; @@ -195,13 +216,13 @@ bool kinetis_probe(target *const t) t->driver = "KL25"; target_add_ram(t, 0x1ffff000, 0x1000); target_add_ram(t, 0x20000000, 0x3000); - kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); break; case 0x231: t->driver = "KL27x128"; // MKL27 >=128kb target_add_ram(t, 0x1fffe000, 0x2000); target_add_ram(t, 0x20000000, 0x6000); - kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); break; case 0x271: switch ((sdid >> 16) & 0x0f) { @@ -209,13 +230,13 @@ bool kinetis_probe(target *const t) t->driver = "KL27x32"; target_add_ram(t, 0x1ffff800, 0x0800); target_add_ram(t, 0x20000000, 0x1800); - kl_gen_add_flash(t, 0x00000000, 0x8000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x8000, 0x400, KL_WRITE_LEN); break; case 5: t->driver = "KL27x64"; target_add_ram(t, 0x1ffff000, 0x1000); target_add_ram(t, 0x20000000, 0x3000); - kl_gen_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x10000, 0x400, KL_WRITE_LEN); break; default: return false; @@ -227,19 +248,19 @@ bool kinetis_probe(target *const t) t->driver = "KL02x32"; target_add_ram(t, 0x1FFFFC00, 0x400); target_add_ram(t, 0x20000000, 0xc00); - kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x7FFF, 0x400, KL_WRITE_LEN); break; case 2: t->driver = "KL02x16"; target_add_ram(t, 0x1FFFFE00, 0x200); target_add_ram(t, 0x20000000, 0x600); - kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x3FFF, 0x400, KL_WRITE_LEN); break; case 1: t->driver = "KL02x8"; target_add_ram(t, 0x1FFFFF00, 0x100); target_add_ram(t, 0x20000000, 0x300); - kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN); break; default: return false; @@ -249,14 +270,14 @@ bool kinetis_probe(target *const t) t->driver = "KL03"; target_add_ram(t, 0x1ffffe00, 0x200); target_add_ram(t, 0x20000000, 0x600); - kl_gen_add_flash(t, 0, 0x8000, 0x400, KL_WRITE_LEN); + kinetis_add_flash(t, 0, 0x8000, 0x400, KL_WRITE_LEN); break; case 0x220: /* K22F family */ t->driver = "K22F"; target_add_ram(t, 0x1c000000, 0x4000000); target_add_ram(t, 0x20000000, 0x100000); - kl_gen_add_flash(t, 0, 0x40000, 0x800, KL_WRITE_LEN); - kl_gen_add_flash(t, 0x40000, 0x40000, 0x800, KL_WRITE_LEN); + kinetis_add_flash(t, 0, 0x40000, 0x800, KL_WRITE_LEN); + kinetis_add_flash(t, 0x40000, 0x40000, 0x800, KL_WRITE_LEN); break; case 0x620: /* K64F family. */ /* This should be 0x640, but according to the errata sheet @@ -266,8 +287,8 @@ bool kinetis_probe(target *const t) t->driver = "K64"; target_add_ram(t, 0x1FFF0000, 0x10000); target_add_ram(t, 0x20000000, 0x30000); - kl_gen_add_flash(t, 0, 0x80000, 0x1000, K64_WRITE_LEN); - kl_gen_add_flash(t, 0x80000, 0x80000, 0x1000, K64_WRITE_LEN); + kinetis_add_flash(t, 0, 0x80000, 0x1000, K64_WRITE_LEN); + kinetis_add_flash(t, 0x80000, 0x80000, 0x1000, K64_WRITE_LEN); break; case 0x000: /* Older K-series */ switch (sdid & 0xff0) { @@ -282,24 +303,24 @@ bool kinetis_probe(target *const t) /* K12 Sub-Family Reference Manual, K12P80M50SF4RM, Rev. 4, February 2013 */ case 0x7: t->driver = "MK12DX128Vxx5"; - target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ - target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00020000, 0x800, KL_WRITE_LEN); /* P-Flash, 128 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ + target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ + target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ + kinetis_add_flash(t, 0x00000000, 0x00020000, 0x800, KL_WRITE_LEN); /* P-Flash, 128 KB, 2 KB Sectors */ + kinetis_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ break; case 0x9: t->driver = "MK12DX256Vxx5"; - target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ - target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ + target_add_ram(t, 0x1fffc000, 0x00004000); /* SRAM_L, 16 KB */ + target_add_ram(t, 0x20000000, 0x00004000); /* SRAM_H, 16 KB */ + kinetis_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kinetis_add_flash(t, 0x10000000, 0x00010000, 0x800, KL_WRITE_LEN); /* FlexNVM, 64 KB, 2 KB Sectors */ break; case 0xb: t->driver = "MK12DN512Vxx5"; - target_add_ram(t, 0x1fff8000, 0x00008000); /* SRAM_L, 32 KB */ - target_add_ram(t, 0x20000000, 0x00008000); /* SRAM_H, 32 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x00040000, 0x00040000, 0x800, KL_WRITE_LEN); /* FlexNVM, 256 KB, 2 KB Sectors */ + target_add_ram(t, 0x1fff8000, 0x00008000); /* SRAM_L, 32 KB */ + target_add_ram(t, 0x20000000, 0x00008000); /* SRAM_H, 32 KB */ + kinetis_add_flash(t, 0x00000000, 0x00040000, 0x800, KL_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kinetis_add_flash(t, 0x00040000, 0x00040000, 0x800, KL_WRITE_LEN); /* FlexNVM, 256 KB, 2 KB Sectors */ break; default: return false; @@ -329,10 +350,10 @@ bool kinetis_probe(target *const t) break; case 0x118: /* S32K118 */ t->driver = "S32K118"; - target_add_ram(t, 0x1ffffc00, 0x00000400); /* SRAM_L, 1 KB */ - target_add_ram(t, 0x20000000, 0x00005800); /* SRAM_H, 22 KB */ - kl_gen_add_flash(t, 0x00000000, 0x00040000, 0x800, K64_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ - kl_gen_add_flash(t, 0x10000000, 0x00008000, 0x800, K64_WRITE_LEN); /* FlexNVM, 32 KB, 2 KB Sectors */ + target_add_ram(t, 0x1ffffc00, 0x00000400); /* SRAM_L, 1 KB */ + target_add_ram(t, 0x20000000, 0x00005800); /* SRAM_H, 22 KB */ + kinetis_add_flash(t, 0x00000000, 0x00040000, 0x800, K64_WRITE_LEN); /* P-Flash, 256 KB, 2 KB Sectors */ + kinetis_add_flash(t, 0x10000000, 0x00008000, 0x800, K64_WRITE_LEN); /* FlexNVM, 32 KB, 2 KB Sectors */ break; /* gen1 s32k14x */ case 0x142: /* S32K142 */ @@ -373,46 +394,46 @@ bool kinetis_probe(target *const t) return true; } -static bool kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint32_t *data, int n_items) +static bool kinetis_fccob_cmd(target *t, uint8_t cmd, uint32_t addr, const uint32_t *data, int n_items) { uint8_t fstat; /* clear errors unconditionally, so we can start a new operation */ - target_mem_write8(t, FTFA_FSTAT, (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)); + target_mem_write8(t, FTFx_FSTAT, (FTFx_FSTAT_ACCERR | FTFx_FSTAT_FPVIOL)); /* Wait for CCIF to be high */ do { - fstat = target_mem_read8(t, FTFA_FSTAT); - } while (!(fstat & FTFA_FSTAT_CCIF)); + fstat = target_mem_read8(t, FTFx_FSTAT); + } while (!(fstat & FTFx_FSTAT_CCIF)); /* Write command to FCCOB */ addr &= 0xffffff; addr |= (uint32_t)cmd << 24; - target_mem_write32(t, FTFA_FCCOB_0, addr); + target_mem_write32(t, FTFx_FCCOB0, addr); if (data) { - target_mem_write32(t, FTFA_FCCOB_1, data[0]); + target_mem_write32(t, FTFx_FCCOB4, data[0]); if (n_items > 1) - target_mem_write32(t, FTFA_FCCOB_2, data[1]); + target_mem_write32(t, FTFx_FCCOB8, data[1]); } /* Enable execution by clearing CCIF */ - target_mem_write8(t, FTFA_FSTAT, FTFA_FSTAT_CCIF); + target_mem_write8(t, FTFx_FSTAT, FTFx_FSTAT_CCIF); /* Wait for execution to complete */ do { - fstat = target_mem_read8(t, FTFA_FSTAT); + fstat = target_mem_read8(t, FTFx_FSTAT); /* Check ACCERR and FPVIOL are zero in FSTAT */ - if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)) + if (fstat & (FTFx_FSTAT_ACCERR | FTFx_FSTAT_FPVIOL)) return false; - } while (!(fstat & FTFA_FSTAT_CCIF)); + } while (!(fstat & FTFx_FSTAT_CCIF)); return true; } -static int kl_gen_flash_erase(struct target_flash *const f, target_addr addr, size_t len) +static int kinetis_flash_cmd_erase(struct target_flash *const f, target_addr addr, size_t len) { while (len) { - if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL, 0)) { + if (kinetis_fccob_cmd(f->t, FTFx_CMD_ERASE_SECTOR, addr, NULL, 0)) { /* Different targets have different flash erase sizes */ if (len > f->blocksize) len -= f->blocksize; @@ -426,10 +447,7 @@ static int kl_gen_flash_erase(struct target_flash *const f, target_addr addr, si return 0; } -#define FLASH_SECURITY_BYTE_ADDRESS 0x40C -#define FLASH_SECURITY_BYTE_UNSECURED 0xFE - -static int kl_gen_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) +static int kinetis_flash_cmd_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { struct kinetis_flash *const kf = (struct kinetis_flash *)f; @@ -441,12 +459,12 @@ static int kl_gen_flash_write(struct target_flash *f, target_addr dest, const vo /* Determine write command based on the alignment. */ uint8_t write_cmd; if (kf->write_len == K64_WRITE_LEN) - write_cmd = FTFE_CMD_PROGRAM_PHRASE; + write_cmd = FTFx_CMD_PROGRAM_PHRASE; else - write_cmd = FTFA_CMD_PROGRAM_LONGWORD; + write_cmd = FTFx_CMD_PROGRAM_LONGWORD; while (len) { - if (kl_gen_command(f->t, write_cmd, dest, src, 1)) { + if (kinetis_fccob_cmd(f->t, write_cmd, dest, src, 1)) { if (len > kf->write_len) len -= kf->write_len; else @@ -459,7 +477,7 @@ static int kl_gen_flash_write(struct target_flash *f, target_addr dest, const vo return 0; } -static int kl_gen_flash_done(struct target_flash *const f) +static int kinetis_flash_done(struct target_flash *const f) { struct kinetis_flash *const kf = (struct kinetis_flash *)f; @@ -477,12 +495,12 @@ static int kl_gen_flash_done(struct target_flash *const f) vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS - 4); vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; - kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2); + kinetis_fccob_cmd(f->t, FTFx_CMD_PROGRAM_PHRASE, FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2); } else { uint32_t vals[1]; vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); vals[0] = (vals[0] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; - kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, FLASH_SECURITY_BYTE_ADDRESS, vals, 1); + kinetis_fccob_cmd(f->t, FTFx_CMD_PROGRAM_LONGWORD, FLASH_SECURITY_BYTE_ADDRESS, vals, 1); } return 0; @@ -496,15 +514,14 @@ static int kl_gen_flash_done(struct target_flash *const f) * device. This provides a fake target to allow a monitor command interface */ -#define KINETIS_MDM_IDR_K22F 0x1c0000 -#define KINETIS_MDM_IDR_KZ03 0x1c0020 - static bool kinetis_mdm_cmd_erase_mass(target *t, int argc, const char **argv); static bool kinetis_mdm_cmd_ke04_mode(target *t, int argc, const char **argv); const struct command_s kinetis_mdm_cmd_list[] = { {"erase_mass", (cmd_handler)kinetis_mdm_cmd_erase_mass, "Erase entire flash memory"}, - {"ke04_mode", (cmd_handler)kinetis_mdm_cmd_ke04_mode, "Allow erase for KE04"}, {NULL, NULL, NULL}}; + {"ke04_mode", (cmd_handler)kinetis_mdm_cmd_ke04_mode, "Allow erase for KE04"}, + {NULL, NULL, NULL}, +}; enum target_halt_reason mdm_halt_poll(target *t, const target_addr *const watch) { @@ -537,16 +554,6 @@ void kinetis_mdm_probe(ADIv5_AP_t *ap) target_add_commands(t, kinetis_mdm_cmd_list, t->driver); } -#define MDM_STATUS ADIV5_AP_REG(0x00) -#define MDM_CONTROL ADIV5_AP_REG(0x04) - -#define MDM_STATUS_MASS_ERASE_ACK (1 << 0) -#define MDM_STATUS_FLASH_READY (1 << 1) -#define MDM_STATUS_MASS_ERASE_ENABLED (1 << 5) - -#define MDM_CONTROL_MASS_ERASE (1 << 0) -#define MDM_CONTROL_SYS_RESET (1 << 3) - /* This is needed as a separate command, as there's no way to * * tell a KE04 from other kinetis in kinetis_mdm_probe() */ static bool kinetis_mdm_cmd_ke04_mode(target *t, int argc, const char **argv) From 0f1006bf0895dfda8230ffde4b1bba535f670337 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 00:21:38 -0400 Subject: [PATCH 14/32] kinetis: Try to be safer about our FCCOB writes so the Flash controller's less likely to get mad --- src/target/kinetis.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 3c075bdf..c38cc987 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -407,13 +407,15 @@ static bool kinetis_fccob_cmd(target *t, uint8_t cmd, uint32_t addr, const uint3 } while (!(fstat & FTFx_FSTAT_CCIF)); /* Write command to FCCOB */ - addr &= 0xffffff; - addr |= (uint32_t)cmd << 24; + addr &= 0x00ffffffU; + addr |= cmd << 24U; target_mem_write32(t, FTFx_FCCOB0, addr); - if (data) { + if (data && n_items) { target_mem_write32(t, FTFx_FCCOB4, data[0]); if (n_items > 1) target_mem_write32(t, FTFx_FCCOB8, data[1]); + else + target_mem_write32(t, FTFx_FCCOB8, 0); } /* Enable execution by clearing CCIF */ From 0dffd2ffd24688904a96c136c9e8004f69fd4a04 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 22 Jun 2022 00:23:13 -0400 Subject: [PATCH 15/32] kinetis: Fixed the flash write command generation for K64 devices --- src/target/kinetis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index c38cc987..53f4eb0f 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -466,7 +466,7 @@ static int kinetis_flash_cmd_write(struct target_flash *f, target_addr dest, con write_cmd = FTFx_CMD_PROGRAM_LONGWORD; while (len) { - if (kinetis_fccob_cmd(f->t, write_cmd, dest, src, 1)) { + if (kinetis_fccob_cmd(f->t, write_cmd, dest, src, kf->write_len >> 2U)) { if (len > kf->write_len) len -= kf->write_len; else From d01acd8030378af65020b5a26771c2a99e38b784 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 28 Jun 2022 23:30:19 -0400 Subject: [PATCH 16/32] kinetis: Clean up how kl_gen_flash_done builds the command buffers to send to ensure the security byte is OK --- src/target/kinetis.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 53f4eb0f..3ab08c3b 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -493,16 +493,16 @@ static int kinetis_flash_done(struct target_flash *const f) * vs 4 byte phrases). */ if (kf->write_len == K64_WRITE_LEN) { - uint32_t vals[2]; - vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS - 4); - vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); - vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; + uint32_t vals[2] = { + target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS - 4), + target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS) + }; + vals[1] = (vals[1] & 0xffffff00U) | FLASH_SECURITY_BYTE_UNSECURED; kinetis_fccob_cmd(f->t, FTFx_CMD_PROGRAM_PHRASE, FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2); } else { - uint32_t vals[1]; - vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); - vals[0] = (vals[0] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; - kinetis_fccob_cmd(f->t, FTFx_CMD_PROGRAM_LONGWORD, FLASH_SECURITY_BYTE_ADDRESS, vals, 1); + uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); + val = (val & 0xffffff00U) | FLASH_SECURITY_BYTE_UNSECURED; + kinetis_fccob_cmd(f->t, FTFx_CMD_PROGRAM_LONGWORD, FLASH_SECURITY_BYTE_ADDRESS, &val, 1); } return 0; From a067e801d77e754eea8fe2931e98183cf5434f3e Mon Sep 17 00:00:00 2001 From: Piotr Esden-Tempski Date: Wed, 13 Jul 2022 17:41:35 -0700 Subject: [PATCH 17/32] BMP V2.3: Fix outdated ADC reads. We are using GD32F103 on the BMP V2.3 hardware. The GD32F103 has an errata for the ADC where the end of conversion (EOC) bit is not reset when reading the ADC result. This resulted in us not waiting for the new value to be acquired and reading an old value instead. The solution for that is resetting the EOC bit manually after reading the ADC result, so that on the next acquisision we wait for the conversion to finish. This patch also increases the sampling time as the GD32 have lower ADC impedance than the STM32 and this should help us read a more accuarate target voltage. --- src/platforms/native/platform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index c732aaa7..5589e242 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -285,7 +285,7 @@ static void adc_init(void) adc_set_single_conversion_mode(ADC1); adc_disable_external_trigger_regular(ADC1); adc_set_right_aligned(ADC1); - adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); + adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_239DOT5CYC); adc_power_on(ADC1); @@ -316,6 +316,8 @@ uint32_t platform_target_voltage_sense(void) while (!adc_eoc(ADC1)); uint32_t val = adc_read_regular(ADC1); /* 0-4095 */ + /* Clear EOC bit. The GD32F103 does not automatically reset it on ADC read. */ + ADC_SR(ADC1) &= ~ADC_SR_EOC; return (val * 99) / 8191; } From 34696c0fec5c33ea1c5c48115d14446800d49c02 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 5 Jul 2022 12:12:18 -0400 Subject: [PATCH 18/32] target: Make the buffers used to program a target's Flash better bounded in lifetime and memory usage --- src/target/target.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/target/target.c b/src/target/target.c index 6e8ba24b..0eb0fe3c 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -271,6 +271,11 @@ int target_flash_write(target *t, dest += tmplen; src += tmplen; len -= tmplen; + /* If the current chunk of Flash is now full from this operation + * then finish operations on the Flash chunk and free the internal buffer. + */ + if (dest == f->start + f->length) + ret |= target_flash_done_buffered(f); } return ret; } From 1cf1ba1ddbaf9a073a62a1e5d5cdb282b0b2aa0d Mon Sep 17 00:00:00 2001 From: Piotr Esden-Tempski Date: Wed, 13 Jul 2022 20:34:05 -0700 Subject: [PATCH 19/32] stm32f4: Fixes erase_mass command return error. The final erase_mass command check is looking for the EOP (End of OPeration) bit to be set. This bit is only set when the EOP interrupts (EOPIE = 1) are enabled. We are not enabling those on the target so this bit will never get set. As we are monitoring the BSY flag to make sure the erase_mass operation is still ongoing and finished it is enough if we just check the error flags. --- src/target/stm32f4.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index b73c3ee9..e28aa96b 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -56,7 +56,7 @@ static int stm32f4_flash_erase(struct target_flash *f, target_addr addr, static int stm32f4_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len); -/* Flash Program ad Erase Controller Register Map */ +/* Flash Program and Erase Controller Register Map */ #define FPEC_BASE 0x40023C00 #define FLASH_ACR (FPEC_BASE+0x00) #define FLASH_KEYR (FPEC_BASE+0x04) @@ -503,11 +503,8 @@ static bool stm32f4_cmd_erase_mass(target *t, int argc, const char **argv) tc_printf(t, "\n"); /* Check for error */ - uint32_t sr = target_mem_read32(t, FLASH_SR); - if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) - return false; - - return true; + const uint32_t result = target_mem_read32(t, FLASH_SR); + return !(result & SR_ERROR_MASK); } /* Dev | DOC |Rev|ID |OPTCR |OPTCR |OPTCR1 |OPTCR1 | OPTCR2 From 47c84fac85682553c4fddabb6727c0140ced06cf Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 01:08:19 +0100 Subject: [PATCH 20/32] gdb_packet: Done a spring pass on the types situation and cleaned things up --- src/gdb_hostio.c | 1 - src/gdb_main.c | 14 ++++---- src/gdb_packet.c | 69 ++++++++++++++++++++-------------------- src/include/gdb_packet.h | 8 ++--- 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/gdb_hostio.c b/src/gdb_hostio.c index 82ff0a6d..0c2e1871 100644 --- a/src/gdb_hostio.c +++ b/src/gdb_hostio.c @@ -130,4 +130,3 @@ int hostio_system(struct target_controller *tc, gdb_putpacket_f("Fsystem,%08X/%X", cmd, cmd_len); return gdb_main_loop(tc, true); } - diff --git a/src/gdb_main.c b/src/gdb_main.c index 38f909c5..1b1e7931 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -100,15 +100,14 @@ static struct target_controller gdb_controller = { int gdb_main_loop(struct target_controller *tc, bool in_syscall) { - int size; bool single_step = false; /* GDB protocol main loop */ - while(1) { + while (1) { SET_IDLE_STATE(1); - size = gdb_getpacket(pbuf, BUF_SIZE); + size_t size = gdb_getpacket(pbuf, BUF_SIZE); SET_IDLE_STATE(0); - switch(pbuf[0]) { + switch (pbuf[0]) { /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); @@ -166,7 +165,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) single_step = true; /* fall through */ case 'c': /* 'c [addr]': Continue [at addr] */ - if(!cur_target) { + if (!cur_target) { gdb_putpacketz("X1D"); break; } @@ -189,10 +188,9 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) /* Wait for target halt */ while(!(reason = target_halt_poll(cur_target, &watch))) { - unsigned char c = gdb_if_getchar_to(0); - if((c == '\x03') || (c == '\x04')) { + char c = (char)gdb_if_getchar_to(0); + if(c == '\x03' || c == '\x04') target_halt_request(cur_target); - } } SET_RUN_STATE(0); diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 33dada53..3ca01ed0 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -30,12 +30,11 @@ #include -int gdb_getpacket(char *packet, int size) +size_t gdb_getpacket(char *packet, size_t size) { - unsigned char c; unsigned char csum; char recv_csum[3]; - int i; + size_t offset = 0; while (1) { /* Wait for packet start */ @@ -44,7 +43,8 @@ int gdb_getpacket(char *packet, int size) * start ('$') or a BMP remote packet start ('!'). */ do { - packet[0] = gdb_if_getchar(); + /* Smells like bad code */ + packet[0] = (char)gdb_if_getchar(); if (packet[0] == 0x04) return 1; } while ((packet[0] != '$') && (packet[0] != REMOTE_SOM)); @@ -52,18 +52,19 @@ int gdb_getpacket(char *packet, int size) if (packet[0] == REMOTE_SOM) { /* This is probably a remote control packet * - get and handle it */ - i = 0; + offset = 0; bool gettingRemotePacket = true; while (gettingRemotePacket) { - c = gdb_if_getchar(); + /* Smells like bad code */ + const char c = (char)gdb_if_getchar(); switch (c) { case REMOTE_SOM: /* Oh dear, packet restarts */ - i = 0; + offset = 0; break; case REMOTE_EOM: /* Complete packet for processing */ - packet[i] = 0; - remotePacketProcess(i, packet); + packet[offset] = 0; + remotePacketProcess(offset, packet); gettingRemotePacket = false; break; @@ -73,8 +74,8 @@ int gdb_getpacket(char *packet, int size) break; default: - if (i < size) { - packet[i++] = c; + if (offset < size) { + packet[offset++] = c; } else { /* Who knows what is going on...return to normality */ gettingRemotePacket = false; @@ -92,30 +93,32 @@ int gdb_getpacket(char *packet, int size) #endif } while (packet[0] != '$'); - i = 0; + offset = 0; csum = 0; + char c; /* Capture packet data into buffer */ - while ((c = gdb_if_getchar()) != '#') { + while ((c = (char)gdb_if_getchar()) != '#') { - if (i == size) /* Oh shit */ + /* If we run out of buffer space, exit early */ + if (offset == size) break; if (c == '$') { /* Restart capture */ - i = 0; + offset = 0; csum = 0; continue; } if (c == '}') { /* escaped char */ c = gdb_if_getchar(); csum += c + '}'; - packet[i++] = c ^ 0x20; + packet[offset++] = c ^ 0x20; continue; } csum += c; - packet[i++] = c; + packet[offset++] = c; } - recv_csum[0] = gdb_if_getchar(); - recv_csum[1] = gdb_if_getchar(); + recv_csum[0] = (char)gdb_if_getchar(); + recv_csum[1] = (char)gdb_if_getchar(); recv_csum[2] = 0; /* return packet if checksum matches */ @@ -126,20 +129,20 @@ int gdb_getpacket(char *packet, int size) gdb_if_putchar('-', 1); /* send nack */ } gdb_if_putchar('+', 1); /* send ack */ - packet[i] = 0; + packet[offset] = 0; #if PC_HOSTED == 1 DEBUG_GDB_WIRE("%s : ", __func__); - for(int j = 0; j < i; j++) { - c = packet[j]; - if ((c >= 32) && (c < 127)) + for (size_t j = 0; j < offset; j++) { + const char c = packet[j]; + if (c >= ' ' && c < 0x7F) DEBUG_GDB_WIRE("%c", c); else DEBUG_GDB_WIRE("\\x%02X", c); } DEBUG_GDB_WIRE("\n"); #endif - return i; + return offset; } static void gdb_next_char(char c, unsigned char *csum) @@ -161,21 +164,19 @@ static void gdb_next_char(char c, unsigned char *csum) } } -void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int size2) +void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size_t size2) { - int i; - unsigned char csum; char xmit_csum[3]; int tries = 0; do { DEBUG_GDB_WIRE("%s : ", __func__); - csum = 0; + unsigned char csum = 0; gdb_if_putchar('$', 0); - for (i = 0; i < size1; ++i) + for (size_t i = 0; i < size1; ++i) gdb_next_char(packet1[i], &csum); - for (i = 0; i < size2; ++i) + for (size_t i = 0; i < size2; ++i) gdb_next_char(packet2[i], &csum); gdb_if_putchar('#', 0); @@ -186,18 +187,16 @@ void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int siz } while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); } -void gdb_putpacket(const char *packet, int size) +void gdb_putpacket(const char *packet, size_t size) { - int i; - unsigned char csum; char xmit_csum[3]; int tries = 0; do { DEBUG_GDB_WIRE("%s : ", __func__); - csum = 0; + unsigned char csum = 0; gdb_if_putchar('$', 0); - for (i = 0; i < size; ++i) + for (size_t i = 0; i < size; ++i) gdb_next_char(packet[i], &csum); gdb_if_putchar('#', 0); snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum); diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index af23c5b2..89733ed1 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -23,9 +23,9 @@ #include -int gdb_getpacket(char *packet, int size); -void gdb_putpacket(const char *packet, int size); -void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int size2); +size_t gdb_getpacket(char *packet, size_t size); +void gdb_putpacket(const char *packet, size_t size); +void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size_t size2); #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) void gdb_putpacket_f(const char *packet, ...); @@ -34,5 +34,3 @@ void gdb_voutf(const char *fmt, va_list); void gdb_outf(const char *fmt, ...); #endif - - From 17ba28c44b9288c12410ccd96f0879df62f5d785 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 01:22:25 +0100 Subject: [PATCH 21/32] gdb_main: Implemented H[m|M|g|G|c] packet support --- src/gdb_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gdb_main.c b/src/gdb_main.c index 1b1e7931..66bc9876 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -161,6 +161,19 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) gdb_putpacketz("OK"); break; } + /* '[m|M|g|G|c][thread-id]' : Set the thread ID for the given subsequent operation + * (we don't actually care which as we only care about the TID for whether to send OK or an error) + */ + case 'H': { + char operation = 0; + uint32_t thread_id = 0; + sscanf(pbuf, "H%c%" SCNx32, &operation, &thread_id); + if (thread_id <= 1) + gdb_putpacketz("OK"); + else + gdb_putpacketz("E01"); + break; + } case 's': /* 's [addr]': Single step [start at addr] */ single_step = true; /* fall through */ From 7322bb3ffaa80f3aebce8d0640a0a4ee55c1f27b Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 01:42:26 +0100 Subject: [PATCH 22/32] gdb_main: More type confusion fixes and cleanup --- src/gdb_main.c | 114 ++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 59 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index 66bc9876..d98c5095 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -43,7 +43,7 @@ enum gdb_signal { GDB_SIGLOST = 29, }; -#define BUF_SIZE 1024 +#define BUF_SIZE 1024U #define ERROR_IF_NO_TARGET() \ if(!cur_target) { gdb_putpacketz("EFF"); break; } @@ -51,17 +51,17 @@ enum gdb_signal { typedef struct { const char *cmd_prefix; - void (*func)(const char *packet, int len); + void (*func)(const char *packet, size_t len); } cmd_executer; -static char pbuf[BUF_SIZE + 1]; +static char pbuf[BUF_SIZE + 1U]; static target *cur_target; static target *last_target; -static void handle_q_packet(char *packet, int len); -static void handle_v_packet(char *packet, int len); -static void handle_z_packet(char *packet, int len); +static void handle_q_packet(char *packet, size_t len); +static void handle_v_packet(char *packet, size_t len); +static void handle_z_packet(char *packet, size_t len); static void gdb_target_destroy_callback(struct target_controller *tc, target *t) { @@ -143,7 +143,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) break; } case 'M': { /* 'M addr,len:XX': Write len bytes to addr */ - uint32_t addr, len; + uint32_t addr = 0; + uint32_t len = 0; int hex; ERROR_IF_NO_TARGET(); sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex); @@ -346,12 +347,12 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) } } -static bool exec_command(char *packet, int len, const cmd_executer *exec) +static bool exec_command(char *packet, const size_t length, const cmd_executer *exec) { while (exec->cmd_prefix) { - const int l = strlen(exec->cmd_prefix); - if (!strncmp(packet, exec->cmd_prefix, l)) { - exec->func(packet + l, len - l); + const size_t prefix_length = strlen(exec->cmd_prefix); + if (!strncmp(packet, exec->cmd_prefix, prefix_length)) { + exec->func(packet + prefix_length, length - prefix_length); return true; } ++exec; @@ -359,19 +360,16 @@ static bool exec_command(char *packet, int len, const cmd_executer *exec) return false; } -static void exec_q_rcmd(const char *packet,int len) +static void exec_q_rcmd(const char *packet, const size_t length) { - char *data; - int datalen; - /* calculate size and allocate buffer for command */ - datalen = len / 2; - data = alloca(datalen + 1); + const size_t datalen = length / 2U; + char *data = alloca(datalen + 1); /* dehexify command */ unhexify(data, packet, datalen); data[datalen] = 0; /* add terminating null */ - int c = command_process(cur_target, data); + const int c = command_process(cur_target, data); if (c < 0) gdb_putpacketz(""); else if (c == 0) @@ -381,41 +379,41 @@ static void exec_q_rcmd(const char *packet,int len) 2 * strlen("Failed\n")); } -static void -handle_q_string_reply(const char *str, const char *param) +static void handle_q_string_reply(const char *reply, const char *param) { - unsigned long addr, len; - const size_t str_len = strlen(str); + const size_t reply_length = strlen(reply); + uint32_t addr = 0; + uint32_t len = 0; - if (sscanf(param, "%08lx,%08lx", &addr, &len) != 2) { + if (sscanf(param, "%08" PRIx32 ",%08" PRIx32, &addr, &len) != 2) { gdb_putpacketz("E01"); return; } - else if (addr > str_len) { + if (addr > reply_length) { gdb_putpacketz("E01"); return; } - else if (addr == str_len) { + if (addr == reply_length) { gdb_putpacketz("l"); return; } - unsigned long output_len = str_len - addr; + size_t output_len = reply_length - addr; if (output_len > len) output_len = len; - gdb_putpacket2("m", 1, str + addr, output_len); + gdb_putpacket2("m", 1U, reply + addr, output_len); } -static void exec_q_supported(const char *packet, int len) +static void exec_q_supported(const char *packet, const size_t length) { (void)packet; - (void)len; + (void)length; gdb_putpacket_f("PacketSize=%X;qXfer:memory-map:read+;qXfer:features:read+", BUF_SIZE); } -static void exec_q_memory_map(const char *packet, int len) +static void exec_q_memory_map(const char *packet, const size_t length) { (void)packet; - (void)len; + (void)length; /* Read target XML memory map */ if ((!cur_target) && last_target) { /* Attach to last target if detached. */ @@ -431,9 +429,9 @@ static void exec_q_memory_map(const char *packet, int len) handle_q_string_reply(buf, packet); } -static void exec_q_feature_read(const char *packet, int len) +static void exec_q_feature_read(const char *packet, const size_t length) { - (void)len; + (void)length; /* Read target description */ if ((!cur_target) && last_target) { /* Attach to last target if detached. */ @@ -446,18 +444,18 @@ static void exec_q_feature_read(const char *packet, int len) handle_q_string_reply(target_tdesc(cur_target), packet); } -static void exec_q_crc(const char *packet, int len) +static void exec_q_crc(const char *packet, const size_t length) { - (void)len; - uint32_t addr, alen; - if (sscanf(packet, "%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) { + (void)length; + uint32_t addr; + uint32_t addr_length; + if (sscanf(packet, "%" PRIx32 ",%" PRIx32, &addr, &addr_length) == 2) { if (!cur_target) { gdb_putpacketz("E01"); return; } uint32_t crc; - int res = generic_crc32(cur_target, &crc, addr, alen); - if (res) + if (generic_crc32(cur_target, &crc, addr, addr_length)) gdb_putpacketz("E03"); else gdb_putpacket_f("C%lx", crc); @@ -474,23 +472,22 @@ static const cmd_executer q_commands[]= {NULL, NULL}, }; -static void -handle_q_packet(char *packet, int len) +static void handle_q_packet(char *packet, const size_t length) { - if (exec_command(packet, len, q_commands)) + if (exec_command(packet, length, q_commands)) return; DEBUG_GDB("*** Unsupported packet: %s\n", packet); gdb_putpacket("", 0); } -static void -handle_v_packet(char *packet, int plen) +static void handle_v_packet(char *packet, const size_t plen) { - unsigned long addr, len; + uint32_t addr = 0; + uint32_t len = 0; int bin; static uint8_t flash_mode = 0; - if (sscanf(packet, "vAttach;%08lx", &addr) == 1) { + if (sscanf(packet, "vAttach;%08" PRIx32, &addr) == 1) { /* Attach to remote target processor */ cur_target = target_attach_n(addr, &gdb_controller); if(cur_target) { @@ -550,9 +547,9 @@ handle_v_packet(char *packet, int plen) } else gdb_putpacketz("E01"); - } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { + } else if (sscanf(packet, "vFlashErase:%08" PRIx32 ",%08" PRIx32, &addr, &len) == 2) { /* Erase Flash Memory */ - DEBUG_GDB("Flash Erase %08lX %08lX\n", addr, len); + DEBUG_GDB("Flash Erase %08zX %08zX\n", addr, len); if (!cur_target) { gdb_putpacketz("EFF"); return; @@ -571,11 +568,11 @@ handle_v_packet(char *packet, int plen) gdb_putpacketz("EFF"); } - } else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) { + } else if (sscanf(packet, "vFlashWrite:%08" PRIx32 ":%n", &addr, &bin) == 1) { /* Write Flash Memory */ - len = plen - bin; - DEBUG_GDB("Flash Write %08lX %08lX\n", addr, len); - if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0) + const size_t count = plen - bin; + DEBUG_GDB("Flash Write %08zX %08zX\n", addr, count); + if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, count) == 0) gdb_putpacketz("OK"); else { flash_mode = 0; @@ -593,18 +590,17 @@ handle_v_packet(char *packet, int plen) } } -static void -handle_z_packet(char *packet, int plen) +static void handle_z_packet(char *packet, const size_t plen) { (void)plen; - uint8_t set = (packet[0] == 'Z') ? 1 : 0; - int type, len; + uint32_t type; + uint32_t len; uint32_t addr; - int ret; + sscanf(packet, "%*[zZ]%" PRIu32 ",%08" PRIx32 ",%" PRIu32, &type, &addr, &len); - sscanf(packet, "%*[zZ]%d,%08" PRIx32 ",%d", &type, &addr, &len); - if(set) + int ret = 0; + if (packet[0] == 'Z') ret = target_breakwatch_set(cur_target, type, addr, len); else ret = target_breakwatch_clear(cur_target, type, addr, len); From 1f22c726347cd00d8231e5b1d43b850dbda0eb97 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 01:45:00 +0100 Subject: [PATCH 23/32] gdb_main: Implemented support for qC queries --- src/gdb_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/gdb_main.c b/src/gdb_main.c index d98c5095..ee45a542 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -462,6 +462,17 @@ static void exec_q_crc(const char *packet, const size_t length) } } +/* + * qC queries are for the current thread. We don't support threads but GDB 11 and 12 require this, + * so we always answer that the current thread is thread 1. + */ +static void exec_q_c(const char *packet, const size_t length) +{ + (void)packet; + (void)length; + gdb_putpacketz("QC1"); +} + static const cmd_executer q_commands[]= { {"qRcmd,", exec_q_rcmd}, @@ -469,6 +480,7 @@ static const cmd_executer q_commands[]= {"qXfer:memory-map:read::", exec_q_memory_map}, {"qXfer:features:read:target.xml:",exec_q_feature_read}, {"qCRC:", exec_q_crc}, + {"qC", exec_q_c}, {NULL, NULL}, }; From 8db1d3085284214f661340d61b601f752508a1fa Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 01:51:51 +0100 Subject: [PATCH 24/32] gdb_main: Reply to vAttach with TID 1 because GDB 11 and 12 are terminally broken otherwise --- src/gdb_main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index ee45a542..b9da704a 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -504,7 +504,16 @@ static void handle_v_packet(char *packet, const size_t plen) cur_target = target_attach_n(addr, &gdb_controller); if(cur_target) { morse(NULL, false); - gdb_putpacketz("T05"); + /* + * We don't actually support threads, but GDB 11 and 12 can't work without + * us saying we attached to thread 1.. see the following for the low-down of this: + * https://sourceware.org/bugzilla/show_bug.cgi?id=28405 + * https://sourceware.org/bugzilla/show_bug.cgi?id=28874 + * https://sourceware.org/pipermail/gdb-patches/2021-December/184171.html + * https://sourceware.org/pipermail/gdb-patches/2022-April/188058.html + * https://sourceware.org/pipermail/gdb-patches/2022-July/190869.html + */ + gdb_putpacketz("T05thread:1;"); } else gdb_putpacketz("E01"); From eb9d9893f8e19db98b78e75bac5346ca36bd7af9 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 02:12:07 +0100 Subject: [PATCH 25/32] hex_utils: Cleaned up and fixed the type confusion that was going on --- src/hex_utils.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/hex_utils.c b/src/hex_utils.c index e18df58e..b87b7331 100644 --- a/src/hex_utils.c +++ b/src/hex_utils.c @@ -26,16 +26,16 @@ static const char hexdigits[] = "0123456789abcdef"; -char * hexify(char *hex, const void *buf, size_t size) +char *hexify(char *hex, const void *buf, const size_t size) { - char *tmp = hex; - const uint8_t *b = buf; + char *dst = hex; + const uint8_t *const src = buf; - while (size--) { - *tmp++ = hexdigits[*b >> 4]; - *tmp++ = hexdigits[*b++ & 0xF]; + for (size_t idx = 0; idx < size; ++idx) { + *dst++ = hexdigits[src[idx] >> 4]; + *dst++ = hexdigits[src[idx] & 0xF]; } - *tmp++ = 0; + *dst++ = 0; return hex; } @@ -43,20 +43,18 @@ char * hexify(char *hex, const void *buf, size_t size) static uint8_t unhex_digit(char hex) { uint8_t tmp = hex - '0'; - if(tmp > 9) + if (tmp > 9) tmp -= 'A' - '0' - 10; - if(tmp > 16) + if (tmp > 16) tmp -= 'a' - 'A'; return tmp; } -char * unhexify(void *buf, const char *hex, size_t size) +char *unhexify(void *buf, const char *hex, const size_t size) { - uint8_t *b = buf; - while (size--) { - *b = unhex_digit(*hex++) << 4; - *b++ |= unhex_digit(*hex++); + uint8_t *const dst = buf; + for (size_t idx = 0; idx < size; ++idx, hex += 2) { + dst[idx] = (unhex_digit(hex[0]) << 4) | unhex_digit(hex[1]); } return buf; } - From c6d1bcb3523734878259d853c33bf9eff0c480bc Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 02:15:33 +0100 Subject: [PATCH 26/32] gdb_main: Cleaned up the naming in the 'g' and 'G' packet handlers --- src/gdb_main.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index b9da704a..591c91f6 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -111,10 +111,9 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); - uint8_t arm_regs[target_regs_size(cur_target)]; - target_regs_read(cur_target, arm_regs); - gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)), - sizeof(arm_regs) * 2); + uint8_t gp_regs[target_regs_size(cur_target)]; + target_regs_read(cur_target, gp_regs); + gdb_putpacket(hexify(pbuf, gp_regs, sizeof(gp_regs)), sizeof(gp_regs) * 2U); break; } case 'm': { /* 'm addr,len': Read len bytes from addr */ @@ -131,14 +130,14 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) if (target_mem_read(cur_target, mem, addr, len)) gdb_putpacketz("E01"); else - gdb_putpacket(hexify(pbuf, mem, len), len * 2); + gdb_putpacket(hexify(pbuf, mem, len), len * 2U); break; } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); - uint8_t arm_regs[target_regs_size(cur_target)]; - unhexify(arm_regs, &pbuf[1], sizeof(arm_regs)); - target_regs_write(cur_target, arm_regs); + uint8_t gp_regs[target_regs_size(cur_target)]; + unhexify(gp_regs, &pbuf[1], sizeof(gp_regs)); + target_regs_write(cur_target, gp_regs); gdb_putpacketz("OK"); break; } From 65ac07441056c6f99c0f57dbee08cf1834775e5e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 05:33:40 +0100 Subject: [PATCH 27/32] gdb_main: Implemented vKill as it's required for GDB 11+ --- src/gdb_main.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index 591c91f6..23b9b605 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -62,6 +62,7 @@ static target *last_target; static void handle_q_packet(char *packet, size_t len); static void handle_v_packet(char *packet, size_t len); static void handle_z_packet(char *packet, size_t len); +static void handle_kill_target(void); static void gdb_target_destroy_callback(struct target_controller *tc, target *t) { @@ -285,12 +286,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) break; case 'k': /* Kill the target */ - if(cur_target) { - target_reset(cur_target); - target_detach(cur_target); - last_target = cur_target; - cur_target = NULL; - } + handle_kill_target(); break; case 'r': /* Reset the target system */ @@ -483,6 +479,16 @@ static const cmd_executer q_commands[]= {NULL, NULL}, }; +static void handle_kill_target(void) +{ + if (cur_target) { + target_reset(cur_target); + target_detach(cur_target); + last_target = cur_target; + cur_target = NULL; + } +} + static void handle_q_packet(char *packet, const size_t length) { if (exec_command(packet, length, q_commands)) @@ -516,6 +522,11 @@ static void handle_v_packet(char *packet, const size_t plen) } else gdb_putpacketz("E01"); + } else if (!strncmp(packet, "vKill;", 6)) { + /* Kill the target - we don't actually care about the PID that follows "vKill;" */ + handle_kill_target(); + gdb_putpacketz("OK"); + } else if (!strncmp(packet, "vRun", 4)) { /* Parse command line for get_cmdline semihosting call */ char cmdline[83]; From 3cc6aa1236a9a6141650451934403662908a00c0 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 05:39:48 +0100 Subject: [PATCH 28/32] gdb_main: Implemented qfThreadInfo and qsThreadInfo for GDB 11+ --- src/gdb_main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/gdb_main.c b/src/gdb_main.c index 23b9b605..a8e1c541 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -468,6 +468,22 @@ static void exec_q_c(const char *packet, const size_t length) gdb_putpacketz("QC1"); } +/* + * qfThreadInfo queries are required in GDB 11 and 12 as these GDBs require the server to support + * threading even when there's only the possiblity for one thread to exist. In this instance, + * we have to tell GDB that there is a single active thread so it doesn't think the "thread" died. + * qsThreadInfo will always follow qfThreadInfo when we reply as we have to specify 'l' at the + * end to terminate the list.. GDB doesn't like this not happening. + */ +static void exec_q_thread_info(const char *packet, const size_t length) +{ + (void)length; + if (packet[-11] == 'f') + gdb_putpacketz("m1"); + else + gdb_putpacketz("l"); +} + static const cmd_executer q_commands[]= { {"qRcmd,", exec_q_rcmd}, @@ -476,6 +492,8 @@ static const cmd_executer q_commands[]= {"qXfer:features:read:target.xml:",exec_q_feature_read}, {"qCRC:", exec_q_crc}, {"qC", exec_q_c}, + {"qfThreadInfo", exec_q_thread_info}, + {"qsThreadInfo", exec_q_thread_info}, {NULL, NULL}, }; From f254e8651126ef05affad77a66d307fedc8c2406 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 22:46:52 +0100 Subject: [PATCH 29/32] gdb_main: Add some output in the scan commands to indicate when still attached that you aren't after the command, despite what GDB thinks --- src/gdb_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index a8e1c541..4f64fd49 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -67,8 +67,10 @@ static void handle_kill_target(void); static void gdb_target_destroy_callback(struct target_controller *tc, target *t) { (void)tc; - if (cur_target == t) + if (cur_target == t) { + gdb_out("You are now detached from the previous target.\n"); cur_target = NULL; + } if (last_target == t) last_target = NULL; @@ -194,7 +196,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) target_addr watch; enum target_halt_reason reason; - if(!cur_target) { + if (!cur_target) { /* Report "target exited" if no target */ gdb_putpacketz("W00"); break; @@ -324,7 +326,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) handle_q_packet(pbuf, size); break; - case 'v': /* General query packet */ + case 'v': /* Verbose command packet */ handle_v_packet(pbuf, size); break; From d2370f780f45d445f68882671bc6d83bced07de5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 23:20:17 +0100 Subject: [PATCH 30/32] gdb_packet: Implement notification packets --- src/gdb_packet.c | 28 ++++++++++++++++++++++------ src/include/gdb_packet.h | 3 +++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 3ca01ed0..6f4f2e15 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -167,10 +167,10 @@ static void gdb_next_char(char c, unsigned char *csum) void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size_t size2) { char xmit_csum[3]; - int tries = 0; + size_t tries = 0; do { - DEBUG_GDB_WIRE("%s : ", __func__); + DEBUG_GDB_WIRE("%s: ", __func__); unsigned char csum = 0; gdb_if_putchar('$', 0); @@ -184,16 +184,16 @@ void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size gdb_if_putchar(xmit_csum[0], 0); gdb_if_putchar(xmit_csum[1], 1); DEBUG_GDB_WIRE("\n"); - } while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); + } while (gdb_if_getchar_to(2000) != '+' && tries++ < 3); } void gdb_putpacket(const char *packet, size_t size) { char xmit_csum[3]; - int tries = 0; + size_t tries = 0; do { - DEBUG_GDB_WIRE("%s : ", __func__); + DEBUG_GDB_WIRE("%s: ", __func__); unsigned char csum = 0; gdb_if_putchar('$', 0); for (size_t i = 0; i < size; ++i) @@ -203,7 +203,23 @@ void gdb_putpacket(const char *packet, size_t size) gdb_if_putchar(xmit_csum[0], 0); gdb_if_putchar(xmit_csum[1], 1); DEBUG_GDB_WIRE("\n"); - } while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); + } while (gdb_if_getchar_to(2000) != '+' && tries++ < 3); +} + +void gdb_put_notification(const char *const packet, const size_t size) +{ + char xmit_csum[3]; + + DEBUG_GDB_WIRE("%s: ", __func__); + uint8_t csum = 0; + gdb_if_putchar('%', 0); + for (size_t i = 0; i < size; ++i) + gdb_next_char(packet[i], &csum); + gdb_if_putchar('#', 0); + snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum); + gdb_if_putchar(xmit_csum[0], 0); + gdb_if_putchar(xmit_csum[1], 1); + DEBUG_GDB_WIRE("\n"); } void gdb_putpacket_f(const char *fmt, ...) diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index 89733ed1..d1e72087 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -21,6 +21,7 @@ #ifndef __GDB_PACKET_H #define __GDB_PACKET_H +#include #include size_t gdb_getpacket(char *packet, size_t size); @@ -28,6 +29,8 @@ void gdb_putpacket(const char *packet, size_t size); void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size_t size2); #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) void gdb_putpacket_f(const char *packet, ...); +void gdb_put_notification(const char *packet, size_t size); +#define gdb_put_notificationz(packet) gdb_put_notification((packet), strlen(packet)) void gdb_out(const char *buf); void gdb_voutf(const char *fmt, va_list); From fc55400aad8f71ee353de4157ed3c28034685d02 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 20 Jul 2022 23:23:04 +0100 Subject: [PATCH 31/32] gdb_main: Implemented a notification to GDB that the "process" has exited when the user runs a new bus scan while attached to a target --- src/gdb_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gdb_main.c b/src/gdb_main.c index 4f64fd49..bd17ae95 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -58,6 +58,7 @@ static char pbuf[BUF_SIZE + 1U]; static target *cur_target; static target *last_target; +static bool gdb_needs_detach_notify = false; static void handle_q_packet(char *packet, size_t len); static void handle_v_packet(char *packet, size_t len); @@ -68,8 +69,10 @@ static void gdb_target_destroy_callback(struct target_controller *tc, target *t) { (void)tc; if (cur_target == t) { + gdb_put_notificationz("%Stop:W00"); gdb_out("You are now detached from the previous target.\n"); cur_target = NULL; + gdb_needs_detach_notify = true; } if (last_target == t) @@ -635,6 +638,13 @@ static void handle_v_packet(char *packet, const size_t plen) gdb_putpacketz(target_flash_done(cur_target) ? "EFF" : "OK"); flash_mode = 0; + } else if (!strcmp(packet, "vStopped")) { + if (gdb_needs_detach_notify) { + gdb_putpacketz("W00"); + gdb_needs_detach_notify = false; + } else + gdb_putpacketz("OK"); + } else { DEBUG_GDB("*** Unsupported packet: %s\n", packet); gdb_putpacket("", 0); From 5cd430647ecfb6dab4a2ed858fb98567723de699 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 21 Jul 2022 06:37:12 +0100 Subject: [PATCH 32/32] gdb_main: Fixed a small DEBUG_GDB regression for vFlashErase and vFlashWrite debugging --- src/gdb_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index bd17ae95..081aa797 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -603,7 +603,7 @@ static void handle_v_packet(char *packet, const size_t plen) } else if (sscanf(packet, "vFlashErase:%08" PRIx32 ",%08" PRIx32, &addr, &len) == 2) { /* Erase Flash Memory */ - DEBUG_GDB("Flash Erase %08zX %08zX\n", addr, len); + DEBUG_GDB("Flash Erase %08" PRIX32 " %08" PRIX32 "\n", addr, len); if (!cur_target) { gdb_putpacketz("EFF"); return; @@ -624,8 +624,8 @@ static void handle_v_packet(char *packet, const size_t plen) } else if (sscanf(packet, "vFlashWrite:%08" PRIx32 ":%n", &addr, &bin) == 1) { /* Write Flash Memory */ - const size_t count = plen - bin; - DEBUG_GDB("Flash Write %08zX %08zX\n", addr, count); + const uint32_t count = plen - bin; + DEBUG_GDB("Flash Write %08" PRIX32 " %08" PRIX32 "\n", addr, count); if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, count) == 0) gdb_putpacketz("OK"); else {