From 768a70d3213fcfcd605961a770c5446276fd1df8 Mon Sep 17 00:00:00 2001 From: jnosky Date: Mon, 14 Nov 2011 16:20:49 -0500 Subject: [PATCH] Added code so gdbserver can fully support the STM32F4 variable page sizes gdbserver can now upload up to 1MB projects to flash --- gdbserver/gdb-server.c | 120 ++++++++++++++++++++++++++--------------- src/stlink-common.c | 79 ++++++++++++++------------- src/stlink-common.h | 3 +- 3 files changed, 122 insertions(+), 80 deletions(-) diff --git a/gdbserver/gdb-server.c b/gdbserver/gdb-server.c index 371d779..b5d66df 100644 --- a/gdbserver/gdb-server.c +++ b/gdbserver/gdb-server.c @@ -21,9 +21,9 @@ #include "gdb-remote.h" #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) @@ -44,19 +44,19 @@ struct chip_params { uint32_t bootrom_base, bootrom_size; } const devices[] = { { 0x410, "F1 Medium-density device", 0x1ffff7e0, - 0x20000, 0x400, 0x5000, 0x1ffff000, 0x800 }, // table 2, pm0063 + 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 + 0x100000, 0x20000, 0x20000, 0x1fff0000, 0x7800 }, // table 1, pm0059 { 0x412, "F1 Low-density device", 0x1ffff7e0, - 0x8000, 0x400, 0x2800, 0x1ffff000, 0x800 }, // table 1, pm0063 - /*No flash size register? page size is variable */ - { 0x413, "F4 device", 0x1FFF7A10, - 0x100000, 0x4000, 0x30000, 0x1fff0000, 0x7800 }, // table 1, pm0081 + 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 + 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 + { 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 }, @@ -64,18 +64,19 @@ struct chip_params { 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 + { 0x430, "F1 XL-density device", 0x1ffff7e0, // pm0068 0x100000, 0x800, 0x18000, 0x1fffe000, 0x1800 }, { 0 } }; int serve(stlink_t *sl, int port); -char* make_memory_map(const struct chip_params *params, uint32_t flash_size); +char* make_memory_map(stlink_t *sl, const struct chip_params *params, uint32_t flash_size); int main(int argc, char** argv) { stlink_t *sl = NULL; - int port = 0; + int port = 0; + uint32_t flash_size; const char * HelpStr = "\nUsage:\n" "\tst-util [Arguments]\n" @@ -209,24 +210,29 @@ int main(int argc, char** argv) { } printf("Device connected: %s\n", params->description); - 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); - - FLASH_PAGE = params->flash_pagesize; - - //sl->flash_pgsz=0x4000; - //sl->flash_size=0x100000; - - uint32_t flash_size; - stlink_read_mem32(sl, params->flash_size_reg, 4); - flash_size = sl->q_buf[0] | (sl->q_buf[1] << 8); + 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; + } - //flash_size=0x100000; + /* 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; - 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); + printf("Flash size is %d\n", flash_size); + current_memory_map = make_memory_map(sl, params, flash_size); while(serve(sl, port) == 0); @@ -238,6 +244,28 @@ int main(int argc, char** argv) { return 0; } +static const char* const memory_map_template_F4 = + "" + "" + "" + " " // code = sram, bootrom or flash; flash is bigger + " " // sram + " " //Sectors 0..3 + " 0x4000" //16kB + " " + " " //Sector 4 + " 0x10000" //64kB + " " + " " //Sectors 5..11 + " 0x20000" //128kB + " " + " " // peripheral regs + " " // cortex regs + " " // bootrom + " " // option byte area + ""; + static const char* const memory_map_template = "" "" // option byte area ""; -char* make_memory_map(const struct chip_params *params, uint32_t flash_size) { +char* make_memory_map(stlink_t *sl, const struct chip_params *params, uint32_t flash_size) { /* This will be freed in serve() */ char* map = malloc(4096); map[0] = '\0'; - snprintf(map, 4096, memory_map_template, - flash_size, - params->sram_size, - flash_size, params->flash_pagesize, - params->bootrom_base, params->bootrom_size); - + 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); + } return map; } @@ -491,13 +524,14 @@ struct flash_block { static struct flash_block* flash_root; -static int flash_add_block(stm32_addr_t addr, unsigned length, - stlink_t *sl) { - if(addr < FLASH_BASE || addr + length > FLASH_BASE + FLASH_SIZE) { +static int flash_add_block(stm32_addr_t addr, unsigned length, stlink_t *sl) { + + if(addr < FLASH_BASE || addr + length > FLASH_BASE + sl->flash_size) { fprintf(stderr, "flash_add_block: incorrect bounds\n"); return -1; } + stlink_calculate_pagesize(sl, addr); if(addr % FLASH_PAGE != 0 || length % FLASH_PAGE != 0) { fprintf(stderr, "flash_add_block: unaligned block\n"); return -1; @@ -568,18 +602,18 @@ static int flash_go(stlink_t *sl) { unsigned length = fb->length; for(stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += FLASH_PAGE) { + + //Update FLASH_PAGE + stlink_calculate_pagesize(sl, page); + #ifdef DEBUG printf("flash_do: page %08x\n", page); #endif - //todo:write flash already does erase so why is this here? - stlink_erase_flash_page(sl, page); - if(stlink_write_flash(sl, page, fb->data + (page - fb->addr), length > FLASH_PAGE ? FLASH_PAGE : length) < 0) goto error; - } - + } } stlink_reset(sl); diff --git a/src/stlink-common.c b/src/stlink-common.c index fcdb405..d55dff6 100644 --- a/src/stlink-common.c +++ b/src/stlink-common.c @@ -1,4 +1,4 @@ - +#define DEBUG_FLASH 0 #include #include @@ -148,8 +148,10 @@ static inline uint32_t read_flash_cr(stlink_t *sl) { stlink_read_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); else stlink_read_mem32(sl, FLASH_CR, sizeof (uint32_t)); - fprintf(stdout, "CR:%X\n", *(uint32_t*) sl->q_buf); - return *(uint32_t*) sl->q_buf; +#if DEBUG_FLASH + fprintf(stdout, "CR:0x%x\n", *(uint32_t*) sl->q_buf); +#endif + return *(uint32_t*) sl->q_buf; } static inline unsigned int is_flash_locked(stlink_t *sl) { @@ -281,7 +283,7 @@ static inline uint32_t read_flash_sr(stlink_t *sl) { stlink_read_mem32(sl, FLASH_F4_SR, sizeof (uint32_t)); else stlink_read_mem32(sl, FLASH_SR, sizeof (uint32_t)); - //fprintf(stdout, "SR:%X\n", *(uint32_t*) sl->q_buf); + //fprintf(stdout, "SR:0x%x\n", *(uint32_t*) sl->q_buf); return *(uint32_t*) sl->q_buf; } @@ -323,7 +325,9 @@ static inline void write_flash_cr_psiz(stlink_t *sl, uint32_t n) { uint32_t x = read_flash_cr(sl); x &= ~(0x03 << 8); x |= (n << 8); - fprintf(stdout, "PSIZ:%X %X\n", x, n); +#if DEBUG_FLASH + fprintf(stdout, "PSIZ:0x%x 0x%x\n", x, n); +#endif write_uint32(sl->q_buf, x); stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); } @@ -334,7 +338,9 @@ static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n) { x &= ~FLASH_F4_CR_SNB_MASK; x |= (n << FLASH_F4_CR_SNB); x |= (1 << FLASH_F4_CR_SER); - fprintf(stdout, "SNB:%X %X\n", x, n); +#if DEBUG_FLASH + fprintf(stdout, "SNB:0x%x 0x%x\n", x, n); +#endif write_uint32(sl->q_buf, x); stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); } @@ -393,7 +399,7 @@ void stlink_identify_device(stlink_t *sl) { (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"); + //printf("Fixing wrong chip_id for STM32F4 Rev A errata\n"); chip_id = 0x413; } sl->chip_id=chip_id; @@ -816,17 +822,17 @@ uint32_t calculate_F4_sectornum(uint32_t flashaddr){ } -uint32_t calculate_sectorsize(stlink_t *sl, uint32_t flashaddr){ +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) return (0x4000); - else if(sector<5) return(0x10000); - else return(0x20000); + if (sector<4) sl->flash_pgsz=0x4000; + else if(sector<5) sl->flash_pgsz=0x10000; + else sl->flash_pgsz=0x20000; } - else return (sl->flash_pgsz); + return (sl->flash_pgsz); } -int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) +int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) { /* page an addr in the page to erase */ @@ -841,13 +847,11 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) unlock_flash_if(sl); /* select the page to erase */ - //Page is passed to us as an addr, so calculate the actual page - uint32_t addr=page; - - page=calculate_F4_sectornum(addr); + // calculate the actual page from the address + uint32_t sector=calculate_F4_sectornum(flashaddr); - fprintf(stderr, "Erasing Sector:%u SectorSize:%u\n", page, calculate_sectorsize(sl, addr)); - write_flash_cr_snb(sl, page); + 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); @@ -858,8 +862,9 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) /* relock the flash */ //todo: fails to program if this is in lock_flash(sl); - fprintf(stdout, "Erase Final CR:%X\n", read_flash_cr(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) @@ -928,7 +933,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) /* write 0 to the first word of the page to be erased */ memset(sl->q_buf, 0, sizeof(uint32_t)); - stlink_write_mem32(sl, page, sizeof(uint32_t)); + stlink_write_mem32(sl, flashaddr, sizeof(uint32_t)); /* reset lock bits */ stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); @@ -948,7 +953,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) set_flash_cr_per(sl); /* select the page to erase */ - write_flash_ar(sl, page); + write_flash_ar(sl, flashaddr); /* start erase operation, reset by hw with bsy bit */ set_flash_cr_strt(sl); @@ -1068,7 +1073,7 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) { } else { - fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id); return -1; } @@ -1104,12 +1109,8 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned stlink_identify_device(sl); -#if 0 /* todo: use in debugging mode only */ - fprintf(stdout, "WriteFlash - addr:%x len:%x\n", addr, len); - fprintf(stdout, "CoreID:%X ChipID:%X\n", sl->core_id, sl->chip_id); -#endif - /* check addr range is inside the flash */ + stlink_calculate_pagesize(sl, addr); if (addr < sl->flash_base) { fprintf(stderr, "addr too low\n"); return -1; @@ -1128,14 +1129,20 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned } /* erase each page */ - for (off = 0; off < len; off += calculate_sectorsize(sl, addr + off) ) { - /* addr must be an addr inside the page */ + 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; } } +#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 + + if (sl->chip_id == STM32F4_CHIP_ID) { /* todo: check write operation */ @@ -1172,7 +1179,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned lock_flash(sl); #if 0 /* todo: debug mode */ - fprintf(stdout, "Final CR:%X\n", read_flash_cr(sl)); + fprintf(stdout, "Final CR:0x%x\n", read_flash_cr(sl)); #endif @@ -1262,7 +1269,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1); page = addr + off; - fprintf(stderr, "invalid write @%x(%x): %x != %x. retrying.\n", + 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 */ @@ -1343,7 +1350,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned if (aligned_size & (4 - 1)) aligned_size = (cmp_size + 4) & ~(4 - 1); - fprintf(stdout, "AlignedSize:%x\n", aligned_size); + fprintf(stdout, "AlignedSize:0x%x\n", aligned_size); stlink_read_mem32(sl, addr + off, aligned_size); if (memcmp(sl->q_buf, base + off, cmp_size)) @@ -1409,7 +1416,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ } else { - fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id); return -1; } @@ -1441,7 +1448,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons } else { - fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id); return -1; } diff --git a/src/stlink-common.h b/src/stlink-common.h index 2230dca..1d9e387 100644 --- a/src/stlink-common.h +++ b/src/stlink-common.h @@ -243,7 +243,8 @@ extern "C" { // privates, publics, the rest.... // TODO sort what is private, and what is not - int stlink_erase_flash_page(stlink_t* sl, stm32_addr_t page); + int stlink_erase_flash_page(stlink_t* sl, stm32_addr_t flashaddr); + uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr); uint16_t read_uint16(const unsigned char *c, const int pt); void stlink_core_stat(stlink_t *sl); void stlink_print_data(stlink_t *sl); -- 2.30.2