]> git.gag.com Git - fw/stlink/commitdiff
Merge branch 'tmaster' into future
authorKarl Palsson <karlp@tweak.net.au>
Tue, 15 Nov 2011 00:57:09 +0000 (00:57 +0000)
committerKarl Palsson <karlp@tweak.net.au>
Tue, 15 Nov 2011 00:57:09 +0000 (00:57 +0000)
This branch should work for F1 and F4 devices.  It has currently been tested
with F1 value line, (a VL discovery board) programmed via gdb via both an
stlinkv1 and an stlinkv2.

F4 has _not_ yet been tested on this branch

Conflicts:
.gitignore
doc/tutorial/tutorial.pdf
example/blink/main.c
gdbserver/Makefile
gdbserver/gdb-server.c
src/stlink-common.c
src/stlink-common.h
src/stlink-usb.c

1  2 
.gitignore
Makefile
README
doc/tutorial/tutorial.pdf
example/blink/main.c
flash/main.c
gdbserver/gdb-server.c
src/stlink-common.c
src/stlink-common.h
src/test_usb.c

diff --cc .gitignore
Simple merge
diff --cc Makefile
index f24ed13b0b88d29d7527d421cf154a05edbe41b9,d66afb8faa51d7a1a62db4fccdced7a6ba184c53..6bf02323d731c9b8d0e360c8b34bcfe812a40897
+++ b/Makefile
@@@ -46,9 -63,9 +46,9 @@@ clean
        $(MAKE) -C gdbserver clean
        
  flash:
 -      $(MAKE) -C flash CONFIG_USE_LIBSG="$(CONFIG_USE_LIBSG)" 
 +      $(MAKE) -C flash
  
  gdbserver:
-       $(MAKE) -C gdbserver
+       $(MAKE) -C gdbserver CONFIG_USE_LIBSG="$(CONFIG_USE_LIBSG)"
  
  .PHONY: clean all flash gdbserver
diff --cc README
Simple merge
index 856977bc7ce42517c50a390be589c18d46fb9b8e,38c4ea07a2cbfb460b4d38897507d454c0d2b60b..d9b9333aef01627c9afecbeff887444662707d95
Binary files differ
index e0438a0dbdec1678b7ff34d823588dceb9e6919d,73fd41bd9c1ad61f124d655eb002ef9d0b6ada7e..0a38069be301c930f6751a393cf60196f0587237
@@@ -41,14 -47,27 +41,17 @@@ static inline void setup_leds(void
  #elif CONFIG_STM32F4_DISCOVERY
  
  #define GPIOD 0x40020C00 /* port D */
 -# define GPIOD_MODER (GPIOD + 0x00) /* port mode register */
 -# define GPIOD_ODR (GPIOD + 0x14) /* port output data register */
 +#define GPIOD_MODER (GPIOD + 0x00) /* port mode register */
 +#define LED_PORT_ODR (GPIOD + 0x14) /* port output data register */
  
 -# define LED_GREEN (1 << 12) /* port B, pin 12 */
 -# define LED_ORANGE (1 << 13) /* port B, pin 13 */
 -# define LED_RED (1 << 14) /* port B, pin 14 */
 -# define LED_BLUE (1 << 15) /* port B, pin 15 */
 +#define LED_GREEN (1 << 12) /* port D, pin 12 */
 +#define LED_ORANGE (1 << 13) /* port D, pin 13 */
 +#define LED_RED (1 << 14) /* port D, pin 14 */
 +#define LED_BLUE (1 << 15) /* port D, pin 15 */
  
+ void _tmain(void) {
+       main();
+ }
  static inline void setup_leds(void)
  {
    *(volatile uint32_t*)GPIOD_MODER |= (1 << (12 * 2)) | (1 << (13 * 2)) |
diff --cc flash/main.c
Simple merge
index e7676219ce8151d84d80498ccd0a75cf7275fb08,b5d66dff563450f4c068b45a4fe4c01f2b9992c6..6033040a3bcff515608b24cd5e82bd38c0e0c75b
  
  #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)
- #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[] = {
 -      { 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;
 +    }
 +    
-       uint32_t chip_id = sl->chip_id;
-       uint32_t core_id = sl->core_id;
++      printf("Chip ID is %08x, Core ID is  %08x.\n", sl->chip_id, sl->core_id);
  
-       /* 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);
 -      /* 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);
@@@ -213,12 -287,17 +219,15 @@@ char* make_memory_map(stlink_t *sl) 
        char* map = malloc(4096);
        map[0] = '\0';
  
-       snprintf(map, 4096, memory_map_template,
+       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;
  }
  
index a853d13ad5a8e7c3b91c59984364df50986ff29e,d55dff68752ce61a2a647e52c49b0cb6b7f5b253..214f6c5735bb4bfd742923cd27699718fad81e05
@@@ -285,11 -392,18 +387,11 @@@ uint32_t stlink_core_id(stlink_t *sl) 
      return sl->core_id;
  }
  
- uint16_t stlink_chip_id(stlink_t *sl) {
 -void stlink_identify_device(stlink_t *sl) {
 -      uint32_t core_id=stlink_core_id(sl);
 -      stlink_read_mem32(sl, 0xE0042000, 4);
++uint32_t stlink_chip_id(stlink_t *sl) {
 +    stlink_read_mem32(sl, 0xE0042000, 4);
      uint32_t chip_id = sl->q_buf[0] | (sl->q_buf[1] << 8) | (sl->q_buf[2] << 16) |
              (sl->q_buf[3] << 24);
 -    /* 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;
 -    }
 -    sl->chip_id=chip_id;
 -    sl->core_id=core_id;
 +    return chip_id;
  }
  
  /**
@@@ -307,55 -421,8 +409,64 @@@ void stlink_cpu_id(stlink_t *sl, cortex
      return;
  }
  
-     sl->core_id = stlink_core_id(sl);
-     
 +/**
 + * reads and decodes the flash parameters, as dynamically as possible
 + * @param sl
 + * @return 0 for success, or -1 for unsupported core type.
 + */
 +int stlink_load_device_params(stlink_t *sl) {
 +    ILOG("Loading device parameters....\n");
 +    const chip_params_t *params = NULL;
++    
++    sl->core_id = stlink_core_id(sl);
 +    uint32_t chip_id = stlink_chip_id(sl);
++    
++    /* Fix chip_id for F4 rev A errata */
++    if (((chip_id & 0xFFF) == 0x411) && (sl->core_id == CORE_M4_R0)) {
++      chip_id = 0x413;
++    }
++
 +    sl->chip_id = chip_id;
 +      for(size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
 +              if(devices[i].chip_id == (chip_id & 0xFFF)) {
 +                      params = &devices[i];
 +                      break;
 +              }
 +      }
 +    if (params == NULL) {
 +        WLOG("unknown chip id! %#x\n", chip_id);
 +        return -1;
 +    }
 +    
 +    // These are fixed...
 +    sl->flash_base = STM32_FLASH_BASE;
 +    sl->sram_base = STM32_SRAM_BASE;
 +    
 +    // read flash size from hardware, if possible...
 +    if ((chip_id & 0xFFF) == STM32_CHIPID_F2) {
 +        sl->flash_size = 0; // FIXME - need to work this out some other way, just set to max possible?
++    } else if ((chip_id & 0xFFF) == STM32_CHIPID_F4) {
++              sl->flash_size = 0x100000;                      //todo: RM0090 error; size register same address as unique ID
 +    } else {
 +        stlink_read_mem32(sl, params->flash_size_reg, 4);
 +        uint32_t flash_size = sl->q_buf[0] | (sl->q_buf[1] << 8);
 +        sl->flash_size = flash_size * 1024;
 +    }
 +    sl->flash_pgsz = params->flash_pagesize;
 +    sl->sram_size = params->sram_size;
 +    sl->sys_base = params->bootrom_base;
 +    sl->sys_size = params->bootrom_size;
 +    
 +    ILOG("Device connected is: %s\n", params->description);
++    // TODO make note of variable page size here.....
 +    ILOG("SRAM size: %#x bytes (%d KiB), Flash: %#x bytes (%d KiB) in pages of %zd bytes\n",
 +        sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024, 
 +        sl->flash_pgsz);
 +    return 0;
 +}
 +
  void stlink_reset(stlink_t *sl) {
 -    D(sl, "\n*** stlink_reset ***\n");
 +    DLOG("*** stlink_reset ***\n");
      sl->backend->reset(sl);
  }
  
@@@ -743,28 -811,64 +854,66 @@@ int write_buffer_to_sram(stlink_t *sl, 
      return 0;
  }
  
-  * @param page
+ uint32_t calculate_F4_sectornum(uint32_t flashaddr){
+     flashaddr &= ~STM32_FLASH_BASE;   //Page now holding the actual flash address
+     if (flashaddr<0x4000) return (0);
+     else if(flashaddr<0x8000) return(1);
+     else if(flashaddr<0xc000) return(2);
+     else if(flashaddr<0x10000) return(3);
+     else if(flashaddr<0x20000) return(4);
+     else return(flashaddr/0x20000)+4;
+ }
+ uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
+       if(sl->chip_id == STM32F4_CHIP_ID) {
+               uint32_t sector=calculate_F4_sectornum(flashaddr);
+               if (sector<4) sl->flash_pgsz=0x4000;
+               else if(sector<5) sl->flash_pgsz=0x10000;
+               else sl->flash_pgsz=0x20000;
+       }
+       return (sl->flash_pgsz);
+ }
 +/**
 + * Erase a page of flash, assumes sl is fully populated with things like chip/core ids
 + * @param sl stlink context
- int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page)
++ * @param flashaddr an address in the flash page to erase
 + * @return 0 on success -ve on failure
 + */
+ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
  {
--  /* page an addr in the page to erase */
-   ILOG("Erasing flash page at addr: %#x\n", page);
-   if (sl->core_id == STM32L_CORE_ID)
 -
 -  stlink_identify_device(sl);
 -
++  ILOG("Erasing flash page at addr: %#x\n", flashaddr);
+   if (sl->chip_id == STM32F4_CHIP_ID)
+   {
+     /* wait for ongoing op to finish */
+     wait_flash_busy(sl);
+     /* unlock if locked */
+     unlock_flash_if(sl);
+     /* select the page to erase */
+     // calculate the actual page from the address
+     uint32_t sector=calculate_F4_sectornum(flashaddr);
+     fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x\n", sector, stlink_calculate_pagesize(sl, flashaddr));
+     write_flash_cr_snb(sl, sector);
+     /* start erase operation */
+     set_flash_cr_strt(sl);
+     /* wait for completion */
+     wait_flash_busy(sl);
+     /* relock the flash */
+     //todo: fails to program if this is in
+     lock_flash(sl);
+ #if DEBUG_FLASH
+       fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl));
+ #endif
+   }
 -
+   else if (sl->core_id == STM32L_CORE_ID)
    {
- #define STM32L_FLASH_REGS_ADDR ((uint32_t)0x40023c00)
- #define STM32L_FLASH_ACR (STM32L_FLASH_REGS_ADDR + 0x00)
- #define STM32L_FLASH_PECR (STM32L_FLASH_REGS_ADDR + 0x04)
- #define STM32L_FLASH_PDKEYR (STM32L_FLASH_REGS_ADDR + 0x08)
- #define STM32L_FLASH_PEKEYR (STM32L_FLASH_REGS_ADDR + 0x0c)
- #define STM32L_FLASH_PRGKEYR (STM32L_FLASH_REGS_ADDR + 0x10)
- #define STM32L_FLASH_OPTKEYR (STM32L_FLASH_REGS_ADDR + 0x14)
- #define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18)
- #define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x0c)
- #define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20)
  
      uint32_t val;
  
      /* relock the flash */
      lock_flash(sl);
    }
    else {
 -    fprintf(stderr, "unknown device!\n");
 +    WLOG("unknown coreid: %x\n", sl->core_id);
      return -1;
    }
  
@@@ -1001,194 -1106,238 +1151,227 @@@ int stlink_fcheck_flash(stlink_t *sl, c
  int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned len) {
      size_t off;
      flash_loader_t fl;
 -
 -    stlink_identify_device(sl);
 -
 +    ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n",
 +        len, len, addr, addr);
      /* check addr range is inside the flash */
+     stlink_calculate_pagesize(sl, addr);
      if (addr < sl->flash_base) {
 -        fprintf(stderr, "addr too low\n");
 +        WLOG("addr too low %#x < %#x\n", addr, sl->flash_base);
          return -1;
      } else if ((addr + len) < addr) {
 -        fprintf(stderr, "addr overruns\n");
 +        WLOG("addr overruns\n");
          return -1;
      } else if ((addr + len) > (sl->flash_base + sl->flash_size)) {
 -        fprintf(stderr, "addr too high\n");
 +        WLOG("addr too high\n");
          return -1;
      } else if ((addr & 1) || (len & 1)) {
 -        fprintf(stderr, "unaligned addr or size\n");
 +        WLOG("unaligned addr or size\n");
          return -1;
      } else if (addr & (sl->flash_pgsz - 1)) {
 -        fprintf(stderr, "addr not a multiple of pagesize, not supported\n");
 +        WLOG("addr not a multiple of pagesize, not supported\n");
          return -1;
      }
  
 +    // Make sure we've loaded the context with the chip details
 +    stlink_core_id(sl);
      /* erase each page */
 -    for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + off) ) {
 -        //addr must be an addr inside the page
 +    int page_count = 0;
-     for (off = 0; off < len; off += sl->flash_pgsz) {
++    for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + off)) {
 +        /* addr must be an addr inside the page */
          if (stlink_erase_flash_page(sl, addr + off) == -1) {
 -           fprintf(stderr, "erase_flash_page(0x%zx) == -1\n", addr + off);
 -          return -1;
 +            WLOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off);
 +            return -1;
          }
 +        page_count++;
      }
 -
 -#if 1 /* todo: use in debugging mode only */
 -    fprintf(stdout, "WriteFlash - Addr:0x%x len:0x%x\n", addr, len);
 -    //fprintf(stdout, "CoreID:0x%x ChipID:0x%x\n", sl->core_id, sl->chip_id);
 -#endif
 -
 +    ILOG("Finished erasing %d pages of %d (%#x) bytes\n", 
 +        page_count, sl->flash_pgsz, sl->flash_pgsz);
  
-     if (sl->core_id == STM32L_CORE_ID)
-     {
-       /* use fast word write. todo: half page. */
+     if (sl->chip_id == STM32F4_CHIP_ID) {
+       /* todo: check write operation */
  
-       uint32_t val;
+       /* First unlock the cr */
+       unlock_flash_if(sl);
  
- #if 0 /* todo: check write operation */
+       /* set parallelisim to 32 bit*/
+       write_flash_cr_psiz(sl, 2);
  
-       uint32_t nwrites = sl->flash_pgsz;
+       /* set programming mode */
+       set_flash_cr_pg(sl);
  
-     redo_write:
+ #define PROGRESS_CHUNK_SIZE 0x1000
+       /* write a word in program memory */
+       for (off = 0; off < len; off += sizeof(uint32_t)) {
+               if (sl->verbose >= 1) {
+                       if ((off & (PROGRESS_CHUNK_SIZE - 1)) == 0) {
+                               /* show progress. writing procedure is slow
+                                          and previous errors are misleading */
+                               const uint32_t pgnum = (off / PROGRESS_CHUNK_SIZE)+1;
+                               const uint32_t pgcount = len / PROGRESS_CHUNK_SIZE;
+                               fprintf(stdout, "Writing %ukB chunk %u out of %u\n", PROGRESS_CHUNK_SIZE/1024, pgnum, pgcount);
+                       }
+               }
  
- #endif /* todo: check write operation */
+               memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t));
+               stlink_write_mem32(sl, addr + off, sizeof(uint32_t));
  
-       /* disable pecr protection */
-       write_uint32(sl->q_buf, 0x89abcdef);
-       stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t));
-       write_uint32(sl->q_buf, 0x02030405);
-       stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t));
-       /* check pecr.pelock is cleared */
-       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
-       val = read_uint32(sl->q_buf, 0);
-       if (val & (1 << 0))
-       {
-       fprintf(stderr, "pecr.pelock not clear\n");
-       return -1;
-       }
+               /* wait for sr.busy to be cleared */
+           wait_flash_busy(sl);
  
-       /* unlock program memory */
-       write_uint32(sl->q_buf, 0x8c9daebf);
-       stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t));
-       write_uint32(sl->q_buf, 0x13141516);
-       stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t));
-       /* check pecr.prglock is cleared */
-       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
-       val = read_uint32(sl->q_buf, 0);
-       if (val & (1 << 1))
-       {
-       fprintf(stderr, "pecr.prglock not clear\n");
-       return -1;
-       }
+       }
+       /* Relock flash */
+       lock_flash(sl);
  
-       /* write a word in program memory */
-       for (off = 0; off < len; off += sizeof(uint32_t))
-       {
-       if (sl->verbose >= 1)
-       {
-         if ((off & (sl->flash_pgsz - 1)) == 0)
-         {
-           /* show progress. writing procedure is slow
-              and previous errors are misleading */
-           const uint32_t pgnum = off / sl->flash_pgsz;
-           const uint32_t pgcount = len / sl->flash_pgsz;
-           fprintf(stdout, "%u pages written out of %u\n", pgnum, pgcount);
-         }
-       }
+ #if 0 /* todo: debug mode */
+       fprintf(stdout, "Final CR:0x%x\n", read_flash_cr(sl));
+ #endif
  
-       memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t));
-       stlink_write_mem32(sl, addr + off, sizeof(uint32_t));
  
-       /* wait for sr.busy to be cleared */
-       while (1)
-       {
-         stlink_read_mem32(sl, STM32L_FLASH_SR, sizeof(uint32_t));
-         if ((read_uint32(sl->q_buf, 0) & (1 << 0)) == 0) break ;
-       }
  
- #if 0 /* todo: check redo write operation */
+     } //STM32F4END
  
-       /* check written bytes. todo: should be on a per page basis. */
-       stlink_read_mem32(sl, addr + off, sizeof(uint32_t));
-       if (memcmp(sl->q_buf, base + off, sizeof(uint32_t)))
-       {
-         /* re erase the page and redo the write operation */
-         uint32_t page;
-         uint32_t val;
+     else if (sl->core_id == STM32L_CORE_ID)    {
+       /* use fast word write. todo: half page. */
  
-         /* fail if successive write count too low */
-         if (nwrites < sl->flash_pgsz) {
-           fprintf(stderr, "writes operation failure count too high, aborting\n");
-           return -1;
-         }
+       uint32_t val;
  
-         nwrites = 0;
+ #if 0 /* todo: check write operation */
  
-         /* assume addr aligned */
-         if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1);
-         page = addr + off;
+       uint32_t nwrites = sl->flash_pgsz;
  
-         fprintf(stderr, "invalid write @%x(%x): %x != %x. retrying.\n",
-                 page, addr + off, read_uint32(base + off, 0), read_uint32(sl->q_buf, 0));
+       redo_write:
  
-         /* reset lock bits */
-         stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
-         val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2);
-         write_uint32(sl->q_buf, val);
-         stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+ #endif /* todo: check write operation */
  
-         stlink_erase_flash_page(sl, page);
+       /* disable pecr protection */
+       write_uint32(sl->q_buf, 0x89abcdef);
+       stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t));
+       write_uint32(sl->q_buf, 0x02030405);
+       stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t));
+       /* check pecr.pelock is cleared */
+       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+       val = read_uint32(sl->q_buf, 0);
+       if (val & (1 << 0)) {
+               fprintf(stderr, "pecr.pelock not clear\n");
+               return -1;
+       }
+       /* unlock program memory */
+       write_uint32(sl->q_buf, 0x8c9daebf);
+       stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t));
+       write_uint32(sl->q_buf, 0x13141516);
+       stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t));
+       /* check pecr.prglock is cleared */
+       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+       val = read_uint32(sl->q_buf, 0);
+       if (val & (1 << 1)) {
+               fprintf(stderr, "pecr.prglock not clear\n");
+               return -1;
+       }
+       /* write a word in program memory */
+       for (off = 0; off < len; off += sizeof(uint32_t)) {
+               if (sl->verbose >= 1) {
+                       if ((off & (sl->flash_pgsz - 1)) == 0) {
+                               /* show progress. writing procedure is slow
+                                  and previous errors are misleading */
+                               const uint32_t pgnum = off / sl->flash_pgsz;
+                               const uint32_t pgcount = len / sl->flash_pgsz;
+                               fprintf(stdout, "%u pages written out of %u\n", pgnum, pgcount);
+                       }
+               }
+               memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t));
+               stlink_write_mem32(sl, addr + off, sizeof(uint32_t));
+               /* wait for sr.busy to be cleared */
+               while (1) {
+                       stlink_read_mem32(sl, STM32L_FLASH_SR, sizeof(uint32_t));
+                       if ((read_uint32(sl->q_buf, 0) & (1 << 0)) == 0) break ;
+               }
  
-         goto redo_write;
-       }
+ #if 0 /* todo: check redo write operation */
  
-       /* increment successive writes counter */
-       ++nwrites;
+               /* check written bytes. todo: should be on a per page basis. */
+               stlink_read_mem32(sl, addr + off, sizeof(uint32_t));
+               if (memcmp(sl->q_buf, base + off, sizeof(uint32_t))) {
+                       /* re erase the page and redo the write operation */
+                       uint32_t page;
+                       uint32_t val;
  
- #endif /* todo: check redo write operation */
+                       /* fail if successive write count too low */
+                       if (nwrites < sl->flash_pgsz) {
+                               fprintf(stderr, "writes operation failure count too high, aborting\n");
+                               return -1;
+                       }
  
-       }
+                       nwrites = 0;
  
-       /* reset lock bits */
-       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
-       val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2);
-       write_uint32(sl->q_buf, val);
-       stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+                       /* assume addr aligned */
+                       if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1);
+                       page = addr + off;
+                       fprintf(stderr, "invalid write @0x%x(0x%x): 0x%x != 0x%x. retrying.\n",
+                                       page, addr + off, read_uint32(base + off, 0), read_uint32(sl->q_buf, 0));
+                       /* reset lock bits */
+                       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+                       val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2);
+                       write_uint32(sl->q_buf, val);
+                       stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+                       stlink_erase_flash_page(sl, page);
+                       goto redo_write;
+               }
+               /* increment successive writes counter */
+               ++nwrites;
+ #endif /* todo: check redo write operation */
+       }
+       /* reset lock bits */
+       stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+       val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2);
+       write_uint32(sl->q_buf, val);
+       stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
 -      }
 -
 -
 -
 +    } else if (sl->core_id == STM32VL_CORE_ID) {
 +        ILOG("Starting Flash write for VL core id\n");
 +        /* flash loader initialization */
 +        if (init_flash_loader(sl, &fl) == -1) {
 +            WLOG("init_flash_loader() == -1\n");
 +            return -1;
 +        }
  
 -    else if (sl->core_id == STM32VL_CORE_ID) {
 -      /* flash loader initialization */
 -      if (init_flash_loader(sl, &fl) == -1) {
 -              fprintf(stderr, "init_flash_loader() == -1\n");
 -              return -1;
 -      }
 -      /* write each page. above WRITE_BLOCK_SIZE fails? */
 +        /* write each page. above WRITE_BLOCK_SIZE fails? */
  #define WRITE_BLOCK_SIZE 0x40
 -      for (off = 0; off < len; off += WRITE_BLOCK_SIZE)      {
 -        /* adjust last write size */
 -        size_t size = WRITE_BLOCK_SIZE;
 -        if ((off + WRITE_BLOCK_SIZE) > len) size = len - off;
 -
 -        /* unlock and set programming mode */
 -        unlock_flash_if(sl);
 -        set_flash_cr_pg(sl);
 -
 -        if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
 -                fprintf(stderr, "run_flash_loader(0x%zx) == -1\n", addr + off);
 -                return -1;
 -        }
 -        lock_flash(sl);
 -      }
 -    }
 -
 -
 -
 -
 -    else
 -    {
 -      fprintf(stderr, "unknown device!\n");
 -      return -1;
 +        int write_block_count = 0;
 +        for (off = 0; off < len; off += WRITE_BLOCK_SIZE) {
 +            ILOG("Writing flash block %d of size %d (%#x)\n", write_block_count,
 +                WRITE_BLOCK_SIZE, WRITE_BLOCK_SIZE);
 +            /* adjust last write size */
 +            size_t size = WRITE_BLOCK_SIZE;
 +            if ((off + WRITE_BLOCK_SIZE) > len) size = len - off;
 +
 +            /* unlock and set programming mode */
 +            unlock_flash_if(sl);
 +            set_flash_cr_pg(sl);
 +            //DLOG("Finished setting flash cr pg, running loader!\n");
 +            if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
 +                WLOG("run_flash_loader(%#zx) failed! == -1\n", addr + off);
 +                return -1;
 +            }
 +            lock_flash(sl);
 +            DLOG("Finished writing block %d\n", write_block_count++);
 +        }
 +    } else {
 +        WLOG("unknown coreid, not sure how to write: %x\n", sl->core_id);
 +        return -1;
      }
  
 -
 -
 -
 -
 -#if(0)
 -    //todo: F4 Can't stlink_read_mem32 an entire sector, not enough ram!
 +    ILOG("Starting verification of write complete\n");
      for (off = 0; off < len; off += sl->flash_pgsz) {
          size_t aligned_size;
  
          if (aligned_size & (4 - 1))
              aligned_size = (cmp_size + 4) & ~(4 - 1);
  
 -              fprintf(stdout, "AlignedSize:0x%x\n", aligned_size);
++              fprintf(stdout, "AlignedSize:%#zx\n", aligned_size);
          stlink_read_mem32(sl, addr + off, aligned_size);
  
          if (memcmp(sl->q_buf, base + off, cmp_size))
index 9279c37f5e1dd2ded6672d2b8748eab54e53b6be,1d9e3878136abf39be00350c80a9342aa60935e5..82967d4b5951a733dd42f198782a806989c98509
@@@ -80,134 -80,21 +80,145 @@@ extern "C" 
  #define STM32VL_CORE_ID 0x1ba01477
  #define STM32L_CORE_ID 0x2ba01477
  #define STM32F4_CORE_ID 0x2ba01477
 +    
 +// stm32 chipids, only lower 12 bits..
 +#define STM32_CHIPID_F1_MEDIUM 0x410
 +#define STM32_CHIPID_F2 0x411
 +#define STM32_CHIPID_F1_LOW 0x412
 +#define STM32_CHIPID_F4 0x413
 +#define STM32_CHIPID_F1_HIGH 0x414
 +#define STM32_CHIPID_L1_MEDIUM 0x416
 +#define STM32_CHIPID_F1_CONN 0x418
 +#define STM32_CHIPID_F1_VL_MEDIUM 0x420
 +#define STM32_CHIPID_F1_VL_HIGH 0x428
 +#define STM32_CHIPID_F1_XL 0x430
 +
 +// Constant STM32 memory map figures
 +#define STM32_FLASH_BASE 0x08000000
 +#define STM32_SRAM_BASE 0x20000000
  
+ /*
+  * 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
+ /* using chip id for F4 ident, since core id is same as F1 */
+ #define STM32F4_CHIP_ID 0x413
  /* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/
  #define C_BUF_LEN 32
  
-                     .flash_size_reg = 0x1FFF7A10,
-                     .flash_pagesize = 0x20000,
 +    typedef struct chip_params_ {
 +      uint32_t chip_id;
 +      char* description;
 +        uint32_t flash_size_reg;
 +      uint32_t flash_pagesize;
 +      uint32_t sram_size;
 +      uint32_t bootrom_base, bootrom_size;
 +    } chip_params_t;
 +    
 +    
 +    // These maps are from a combination of the Programming Manuals, and 
 +    // also the Reference manuals.  (flash size reg is normally in ref man)
 + static const chip_params_t devices[] = {
 +        { // table 2, PM0063
 +            .chip_id = 0x410,
 +            .description = "F1 Medium-density device",
 +            .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x400,
 +                    .sram_size = 0x5000,
 +                    .bootrom_base = 0x1ffff000,
 +                    .bootrom_size = 0x800
 +        },
 +        {  // table 1, PM0059
 +            .chip_id = 0x411,
 +                    .description = "F2 device",
 +                    .flash_size_reg = 0, /* no flash size reg found in the docs! */
 +                    .flash_pagesize = 0x20000,
 +                    .sram_size = 0x20000,
 +                    .bootrom_base = 0x1fff0000,
 +                    .bootrom_size = 0x7800
 +        },
 +        { // PM0063
 +            .chip_id = 0x412,
 +                    .description = "F1 Low-density device",
 +                    .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x400,
 +                    .sram_size = 0x2800,
 +                    .bootrom_base = 0x1ffff000,
 +                    .bootrom_size = 0x800
 +        },
 +        {
 +            .chip_id = 0x413,
 +                    .description = "F4 device",
++                    .flash_size_reg = 0x1FFF7A10,  //RM0090 error same as unique ID
++                    .flash_pagesize = 0x4000,
 +                    .sram_size = 0x30000,
 +                    .bootrom_base = 0x1fff0000,
 +                    .bootrom_size = 0x7800
 +        },
 +        {
 +            .chip_id = 0x414,
 +                    .description = "F1 High-density device",
 +                    .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x800,
 +                    .sram_size = 0x10000,
 +                    .bootrom_base = 0x1ffff000,
 +                    .bootrom_size = 0x800
 +        },
 +        {
 +          // This ignores the EEPROM! (and uses the page erase size,
 +          // not the sector write protection...)
 +            .chip_id = 0x416,
 +                    .description = "L1 Med-density device",
 +                    .flash_size_reg = 0x1ff8004c,
 +                    .flash_pagesize = 0x100,
 +                    .sram_size = 0x4000,
 +                    .bootrom_base = 0x1ff00000,
 +                    .bootrom_size = 0x1000
 +        },
 +        {
 +            .chip_id = 0x418,
 +                    .description = "F1 Connectivity line device",
 +                    .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x800,
 +                    .sram_size = 0x10000,
 +                    .bootrom_base = 0x1fffb000,
 +                    .bootrom_size = 0x4800
 +        },
 +        {
 +            .chip_id = 0x420,
 +                    .description = "F1 Medium-density Value Line device",
 +                    .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x400,
 +                    .sram_size = 0x2000,
 +                    .bootrom_base = 0x1ffff000,
 +                    .bootrom_size = 0x800
 +        },
 +        {
 +            .chip_id = 0x428,
 +                    .description = "F1 High-density value line device",
 +                    .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x800,
 +                    .sram_size = 0x8000,
 +                    .bootrom_base = 0x1ffff000,
 +                    .bootrom_size = 0x800
 +        },
 +        {
 +            .chip_id = 0x430,
 +                    .description = "F1 XL-density device",
 +                    .flash_size_reg = 0x1ffff7e0,
 +                    .flash_pagesize = 0x800,
 +                    .sram_size = 0x18000,
 +                    .bootrom_base = 0x1fffe000,
 +                    .bootrom_size = 0x1800
 +        }
 + };
 +
 +    
      typedef struct {
          uint32_t r[16];
          uint32_t xpsr;
          // transport layer verboseness: 0 for no debug info, 10 for lots
          int verbose;
          uint32_t core_id;
 -        uint16_t chip_id;
 +        uint32_t chip_id;
          int core_stat;
  
 -
 -
 -        /* medium density stm32 flash settings */
 -#define STM32_FLASH_BASE 0x08000000
 -#define STM32_FLASH_SIZE (128 * 1024)
  #define STM32_FLASH_PGSZ 1024
  #define STM32L_FLASH_PGSZ 256
+ #define STM32F4_FLASH_PGSZ 16384
+ #define STM32F4_FLASH_SIZE (128 * 1024 * 8)
          stm32_addr_t flash_base;
          size_t flash_size;
          size_t flash_pgsz;
      int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr);
      
      // PUBLIC
--    uint16_t stlink_chip_id(stlink_t *sl);
++    uint32_t stlink_chip_id(stlink_t *sl);
      void stlink_cpu_id(stlink_t *sl, cortex_m3_cpuid_t *cpuid);
  
      // privates, publics, the rest....
diff --cc src/test_usb.c
index 343e355a358f96ed327006074f760cd0ff78fe2b,4901a8f93a1eeba6707ef56c576a2ec698a7c3f2..be4981db051069cc0c97f0ee34572c56d9a59bcd
@@@ -27,8 -27,9 +27,8 @@@ int main(int ac, char** av) 
  
          printf("-- mode after entering swd mode: %d\n", stlink_current_mode(sl));
  
-         printf("-- chip id: %#x\n", stlink_chip_id(sl));
-         printf("-- core_id: %#x\n", stlink_core_id(sl));
 -      stlink_identify_device(sl);
+         printf("-- chip id: %#x\n", sl->chip_id);
+         printf("-- core_id: %#x\n", sl->core_id);
  
          cortex_m3_cpuid_t cpuid;
          stlink_cpu_id(sl, &cpuid);