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 7e84d24c..081aa797 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,23 +51,29 @@ 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 bool gdb_needs_detach_notify = false; -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 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_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) last_target = NULL; @@ -100,22 +106,20 @@ 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(); - 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 */ @@ -132,19 +136,20 @@ 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; } 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); @@ -162,11 +167,24 @@ 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 */ case 'c': /* 'c [addr]': Continue [at addr] */ - if(!cur_target) { + if (!cur_target) { gdb_putpacketz("X1D"); break; } @@ -181,7 +199,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; @@ -189,10 +207,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); @@ -274,12 +291,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 */ @@ -317,7 +329,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; @@ -335,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; @@ -348,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) @@ -370,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. */ @@ -420,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. */ @@ -435,24 +444,51 @@ 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); } } +/* + * 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"); +} + +/* + * 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}, @@ -460,34 +496,60 @@ 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}, + {"qfThreadInfo", exec_q_thread_info}, + {"qsThreadInfo", exec_q_thread_info}, {NULL, NULL}, }; -static void -handle_q_packet(char *packet, int len) +static void handle_kill_target(void) { - if (exec_command(packet, len, q_commands)) + 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)) 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) { 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"); + } 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]; @@ -539,9 +601,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 %08" PRIX32 " %08" PRIX32 "\n", addr, len); if (!cur_target) { gdb_putpacketz("EFF"); return; @@ -560,11 +622,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 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 { flash_mode = 0; @@ -576,24 +638,30 @@ handle_v_packet(char *packet, int 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); } } -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); diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 33dada53..6f4f2e15 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; + size_t tries = 0; do { - DEBUG_GDB_WIRE("%s : ", __func__); - csum = 0; + DEBUG_GDB_WIRE("%s: ", __func__); + 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); @@ -183,28 +184,42 @@ void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int siz 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) +void gdb_putpacket(const char *packet, size_t size) { - int i; - unsigned char csum; char xmit_csum[3]; - int tries = 0; + size_t tries = 0; do { - DEBUG_GDB_WIRE("%s : ", __func__); - csum = 0; + DEBUG_GDB_WIRE("%s: ", __func__); + 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); 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/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; } - diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index af23c5b2..d1e72087 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -21,18 +21,19 @@ #ifndef __GDB_PACKET_H #define __GDB_PACKET_H +#include #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, ...); +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); void gdb_outf(const char *fmt, ...); #endif - - 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]; 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; } diff --git a/src/target/ch32f1.c b/src/target/ch32f1.c index 8da38951..b9b2588d 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,29 +32,20 @@ #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 -#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) @@ -66,19 +57,16 @@ extern const struct command_s stm32f1_cmd_list[]; // Reuse stm32f1 stuff #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 - - - /** \fn ch32f1_add_flash \brief "fast" flash driver for CH32F10x chips @@ -101,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)) { \ - ERROR_CH("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)) { \ - ERROR_CH("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 @@ -140,24 +131,24 @@ 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); + 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){ - 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,56 +157,55 @@ 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) return false; - if(t->idcode !=0x410) { // only ch32f103 + const uint32_t idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0x00000fffU; + if (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; - } + t->idcode = idcode; 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; } + /** \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; + volatile uint32_t 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 +216,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 +231,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; + volatile uint32_t 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 +271,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 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 +284,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; + volatile uint32_t 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%" PRIx32 " ,size=%zu\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 +306,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 +323,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 +335,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 +359,3 @@ static int ch32f1_flash_write(struct target_flash *f, return 0; } -// EOF diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 0c25509d..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: @@ -502,7 +519,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 +692,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; diff --git a/src/target/kinetis.c b/src/target/kinetis.c index 5e44bfe8..3ab08c3b 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -37,77 +37,96 @@ #include "general.h" #include "target.h" #include "target_internal.h" +#include "adiv5.h" -#define SIM_SDID 0x40048024 -#define SIM_FCFG1 0x4004804C +#define KINETIS_MDM_IDR_K22F 0x1c0000 +#define KINETIS_MDM_IDR_KZ03 0x1c0020 -#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 MDM_STATUS ADIV5_AP_REG(0x00) +#define MDM_CONTROL ADIV5_AP_REG(0x04) -#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 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 FTFA_CMD_CHECK_ERASE 0x01 -#define FTFA_CMD_PROGRAM_CHECK 0x02 -#define FTFA_CMD_READ_RESOURCE 0x03 -#define FTFA_CMD_PROGRAM_LONGWORD 0x06 +#define MDM_CONTROL_MASS_ERASE (1 << 0) +#define MDM_CONTROL_SYS_RESET (1 << 3) + +#define SIM_SDID 0x40048024 +#define SIM_FCFG1 0x4004804C + +#define FLASH_SECURITY_BYTE_ADDRESS 0x40C +#define FLASH_SECURITY_BYTE_UNSECURED 0xFE + +#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 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 */ #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); } 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(target *t, uint32_t addr, size_t length, - size_t erasesize, size_t write_len) +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)); 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; } @@ -116,15 +135,26 @@ static void kl_gen_add_flash(target *t, uint32_t addr, size_t length, 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); } -bool kinetis_probe(target *t) +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); + + 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) { uint32_t sdid = target_mem_read32(t, SIM_SDID); uint32_t fcfg1 = target_mem_read32(t, SIM_FCFG1); @@ -132,52 +162,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"; + 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); - break; + case 0x05: /* 64 KB */ + t->driver = "KL16Z64Vxxx"; + 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); - break; + case 0x07: /* 128 KB */ + t->driver = "KL16Z128Vxxx"; + 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); - break; - default: - return false; - break; + case 0x09: /* 256 KB */ + t->driver = "KL16Z256Vxxx"; + kinetis_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); + break; + default: + return false; + break; } break; @@ -186,68 +216,68 @@ bool kinetis_probe(target *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) { - 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); + 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); + kinetis_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); + 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); + 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); + kinetis_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN); + break; + default: + return false; } break; case 0x031: /* KL03 family */ 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 @@ -255,115 +285,107 @@ bool kinetis_probe(target *t) * subfamily nibble as 2 */ 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); + target_add_ram(t, 0x1FFF0000, 0x10000); + target_add_ram(t, 0x20000000, 0x30000); + 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) { - 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 */ + 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 */ + 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 */ + 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; - 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 */ - 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 */ + 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; - /* 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 */ + /* 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; } @@ -372,47 +394,48 @@ do_common_s32k14x: 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); - if (data) { - target_mem_write32(t, FTFA_FCCOB_1, data[0]); + addr &= 0x00ffffffU; + addr |= cmd << 24U; + target_mem_write32(t, FTFx_FCCOB0, addr); + if (data && n_items) { + 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]); + else + target_mem_write32(t, FTFx_FCCOB8, 0); } /* 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 *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,72 +449,60 @@ 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_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 *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. */ uint8_t write_cmd; - if (kf->write_len == K64_WRITE_LEN) { - write_cmd = FTFE_CMD_PROGRAM_PHRASE; - } else { - write_cmd = FTFA_CMD_PROGRAM_LONGWORD; - } + if (kf->write_len == K64_WRITE_LEN) + write_cmd = FTFx_CMD_PROGRAM_PHRASE; + else + 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, kf->write_len >> 2U)) { if (len > kf->write_len) len -= kf->write_len; else len = 0; dest += kf->write_len; src += kf->write_len; - } else { + } else return 1; - } } return 0; } -static int kl_gen_flash_done(struct target_flash *f) +static int kinetis_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; - 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) { - 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; - kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, - FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2); + if (kf->write_len == K64_WRITE_LEN) { + 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; - kl_gen_command(f->t, FTFA_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; @@ -504,10 +515,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 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); @@ -515,18 +522,19 @@ 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} + {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,23 +549,13 @@ 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; 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) @@ -569,6 +567,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 +575,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) { 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 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; }