X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=gdbserver%2Fgdb-server.c;h=30ee01483554b85afd8783fb01b050c279cb5628;hb=2f7b70f1a8ef8d1204b1d16b58c4d3a160f8156a;hp=77d7562a4ab147543fe86c31f0af325665b31508;hpb=371b100cb08289f7507c5fb2b245ebc63c403411;p=fw%2Fstlink diff --git a/gdbserver/gdb-server.c b/gdbserver/gdb-server.c index 77d7562..30ee014 100644 --- a/gdbserver/gdb-server.c +++ b/gdbserver/gdb-server.c @@ -6,6 +6,7 @@ license that can be found in the LICENSE file. */ +#include #include #include #include @@ -14,67 +15,257 @@ #include #include #include +#include #include #include "gdb-remote.h" +#define DEFAULT_LOGGING_LEVEL 10 +#define DEFAULT_GDB_LISTEN_PORT 4242 + +#define STRINGIFY_inner(name) #name +#define STRINGIFY(name) STRINGIFY_inner(name) + #define FLASH_BASE 0x08000000 #define FLASH_PAGE (sl->flash_pgsz) #define FLASH_PAGE_MASK (~((1 << 10) - 1)) #define FLASH_SIZE (FLASH_PAGE * 128) +volatile int do_exit = 0; +void ctrl_c(int sig) +{ + do_exit = 1; +} + static const char hex[] = "0123456789abcdef"; static const char* current_memory_map = NULL; +/* + * Chip IDs are explained in the appropriate programming manual for the + * DBGMCU_IDCODE register (0xE0042000) + */ + +#define CORE_M3_R1 0x1BA00477 +#define CORE_M3_R2 0x4BA00477 +#define CORE_M4_R0 0x2BA01477 + struct chip_params { uint32_t chip_id; char* description; + uint32_t flash_size_reg; uint32_t max_flash_size, flash_pagesize; uint32_t sram_size; uint32_t bootrom_base, bootrom_size; } const devices[] = { - { 0x412, "Low-density device", - 0x8000, 0x400, 0x2800, 0x1ffff000, 0x800 }, // table 1, pm0063 - { 0x410, "Medium-density device", + { 0x410, "F1 Medium-density device", 0x1ffff7e0, 0x20000, 0x400, 0x5000, 0x1ffff000, 0x800 }, // table 2, pm0063 - { 0x414, "High-density device", + { 0x411, "F2 device", 0, /* No flash size register found in the docs*/ + 0x100000, 0x20000, 0x20000, 0x1fff0000, 0x7800 }, // table 1, pm0059 + { 0x412, "F1 Low-density device", 0x1ffff7e0, + 0x8000, 0x400, 0x2800, 0x1ffff000, 0x800 }, // table 1, pm0063 + { 0x413, "F4 device", 0x1FFF7A10, + 0x100000, 0x20000, 0x30000, 0x1fff0000, 0x7800 }, // table 1, pm0081 + { 0x414, "F1 High-density device", 0x1ffff7e0, 0x80000, 0x800, 0x10000, 0x1ffff000, 0x800 }, // table 3 pm0063 // This ignores the EEPROM! (and uses the page erase size, // not the sector write protection...) - { 0x416, "EnergyLite device", - 0x2000, 0x100, 0x4000, 0x1ff00000, 0x1000 }, - { 0x418, "Connectivity line device", + { 0x416, "L1 Med-density device", 0x1FF8004C, // table 1, pm0062 + 0x20000, 0x100, 0x4000, 0x1ff00000, 0x1000 }, + { 0x418, "F1 Connectivity line device", 0x1ffff7e0, 0x40000, 0x800, 0x10000, 0x1fffb000, 0x4800 }, - { 0x420, "Medium-density value line device", + { 0x420, "F1 Medium-density value line device", 0x1ffff7e0, 0x20000, 0x400, 0x2000, 0x1ffff000, 0x800 }, - { 0x428, "High-density value line device", + { 0x428, "F1 High-density value line device", 0x1ffff7e0, 0x80000, 0x800, 0x8000, 0x1ffff000, 0x800 }, - { 0x430, "XL-density device", // pm0068 + { 0x430, "F1 XL-density device", 0x1ffff7e0, // pm0068 0x100000, 0x800, 0x18000, 0x1fffe000, 0x1800 }, { 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; +} st_state_t; + + int serve(stlink_t *sl, int port); char* make_memory_map(const struct chip_params *params, uint32_t flash_size); + +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'}, + {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" + " -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" + " -p 4242, --listen_port=1234\n" + "\t\t\tSet the gdb server listen port. " + "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" + ; + + + int option_index = 0; + int c; + int q; + while ((c = getopt_long(argc, argv, "hv::d:s:1p:", 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"); + printf("option %s", long_options[option_index].name); + if (optarg) { + printf(" with arg %s", optarg); + } + printf("\n"); + break; + case 'h': + printf(help_str, argv[0]); + exit(EXIT_SUCCESS); + break; + case 'v': + if (optarg) { + st->logging_level = atoi(optarg); + } else { + st->logging_level = DEFAULT_LOGGING_LEVEL; + } + break; + case 'd': + if (strlen(optarg) > sizeof (st->devicename)) { + fprintf(stderr, "device name too long: %ld\n", strlen(optarg)); + } else { + strcpy(st->devicename, optarg); + } + break; + case '1': + st->stlink_version = 1; + break; + case 's': + sscanf(optarg, "%i", &q); + if (q < 0 || q > 2) { + fprintf(stderr, "stlink version %d unknown!\n", q); + exit(EXIT_FAILURE); + } + st->stlink_version = q; + break; + case 'p': + sscanf(optarg, "%i", &q); + if (q < 0) { + fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); + exit(EXIT_FAILURE); + } + st->listen_port = q; + break; + } + } + + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + return 0; +} + + int main(int argc, char** argv) { - if(argc != 3) { - fprintf(stderr, "Usage: %s /dev/sgX\n", argv[0]); - return 1; + + stlink_t *sl = NULL; + + st_state_t state; + memset(&state, 0, sizeof(state)); + // set defaults... + state.stlink_version = 2; + state.logging_level = 10; + state.listen_port = DEFAULT_GDB_LISTEN_PORT; + parse_options(argc, argv, &state); + switch (state.stlink_version) { + case 2: + sl = stlink_open_usb(state.logging_level); + if(sl == NULL) return 1; + break; + case 1: +#if (CONFIG_USE_LIBSG == 1) + if (strlen(state.devicename) == 0) { + const int DevNumMax = 99; + int ExistDevCount = 0; + + for (int DevNum = 0; DevNum <= DevNumMax; DevNum++) { + if (DevNum < 10) { + char DevName[] = "/dev/sgX"; + const int X_index = 7; + DevName[X_index] = DevNum + '0'; + if (!access(DevName, F_OK)) { + sl = stlink_quirk_open(DevName, 0); + ExistDevCount++; + } + } else if (DevNum < 100) { + char DevName[] = "/dev/sgXY"; + const int X_index = 7; + const int Y_index = 8; + DevName[X_index] = DevNum / 10 + '0'; + DevName[Y_index] = DevNum % 10 + '0'; + if (!access(DevName, F_OK)) { + sl = stlink_quirk_open(DevName, 0); + ExistDevCount++; + } + } + if (sl != NULL) break; + } + + if (sl == NULL) { + fprintf(stdout, "\nNumber of /dev/sgX devices found: %i \n", + ExistDevCount); + fprintf(stderr, "ST-LINK not found\n"); + return 1; + } + } else { + sl = stlink_quirk_open(state.devicename, state.logging_level); + } + break; +#else + fprintf(stderr, "Support for stlink v1 disabled at build time...\n"); + fprintf(stderr, "Perhaps you're on OSX, and we haven't finished removing the libsg deps?\n"); + exit(EXIT_FAILURE); +#endif } - // FIXME - hardcoded to usb.... - stlink_t *sl =stlink_open_usb(argv[2], 10); - if (sl == NULL) - return 1; + if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { + stlink_exit_dfu_mode(sl); + } - if(stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) - stlink_enter_swd_mode(sl); + if(stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { + stlink_enter_swd_mode(sl); + } uint32_t chip_id = stlink_chip_id(sl); - printf("Chip ID is %08x.\n", chip_id); + uint32_t core_id = stlink_core_id(sl); + + /* Fix chip_id for F4 */ + if (((chip_id & 0xFFF) == 0x411) && (core_id == CORE_M4_R0)) { + printf("Fixing wrong chip_id for STM32F4 Rev A errata\n"); + chip_id = 0x413; + } + + printf("Chip ID is %08x, Core ID is %08x.\n", chip_id, core_id); const struct chip_params* params = NULL; @@ -98,17 +289,18 @@ int main(int argc, char** argv) { uint32_t flash_size; - stlink_read_mem32(sl, 0x1FFFF7E0, 4); // FIXME - that's never going to work! + stlink_read_mem32(sl, params->flash_size_reg, 4); flash_size = sl->q_buf[0] | (sl->q_buf[1] << 8); printf("Flash size is %d KiB.\n", flash_size); // memory map is in 1k blocks. current_memory_map = make_memory_map(params, flash_size * 0x400); - int port = atoi(argv[1]); - - while(serve(sl, port) == 0); + while(serve(sl, state.listen_port) == 0); + /* Switch back to mass storage mode before closing. */ + stlink_run(sl); + stlink_exit_debug_mode(sl); stlink_close(sl); return 0; @@ -288,12 +480,14 @@ struct code_hw_breakpoint code_breaks[CODE_BREAK_NUM]; static void init_code_breakpoints(stlink_t *sl) { memset(sl->q_buf, 0, 4); sl->q_buf[0] = 0x03; // KEY | ENABLE - stlink_write_mem32(sl, 0xe0002000, 4); + stlink_write_mem32(sl, CM3_REG_FP_CTRL, 4); + printf("KARL - should read back as 0x03, not 60 02 00 00\n"); + stlink_read_mem32(sl, CM3_REG_FP_CTRL, 4); memset(sl->q_buf, 0, 4); for(int i = 0; i < CODE_BREAK_NUM; i++) { code_breaks[i].type = 0; - stlink_write_mem32(sl, 0xe0002008 + i * 4, 4); + stlink_write_mem32(sl, CM3_REG_FP_COMP0 + i * 4, 4); } } @@ -503,7 +697,9 @@ int serve(stlink_t *sl, int port) { printf("Listening at *:%d...\n", port); + (void) signal (SIGINT, ctrl_c); int client = accept(sock, NULL, NULL); + signal (SIGINT, SIG_DFL); if(client < 0) { perror("accept"); return 1; @@ -560,8 +756,9 @@ int serve(stlink_t *sl, int port) { if(!strcmp(queryName, "Supported")) { reply = strdup("PacketSize=3fff;qXfer:memory-map:read+"); } else if(!strcmp(queryName, "Xfer")) { - char *type, *op, *annex, *s_addr, *s_length; + char *type, *op, *s_addr, *s_length; char *tok = params; + char *annex __attribute__((unused)); type = strsep(&tok, ":"); op = strsep(&tok, ":");