From eed1cc81ff27608f6b306bfb2dcccc9d61de7975 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 22 Jan 2022 14:41:09 +0100 Subject: [PATCH 1/8] STM32F4: Move DBGMCU_handling to target specific code. Apply for F4 too. --- src/target/adiv5.c | 17 ----------------- src/target/stm32f4.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 7d167093..af6251a7 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -429,23 +429,6 @@ static bool cortexm_prepare(ADIv5_AP_t *ap) return false; } } - /* Apply device specific settings for successfull Romtable scan - * - * STM32F7 in WFI will not read ROMTABLE when using WFI - */ - if ((ap->dp->targetid >> 1 & 0x7ff) == 0x20) { - uint32_t dbgmcu_cr = 7; - uint32_t dbgmcu_cr_addr = 0xE0042004; - switch ((ap->dp->targetid >> 16) & 0xfff) { - case 0x449: - case 0x451: - case 0x452: - ap->ap_storage = adiv5_mem_read32(ap, dbgmcu_cr_addr); - dbgmcu_cr = ap->ap_storage | 7; - adiv5_mem_write(ap, dbgmcu_cr_addr, &dbgmcu_cr, sizeof(dbgmcu_cr)); - break; - } - } return true; } diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index a2bd45b2..5547660d 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -110,6 +110,10 @@ static int stm32f4_flash_write(struct target_flash *f, #define AXIM_BASE 0x8000000 #define ITCM_BASE 0x0200000 +#define DBGMCU_CR_DBG_SLEEP (0x1U << 0U) +#define DBGMCU_CR_DBG_STOP (0x1U << 1U) +#define DBGMCU_CR_DBG_STANDBY (0x1U << 2U) + struct stm32f4_flash { struct target_flash f; enum align psize; @@ -117,6 +121,10 @@ struct stm32f4_flash { uint8_t bank_split; }; +struct stm32f4_priv_s { + uint32_t dbgmcu_cr; +}; + enum IDS_STM32F247 { ID_STM32F20X = 0x411, ID_STM32F40X = 0x413, @@ -194,10 +202,12 @@ static char *stm32f4_get_chip_name(uint32_t idcode) } } -static void stm32f7_detach(target *t) +static void stm32f4_detach(target *t) { - ADIv5_AP_t *ap = cortexm_ap(t); - target_mem_write32(t, DBGMCU_CR, ap->ap_storage); + struct stm32f4_priv_s *ps = (struct stm32f4_priv_s*)t->target_storage; + + /*reverse all changes to DBGMCU_CR*/ + target_mem_write32(t, DBGMCU_CR, ps->dbgmcu_cr); cortexm_detach(t); } @@ -214,8 +224,6 @@ bool stm32f4_probe(target *t) case ID_STM32F74X: /* F74x RM0385 Rev.4 */ case ID_STM32F76X: /* F76x F77x RM0410 */ case ID_STM32F72X: /* F72x F73x RM0431 */ - t->detach = stm32f7_detach; - /* fall through */ case ID_STM32F40X: case ID_STM32F42X: /* 427/437 */ case ID_STM32F46X: /* 469/479 */ @@ -226,6 +234,7 @@ bool stm32f4_probe(target *t) case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */ case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */ case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ + t->detach = stm32f4_detach; t->driver = stm32f4_get_chip_name(t->idcode); t->attach = stm32f4_attach; target_add_commands(t, stm32f4_cmd_list, t->driver); @@ -295,6 +304,19 @@ static bool stm32f4_attach(target *t) return false; } bool use_dual_bank = false; + /* Save DBGMCU_CR to restore it when detaching*/ + struct stm32f4_priv_s *priv_storage = calloc(1, sizeof(*priv_storage)); + if (!priv_storage) { /* calloc failed: heap exhaustion */ + DEBUG_WARN("calloc: failed in %s\n", __func__); + return false; + } + priv_storage->dbgmcu_cr = target_mem_read32(t, DBGMCU_CR); + t->target_storage = (void*)priv_storage; + /* Enable debugging during all low power modes*/ + target_mem_write32(t, DBGMCU_CR, DBGMCU_CR_DBG_SLEEP | + DBGMCU_CR_DBG_STANDBY | DBGMCU_CR_DBG_STOP); + + /* Free previously loaded memory map */ target_mem_map_free(t); if (is_f7) { target_add_ram(t, 0x00000000, 0x4000); /* 16 k ITCM Ram */ From 804a1a4f4390d5930282b3bc654c848e70acfae1 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 31 Mar 2022 13:46:29 -0400 Subject: [PATCH 2/8] stm32f4: Attach logic cleanup by making sure we only set the extra bits needed when writing DBGMCU_CR --- src/target/stm32f4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 5547660d..b73c3ee9 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -313,8 +313,8 @@ static bool stm32f4_attach(target *t) priv_storage->dbgmcu_cr = target_mem_read32(t, DBGMCU_CR); t->target_storage = (void*)priv_storage; /* Enable debugging during all low power modes*/ - target_mem_write32(t, DBGMCU_CR, DBGMCU_CR_DBG_SLEEP | - DBGMCU_CR_DBG_STANDBY | DBGMCU_CR_DBG_STOP); + target_mem_write32(t, DBGMCU_CR, priv_storage->dbgmcu_cr | + DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STANDBY | DBGMCU_CR_DBG_STOP); /* Free previously loaded memory map */ target_mem_map_free(t); From e424859ecb480c77bd6bd484f36d8d6001e3a5ea Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 31 Mar 2022 14:03:29 -0400 Subject: [PATCH 3/8] gdb_main: Formatting cleanup --- src/gdb_main.c | 154 +++++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index 7901f215..7e84d24c 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -51,12 +51,10 @@ enum gdb_signal { typedef struct { const char *cmd_prefix; - void (*func)(const char *packet,int len); -}cmd_executer; + void (*func)(const char *packet, int len); +} cmd_executer; - - -static char pbuf[BUF_SIZE+1]; +static char pbuf[BUF_SIZE + 1]; static target *cur_target; static target *last_target; @@ -119,7 +117,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)), sizeof(arm_regs) * 2); break; - } + } case 'm': { /* 'm addr,len': Read len bytes from addr */ uint32_t addr, len; ERROR_IF_NO_TARGET(); @@ -134,9 +132,9 @@ 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 * 2); break; - } + } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); uint8_t arm_regs[target_regs_size(cur_target)]; @@ -144,7 +142,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) target_regs_write(cur_target, arm_regs); gdb_putpacketz("OK"); break; - } + } case 'M': { /* 'M addr,len:XX': Write len bytes to addr */ uint32_t addr, len; int hex; @@ -163,7 +161,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) else gdb_putpacketz("OK"); break; - } + } case 's': /* 's [addr]': Single step [start at addr] */ single_step = true; /* fall through */ @@ -217,7 +215,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) gdb_putpacket_f("T%02X", GDB_SIGTRAP); } break; - } + } /* Optional GDB packet support */ case 'p': { /* Read single register */ @@ -226,32 +224,31 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) sscanf(pbuf, "p%" SCNx32, ®); uint8_t val[8]; size_t s = target_reg_read(cur_target, reg, val, sizeof(val)); - if (s > 0) { + if (s > 0) gdb_putpacket(hexify(pbuf, val, s), s * 2); - } else { + else gdb_putpacketz("EFF"); - } break; - } + } case 'P': { /* Write single register */ ERROR_IF_NO_TARGET(); uint32_t reg; int n; sscanf(pbuf, "P%" SCNx32 "=%n", ®, &n); - uint8_t val[strlen(&pbuf[n])/2]; + // TODO: FIXME, VLAs considered harmful. + uint8_t val[strlen(&pbuf[n]) / 2]; unhexify(val, pbuf + n, sizeof(val)); - if (target_reg_write(cur_target, reg, val, sizeof(val)) > 0) { + if (target_reg_write(cur_target, reg, val, sizeof(val)) > 0) gdb_putpacketz("OK"); - } else { + else gdb_putpacketz("EFF"); - } break; - } + } case 'F': /* Semihosting call finished */ - if (in_syscall) { + if (in_syscall) return hostio_reply(tc, pbuf, size); - } else { + else { DEBUG_GDB("*** F packet when not in syscall! '%s'\n", pbuf); gdb_putpacketz(""); } @@ -309,12 +306,12 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) } DEBUG_GDB("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); - if (target_mem_write(cur_target, addr, pbuf+bin, len)) + if (target_mem_write(cur_target, addr, pbuf + bin, len)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); break; - } + } case 'q': /* General query packet */ handle_q_packet(pbuf, size); @@ -337,35 +334,36 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) } } } -bool exec_command(char *packet, int len, const cmd_executer *exec) + +static bool exec_command(char *packet, int len, const cmd_executer *exec) { - while(exec->cmd_prefix) { - int l=strlen(exec->cmd_prefix); - if(!strncmp(packet,exec->cmd_prefix,l)) { - exec->func(packet+l,len-l); + while (exec->cmd_prefix) { + const int l = strlen(exec->cmd_prefix); + if (!strncmp(packet, exec->cmd_prefix, l)) { + exec->func(packet + l, len - l); return true; } - exec++; + ++exec; } return false; } static void exec_q_rcmd(const char *packet,int len) { -char *data; -int datalen; + char *data; + int datalen; /* calculate size and allocate buffer for command */ - datalen = len/ 2; - data = alloca(datalen+1); + datalen = len / 2; + data = alloca(datalen + 1); /* dehexify command */ unhexify(data, packet, datalen); data[datalen] = 0; /* add terminating null */ int c = command_process(cur_target, data); - if(c < 0) + if (c < 0) gdb_putpacketz(""); - else if(c == 0) + else if (c == 0) gdb_putpacketz("OK"); else gdb_putpacket(hexify(pbuf, "Failed\n", strlen("Failed\n")), @@ -376,23 +374,26 @@ static void handle_q_string_reply(const char *str, const char *param) { unsigned long addr, len; + const size_t str_len = strlen(str); if (sscanf(param, "%08lx,%08lx", &addr, &len) != 2) { gdb_putpacketz("E01"); return; } - if (addr > strlen (str)) { + else if (addr > str_len) { gdb_putpacketz("E01"); return; } - if(addr== strlen (str)) { + else if (addr == str_len) { gdb_putpacketz("l"); return; } - unsigned long output_len=strlen(str)-addr; - if(output_len>len) output_len=len; - gdb_putpacket2("m",1,str+addr,output_len); + unsigned long output_len = str_len - addr; + if (output_len > len) + output_len = len; + gdb_putpacket2("m", 1, str + addr, output_len); } + static void exec_q_supported(const char *packet, int len) { (void)packet; @@ -400,12 +401,12 @@ static void exec_q_supported(const char *packet, int len) 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, int len) { (void)packet; (void)len; /* Read target XML memory map */ - if((!cur_target) && last_target) { + if ((!cur_target) && last_target) { /* Attach to last target if detached. */ cur_target = target_attach(last_target, &gdb_controller); @@ -423,7 +424,7 @@ static void exec_q_feature_read(const char *packet, int len) { (void)len; /* Read target description */ - if((!cur_target) && last_target) { + if ((!cur_target) && last_target) { /* Attach to last target if detached. */ cur_target = target_attach(last_target, &gdb_controller); } @@ -431,7 +432,7 @@ static void exec_q_feature_read(const char *packet, int len) gdb_putpacketz("E01"); return; } - handle_q_string_reply(target_tdesc(cur_target), packet ); + handle_q_string_reply(target_tdesc(cur_target), packet); } static void exec_q_crc(const char *packet, int len) @@ -439,7 +440,7 @@ static void exec_q_crc(const char *packet, int len) (void)len; uint32_t addr, alen; if (sscanf(packet, "%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) { - if(!cur_target) { + if (!cur_target) { gdb_putpacketz("E01"); return; } @@ -451,6 +452,7 @@ static void exec_q_crc(const char *packet, int len) gdb_putpacket_f("C%lx", crc); } } + static const cmd_executer q_commands[]= { {"qRcmd,", exec_q_rcmd}, @@ -458,16 +460,14 @@ 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}, - - {NULL,NULL}, + {NULL, NULL}, }; static void handle_q_packet(char *packet, int len) { - if(exec_command(packet,len,q_commands)) { + if (exec_command(packet, len, q_commands)) return; - } DEBUG_GDB("*** Unsupported packet: %s\n", packet); gdb_putpacket("", 0); } @@ -493,35 +493,37 @@ handle_v_packet(char *packet, int plen) char cmdline[83]; char *pcmdline = cmdline; char *tok = packet + 4; - if (*tok == ';') tok++; - *cmdline='\0'; + if (*tok == ';') + ++tok; + cmdline[0] = '\0'; while(*tok != '\0') { - if(strlen(cmdline)+3 >= sizeof(cmdline)) break; + if (strlen(cmdline) + 3 >= sizeof(cmdline)) + break; if (*tok == ';') { - *pcmdline++=' '; - *pcmdline='\0'; + *pcmdline++ = ' '; + pcmdline[0] = '\0'; tok++; continue; } - if (isxdigit(*tok) && isxdigit(*(tok+1))) { + if (isxdigit(tok[0]) && isxdigit(tok[1])) { unhexify(pcmdline, tok, 2); if ((*pcmdline == ' ') || (*pcmdline == '\\')) { - *(pcmdline+1)=*pcmdline; - *pcmdline++='\\'; + pcmdline[1] = *pcmdline; + *pcmdline++ = '\\'; } pcmdline++; - tok+=2; - *pcmdline='\0'; + tok += 2; + pcmdline[0] = '\0'; continue; } break; } /* Run target program. For us (embedded) this means reset. */ - if(cur_target) { + if (cur_target) { target_set_cmdline(cur_target, cmdline); target_reset(cur_target); gdb_putpacketz("T05"); - } else if(last_target) { + } else if (last_target) { cur_target = target_attach(last_target, &gdb_controller); @@ -531,24 +533,29 @@ handle_v_packet(char *packet, int plen) target_reset(cur_target); morse(NULL, false); gdb_putpacketz("T05"); - } else gdb_putpacketz("E01"); + } else + gdb_putpacketz("E01"); - } else gdb_putpacketz("E01"); + } else + gdb_putpacketz("E01"); } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { /* Erase Flash Memory */ DEBUG_GDB("Flash Erase %08lX %08lX\n", addr, len); - if(!cur_target) { gdb_putpacketz("EFF"); return; } + if (!cur_target) { + gdb_putpacketz("EFF"); + return; + } - if(!flash_mode) { + if (!flash_mode) { /* Reset target if first flash command! */ /* This saves us if we're interrupted in IRQ context */ target_reset(cur_target); flash_mode = 1; } - if(target_flash_erase(cur_target, addr, len) == 0) { + if (target_flash_erase(cur_target, addr, len) == 0) gdb_putpacketz("OK"); - } else { + else { flash_mode = 0; gdb_putpacketz("EFF"); } @@ -557,9 +564,9 @@ handle_v_packet(char *packet, int plen) /* 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) { + if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0) gdb_putpacketz("OK"); - } else { + else { flash_mode = 0; gdb_putpacketz("EFF"); } @@ -591,13 +598,12 @@ handle_z_packet(char *packet, int plen) else ret = target_breakwatch_clear(cur_target, type, addr, len); - if (ret < 0) { + if (ret < 0) gdb_putpacketz("E01"); - } else if (ret > 0) { + else if (ret > 0) gdb_putpacketz(""); - } else { + else gdb_putpacketz("OK"); - } } void gdb_main(void) From be83c2861e14a61f6c1bb86b9b0ec1204693e57a Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 31 Mar 2022 14:11:38 -0400 Subject: [PATCH 4/8] gdb_packet: Formatting cleanup --- src/gdb_packet.c | 105 +++++++++++++++++++++------------------ src/include/gdb_packet.h | 2 +- 2 files changed, 57 insertions(+), 50 deletions(-) diff --git a/src/gdb_packet.c b/src/gdb_packet.c index e25cd5c9..33dada53 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -37,7 +37,7 @@ int gdb_getpacket(char *packet, int size) char recv_csum[3]; int i; - while(1) { + while (1) { /* Wait for packet start */ do { /* Spin waiting for a start of packet character - either a gdb @@ -45,38 +45,39 @@ int gdb_getpacket(char *packet, int size) */ do { packet[0] = gdb_if_getchar(); - if (packet[0]==0x04) return 1; + if (packet[0] == 0x04) + return 1; } while ((packet[0] != '$') && (packet[0] != REMOTE_SOM)); #if PC_HOSTED == 0 - if (packet[0]==REMOTE_SOM) { + if (packet[0] == REMOTE_SOM) { /* This is probably a remote control packet * - get and handle it */ - i=0; - bool gettingRemotePacket=true; + i = 0; + bool gettingRemotePacket = true; while (gettingRemotePacket) { - c=gdb_if_getchar(); + c = gdb_if_getchar(); switch (c) { case REMOTE_SOM: /* Oh dear, packet restarts */ - i=0; + i = 0; break; case REMOTE_EOM: /* Complete packet for processing */ - packet[i]=0; - remotePacketProcess(i,packet); - gettingRemotePacket=false; + packet[i] = 0; + remotePacketProcess(i, packet); + gettingRemotePacket = false; break; case '$': /* A 'real' gdb packet, best stop squatting now */ - packet[0]='$'; - gettingRemotePacket=false; + packet[0] = '$'; + gettingRemotePacket = false; break; default: - if (i= 32) && (c < 127)) - DEBUG_GDB_WIRE("%c", c); - else - DEBUG_GDB_WIRE("\\x%02X", c); - #endif - if((c == '$') || (c == '#') || (c == '}') || (c == '*')) { - gdb_if_putchar('}', 0); - gdb_if_putchar(c ^ 0x20, 0); - *csum += '}' + (c ^ 0x20); - } else { - gdb_if_putchar(c, 0); - *csum += c; - } +#if PC_HOSTED == 1 + if ((c >= 32) && (c < 127)) + DEBUG_GDB_WIRE("%c", c); + else + DEBUG_GDB_WIRE("\\x%02X", c); +#endif + if ((c == '$') || (c == '#') || (c == '}') || (c == '*')) { + gdb_if_putchar('}', 0); + gdb_if_putchar(c ^ 0x20, 0); + *csum += '}' + (c ^ 0x20); + } + else { + gdb_if_putchar(c, 0); + *csum += c; + } } -void gdb_putpacket2(const char *packet1, int size1,const char *packet2, int size2) +void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int size2) { int i; unsigned char csum; @@ -168,18 +173,19 @@ void gdb_putpacket2(const char *packet1, int size1,const char *packet2, int size csum = 0; gdb_if_putchar('$', 0); - for(i = 0; i < size1; i++) - gdb_next_char( packet1[i],&csum); - for(i = 0; i < size2; i++) - gdb_next_char( packet2[i],&csum); + for (i = 0; i < size1; ++i) + gdb_next_char(packet1[i], &csum); + for (i = 0; i < size2; ++i) + gdb_next_char(packet2[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"); - } while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); + } while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); } + void gdb_putpacket(const char *packet, int size) { int i; @@ -191,14 +197,14 @@ void gdb_putpacket(const char *packet, int size) DEBUG_GDB_WIRE("%s : ", __func__); csum = 0; gdb_if_putchar('$', 0); - for(i = 0; i < size; i++) - gdb_next_char(packet[i],&csum); + for (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"); - } while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); + } while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); } void gdb_putpacket_f(const char *fmt, ...) @@ -216,12 +222,13 @@ void gdb_putpacket_f(const char *fmt, ...) void gdb_out(const char *buf) { - char *hexdata; - - int l=strlen(buf); - hexdata = alloca(2*l+1); + int l = strlen(buf); + char *hexdata = calloc(1, 2 * l + 1); + if (!hexdata) + return; hexify(hexdata, buf, l); - gdb_putpacket2("O",1,hexdata, 2*l); + gdb_putpacket2("O", 1, hexdata, 2 * l); + free(hexdata); } void gdb_voutf(const char *fmt, va_list ap) diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index c36981c6..af23c5b2 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -25,7 +25,7 @@ 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); +void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int size2); #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) void gdb_putpacket_f(const char *packet, ...); From 90d15e6633e15077a7ac3fed0d460e5d89fe9daa Mon Sep 17 00:00:00 2001 From: mean Date: Sat, 2 Apr 2022 15:48:29 +0200 Subject: [PATCH 5/8] add probe for ch32 + make room for other clones --- src/target/cortexm.c | 18 +++++++++++++++--- src/target/stm32f1.c | 4 +++- src/target/target_internal.h | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 2288063e..6aa44ff5 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -55,6 +55,9 @@ #include #endif +#define PROBE(x) \ + do { if ((x)(t)) {return true;} else target_check_error(t); } while (0) + static const char cortexm_driver_str[] = "ARM Cortex-M"; static bool cortexm_vector_catch(target *t, int argc, char *argv[]); @@ -209,6 +212,17 @@ static const char tdesc_cortex_mf[] = " " ""; +/* + Probe STM32F103 clones + */ +static bool stm32f1_clones_probe(target *t) +{ + PROBE(ch32f1_probe); + PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */ + return false; +} + + ADIv5_AP_t *cortexm_ap(target *t) { return ((struct cortexm_priv *)t->priv)->ap; @@ -378,8 +392,6 @@ bool cortexm_probe(ADIv5_AP_t *ap) } else { target_check_error(t); } -#define PROBE(x) \ - do { if ((x)(t)) {return true;} else target_check_error(t); } while (0) switch (ap->ap_designer) { case AP_DESIGNER_FREESCALE: @@ -442,7 +454,7 @@ bool cortexm_probe(ADIv5_AP_t *ap) PROBE(rp_probe); PROBE(lpc11xx_probe); /* LPC8 */ } else if (ap->ap_partno == 0x4c3) { /* Cortex-M3 ROM */ - PROBE(stm32f1_probe); /* Care for STM32F1 clones */ + PROBE(stm32f1_clones_probe); /* Care for STM32F1 clones */ PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */ } else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */ PROBE(lpc11xx_probe); /* LPC24C11 */ diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c index 76bfb1ad..13425d1e 100644 --- a/src/target/stm32f1.c +++ b/src/target/stm32f1.c @@ -97,7 +97,9 @@ static int stm32f1_flash_write(struct target_flash *f, #define FLASHSIZE 0x1FFFF7E0 #define FLASHSIZE_F0 0x1FFFF7CC - +// +#include "stm32f1_ch32.c" +// static void stm32f1_add_flash(target *t, uint32_t addr, size_t length, size_t erasesize) { diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 17f95800..b92e1411 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -173,6 +173,7 @@ int tc_system(target *t, target_addr cmd, size_t cmdlen); /* Probe for various targets. * Actual functions implemented in their respective drivers. */ +bool ch32f1_probe(target *t); // will catch all the clones bool gd32f1_probe(target *t); bool stm32f1_probe(target *t); bool stm32f4_probe(target *t); From 9b23265dde9e7191ab39fa0b746e1da7529840d1 Mon Sep 17 00:00:00 2001 From: mean Date: Sat, 2 Apr 2022 15:48:42 +0200 Subject: [PATCH 6/8] add support for ch32 flash write, it is a bit hackish --- src/target/stm32f1_ch32.c | 350 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 src/target/stm32f1_ch32.c diff --git a/src/target/stm32f1_ch32.c b/src/target/stm32f1_ch32.c new file mode 100644 index 00000000..4b50820a --- /dev/null +++ b/src/target/stm32f1_ch32.c @@ -0,0 +1,350 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2022 Black Sphere Technologies Ltd. + * See CH32 Sample code from WCH StdPeriphLib_CH32F1/Examples/FLASH/FLASH_Program + * + * The CH32 seems to like the EOP bit to be cleared at the end of erase/flash operation + * The following code works fine in BMP hosted mode + * It does NOT work with a real BMP, only the first 128 bytes block is successfully written + * + */ +#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 + + + 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); +#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 +#define FLASH_MAGIC (FPEC_BASE+0x34) + +static volatile uint32_t magic,sr,ct; + +/** + \fn ch32f1_add_flash + \brief "fast" flash driver for CH32F10x chips +*/ +static void ch32f1_add_flash(target *t, + uint32_t addr, size_t length, size_t erasesize) +{ + struct target_flash *f = calloc(1, sizeof(*f)); + if (!f) { /* calloc failed: heap exhaustion */ + DEBUG_WARN("calloc: failed in %s\n", __func__); + return; + } + + f->start = addr; + f->length = length; + f->blocksize = erasesize; + f->erase = ch32f1_flash_erase; + f->write = ch32f1_flash_write; + f->buf_size = erasesize; + f->erased = 0xff; + target_add_flash(t, f); +} + + + + + +#define WAIT_BUSY() do { \ + sr = target_mem_read32(t, FLASH_SR); \ + if(target_check_error(t)) { \ + ERROR_CH("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)) { \ + ERROR_CH("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 SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \ + ct|=(bit); \ + target_mem_write32(t, FLASH_CR, ct);} + + +#define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \ + ct&=~(bit); \ + target_mem_write32(t, FLASH_CR, ct);} + +// Which one is the right value ? +#define MAGIC_WORD 0x100 +// #define MAGIC_WORD 0x100 +#define MAGIC(adr) { magic=target_mem_read32(t,(adr) ^ MAGIC_WORD); \ + target_mem_write32(t, FLASH_MAGIC , magic); } + +/** + \fn ch32f1_flash_unlock + \brief unlock ch32f103 in fast mode +*/ +static int ch32f1_flash_unlock(target *t) +{ + DEBUG_CH("CH32: flash unlock \n"); + + 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); + 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); + return -1; + } + return 0; +} +static int ch32f1_flash_lock(target *t) +{ + DEBUG_CH("CH32: flash lock \n"); + SET_CR(FLASH_CR_LOCK); + return 0; +} + +/** + \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) + 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)) + { + 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); + target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD/VL-LD/VL-MD"); + t->driver = "CH32F1 medium density (stm32f1 clone)"; + + // make sure we have 2 wait states + //target_mem_write32(t, FLASH_ACR,2); + 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) +{ + target *t = f->t; + DEBUG_CH("CH32: flash erase \n"); + +// Make sure we have 2 wait states, prefetch disabled + //target_mem_write32(t, FLASH_ACR , 2); + + if (ch32f1_flash_unlock(t)) + { + ERROR_CH("CH32: Unlock failed\n"); + return -1; + } + // Fast Erase 128 bytes pages (ch32 mode) + while(len) + { + SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER + /* write address to FMA */ + target_mem_write32(t, FLASH_AR , addr); + /* Flash page erase start instruction */ + SET_CR( FLASH_CR_STRT ); + WAIT_EOP(); + CLEAR_EOP(); + CLEAR_CR( FLASH_CR_STRT ); + // Magic + MAGIC(addr); + if (len > 128) + len -= 128; + else + len = 0; + addr += 128; + } + 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); + return -1; + } + return 0; +} + +/** + \fn waitFlashReady + \brief poll the beginning of a block till it is fffff, meaning we can proceeed + +*/ + +static bool waitFlashReady(target *t,uint32_t adr) +{ + // Wait a bit + // the # of cycles needed to do N read access over SWD + // the actual number is around 10 + // then check we do read ffff (/!\ even if we read ffff it does not mean its ok + // these are the data from the previous operation and they could be ffff) + 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; +} +/** + \fn ch32f1_flash_write + \brief fast flash for ch32. Load 128 bytes chunk and then flash them +*/ + +static int upload(target *t, uint32_t dest, const void *src, uint32_t offset) +{ + const uint32_t *ss=(const uint32_t *)(src+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]); + SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */ + WAIT_EOP(); + CLEAR_EOP(); + CLEAR_CR(FLASH_CR_FTPG_CH32); + MAGIC((dest+offset)); + return 0; +} +/** + \fn ch32_buffer_clear + \brief clear the write buffer +*/ +int ch32_buffer_clear(target *t) +{ + 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 + +/** + +*/ +static int ch32f1_flash_write(struct target_flash *f, + target_addr dest, const void *src, size_t len) +{ + target *t = f->t; + size_t length = len; +#ifdef CH32_VERIFY + target_addr orgDest=dest; + const void *orgSrc=src; +#endif + DEBUG_CH("CH32: flash write 0x%x ,size=%d\n",dest,len); + + while(length>0) + { + if(ch32f1_flash_unlock(t)) + { + ERROR_CH("ch32f1 cannot fast unlock\n"); + return -1; + } + WAIT_BUSY(); + + // Buffer reset... + ch32_buffer_clear(t); + // Load 128 bytes to buffer + if(!waitFlashReady(t,dest)) + { + return -1; + } + for(int i=0;i<8;i++) + { + if(upload(t,dest,src, 16*i)) + { + ERROR_CH("Cannot upload to buffer\n"); + } + } + + // write buffer + SET_CR(FLASH_CR_FTPG_CH32); + target_mem_write32(t, FLASH_AR, dest); // 10 + SET_CR(FLASH_CR_STRT); // 11 Start + WAIT_EOP(); // 12 + CLEAR_EOP(); + CLEAR_CR(FLASH_CR_FTPG_CH32); + + MAGIC((dest)); + + // next + if(length>128) + length-=128; + else + length=0; + dest+=128; + src+=128; + + 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); + return -1; + } + + } +#ifdef CH32_VERIFY + DEBUG_CH("Verifying\n"); + int i=0; + for(i=0;i<(int)len;i+=4) + { + uint32_t mem=target_mem_read32(t, orgDest+i); + uint32_t mem2=*(uint32_t *)(orgSrc+i); + if(mem!=mem2) + { + 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); + return -1; + } + } +#endif + + return 0; +} +// EOF From fb216a2a989fb875acb31299d1d03171d6ea8735 Mon Sep 17 00:00:00 2001 From: mean Date: Sat, 2 Apr 2022 15:51:20 +0200 Subject: [PATCH 7/8] tabify --- src/target/cortexm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 6aa44ff5..b686d46b 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -217,9 +217,9 @@ static const char tdesc_cortex_mf[] = */ static bool stm32f1_clones_probe(target *t) { - PROBE(ch32f1_probe); - PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */ - return false; + PROBE(ch32f1_probe); + PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */ + return false; } From a3feae60aab1fb85fe44b33123e020a9d7c8e18c Mon Sep 17 00:00:00 2001 From: mean Date: Sat, 2 Apr 2022 15:58:18 +0200 Subject: [PATCH 8/8] cleanup tabs --- src/target/stm32f1_ch32.c | 396 ++++++++++++++++++-------------------- 1 file changed, 192 insertions(+), 204 deletions(-) diff --git a/src/target/stm32f1_ch32.c b/src/target/stm32f1_ch32.c index 4b50820a..b8f5cfc1 100644 --- a/src/target/stm32f1_ch32.c +++ b/src/target/stm32f1_ch32.c @@ -10,18 +10,18 @@ * */ #if PC_HOSTED == 1 - #define DEBUG_CH DEBUG_INFO - #define ERROR_CH DEBUG_WARN + #define DEBUG_CH DEBUG_INFO + #define ERROR_CH DEBUG_WARN #else - #define DEBUG_CH(...) {} //DEBUG_WARN //(...) {} - #define ERROR_CH DEBUG_WARN //DEBUG_WARN + #define DEBUG_CH(...) {} //DEBUG_WARN //(...) {} + #define ERROR_CH DEBUG_WARN //DEBUG_WARN #endif static int ch32f1_flash_erase(struct target_flash *f, - target_addr addr, size_t len); + target_addr addr, size_t len); 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); #define FLASH_MODEKEYR_CH32 (FPEC_BASE+0x24) // Fast mode for CH32F10x #define FLASH_CR_FLOCK_CH32 (1<<15) // fast unlock @@ -36,26 +36,25 @@ static volatile uint32_t magic,sr,ct; /** - \fn ch32f1_add_flash - \brief "fast" flash driver for CH32F10x chips + \fn ch32f1_add_flash + \brief "fast" flash driver for CH32F10x chips */ -static void ch32f1_add_flash(target *t, - uint32_t addr, size_t length, size_t erasesize) +static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t erasesize) { - struct target_flash *f = calloc(1, sizeof(*f)); - if (!f) { /* calloc failed: heap exhaustion */ - DEBUG_WARN("calloc: failed in %s\n", __func__); - return; - } + struct target_flash *f = calloc(1, sizeof(*f)); + if (!f) { /* calloc failed: heap exhaustion */ + DEBUG_WARN("calloc: failed in %s\n", __func__); + return; + } - f->start = addr; - f->length = length; - f->blocksize = erasesize; - f->erase = ch32f1_flash_erase; - f->write = ch32f1_flash_write; - f->buf_size = erasesize; - f->erased = 0xff; - target_add_flash(t, f); + f->start = addr; + f->length = length; + f->blocksize = erasesize; + f->erase = ch32f1_flash_erase; + f->write = ch32f1_flash_write; + f->buf_size = erasesize; + f->erased = 0xff; + target_add_flash(t, f); } @@ -63,37 +62,37 @@ static void ch32f1_add_flash(target *t, #define WAIT_BUSY() do { \ - sr = target_mem_read32(t, FLASH_SR); \ - if(target_check_error(t)) { \ - ERROR_CH("ch32f1 flash write: comm error\n"); \ - return -1; \ - } \ - } while (sr & FLASH_SR_BSY); + sr = target_mem_read32(t, FLASH_SR); \ + if(target_check_error(t)) { \ + ERROR_CH("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)) { \ - ERROR_CH("ch32f1 flash write: comm error\n"); \ - return -1; \ - } \ - } while (!(sr & FLASH_SR_EOP)); + sr = target_mem_read32(t, FLASH_SR); \ + if(target_check_error(t)) { \ + ERROR_CH("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 SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \ - ct|=(bit); \ - target_mem_write32(t, FLASH_CR, ct);} + ct|=(bit); \ + target_mem_write32(t, FLASH_CR, ct);} #define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \ - ct&=~(bit); \ - target_mem_write32(t, FLASH_CR, ct);} + ct&=~(bit); \ + target_mem_write32(t, FLASH_CR, ct);} // Which one is the right value ? #define MAGIC_WORD 0x100 // #define MAGIC_WORD 0x100 #define MAGIC(adr) { magic=target_mem_read32(t,(adr) ^ MAGIC_WORD); \ - target_mem_write32(t, FLASH_MAGIC , magic); } + target_mem_write32(t, FLASH_MAGIC , magic); } /** \fn ch32f1_flash_unlock @@ -101,63 +100,61 @@ static void ch32f1_add_flash(target *t, */ static int ch32f1_flash_unlock(target *t) { - DEBUG_CH("CH32: flash unlock \n"); + DEBUG_CH("CH32: flash unlock \n"); - 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); - 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); - return -1; - } - return 0; + 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); + 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); + return -1; + } + return 0; } static int ch32f1_flash_lock(target *t) { - DEBUG_CH("CH32: flash lock \n"); - SET_CR(FLASH_CR_LOCK); - return 0; + DEBUG_CH("CH32: flash lock \n"); + SET_CR(FLASH_CR_LOCK); + return 0; } /** - \brief identify the ch32f1 chip - Actually grab all cortex m3 with designer = arm not caught earlier... + \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) - return false; - if(t->idcode !=0x410) // only ch32f103 - { - return false; - } + t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; + if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3) + 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)) - { - return false; - } + // try to flock + ch32f1_flash_lock(t); + // if this fails it is not a CH32 chip + if(ch32f1_flash_unlock(t)) { + return false; + } - uint32_t signature= target_mem_read32(t, FLASHSIZE); - uint32_t flashSize=signature & 0xFFFF; + 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); - target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD/VL-LD/VL-MD"); - t->driver = "CH32F1 medium density (stm32f1 clone)"; + target_add_ram(t, 0x20000000, 0x5000); + 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)"; - // make sure we have 2 wait states - //target_mem_write32(t, FLASH_ACR,2); - return true; + // make sure we have 2 wait states + //target_mem_write32(t, FLASH_ACR,2); + return true; } /** \fn ch32f1_flash_erase @@ -165,49 +162,46 @@ bool ch32f1_probe(target *t) */ int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len) { - target *t = f->t; - DEBUG_CH("CH32: flash erase \n"); + target *t = f->t; + DEBUG_CH("CH32: flash erase \n"); // Make sure we have 2 wait states, prefetch disabled - //target_mem_write32(t, FLASH_ACR , 2); + //target_mem_write32(t, FLASH_ACR , 2); - if (ch32f1_flash_unlock(t)) - { - ERROR_CH("CH32: Unlock failed\n"); - return -1; - } - // Fast Erase 128 bytes pages (ch32 mode) - while(len) - { - SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER - /* write address to FMA */ - target_mem_write32(t, FLASH_AR , addr); - /* Flash page erase start instruction */ - SET_CR( FLASH_CR_STRT ); - WAIT_EOP(); - CLEAR_EOP(); - CLEAR_CR( FLASH_CR_STRT ); - // Magic - MAGIC(addr); - if (len > 128) - len -= 128; - else - len = 0; - addr += 128; - } - 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); - return -1; - } - return 0; + if (ch32f1_flash_unlock(t)) { + ERROR_CH("CH32: Unlock failed\n"); + return -1; + } + // Fast Erase 128 bytes pages (ch32 mode) + while(len) { + SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER + /* write address to FMA */ + target_mem_write32(t, FLASH_AR , addr); + /* Flash page erase start instruction */ + SET_CR( FLASH_CR_STRT ); + WAIT_EOP(); + CLEAR_EOP(); + CLEAR_CR( FLASH_CR_STRT ); + // Magic + MAGIC(addr); + if (len > 128) + len -= 128; + else + len = 0; + addr += 128; + } + 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); + return -1; + } + return 0; } /** - \fn waitFlashReady - \brief poll the beginning of a block till it is fffff, meaning we can proceeed + \fn waitFlashReady + \brief poll the beginning of a block till it is fffff, meaning we can proceeed */ @@ -220,10 +214,9 @@ static bool waitFlashReady(target *t,uint32_t adr) // these are the data from the previous operation and they could be ffff) 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; + if(ff!=0xffffffffUL) { + ERROR_CH("ch32f1 Not erased properly at %x or flash access issue\n",adr); + return false; } return true; } @@ -234,24 +227,24 @@ static bool waitFlashReady(target *t,uint32_t adr) static int upload(target *t, uint32_t dest, const void *src, uint32_t offset) { - const uint32_t *ss=(const uint32_t *)(src+offset); - uint32_t dd=dest+offset; + const uint32_t *ss=(const uint32_t *)(src+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]); - SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */ - WAIT_EOP(); - CLEAR_EOP(); - CLEAR_CR(FLASH_CR_FTPG_CH32); - MAGIC((dest+offset)); - return 0; + 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]); + SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */ + WAIT_EOP(); + CLEAR_EOP(); + CLEAR_CR(FLASH_CR_FTPG_CH32); + MAGIC((dest+offset)); + return 0; } /** - \fn ch32_buffer_clear - \brief clear the write buffer + \fn ch32_buffer_clear + \brief clear the write buffer */ int ch32_buffer_clear(target *t) { @@ -267,84 +260,79 @@ int ch32_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) { - target *t = f->t; - size_t length = len; + target *t = f->t; + size_t length = len; #ifdef CH32_VERIFY - target_addr orgDest=dest; - const void *orgSrc=src; + target_addr orgDest=dest; + const void *orgSrc=src; #endif - DEBUG_CH("CH32: flash write 0x%x ,size=%d\n",dest,len); + DEBUG_CH("CH32: flash write 0x%x ,size=%d\n",dest,len); - while(length>0) - { - if(ch32f1_flash_unlock(t)) - { - ERROR_CH("ch32f1 cannot fast unlock\n"); - return -1; - } - WAIT_BUSY(); + while(length>0) + { + if(ch32f1_flash_unlock(t)) { + ERROR_CH("ch32f1 cannot fast unlock\n"); + return -1; + } + WAIT_BUSY(); - // Buffer reset... - ch32_buffer_clear(t); - // Load 128 bytes to buffer - if(!waitFlashReady(t,dest)) - { - return -1; - } - for(int i=0;i<8;i++) - { - if(upload(t,dest,src, 16*i)) - { - ERROR_CH("Cannot upload to buffer\n"); - } - } + // Buffer reset... + ch32_buffer_clear(t); + // Load 128 bytes to buffer + if(!waitFlashReady(t,dest)) { + return -1; + } + for(int i=0;i<8;i++) { + if(upload(t,dest,src, 16*i)) { + ERROR_CH("Cannot upload to buffer\n"); + return -1; + } + } + // write buffer + SET_CR(FLASH_CR_FTPG_CH32); + target_mem_write32(t, FLASH_AR, dest); // 10 + SET_CR(FLASH_CR_STRT); // 11 Start + WAIT_EOP(); // 12 + CLEAR_EOP(); + CLEAR_CR(FLASH_CR_FTPG_CH32); - // write buffer - SET_CR(FLASH_CR_FTPG_CH32); - target_mem_write32(t, FLASH_AR, dest); // 10 - SET_CR(FLASH_CR_STRT); // 11 Start - WAIT_EOP(); // 12 - CLEAR_EOP(); - CLEAR_CR(FLASH_CR_FTPG_CH32); + MAGIC((dest)); - MAGIC((dest)); + // next + if(length>128) + length-=128; + else + length=0; + dest+=128; + src+=128; - // next - if(length>128) - length-=128; - else - length=0; - dest+=128; - src+=128; + 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); + return -1; + } - 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); - return -1; - } - - } + } #ifdef CH32_VERIFY - DEBUG_CH("Verifying\n"); - int i=0; - for(i=0;i<(int)len;i+=4) - { - uint32_t mem=target_mem_read32(t, orgDest+i); - uint32_t mem2=*(uint32_t *)(orgSrc+i); - if(mem!=mem2) - { - 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); - return -1; - } - } + DEBUG_CH("Verifying\n"); + int i=0; + for(i=0;i<(int)len;i+=4) + { + uint32_t mem=target_mem_read32(t, orgDest+i); + uint32_t mem2=*(uint32_t *)(orgSrc+i); + if(mem!=mem2) + { + 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); + return -1; + } + } #endif - return 0; + return 0; } // EOF