Extra registers integration with GDB
[fw/stlink] / src / stlink-common.c
index 03e1cce5228dd3f646c9c29a59f43128ca047555..1e9c01114ffdbdaafdc90229e08fbb8ed22cf6f2 100644 (file)
@@ -9,8 +9,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/mman.h>
-
+#include "mmap.h"
 
 #include "stlink-common.h"
 #include "uglylogging.h"
@@ -136,7 +135,7 @@ static inline uint32_t read_flash_obr(stlink_t *sl) {
 
 static inline uint32_t read_flash_cr(stlink_t *sl) {
         uint32_t res;
-       if(sl->chip_id==STM32F4_CHIP_ID)
+       if((sl->chip_id==STM32_CHIPID_F2) ||(sl->chip_id==STM32_CHIPID_F4))
                res = stlink_read_debug32(sl, FLASH_F4_CR);
        else
                res = stlink_read_debug32(sl, FLASH_CR);
@@ -148,7 +147,7 @@ static inline uint32_t read_flash_cr(stlink_t *sl) {
 
 static inline unsigned int is_flash_locked(stlink_t *sl) {
     /* return non zero for true */
-       if(sl->chip_id==STM32F4_CHIP_ID)
+       if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
                return read_flash_cr(sl) & (1 << FLASH_F4_CR_LOCK);
        else
                return read_flash_cr(sl) & (1 << FLASH_CR_LOCK);
@@ -160,7 +159,7 @@ static void unlock_flash(stlink_t *sl) {
        an invalid sequence results in a definitive lock of
        the FPEC block until next reset.
      */
-    if(sl->chip_id==STM32F4_CHIP_ID) {
+    if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
        stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY1);
                stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY2);
     }
@@ -186,7 +185,7 @@ static int unlock_flash_if(stlink_t *sl) {
 }
 
 static void lock_flash(stlink_t *sl) {
-    if(sl->chip_id==STM32F4_CHIP_ID) {
+    if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
        const uint32_t n = read_flash_cr(sl) | (1 << FLASH_F4_CR_LOCK);
        stlink_write_debug32(sl, FLASH_F4_CR, n);
     }
@@ -199,7 +198,7 @@ static void lock_flash(stlink_t *sl) {
 
 
 static void set_flash_cr_pg(stlink_t *sl) {
-    if(sl->chip_id==STM32F4_CHIP_ID) {
+    if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
                uint32_t x = read_flash_cr(sl);
                x |= (1 << FLASH_CR_PG);
        stlink_write_debug32(sl, FLASH_F4_CR, x);
@@ -212,7 +211,7 @@ static void set_flash_cr_pg(stlink_t *sl) {
 
 static void __attribute__((unused)) clear_flash_cr_pg(stlink_t *sl) {
     const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
-    if(sl->chip_id==STM32F4_CHIP_ID)
+    if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
        stlink_write_debug32(sl, FLASH_F4_CR, n);
     else
         stlink_write_debug32(sl, FLASH_CR, n);
@@ -229,7 +228,7 @@ static void __attribute__((unused)) clear_flash_cr_per(stlink_t *sl) {
 }
 
 static void set_flash_cr_mer(stlink_t *sl) {
-    if(sl->chip_id == STM32F4_CHIP_ID)
+    if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
         stlink_write_debug32(sl, FLASH_F4_CR,
                              stlink_read_debug32(sl, FLASH_F4_CR) | (1 << FLASH_CR_MER));
     else 
@@ -238,7 +237,7 @@ static void set_flash_cr_mer(stlink_t *sl) {
 }
 
 static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
-    if(sl->chip_id == STM32F4_CHIP_ID)
+    if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
         stlink_write_debug32(sl, FLASH_F4_CR,
                              stlink_read_debug32(sl, FLASH_F4_CR) & ~(1 << FLASH_CR_MER));
     else 
@@ -247,7 +246,7 @@ static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
 }
 
 static void set_flash_cr_strt(stlink_t *sl) {
-       if(sl->chip_id == STM32F4_CHIP_ID)
+       if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
        {
                uint32_t x = read_flash_cr(sl);
                x |= (1 << FLASH_F4_CR_STRT);
@@ -266,7 +265,7 @@ static inline uint32_t read_flash_acr(stlink_t *sl) {
 
 static inline uint32_t read_flash_sr(stlink_t *sl) {
        uint32_t res;
-       if(sl->chip_id==STM32F4_CHIP_ID)
+       if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
                res = stlink_read_debug32(sl, FLASH_F4_SR);
        else
                res = stlink_read_debug32(sl, FLASH_SR);
@@ -275,7 +274,7 @@ static inline uint32_t read_flash_sr(stlink_t *sl) {
 }
 
 static inline unsigned int is_flash_busy(stlink_t *sl) {
-       if(sl->chip_id==STM32F4_CHIP_ID)
+       if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
                return read_flash_sr(sl) & (1 << FLASH_F4_SR_BSY);
        else
                return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
@@ -395,6 +394,7 @@ uint32_t stlink_core_id(stlink_t *sl) {
 
 uint32_t stlink_chip_id(stlink_t *sl) {
     uint32_t chip_id = stlink_read_debug32(sl, 0xE0042000);
+    if (chip_id == 0) chip_id = stlink_read_debug32(sl, 0x40015800);   //Try Corex M0 DBGMCU_IDCODE register address
     return chip_id;
 }
 
@@ -448,7 +448,7 @@ int stlink_load_device_params(stlink_t *sl) {
     
     // read flash size from hardware, if possible...
     if (sl->chip_id == STM32_CHIPID_F2) {
-        sl->flash_size = 0; // FIXME - need to work this out some other way, just set to max possible?
+        sl->flash_size = 0x100000; /* Use maximum, User must care!*/
     } else if (sl->chip_id == STM32_CHIPID_F4) {
                sl->flash_size = 0x100000;                      //todo: RM0090 error; size register same address as unique ID
     } else {
@@ -577,6 +577,11 @@ void stlink_read_all_regs(stlink_t *sl, reg *regp) {
     sl->backend->read_all_regs(sl, regp);
 }
 
+void stlink_read_all_unsupported_regs(stlink_t *sl, reg *regp) {
+    DLOG("*** stlink_read_all_unsupported_regs ***\n");
+    sl->backend->read_all_unsupported_regs(sl, regp);
+}
+
 void stlink_write_reg(stlink_t *sl, uint32_t reg, int idx) {
     DLOG("*** stlink_write_reg\n");
     sl->backend->write_reg(sl, reg, idx);
@@ -594,6 +599,27 @@ void stlink_read_reg(stlink_t *sl, int r_idx, reg *regp) {
     sl->backend->read_reg(sl, r_idx, regp);
 }
 
+void stlink_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
+    int r_convert;
+
+    DLOG("*** stlink_read_unsupported_reg\n");
+    DLOG(" (%d) ***\n", r_idx);
+
+    /* Convert to values used by DCRSR */
+    if (r_idx >= 0x1C && r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */
+        r_convert = 0x14;
+    } else if (r_idx == 0x40) {     /* FPSCR */
+        r_convert = 0x21;
+    } else if (r_idx >= 0x20 && r_idx < 0x40) {
+        r_convert = 0x40 + (r_idx - 0x20);
+    } else {
+        fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n");
+        return;
+    }
+
+    sl->backend->read_unsupported_reg(sl, r_convert, regp);
+}
+
 unsigned int is_core_halted(stlink_t *sl) {
     /* return non zero if core is halted */
     stlink_status(sl);
@@ -927,7 +953,7 @@ uint32_t calculate_F4_sectornum(uint32_t flashaddr){
 }
 
 uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
-       if(sl->chip_id == STM32F4_CHIP_ID) {
+       if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
                uint32_t sector=calculate_F4_sectornum(flashaddr);
                if (sector<4) sl->flash_pgsz=0x4000;
                else if(sector<5) sl->flash_pgsz=0x10000;
@@ -944,7 +970,7 @@ uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
  */
 int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
 {
-  if (sl->chip_id == STM32F4_CHIP_ID)
+  if ((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
   {
     /* wait for ongoing op to finish */
     wait_flash_busy(sl);
@@ -972,7 +998,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
        fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl));
 #endif
   }
-  else if (sl->core_id == STM32L_CORE_ID)
+  else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM)
   {
 
     uint32_t val;
@@ -1182,10 +1208,32 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
       0x00, 0xbe
     };
 
+       static const uint8_t loader_code_stm32f4[] = {
+               // flashloaders/stm32f4.s
+
+               0x07, 0x4b,
+
+               0x62, 0xb1,
+               0x04, 0x68,
+               0x0c, 0x60,
+
+               0xdc, 0x89,
+               0x14, 0xf0, 0x01, 0x0f,
+               0xfb, 0xd1,
+               0x00, 0xf1, 0x04, 0x00,
+               0x01, 0xf1, 0x04, 0x01,
+               0xa2, 0xf1, 0x01, 0x02,
+               0xf1, 0xe7,
+
+               0x00, 0xbe,
+
+               0x00, 0x3c, 0x02, 0x40,
+       };
+
     const uint8_t* loader_code;
     size_t loader_size;
 
-    if (sl->core_id == STM32L_CORE_ID) /* stm32l */
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) /* stm32l */
     {
       loader_code = loader_code_stm32l;
       loader_size = sizeof(loader_code_stm32l);
@@ -1195,6 +1243,11 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
       loader_code = loader_code_stm32vl;
       loader_size = sizeof(loader_code_stm32vl);
     }
+       else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4)
+       {
+               loader_code = loader_code_stm32f4;
+               loader_size = sizeof(loader_code_stm32f4);
+       }
     else
     {
       WLOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id);
@@ -1237,17 +1290,13 @@ int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) {
  */
 int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, unsigned length) {
     size_t off;
-    if (sl->chip_id == STM32_CHIPID_F4) {
-        DLOG("(FIXME)Skipping verification for F4, not enough ram (yet)\n");
-        return 0;
-    }
+    size_t cmp_size = (sl->flash_pgsz > 0x1800)? 0x1800:sl->flash_pgsz;
     ILOG("Starting verification of write complete\n");
-    for (off = 0; off < length; off += sl->flash_pgsz) {
+    for (off = 0; off < length; off += cmp_size) {
         size_t aligned_size;
 
         /* adjust last page size */
-        size_t cmp_size = sl->flash_pgsz;
-        if ((off + sl->flash_pgsz) > length)
+        if ((off + cmp_size) > length)
             cmp_size = length - off;
 
         aligned_size = cmp_size;
@@ -1300,7 +1349,7 @@ int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uns
         if (sl->verbose >= 1) {
             /* show progress. writing procedure is slow
                and previous errors are misleading */
-            fprintf(stdout, "\r%3u/%u halfpages written", count, num_half_pages);
+            fprintf(stdout, "\r%3u/%u halfpages written", count + 1, num_half_pages);
             fflush(stdout);
         }
         while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0) {
@@ -1359,9 +1408,16 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
     ILOG("Finished erasing %d pages of %d (%#x) bytes\n", 
         page_count, sl->flash_pgsz, sl->flash_pgsz);
 
-    if (sl->chip_id == STM32F4_CHIP_ID) {
+    if ((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
        /* todo: check write operation */
 
+               ILOG("Starting Flash write for F2/F4\n");
+               /* flash loader initialization */
+               if (init_flash_loader(sl, &fl) == -1) {
+                       WLOG("init_flash_loader() == -1\n");
+                       return -1;
+               }
+
        /* First unlock the cr */
        unlock_flash_if(sl);
 
@@ -1372,6 +1428,20 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
        /* set programming mode */
        set_flash_cr_pg(sl);
 
+               for(off = 0; off < len;) {
+                       size_t size = len - off > 0x8000 ? 0x8000 : len - off;
+
+                       printf("size: %u\n", size);
+
+                       if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
+                               WLOG("run_flash_loader(%#zx) failed! == -1\n", addr + off);
+                               return -1;
+                       }
+
+                       off += size;
+               }
+
+#if 0
 #define PROGRESS_CHUNK_SIZE 0x1000
        /* write a word in program memory */
        for (off = 0; off < len; off += sizeof(uint32_t)) {
@@ -1381,7 +1451,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
                                /* 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;
+                               const uint32_t pgcount = len / PROGRESS_CHUNK_SIZE +1;
                                fprintf(stdout, "Writing %ukB chunk %u out of %u\n", PROGRESS_CHUNK_SIZE/1024, pgnum, pgcount);
                        }
                }
@@ -1393,6 +1463,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
            wait_flash_busy(sl);
 
        }
+#endif
        /* Relock flash */
        lock_flash(sl);
 
@@ -1404,7 +1475,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
 
     }  //STM32F4END
 
-    else if (sl->core_id == STM32L_CORE_ID)    {
+    else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM)    {
        /* use fast word write. todo: half page. */
        uint32_t val;
 
@@ -1455,7 +1526,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
                    fprintf(stdout, "\r");
 
                if ((off % sl->flash_pgsz) > (sl->flash_pgsz -5)) {
-                   fprintf(stdout, "\r%3u/%u pages written", 
+                   fprintf(stdout, "\r%3zd/%3zd pages written",
                            off/sl->flash_pgsz, len/sl->flash_pgsz);
                    fflush(stdout);
                }
@@ -1599,7 +1670,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
         return -1;
     }
 
-    if (sl->core_id == STM32L_CORE_ID) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
 
       size_t count = size / sizeof(uint32_t);
       if (size % sizeof(uint32_t)) ++count;
@@ -1622,6 +1693,17 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
       stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */
       stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
 
+       } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+
+               size_t count = size / sizeof(uint32_t);
+               if (size % sizeof(uint32_t)) ++count;
+
+               /* setup core */
+               stlink_write_reg(sl, fl->buf_addr, 0); /* source */
+               stlink_write_reg(sl, target, 1); /* target */
+               stlink_write_reg(sl, count, 2); /* count (32 bits words) */
+               stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
+
     } else {
       fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id);
       return -1;
@@ -1642,7 +1724,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
     }
         
     /* check written byte count */
-    if (sl->core_id == STM32L_CORE_ID) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
 
       size_t count = size / sizeof(uint32_t);
       if (size % sizeof(uint32_t)) ++count;
@@ -1661,6 +1743,14 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
         return -1;
       }
 
+       } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+
+               stlink_read_reg(sl, 2, &rr);
+               if (rr.r[2] != 0) {
+                       fprintf(stderr, "write error, count == %u\n", rr.r[2]);
+                       return -1;
+               }
+
     } else {
 
       fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id);