Merge branch 'tmaster' into future
[fw/stlink] / gdbserver / gdb-server.c
index b5d66dff563450f4c068b45a4fe4c01f2b9992c6..6033040a3bcff515608b24cd5e82bd38c0e0c75b 100644 (file)
@@ -6,6 +6,7 @@
  license that can be found in the LICENSE file.
 */
 
+#include <getopt.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 
 #include "gdb-remote.h"
 
+#define DEFAULT_LOGGING_LEVEL 50
+#define DEFAULT_GDB_LISTEN_PORT 4242
+
+#define STRINGIFY_inner(name) #name
+#define STRINGIFY(name) STRINGIFY_inner(name)
+
 #define FLASH_BASE 0x08000000
 
 //Allways update the FLASH_PAGE before each use, by calling stlink_calculate_pagesize
 #define FLASH_PAGE (sl->flash_pgsz)
 
-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;
 
-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[] = {
-       { 0x410, "F1 Medium-density device", 0x1ffff7e0,
-         0x20000,  0x400, 0x5000,  0x1ffff000, 0x800  },               // table 2, pm0063
-       { 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
-         /*Page size is variable */
-       { 0x413, "F4 device", 0x1FFF7A10,                                               //RM0090 error same as unique ID
-         0x100000,   0x4000, 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, "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, "F1 Medium-density value line device", 0x1ffff7e0,
-         0x20000,  0x400, 0x2000,  0x1ffff000, 0x800  },
-       { 0x428, "F1 High-density value line device", 0x1ffff7e0,
-         0x80000,  0x800, 0x8000,  0x1ffff000, 0x800  },
-       { 0x430, "F1 XL-density device", 0x1ffff7e0,                    // pm0068
-         0x100000, 0x800, 0x18000, 0x1fffe000, 0x1800 },
-       { 0 }
-};
-
-int serve(stlink_t *sl, int port);
-char* make_memory_map(stlink_t *sl, const struct chip_params *params, uint32_t flash_size);
+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 main(int argc, char** argv) {
 
-       stlink_t *sl = NULL;
-       int port = 0;
-       uint32_t flash_size;
-
-       const char * HelpStr =  "\nUsage:\n"
-                                 "\tst-util [Arguments]\n"
-                                 "\tArguments (no more than 2):\n"
-                                  "\t\t<Port>: Port. Default: 4242.\n"
-                                  "\t\t{usb|sgauto|/dev/sgX}: Transport, "
-                                   "where X = {0, 1, 2, ...}. Default: USB.\n"
-                                 "\tExamples:\n"
-                                  "\t\tst-util 1234\n"
-                                  "\t\tst-util sgauto\n"
-                                  "\t\tst-util 1234 usb\n"
-                                  "\t\tst-util /dev/sgX 1234\n"
-                                  "\t\tst-util 1234 /dev/sgX\n";
-        
-        
-        // Parsing the arguments of command line ...
-        
-        if (argc == 1 || argc > 3) {
-            fprintf(stderr, HelpStr, NULL);
-            return 1;
-        }
-                
-        for(int a = 1; a < argc; a++) {
-            
-            // Port
-            int p = atoi(argv[a]);
-            if (p < 0 || p > 0xFFFF) {
-                fprintf(stderr, "Invalid port\n");
-                fprintf(stderr, HelpStr, NULL);
-                return 1;
-            }
-            if (p > 0 && port == 0) {port = p; continue;}
-            
-            // if (p == 0) ...
-            
-            if (sl != NULL) {
-                fprintf(stderr, "Invalid argumets\n");
-                fprintf(stderr, HelpStr, NULL);
-                return 1;
-            }
-            
-            // usb
-            if (!strcmp(argv[a], "usb")) {
-                sl = stlink_open_usb(10);
-                if(sl == NULL) return 1;
-                continue;
+int serve(stlink_t *sl, int port);
+char* make_memory_map(stlink_t *sl);
+
+
+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>, --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);
             }
-
-            // /dev/sgX
-            if (!strncmp(argv[a], "/dev/sgX", 7)) {
-                if(!CONFIG_USE_LIBSG) {
-                    fprintf(stderr, "libsg not use\n");
-                    return 1;
-                }
-                sl = stlink_quirk_open(argv[a], 0);
-                if(sl == NULL) return 1;
-                continue;
+            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;
             }
-
-            // sg_auto
-            if (!strcmp(argv[a], "sgauto")) {
-                if(!CONFIG_USE_LIBSG) {
-                    fprintf(stderr, "libsg not use\n");
-                    return 1;
-                }
-
-                // Search ST-LINK (from /dev/sg0 to /dev/sg99)
-                for(int DevNum = 0; DevNum <= 99; DevNum++)
-                {
-                    if(DevNum < 10) {
-                        char DevName[] = "/dev/sgX";
-                        DevName[7] = DevNum + '0';
-                        if ( !access(DevName, F_OK) )
-                            sl = stlink_quirk_open(DevName, 0);
-                    }
-                    else {
-                        char DevName[] = "/dev/sgXY";
-                        DevName[7] = DevNum/10 + '0';
-                        DevName[8] = DevNum%10 + '0';
-                        if ( !access(DevName, F_OK) )
-                            sl = stlink_quirk_open(DevName, 0);
-                    }
-                   if (sl != NULL) break;
-                }
-
-                if(sl == NULL) return 1;
-                continue;
+            break;
+        case 'd':
+            if (strlen(optarg) > sizeof (st->devicename)) {
+                fprintf(stderr, "device name too long: %zd\n", strlen(optarg));
+            } else {
+                strcpy(st->devicename, optarg);
             }
-            
-            // Invalid argumets
-            fprintf(stderr, "Invalid argumets\n");
-            fprintf(stderr, HelpStr, NULL);
-            return 1;
+            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;
         }
-         
-        // Default transport: USB
-        if (sl == NULL) sl = stlink_open_usb(10);
-        // Default port: 4242
-        if (port == 0) port = 4242;
-        
-        // End parsing
-        
-        
-        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);
-       }
-
-       stlink_identify_device(sl);
-       printf("Chip ID is %08x, Core ID is  %08x.\n", sl->chip_id, sl->core_id);
-
-       sl->verbose=0;
+    }
 
-       const struct chip_params* params = NULL;
+    if (optind < argc) {
+        printf("non-option ARGV-elements: ");
+        while (optind < argc)
+            printf("%s ", argv[optind++]);
+        printf("\n");
+    }
+    return 0;
+}
 
-       for(int i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
-               if(devices[i].chip_id == (sl->chip_id & 0xFFF)) {
-                       params = &devices[i];
-                       break;
-               }
-       }
 
-       if(params == NULL) {
-               fprintf(stderr, "Cannot recognize the connected device!\n");
-               return 0;
-       }
+int main(int argc, char** argv) {
 
-       printf("Device connected: %s\n", params->description);
+       stlink_t *sl = NULL;
 
-       if(sl->chip_id==STM32F4_CHIP_ID) {
-               flash_size=0x100000;                    //todo: RM0090 error; size register same address as unique ID
-               printf("Device parameters: SRAM: 0x%x bytes, Flash: up to 0x%x bytes with variable page size\n",
-                       params->sram_size, flash_size);
-       }
-       else {
-               printf("Device parameters: SRAM: 0x%x bytes, Flash: up to 0x%x bytes in pages of 0x%x bytes\n",
-                       params->sram_size, params->max_flash_size, params->flash_pagesize);
-               stlink_read_mem32(sl, params->flash_size_reg, 4);
-               flash_size = sl->q_buf[0] | (sl->q_buf[1] << 8);
-               //flash_size_reg is in 1k blocks.
-               flash_size *= 0x400;
-       }
+       st_state_t state;
+       memset(&state, 0, sizeof(state));
+       // set defaults...
+       state.stlink_version = 2;
+       state.logging_level = DEFAULT_LOGGING_LEVEL;
+       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:
+               sl = stlink_v1_open(state.logging_level);
+               if(sl == NULL) return 1;
+               break;
+    }
+    
+       printf("Chip ID is %08x, Core ID is  %08x.\n", sl->chip_id, sl->core_id);
 
-       /* Init PAGE_SIZE for fixed page size devices.
-        * stlink_calculate_pagesize will then return this value for them.
-        * variable pagesize devices must allways update FLASH_PAGE before use! */
-       FLASH_PAGE = params->flash_pagesize;
-       sl->flash_size=flash_size;
+       sl->verbose=0;
 
-       printf("Flash size is %d\n", flash_size);
-       current_memory_map = make_memory_map(sl, params, flash_size);
+       current_memory_map = make_memory_map(sl);
 
-       while(serve(sl, port) == 0);
+       while(serve(sl, state.listen_port) == 0);
 
        /* Switch back to mass storage mode before closing. */
        stlink_run(sl);
@@ -282,21 +214,19 @@ static const char* const memory_map_template =
   "  <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x8\"/>"        // option byte area
   "</memory-map>";
 
-char* make_memory_map(stlink_t *sl, const struct chip_params *params, uint32_t flash_size) {
+char* make_memory_map(stlink_t *sl) {
        /* This will be freed in serve() */
        char* map = malloc(4096);
        map[0] = '\0';
 
        if(sl->chip_id==STM32F4_CHIP_ID) {
        strcpy(map, memory_map_template_F4);
-    }
-
-    else {
-       snprintf(map, 4096, memory_map_template,
-                       flash_size,
-                       params->sram_size,
-                       flash_size, params->flash_pagesize,
-                       params->bootrom_base, params->bootrom_size);
+    } else {
+        snprintf(map, 4096, memory_map_template,
+                       sl->flash_size,
+                       sl->sram_size,
+                       sl->flash_size, sl->flash_pgsz,
+                       sl->sys_base, sl->sys_size);
     }
        return map;
 }
@@ -664,7 +594,6 @@ 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) {