Merge tag '1.2.0' into debian
[fw/stlink] / flash / main.c
index 2679bbbce930d0f508fa5d664b4cd48289da233a..0ba429c669dbd0f5d4a6c14f0e90149c236b0704 100644 (file)
@@ -3,6 +3,7 @@
 // TODO - this should be done as just a simple flag to the st-util command line...
 
 
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #define DEBUG_LOG_LEVEL 100
 #define STND_LOG_LEVEL  50
 
+stlink_t *connected_stlink = NULL;
+
+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);
+}
+
 enum st_cmds {DO_WRITE = 0, DO_READ = 1, DO_ERASE = 2};
 struct opts
 {
     enum st_cmds cmd;
     const char* devname;
+       char *serial;
     const char* filename;
     stm32_addr_t addr;
     size_t size;
@@ -26,11 +41,11 @@ struct opts
 
 static void usage(void)
 {
-    puts("stlinkv1 command line: ./st-flash [--debug] [--reset] {read|write} /dev/sgX path addr <size>");
+    puts("stlinkv1 command line: ./st-flash [--debug] [--reset] [--serial <iSerial>] {read|write} /dev/sgX path addr <size>");
     puts("stlinkv1 command line: ./st-flash [--debug] /dev/sgX erase");
-    puts("stlinkv2 command line: ./st-flash [--debug] [--reset] {read|write} path addr <size>");
-    puts("stlinkv2 command line: ./st-flash [--debug] erase");
-    puts("                       use hex format for addr and <size>");
+    puts("stlinkv2 command line: ./st-flash [--debug] [--reset] [--serial <iSerial>] {read|write} path addr <size>");
+    puts("stlinkv2 command line: ./st-flash [--debug] [--serial <iSerial>] erase");
+    puts("                       use hex format for addr, <iSerial> and <size>");
 }
 
 static int get_opts(struct opts* o, int ac, char** av)
@@ -64,6 +79,31 @@ static int get_opts(struct opts* o, int ac, char** av)
         o->reset = 0;
     }
 
+    if (strcmp(av[0], "--serial") == 0)
+    {
+        ac--;
+        av++;
+           int i=strlen(av[0]);
+           if(i%2 != 0){
+                   puts("no valid hex value, length must be multiple of 2\n");
+                   return -1;
+           }
+           int j=0;
+           while(i>=0 && j<=13){
+                   char buffer[3]={0};
+                   memcpy(buffer,&av[0][i],2);
+                   o->serial[12-j] = (char)strtol((const char*)buffer,NULL, 16);
+                   j++;
+                   i-=2;
+           }
+        ac--;
+        av++;
+    }
+    else
+    {
+        o->serial = NULL;
+    }
+
     if (ac < 1) return -1;
 
     /* stlinkv2 */
@@ -123,6 +163,8 @@ int main(int ac, char** av)
 {
     stlink_t* sl = NULL;
     struct opts o;
+    char serial_buffer[13] = {0};
+    o.serial = serial_buffer;
     int err = -1;
 
     o.size = 0;
@@ -130,31 +172,48 @@ int main(int ac, char** av)
     {
         printf("invalid command line\n");
         usage();
-        goto on_error;
+        return -1;
     }
 
     if (o.devname != NULL) /* stlinkv1 */
-    {
         sl = stlink_v1_open(o.log_level, 1);
-        if (sl == NULL) goto on_error;
-        sl->verbose = o.log_level;
-    }
     else /* stlinkv2 */
-    {
-        sl = stlink_open_usb(o.log_level, 1);
-        if (sl == NULL) goto on_error;
-        sl->verbose = o.log_level;
-    }
+           sl = stlink_open_usb(o.log_level, 1, o.serial);
 
-    if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE)
-        stlink_exit_dfu_mode(sl);
+    if (sl == NULL)
+        return -1;
 
-    if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
-        stlink_enter_swd_mode(sl);
+    sl->verbose = o.log_level;
+
+    connected_stlink = sl;
+    signal(SIGINT, &cleanup);
+    signal(SIGTERM, &cleanup);
+    signal(SIGSEGV, &cleanup);
+
+    if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
+        if (stlink_exit_dfu_mode(sl)) {
+            printf("Failed to exit DFU mode\n");
+            goto on_error;
+        }
+    }
+
+    if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) {
+        if (stlink_enter_swd_mode(sl)) {
+            printf("Failed to enter SWD mode\n");
+            goto on_error;
+        }
+    }
 
     if (o.reset){
-        stlink_jtag_reset(sl,2);
-        stlink_reset(sl);
+        if (stlink_jtag_reset(sl, 2)) {
+            printf("Failed to reset JTAG\n");
+            goto on_error;
+        }
+
+        if (stlink_reset(sl)) {
+            printf("Failed to reset device\n");
+            goto on_error;
+        }
     }
 
     // Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013
@@ -170,8 +229,15 @@ int main(int ac, char** av)
     }
 
     // Core must be halted to use RAM based flashloaders
-    stlink_force_debug(sl);
-    stlink_status(sl);
+    if (stlink_force_debug(sl)) {
+        printf("Failed to halt the core\n");
+        goto on_error;
+    }
+
+    if (stlink_status(sl)) {
+        printf("Failed to get Core's status\n");
+        goto on_error;
+    }
 
     if (o.cmd == DO_WRITE) /* write */
     {
@@ -189,7 +255,7 @@ int main(int ac, char** av)
             err = stlink_fwrite_sram(sl, o.filename, o.addr);
             if (err == -1)
             {
-                printf("stlink_sram_flash() == -1\n");
+                printf("stlink_fwrite_sram() == -1\n");
                 goto on_error;
             }
         }
@@ -198,7 +264,7 @@ int main(int ac, char** av)
         err = stlink_erase_flash_mass(sl);
         if (err == -1)
         {
-            printf("stlink_fwrite_flash() == -1\n");
+            printf("stlink_erase_flash_mass() == -1\n");
             goto on_error;
         }
     }
@@ -227,11 +293,8 @@ int main(int ac, char** av)
     err = 0;
 
 on_error:
-    if (sl != NULL)
-    {
-        stlink_exit_debug_mode(sl);
-        stlink_close(sl);
-    }
+    stlink_exit_debug_mode(sl);
+    stlink_close(sl);
 
     return err;
 }