|
@ -47,39 +47,12 @@ const struct command_s stm32f4_cmd_list[] = { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len); |
|
|
static int stm32f4_flash_erase(struct target_flash *f, uint32_t addr, size_t len); |
|
|
static int stm32f4_flash_write(target *t, uint32_t dest, |
|
|
static int stm32f4_flash_write(struct target_flash *f, |
|
|
const uint8_t *src, size_t len); |
|
|
uint32_t dest, const void *src, size_t len); |
|
|
|
|
|
|
|
|
static const char stm32f4_driver_str[] = "STM32F4xx"; |
|
|
static const char stm32f4_driver_str[] = "STM32F4xx"; |
|
|
|
|
|
|
|
|
static const char stm32f4_xml_memory_map[] = "<?xml version=\"1.0\"?>" |
|
|
|
|
|
/* "<!DOCTYPE memory-map "
|
|
|
|
|
|
" PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\"" |
|
|
|
|
|
" \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"*/ |
|
|
|
|
|
"<memory-map>" |
|
|
|
|
|
" <memory type=\"flash\" start=\"0x8000000\" length=\"0x10000\">" |
|
|
|
|
|
" <property name=\"blocksize\">0x4000</property>" |
|
|
|
|
|
" </memory>" |
|
|
|
|
|
" <memory type=\"flash\" start=\"0x8010000\" length=\"0x10000\">" |
|
|
|
|
|
" <property name=\"blocksize\">0x10000</property>" |
|
|
|
|
|
" </memory>" |
|
|
|
|
|
" <memory type=\"flash\" start=\"0x8020000\" length=\"0xE0000\">" |
|
|
|
|
|
" <property name=\"blocksize\">0x20000</property>" |
|
|
|
|
|
" </memory>" |
|
|
|
|
|
" <memory type=\"flash\" start=\"0x8100000\" length=\"0x10000\">" |
|
|
|
|
|
" <property name=\"blocksize\">0x4000</property>" |
|
|
|
|
|
" </memory>" |
|
|
|
|
|
" <memory type=\"flash\" start=\"0x8110000\" length=\"0x10000\">" |
|
|
|
|
|
" <property name=\"blocksize\">0x10000</property>" |
|
|
|
|
|
" </memory>" |
|
|
|
|
|
" <memory type=\"flash\" start=\"0x8120000\" length=\"0xE0000\">" |
|
|
|
|
|
" <property name=\"blocksize\">0x20000</property>" |
|
|
|
|
|
" </memory>" |
|
|
|
|
|
" <memory type=\"ram\" start=\"0x20000000\" length=\"0x30000\"/>" |
|
|
|
|
|
" <memory type=\"ram\" start=\"0x10000000\" length=\"0x10000\"/>" |
|
|
|
|
|
"</memory-map>"; |
|
|
|
|
|
|
|
|
|
|
|
/* Flash Program ad Erase Controller Register Map */ |
|
|
/* Flash Program ad Erase Controller Register Map */ |
|
|
#define FPEC_BASE 0x40023C00 |
|
|
#define FPEC_BASE 0x40023C00 |
|
|
#define FLASH_ACR (FPEC_BASE+0x00) |
|
|
#define FLASH_ACR (FPEC_BASE+0x00) |
|
@ -127,6 +100,28 @@ static const uint16_t stm32f4_flash_write_stub[] = { |
|
|
#define SRAM_BASE 0x20000000 |
|
|
#define SRAM_BASE 0x20000000 |
|
|
#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f4_flash_write_stub), 4) |
|
|
#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f4_flash_write_stub), 4) |
|
|
|
|
|
|
|
|
|
|
|
struct stm32f4_flash { |
|
|
|
|
|
struct target_flash f; |
|
|
|
|
|
uint8_t base_sector; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void stm32f4_add_flash(target *t, |
|
|
|
|
|
uint32_t addr, size_t length, size_t blocksize, |
|
|
|
|
|
uint8_t base_sector) |
|
|
|
|
|
{ |
|
|
|
|
|
struct stm32f4_flash *sf = calloc(1, sizeof(*sf)); |
|
|
|
|
|
struct target_flash *f = &sf->f; |
|
|
|
|
|
f->start = addr; |
|
|
|
|
|
f->length = length; |
|
|
|
|
|
f->blocksize = blocksize; |
|
|
|
|
|
f->erase = stm32f4_flash_erase; |
|
|
|
|
|
f->write = stm32f4_flash_write; |
|
|
|
|
|
f->align = 4; |
|
|
|
|
|
f->erased = 0xff; |
|
|
|
|
|
sf->base_sector = base_sector; |
|
|
|
|
|
target_add_flash(t, f); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
bool stm32f4_probe(target *t) |
|
|
bool stm32f4_probe(target *t) |
|
|
{ |
|
|
{ |
|
|
uint32_t idcode; |
|
|
uint32_t idcode; |
|
@ -139,10 +134,12 @@ bool stm32f4_probe(target *t) |
|
|
case 0x423: /* F401 B/C RM0368 Rev.3 */ |
|
|
case 0x423: /* F401 B/C RM0368 Rev.3 */ |
|
|
case 0x431: /* F411 RM0383 Rev.4 */ |
|
|
case 0x431: /* F411 RM0383 Rev.4 */ |
|
|
case 0x433: /* F401 D/E RM0368 Rev.3 */ |
|
|
case 0x433: /* F401 D/E RM0368 Rev.3 */ |
|
|
t->xml_mem_map = stm32f4_xml_memory_map; |
|
|
|
|
|
t->driver = stm32f4_driver_str; |
|
|
t->driver = stm32f4_driver_str; |
|
|
t->flash_erase = stm32f4_flash_erase; |
|
|
target_add_ram(t, 0x10000000, 0x10000); |
|
|
t->flash_write = stm32f4_flash_write; |
|
|
target_add_ram(t, 0x20000000, 0x30000); |
|
|
|
|
|
stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); |
|
|
|
|
|
stm32f4_add_flash(t, 0x8010000, 0x10000, 0x10000, 4); |
|
|
|
|
|
stm32f4_add_flash(t, 0x8020000, 0xE0000, 0x20000, 5); |
|
|
target_add_commands(t, stm32f4_cmd_list, "STM32F4"); |
|
|
target_add_commands(t, stm32f4_cmd_list, "STM32F4"); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
@ -158,30 +155,18 @@ static void stm32f4_flash_unlock(target *t) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len) |
|
|
static int stm32f4_flash_erase(struct target_flash *f, uint32_t addr, size_t len) |
|
|
{ |
|
|
{ |
|
|
|
|
|
target *t = f->t; |
|
|
uint16_t sr; |
|
|
uint16_t sr; |
|
|
uint32_t cr; |
|
|
uint8_t sector = ((struct stm32f4_flash *)f)->base_sector + |
|
|
uint32_t pagesize; |
|
|
(addr - f->start)/f->blocksize; |
|
|
|
|
|
|
|
|
addr &= 0x07FFC000; |
|
|
|
|
|
|
|
|
|
|
|
stm32f4_flash_unlock(t); |
|
|
stm32f4_flash_unlock(t); |
|
|
|
|
|
|
|
|
while(len) { |
|
|
while(len) { |
|
|
if (addr < 0x10000) { /* Sector 0..3 */ |
|
|
uint32_t cr = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER | |
|
|
cr = (addr >> 11); |
|
|
(sector << 3); |
|
|
pagesize = 0x4000; |
|
|
|
|
|
} else if (addr < 0x20000) { /* Sector 4 */ |
|
|
|
|
|
cr = (4 << 3); |
|
|
|
|
|
pagesize = 0x10000; |
|
|
|
|
|
} else if (addr < 0x100000) { /* Sector 5..11 */ |
|
|
|
|
|
cr = (((addr - 0x20000) >> 14) + 0x28); |
|
|
|
|
|
pagesize = 0x20000; |
|
|
|
|
|
} else { /* Sector > 11 ?? */ |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; |
|
|
|
|
|
/* Flash page erase instruction */ |
|
|
/* Flash page erase instruction */ |
|
|
target_mem_write32(t, FLASH_CR, cr); |
|
|
target_mem_write32(t, FLASH_CR, cr); |
|
|
/* write address to FMA */ |
|
|
/* write address to FMA */ |
|
@ -192,8 +177,8 @@ static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len) |
|
|
if(target_check_error(t)) |
|
|
if(target_check_error(t)) |
|
|
return -1; |
|
|
return -1; |
|
|
|
|
|
|
|
|
len -= pagesize; |
|
|
len -= f->blocksize; |
|
|
addr += pagesize; |
|
|
sector++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Check for error */ |
|
|
/* Check for error */ |
|
@ -204,23 +189,15 @@ static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len) |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int stm32f4_flash_write(target *t, uint32_t dest, |
|
|
static int stm32f4_flash_write(struct target_flash *f, |
|
|
const uint8_t *src, size_t len) |
|
|
uint32_t dest, const void *src, size_t len) |
|
|
{ |
|
|
{ |
|
|
uint32_t offset = dest % 4; |
|
|
|
|
|
uint8_t data[ALIGN(offset + len, 4)]; |
|
|
|
|
|
|
|
|
|
|
|
/* Construct data buffer used by stub */ |
|
|
|
|
|
/* pad partial words with all 1s to avoid damaging overlapping areas */ |
|
|
|
|
|
memset(data, 0xff, sizeof(data)); |
|
|
|
|
|
memcpy((uint8_t *)data + offset, src, len); |
|
|
|
|
|
|
|
|
|
|
|
/* Write buffer to target ram call stub */ |
|
|
/* Write buffer to target ram call stub */ |
|
|
target_mem_write(t, SRAM_BASE, stm32f4_flash_write_stub, |
|
|
target_mem_write(f->t, SRAM_BASE, stm32f4_flash_write_stub, |
|
|
sizeof(stm32f4_flash_write_stub)); |
|
|
sizeof(stm32f4_flash_write_stub)); |
|
|
target_mem_write(t, STUB_BUFFER_BASE, data, sizeof(data)); |
|
|
target_mem_write(f->t, STUB_BUFFER_BASE, src, len); |
|
|
return cortexm_run_stub(t, SRAM_BASE, dest - offset, |
|
|
return cortexm_run_stub(f->t, SRAM_BASE, dest, |
|
|
STUB_BUFFER_BASE, sizeof(data), 0); |
|
|
STUB_BUFFER_BASE, len, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static bool stm32f4_cmd_erase_mass(target *t) |
|
|
static bool stm32f4_cmd_erase_mass(target *t) |
|
|