X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gdbserver%2Fgdb-server.c;h=a3ed335ad1d42a161bdf9dd9b9ec3b3d976822d7;hb=788d2df7723e9da3a0369365f56830ab9541e9c7;hp=414ad8a7b477016ddf46a845042ab96c1d1b1a97;hpb=9bed540624ac45ff334917a51c564caa278d5833;p=fw%2Fstlink diff --git a/gdbserver/gdb-server.c b/gdbserver/gdb-server.c index 414ad8a..a3ed335 100644 --- a/gdbserver/gdb-server.c +++ b/gdbserver/gdb-server.c @@ -7,9 +7,11 @@ */ #include +#include #include #include #include +#include #include #include #ifdef __MINGW32__ @@ -18,7 +20,6 @@ #include #include #include -#include #endif #include @@ -36,46 +37,53 @@ //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; -/* Persistent mode flag. - * In persistent mode, server starts listening again - * on GDB disconnect. */ -int persistent = 0; - typedef struct _st_state_t { // things from command line, bleh int stlink_version; - // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars - char devicename[100]; int logging_level; - int listen_port; + int listen_port; + int persistent; + int reset; } 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[] = { {"help", no_argument, NULL, 'h'}, {"verbose", optional_argument, NULL, 'v'}, - {"device", required_argument, NULL, 'd'}, {"stlink_version", required_argument, NULL, 's'}, {"stlinkv1", no_argument, NULL, '1'}, {"listen_port", required_argument, NULL, 'p'}, {"multi", optional_argument, NULL, 'm'}, + {"no-reset", optional_argument, NULL, 'n'}, {0, 0, 0, 0}, }; const char * help_str = "%s - usage:\n\n" " -h, --help\t\tPrint this help\n" - " -vXX, --verbose=XX\tspecify a specific verbosity level (0..99)\n" - " -v, --verbose\tspecify generally verbose logging\n" - " -d , --device=/dev/stlink2_1\n" - "\t\t\tWhere is your stlink device connected?\n" + " -vXX, --verbose=XX\tSpecify a specific verbosity level (0..99)\n" + " -v, --verbose\t\tSpecify generally verbose logging\n" " -s X, --stlink_version=X\n" "\t\t\tChoose what version of stlink to use, (defaults to 2)\n" " -1, --stlinkv1\tForce stlink version 1\n" @@ -85,13 +93,19 @@ int parse_options(int argc, char** argv, st_state_t *st) { " -m, --multi\n" "\t\t\tSet gdb server to extended mode.\n" "\t\t\tst-util will continue listening for connections after disconnect.\n" + " -n, --no-reset\n" + "\t\t\tDo not reset board on connection.\n" + "\n" + "The STLINKv2 device to use can be specified in the environment\n" + "variable STLINK_DEVICE on the format :.\n" + "\n" ; int option_index = 0; int c; int q; - while ((c = getopt_long(argc, argv, "hv::d:s:1p:m", long_options, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "hv::s:1p:mn", 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"); @@ -111,13 +125,6 @@ int parse_options(int argc, char** argv, st_state_t *st) { } else { st->logging_level = DEFAULT_LOGGING_LEVEL; } - break; - case 'd': - if (strlen(optarg) > sizeof (st->devicename)) { - fprintf(stderr, "device name too long: %zd\n", strlen(optarg)); - } else { - strcpy(st->devicename, optarg); - } break; case '1': st->stlink_version = 1; @@ -139,7 +146,10 @@ int parse_options(int argc, char** argv, st_state_t *st) { st->listen_port = q; break; case 'm': - persistent = 1; + st->persistent = 1; + break; + case 'n': + st->reset = 0; break; } } @@ -155,6 +165,7 @@ int parse_options(int argc, char** argv, st_state_t *st) { int main(int argc, char** argv) { + int32_t voltage; stlink_t *sl = NULL; @@ -164,20 +175,34 @@ int main(int argc, char** argv) { state.stlink_version = 2; state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; + state.reset = 1; /* By default, reset board */ parse_options(argc, argv, &state); switch (state.stlink_version) { case 2: - sl = stlink_open_usb(state.logging_level); + sl = stlink_open_usb(state.logging_level, 0); if(sl == NULL) return 1; break; case 1: - sl = stlink_v1_open(state.logging_level); + sl = stlink_v1_open(state.logging_level, 0); if(sl == NULL) return 1; break; } + connected_stlink = sl; + signal(SIGINT, &cleanup); + signal(SIGTERM, &cleanup); + + if (state.reset) { + stlink_reset(sl); + } + printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); + voltage = stlink_target_voltage(sl); + if (voltage != -1) { + printf("Target voltage is %d mV.\n", voltage); + } + sl->verbose=0; current_memory_map = make_memory_map(sl); @@ -190,8 +215,11 @@ int main(int argc, char** argv) { #endif do { - serve(sl, state.listen_port); - } while (persistent); + serve(sl, &state); + + /* Continue */ + stlink_run(sl); + } while (state.persistent); #ifdef __MINGW32__ winsock_error: @@ -199,7 +227,6 @@ winsock_error: #endif /* Switch back to mass storage mode before closing. */ - stlink_run(sl); stlink_exit_debug_mode(sl); stlink_close(sl); @@ -356,7 +383,7 @@ struct code_hw_watchpoint { struct code_hw_watchpoint data_watches[DATA_WATCH_NUM]; static void init_data_watchpoints(stlink_t *sl) { - #ifdef DEBUG + #if DEBUG printf("init watchpoints\n"); #endif @@ -391,7 +418,7 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr for(i = 0; i < DATA_WATCH_NUM; i++) { // is this an empty slot ? if(data_watches[i].fun == WATCHDISABLED) { - #ifdef DEBUG + #if DEBUG printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len); #endif @@ -415,7 +442,7 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr } } - #ifdef DEBUG + #if DEBUG printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len); #endif return -1; @@ -427,7 +454,7 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) for(i = 0 ; i < DATA_WATCH_NUM; i++) { if((data_watches[i].addr == addr) && (data_watches[i].fun != WATCHDISABLED)) { - #ifdef DEBUG + #if DEBUG printf("delete watchpoint %d addr %x\n", i, addr); #endif @@ -438,7 +465,7 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) } } - #ifdef DEBUG + #if DEBUG printf("failure: delete watchpoint addr %x\n", addr); #endif @@ -446,6 +473,7 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) } #define CODE_BREAK_NUM 6 +#define CODE_LIT_NUM 2 #define CODE_BREAK_LOW 0x01 #define CODE_BREAK_HIGH 0x02 @@ -459,8 +487,14 @@ struct code_hw_breakpoint code_breaks[CODE_BREAK_NUM]; static void init_code_breakpoints(stlink_t *sl) { memset(sl->q_buf, 0, 4); stlink_write_debug32(sl, CM3_REG_FP_CTRL, 0x03 /*KEY | ENABLE4*/); - printf("KARL - should read back as 0x03, not 60 02 00 00\n"); - stlink_read_debug32(sl, CM3_REG_FP_CTRL); + unsigned int val = stlink_read_debug32(sl, CM3_REG_FP_CTRL); + if (((val & 3) != 1) || + ((((val >> 8) & 0x70) | ((val >> 4) & 0xf)) != CODE_BREAK_NUM) || + (((val >> 8) & 0xf) != CODE_LIT_NUM)){ + fprintf(stderr, "[FP_CTRL] = 0x%08x expecting 0x%08x\n", val, + ((CODE_BREAK_NUM & 0x70) << 8) | (CODE_LIT_NUM << 8) | ((CODE_BREAK_NUM & 0xf) << 4) | 1); + } + for(int i = 0; i < CODE_BREAK_NUM; i++) { code_breaks[i].type = 0; @@ -499,7 +533,7 @@ static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) { else brk->type &= ~type; if(brk->type == 0) { - #ifdef DEBUG + #if DEBUG printf("clearing hw break %d\n", id); #endif @@ -507,7 +541,7 @@ static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) { } else { uint32_t mask = (brk->addr) | 1 | (brk->type << 30); - #ifdef DEBUG + #if DEBUG printf("setting hw break %d at %08x (%d)\n", id, brk->addr, brk->type); printf("reg %08x \n", @@ -603,7 +637,7 @@ static int flash_go(stlink_t *sl) { stlink_reset(sl); for(struct flash_block* fb = flash_root; fb; fb = fb->next) { - #ifdef DEBUG + #if DEBUG printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length); #endif @@ -613,7 +647,7 @@ static int flash_go(stlink_t *sl) { //Update FLASH_PAGE stlink_calculate_pagesize(sl, page); - #ifdef DEBUG + #if DEBUG printf("flash_do: page %08x\n", page); #endif @@ -639,7 +673,7 @@ error: return error; } -int serve(stlink_t *sl, int port) { +int serve(stlink_t *sl, st_state_t *st) { int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) { perror("socket"); @@ -652,8 +686,8 @@ int serve(stlink_t *sl, int port) { struct sockaddr_in serv_addr; memset(&serv_addr,0,sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - serv_addr.sin_port = htons(port); + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(st->listen_port); if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("bind"); @@ -665,12 +699,7 @@ int serve(stlink_t *sl, int port) { return 1; } - stlink_force_debug(sl); - stlink_reset(sl); - 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); @@ -681,6 +710,13 @@ int serve(stlink_t *sl, int port) { close(sock); + stlink_force_debug(sl); + if (st->reset) { + stlink_reset(sl); + } + init_code_breakpoints(sl); + init_data_watchpoints(sl); + printf("GDB connected.\n"); /* @@ -698,7 +734,7 @@ int serve(stlink_t *sl, int port) { return 1; } - #ifdef DEBUG + #if DEBUG printf("recv: %s\n", packet); #endif @@ -723,7 +759,7 @@ int serve(stlink_t *sl, int port) { char* queryName = calloc(queryNameLength + 1, 1); strncpy(queryName, &packet[1], queryNameLength); - #ifdef DEBUG + #if DEBUG printf("query: %s;%s\n", queryName, params); #endif @@ -748,7 +784,7 @@ int serve(stlink_t *sl, int port) { unsigned addr = strtoul(__s_addr, NULL, 16), length = strtoul(s_length, NULL, 16); - #ifdef DEBUG + #if DEBUG printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n", type, op, annex, addr, length); #endif @@ -785,7 +821,7 @@ int serve(stlink_t *sl, int port) { if (!strncmp(params,"726573756d65",12)) {// resume -#ifdef DEBUG +#if DEBUG printf("Rcmd: resume\n"); #endif stlink_run(sl); @@ -796,7 +832,7 @@ int serve(stlink_t *sl, int port) { stlink_force_debug(sl); -#ifdef DEBUG +#if DEBUG printf("Rcmd: halt\n"); #endif } else if (!strncmp(params,"6a7461675f7265736574",20)) { //jtag_reset @@ -806,7 +842,7 @@ int serve(stlink_t *sl, int port) { stlink_jtag_reset(sl, 0); stlink_force_debug(sl); -#ifdef DEBUG +#if DEBUG printf("Rcmd: jtag_reset\n"); #endif } else if (!strncmp(params,"7265736574",10)) { //reset @@ -817,11 +853,11 @@ int serve(stlink_t *sl, int port) { init_code_breakpoints(sl); init_data_watchpoints(sl); -#ifdef DEBUG +#if DEBUG printf("Rcmd: reset\n"); #endif } else { -#ifdef DEBUG +#if DEBUG printf("Rcmd: %s\n", params); #endif @@ -853,7 +889,7 @@ int serve(stlink_t *sl, int port) { unsigned addr = strtoul(__s_addr, NULL, 16), length = strtoul(s_length, NULL, 16); - #ifdef DEBUG + #if DEBUG printf("FlashErase: addr:%08x,len:%04x\n", addr, length); #endif @@ -891,7 +927,7 @@ int serve(stlink_t *sl, int port) { if(dec_index % 2 != 0) dec_index++; - #ifdef DEBUG + #if DEBUG printf("binary packet %d -> %d\n", data_length, dec_index); #endif @@ -1207,7 +1243,7 @@ int serve(stlink_t *sl, int port) { * Also, set to persistent mode * to allow GDB disconnect. */ - persistent = 1; + st->persistent = 1; reply = strdup("OK"); @@ -1233,7 +1269,7 @@ int serve(stlink_t *sl, int port) { } if(reply) { - #ifdef DEBUG + #if DEBUG printf("send: %s\n", reply); #endif