X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gdbserver%2Fgdb-server.c;h=32f0d8bafa6197ad14f2da2162fef58d7aae01d1;hb=2216d28452f5e97088fbfd4bd6f6daf187d5e53a;hp=7a525d53530059c68fe5c0f9560e61f0ca8ba9ae;hpb=105b293a1501154c69663b4fb29671a8d2cc62ec;p=fw%2Fstlink diff --git a/gdbserver/gdb-server.c b/gdbserver/gdb-server.c index 7a525d5..32f0d8b 100644 --- a/gdbserver/gdb-server.c +++ b/gdbserver/gdb-server.c @@ -36,6 +36,8 @@ //Allways update the FLASH_PAGE before each use, by calling stlink_calculate_pagesize #define FLASH_PAGE (sl->flash_pgsz) +stlink_t *connected_stlink = NULL; + static const char hex[] = "0123456789abcdef"; static const char* current_memory_map = NULL; @@ -47,12 +49,23 @@ typedef struct _st_state_t { char devicename[100]; int logging_level; int listen_port; + int persistent; } st_state_t; -int serve(stlink_t *sl, int port); +int serve(stlink_t *sl, st_state_t *st); char* make_memory_map(stlink_t *sl); +static void cleanup(int signal __attribute__((unused))) { + if (connected_stlink) { + /* Switch back to mass storage mode before closing. */ + stlink_run(connected_stlink); + stlink_exit_debug_mode(connected_stlink); + stlink_close(connected_stlink); + } + + exit(1); +} int parse_options(int argc, char** argv, st_state_t *st) { static struct option long_options[] = { @@ -62,6 +75,7 @@ int parse_options(int argc, char** argv, st_state_t *st) { {"stlink_version", required_argument, NULL, 's'}, {"stlinkv1", no_argument, NULL, '1'}, {"listen_port", required_argument, NULL, 'p'}, + {"multi", optional_argument, NULL, 'm'}, {0, 0, 0, 0}, }; const char * help_str = "%s - usage:\n\n" @@ -76,13 +90,16 @@ int parse_options(int argc, char** argv, st_state_t *st) { " -p 4242, --listen_port=1234\n" "\t\t\tSet the gdb server listen port. " "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" + " -m, --multi\n" + "\t\t\tSet gdb server to extended mode.\n" + "\t\t\tst-util will continue listening for connections after disconnect.\n" ; int option_index = 0; int c; int q; - while ((c = getopt_long(argc, argv, "hv::d:s:1p:", long_options, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "hv::d:s:1p:m", long_options, &option_index)) != -1) { switch (c) { case 0: printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n"); @@ -129,6 +146,9 @@ int parse_options(int argc, char** argv, st_state_t *st) { } st->listen_port = q; break; + case 'm': + st->persistent = 1; + break; } } @@ -163,7 +183,10 @@ int main(int argc, char** argv) { if(sl == NULL) return 1; break; } - + + connected_stlink = sl; + signal(SIGINT, &cleanup); + printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); sl->verbose=0; @@ -177,7 +200,9 @@ int main(int argc, char** argv) { } #endif - while(serve(sl, state.listen_port) == 0); + do { + serve(sl, &state); + } while (state.persistent); #ifdef __MINGW32__ winsock_error: @@ -192,6 +217,71 @@ winsock_error: return 0; } +static const char* const target_description_F4 = + "" + "" + "" + " arm" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + static const char* const memory_map_template_F4 = "" "listen_port); if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("bind"); @@ -591,7 +681,7 @@ int serve(stlink_t *sl, int port) { init_code_breakpoints(sl); init_data_watchpoints(sl); - printf("Listening at *:%d...\n", port); + printf("Listening at *:%d...\n", st->listen_port); int client = accept(sock, NULL, NULL); //signal (SIGINT, SIG_DFL); @@ -649,7 +739,12 @@ int serve(stlink_t *sl, int port) { #endif if(!strcmp(queryName, "Supported")) { - reply = strdup("PacketSize=3fff;qXfer:memory-map:read+"); + if(sl->chip_id==STM32_CHIPID_F4) { + reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+"); + } + else { + reply = strdup("PacketSize=3fff;qXfer:memory-map:read+"); + } } else if(!strcmp(queryName, "Xfer")) { char *type, *op, *__s_addr, *s_length; char *tok = params; @@ -674,6 +769,9 @@ int serve(stlink_t *sl, int port) { if(!strcmp(type, "memory-map") && !strcmp(op, "read")) data = current_memory_map; + if(!strcmp(type, "features") && !strcmp(op, "read")) + data = target_description_F4; + if(data) { unsigned data_length = strlen(data); if(addr + length > data_length) @@ -695,31 +793,41 @@ int serve(stlink_t *sl, int port) { } else { params = separator + 1; } - - if (!strncmp(params,"7265",4)) {// resume + + if (!strncmp(params,"726573756d65",12)) {// resume #ifdef DEBUG printf("Rcmd: resume\n"); #endif stlink_run(sl); reply = strdup("OK"); - } else if (!strncmp(params,"6861",4)) { //half + } else if (!strncmp(params,"68616c74",8)) { //halt reply = strdup("OK"); - + stlink_force_debug(sl); #ifdef DEBUG printf("Rcmd: halt\n"); #endif - } else if (!strncmp(params,"7265",4)) { //reset + } else if (!strncmp(params,"6a7461675f7265736574",20)) { //jtag_reset + reply = strdup("OK"); + + stlink_jtag_reset(sl, 1); + stlink_jtag_reset(sl, 0); + stlink_force_debug(sl); + +#ifdef DEBUG + printf("Rcmd: jtag_reset\n"); +#endif + } else if (!strncmp(params,"7265736574",10)) { //reset reply = strdup("OK"); - + stlink_force_debug(sl); stlink_reset(sl); init_code_breakpoints(sl); init_data_watchpoints(sl); - + #ifdef DEBUG printf("Rcmd: reset\n"); #endif @@ -729,7 +837,7 @@ int serve(stlink_t *sl, int port) { #endif } - + } if(reply == NULL) @@ -881,6 +989,30 @@ int serve(stlink_t *sl, int port) { } else if(id == 0x19) { stlink_read_reg(sl, 16, ®p); myreg = htonl(regp.xpsr); + } else if(id == 0x1A) { + stlink_read_reg(sl, 17, ®p); + myreg = htonl(regp.main_sp); + } else if(id == 0x1B) { + stlink_read_reg(sl, 18, ®p); + myreg = htonl(regp.process_sp); + } else if(id == 0x1C) { + stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.control); + } else if(id == 0x1D) { + stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.faultmask); + } else if(id == 0x1E) { + stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.basepri); + } else if(id == 0x1F) { + stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.primask); + } else if(id >= 0x20 && id < 0x40) { + stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.s[id-0x20]); + } else if(id == 0x40) { + stlink_read_unsupported_reg(sl, id, ®p); + myreg = htonl(regp.fpscr); } else { reply = strdup("E00"); } @@ -902,6 +1034,22 @@ int serve(stlink_t *sl, int port) { stlink_write_reg(sl, ntohl(value), reg); } else if(reg == 0x19) { stlink_write_reg(sl, ntohl(value), 16); + } else if(reg == 0x1A) { + stlink_write_reg(sl, ntohl(value), 17); + } else if(reg == 0x1B) { + stlink_write_reg(sl, ntohl(value), 18); + } else if(reg == 0x1C) { + stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if(reg == 0x1D) { + stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if(reg == 0x1E) { + stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if(reg == 0x1F) { + stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if(reg >= 0x20 && reg < 0x40) { + stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); + } else if(reg == 0x40) { + stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p); } else { reply = strdup("E00"); } @@ -932,9 +1080,9 @@ int serve(stlink_t *sl, int port) { unsigned count = strtoul(s_count, NULL, 16); unsigned adj_start = start % 4; + unsigned count_rnd = (count + adj_start + 4 - 1) / 4 * 4; - stlink_read_mem32(sl, start - adj_start, (count % 4 == 0) ? - count : count + 4 - (count % 4)); + stlink_read_mem32(sl, start - adj_start, count_rnd); reply = calloc(count * 2 + 1, 1); for(unsigned int i = 0; i < count; i++) { @@ -953,20 +1101,43 @@ int serve(stlink_t *sl, int port) { stm32_addr_t start = strtoul(s_start, NULL, 16); unsigned count = strtoul(s_count, NULL, 16); - for(unsigned int i = 0; i < count; i ++) { + if(start % 4) { + unsigned align_count = 4 - start % 4; + if (align_count > count) align_count = count; + for(unsigned int i = 0; i < align_count; i ++) { char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 }; uint8_t byte = strtoul(hex, NULL, 16); sl->q_buf[i] = byte; + } + stlink_write_mem8(sl, start, align_count); + start += align_count; + count -= align_count; + hexdata += 2*align_count; } - if((count % 4) == 0 && (start % 4) == 0) { - stlink_write_mem32(sl, start, count); - } else { - stlink_write_mem8(sl, start, count); + if(count - count % 4) { + unsigned aligned_count = count - count % 4; + + for(unsigned int i = 0; i < aligned_count; i ++) { + char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 }; + uint8_t byte = strtoul(hex, NULL, 16); + sl->q_buf[i] = byte; + } + stlink_write_mem32(sl, start, aligned_count); + count -= aligned_count; + start += aligned_count; + hexdata += 2*aligned_count; } + if(count) { + for(unsigned int i = 0; i < count; i ++) { + char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 }; + uint8_t byte = strtoul(hex, NULL, 16); + sl->q_buf[i] = byte; + } + stlink_write_mem8(sl, start, count); + } reply = strdup("OK"); - break; } @@ -995,13 +1166,14 @@ int serve(stlink_t *sl, int port) { wf = WATCHREAD; } else { wf = WATCHACCESS; - if(add_data_watchpoint(sl, wf, addr, len) < 0) { - reply = strdup("E00"); - } else { - reply = strdup("OK"); - break; - } } + + if(add_data_watchpoint(sl, wf, addr, len) < 0) { + reply = strdup("E00"); + } else { + reply = strdup("OK"); + break; + } } default: @@ -1042,6 +1214,12 @@ int serve(stlink_t *sl, int port) { * We do support that always. */ + /* + * Also, set to persistent mode + * to allow GDB disconnect. + */ + st->persistent = 1; + reply = strdup("OK"); break; @@ -1073,6 +1251,8 @@ int serve(stlink_t *sl, int port) { int result = gdb_send_packet(client, reply); if(result != 0) { fprintf(stderr, "cannot send: %d\n", result); + free(reply); + free(packet); return 1; }