Merge commit 'a3feae60aab1fb85fe44b33123e020a9d7c8e18c' into sam-update

This commit is contained in:
Jason Kotzin 2022-08-10 22:26:37 -07:00
commit e43b07172b
9 changed files with 521 additions and 150 deletions

View File

@ -54,8 +54,6 @@ typedef struct
void (*func)(const char *packet, int len);
} cmd_executer;
static char pbuf[BUF_SIZE + 1];
static target *cur_target;
@ -226,11 +224,10 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
sscanf(pbuf, "p%" SCNx32, &reg);
uint8_t val[8];
size_t s = target_reg_read(cur_target, reg, val, sizeof(val));
if (s > 0) {
if (s > 0)
gdb_putpacket(hexify(pbuf, val, s), s * 2);
} else {
else
gdb_putpacketz("EFF");
}
break;
}
case 'P': { /* Write single register */
@ -238,20 +235,20 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
uint32_t reg;
int n;
sscanf(pbuf, "P%" SCNx32 "=%n", &reg, &n);
// TODO: FIXME, VLAs considered harmful.
uint8_t val[strlen(&pbuf[n]) / 2];
unhexify(val, pbuf + n, sizeof(val));
if (target_reg_write(cur_target, reg, val, sizeof(val)) > 0) {
if (target_reg_write(cur_target, reg, val, sizeof(val)) > 0)
gdb_putpacketz("OK");
} else {
else
gdb_putpacketz("EFF");
}
break;
}
case 'F': /* Semihosting call finished */
if (in_syscall) {
if (in_syscall)
return hostio_reply(tc, pbuf, size);
} else {
else {
DEBUG_GDB("*** F packet when not in syscall! '%s'\n", pbuf);
gdb_putpacketz("");
}
@ -337,15 +334,16 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
}
}
}
bool exec_command(char *packet, int len, const cmd_executer *exec)
static bool exec_command(char *packet, int len, const cmd_executer *exec)
{
while (exec->cmd_prefix) {
int l=strlen(exec->cmd_prefix);
const int l = strlen(exec->cmd_prefix);
if (!strncmp(packet, exec->cmd_prefix, l)) {
exec->func(packet + l, len - l);
return true;
}
exec++;
++exec;
}
return false;
}
@ -376,23 +374,26 @@ static void
handle_q_string_reply(const char *str, const char *param)
{
unsigned long addr, len;
const size_t str_len = strlen(str);
if (sscanf(param, "%08lx,%08lx", &addr, &len) != 2) {
gdb_putpacketz("E01");
return;
}
if (addr > strlen (str)) {
else if (addr > str_len) {
gdb_putpacketz("E01");
return;
}
if(addr== strlen (str)) {
else if (addr == str_len) {
gdb_putpacketz("l");
return;
}
unsigned long output_len=strlen(str)-addr;
if(output_len>len) output_len=len;
unsigned long output_len = str_len - addr;
if (output_len > len)
output_len = len;
gdb_putpacket2("m", 1, str + addr, output_len);
}
static void exec_q_supported(const char *packet, int len)
{
(void)packet;
@ -451,6 +452,7 @@ static void exec_q_crc(const char *packet, int len)
gdb_putpacket_f("C%lx", crc);
}
}
static const cmd_executer q_commands[]=
{
{"qRcmd,", exec_q_rcmd},
@ -458,16 +460,14 @@ static const cmd_executer q_commands[]=
{"qXfer:memory-map:read::", exec_q_memory_map},
{"qXfer:features:read:target.xml:",exec_q_feature_read},
{"qCRC:", exec_q_crc},
{NULL, NULL},
};
static void
handle_q_packet(char *packet, int len)
{
if(exec_command(packet,len,q_commands)) {
if (exec_command(packet, len, q_commands))
return;
}
DEBUG_GDB("*** Unsupported packet: %s\n", packet);
gdb_putpacket("", 0);
}
@ -493,25 +493,27 @@ handle_v_packet(char *packet, int plen)
char cmdline[83];
char *pcmdline = cmdline;
char *tok = packet + 4;
if (*tok == ';') tok++;
*cmdline='\0';
if (*tok == ';')
++tok;
cmdline[0] = '\0';
while(*tok != '\0') {
if(strlen(cmdline)+3 >= sizeof(cmdline)) break;
if (strlen(cmdline) + 3 >= sizeof(cmdline))
break;
if (*tok == ';') {
*pcmdline++ = ' ';
*pcmdline='\0';
pcmdline[0] = '\0';
tok++;
continue;
}
if (isxdigit(*tok) && isxdigit(*(tok+1))) {
if (isxdigit(tok[0]) && isxdigit(tok[1])) {
unhexify(pcmdline, tok, 2);
if ((*pcmdline == ' ') || (*pcmdline == '\\')) {
*(pcmdline+1)=*pcmdline;
pcmdline[1] = *pcmdline;
*pcmdline++ = '\\';
}
pcmdline++;
tok += 2;
*pcmdline='\0';
pcmdline[0] = '\0';
continue;
}
break;
@ -531,14 +533,19 @@ handle_v_packet(char *packet, int plen)
target_reset(cur_target);
morse(NULL, false);
gdb_putpacketz("T05");
} else gdb_putpacketz("E01");
} else
gdb_putpacketz("E01");
} else gdb_putpacketz("E01");
} else
gdb_putpacketz("E01");
} else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) {
/* Erase Flash Memory */
DEBUG_GDB("Flash Erase %08lX %08lX\n", addr, len);
if(!cur_target) { gdb_putpacketz("EFF"); return; }
if (!cur_target) {
gdb_putpacketz("EFF");
return;
}
if (!flash_mode) {
/* Reset target if first flash command! */
@ -546,9 +553,9 @@ handle_v_packet(char *packet, int plen)
target_reset(cur_target);
flash_mode = 1;
}
if(target_flash_erase(cur_target, addr, len) == 0) {
if (target_flash_erase(cur_target, addr, len) == 0)
gdb_putpacketz("OK");
} else {
else {
flash_mode = 0;
gdb_putpacketz("EFF");
}
@ -557,9 +564,9 @@ handle_v_packet(char *packet, int plen)
/* Write Flash Memory */
len = plen - bin;
DEBUG_GDB("Flash Write %08lX %08lX\n", addr, len);
if(cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0) {
if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0)
gdb_putpacketz("OK");
} else {
else {
flash_mode = 0;
gdb_putpacketz("EFF");
}
@ -591,14 +598,13 @@ handle_z_packet(char *packet, int plen)
else
ret = target_breakwatch_clear(cur_target, type, addr, len);
if (ret < 0) {
if (ret < 0)
gdb_putpacketz("E01");
} else if (ret > 0) {
else if (ret > 0)
gdb_putpacketz("");
} else {
else
gdb_putpacketz("OK");
}
}
void gdb_main(void)
{

View File

@ -45,7 +45,8 @@ int gdb_getpacket(char *packet, int size)
*/
do {
packet[0] = gdb_if_getchar();
if (packet[0]==0x04) return 1;
if (packet[0] == 0x04)
return 1;
} while ((packet[0] != '$') && (packet[0] != REMOTE_SOM));
#if PC_HOSTED == 0
if (packet[0] == REMOTE_SOM) {
@ -91,11 +92,13 @@ int gdb_getpacket(char *packet, int size)
#endif
} while (packet[0] != '$');
i = 0; csum = 0;
i = 0;
csum = 0;
/* Capture packet data into buffer */
while ((c = gdb_if_getchar()) != '#') {
if(i == size) break; /* Oh shit */
if (i == size) /* Oh shit */
break;
if (c == '$') { /* Restart capture */
i = 0;
@ -116,7 +119,8 @@ int gdb_getpacket(char *packet, int size)
recv_csum[2] = 0;
/* return packet if checksum matches */
if(csum == strtol(recv_csum, NULL, 16)) break;
if (csum == strtol(recv_csum, NULL, 16))
break;
/* get here if checksum fails */
gdb_if_putchar('-', 1); /* send nack */
@ -150,7 +154,8 @@ static void gdb_next_char(char c, unsigned char *csum)
gdb_if_putchar('}', 0);
gdb_if_putchar(c ^ 0x20, 0);
*csum += '}' + (c ^ 0x20);
} else {
}
else {
gdb_if_putchar(c, 0);
*csum += c;
}
@ -168,9 +173,9 @@ void gdb_putpacket2(const char *packet1, int size1,const char *packet2, int size
csum = 0;
gdb_if_putchar('$', 0);
for(i = 0; i < size1; i++)
for (i = 0; i < size1; ++i)
gdb_next_char(packet1[i], &csum);
for(i = 0; i < size2; i++)
for (i = 0; i < size2; ++i)
gdb_next_char(packet2[i], &csum);
gdb_if_putchar('#', 0);
@ -180,6 +185,7 @@ void gdb_putpacket2(const char *packet1, int size1,const char *packet2, int size
DEBUG_GDB_WIRE("\n");
} while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
}
void gdb_putpacket(const char *packet, int size)
{
int i;
@ -191,7 +197,7 @@ void gdb_putpacket(const char *packet, int size)
DEBUG_GDB_WIRE("%s : ", __func__);
csum = 0;
gdb_if_putchar('$', 0);
for(i = 0; i < size; i++)
for (i = 0; i < size; ++i)
gdb_next_char(packet[i], &csum);
gdb_if_putchar('#', 0);
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
@ -216,12 +222,13 @@ void gdb_putpacket_f(const char *fmt, ...)
void gdb_out(const char *buf)
{
char *hexdata;
int l = strlen(buf);
hexdata = alloca(2*l+1);
char *hexdata = calloc(1, 2 * l + 1);
if (!hexdata)
return;
hexify(hexdata, buf, l);
gdb_putpacket2("O", 1, hexdata, 2 * l);
free(hexdata);
}
void gdb_voutf(const char *fmt, va_list ap)

View File

@ -429,23 +429,6 @@ static bool cortexm_prepare(ADIv5_AP_t *ap)
return false;
}
}
/* Apply device specific settings for successfull Romtable scan
*
* STM32F7 in WFI will not read ROMTABLE when using WFI
*/
if ((ap->dp->targetid >> 1 & 0x7ff) == 0x20) {
uint32_t dbgmcu_cr = 7;
uint32_t dbgmcu_cr_addr = 0xE0042004;
switch ((ap->dp->targetid >> 16) & 0xfff) {
case 0x449:
case 0x451:
case 0x452:
ap->ap_storage = adiv5_mem_read32(ap, dbgmcu_cr_addr);
dbgmcu_cr = ap->ap_storage | 7;
adiv5_mem_write(ap, dbgmcu_cr_addr, &dbgmcu_cr, sizeof(dbgmcu_cr));
break;
}
}
return true;
}

View File

@ -55,6 +55,9 @@
#include <fcntl.h>
#endif
#define PROBE(x) \
do { if ((x)(t)) {return true;} else target_check_error(t); } while (0)
static const char cortexm_driver_str[] = "ARM Cortex-M";
static bool cortexm_vector_catch(target *t, int argc, char *argv[]);
@ -209,6 +212,17 @@ static const char tdesc_cortex_mf[] =
" </feature>"
"</target>";
/*
Probe STM32F103 clones
*/
static bool stm32f1_clones_probe(target *t)
{
PROBE(ch32f1_probe);
PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */
return false;
}
ADIv5_AP_t *cortexm_ap(target *t)
{
return ((struct cortexm_priv *)t->priv)->ap;
@ -378,8 +392,6 @@ bool cortexm_probe(ADIv5_AP_t *ap)
} else {
target_check_error(t);
}
#define PROBE(x) \
do { if ((x)(t)) {return true;} else target_check_error(t); } while (0)
switch (ap->ap_designer) {
case AP_DESIGNER_FREESCALE:
@ -442,7 +454,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
PROBE(rp_probe);
PROBE(lpc11xx_probe); /* LPC8 */
} else if (ap->ap_partno == 0x4c3) { /* Cortex-M3 ROM */
PROBE(stm32f1_probe); /* Care for STM32F1 clones */
PROBE(stm32f1_clones_probe); /* Care for STM32F1 clones */
PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */
} else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */
PROBE(lpc11xx_probe); /* LPC24C11 */

View File

@ -97,7 +97,9 @@ static int stm32f1_flash_write(struct target_flash *f,
#define FLASHSIZE 0x1FFFF7E0
#define FLASHSIZE_F0 0x1FFFF7CC
//
#include "stm32f1_ch32.c"
//
static void stm32f1_add_flash(target *t,
uint32_t addr, size_t length, size_t erasesize)
{

338
src/target/stm32f1_ch32.c Normal file
View File

@ -0,0 +1,338 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2022 Black Sphere Technologies Ltd.
* See CH32 Sample code from WCH StdPeriphLib_CH32F1/Examples/FLASH/FLASH_Program
*
* The CH32 seems to like the EOP bit to be cleared at the end of erase/flash operation
* The following code works fine in BMP hosted mode
* It does NOT work with a real BMP, only the first 128 bytes block is successfully written
*
*/
#if PC_HOSTED == 1
#define DEBUG_CH DEBUG_INFO
#define ERROR_CH DEBUG_WARN
#else
#define DEBUG_CH(...) {} //DEBUG_WARN //(...) {}
#define ERROR_CH DEBUG_WARN //DEBUG_WARN
#endif
static int ch32f1_flash_erase(struct target_flash *f,
target_addr addr, size_t len);
static int ch32f1_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len);
#define FLASH_MODEKEYR_CH32 (FPEC_BASE+0x24) // Fast mode for CH32F10x
#define FLASH_CR_FLOCK_CH32 (1<<15) // fast unlock
#define FLASH_CR_FTPG_CH32 (1<<16) // fast page program
#define FLASH_CR_FTER_CH32 (1<<17) // fast page erase
#define FLASH_CR_BUF_LOAD_CH32 (1<<18) // Buffer load
#define FLASH_CR_BUF_RESET_CH32 (1<<19) // Buffer reset
#define FLASH_SR_EOP (1<<5) // End of programming
#define FLASH_BEGIN_ADDRESS_CH32 0x8000000
#define FLASH_MAGIC (FPEC_BASE+0x34)
static volatile uint32_t magic,sr,ct;
/**
\fn ch32f1_add_flash
\brief "fast" flash driver for CH32F10x chips
*/
static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t erasesize)
{
struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */
DEBUG_WARN("calloc: failed in %s\n", __func__);
return;
}
f->start = addr;
f->length = length;
f->blocksize = erasesize;
f->erase = ch32f1_flash_erase;
f->write = ch32f1_flash_write;
f->buf_size = erasesize;
f->erased = 0xff;
target_add_flash(t, f);
}
#define WAIT_BUSY() do { \
sr = target_mem_read32(t, FLASH_SR); \
if(target_check_error(t)) { \
ERROR_CH("ch32f1 flash write: comm error\n"); \
return -1; \
} \
} while (sr & FLASH_SR_BSY);
#define WAIT_EOP() do { \
sr = target_mem_read32(t, FLASH_SR); \
if(target_check_error(t)) { \
ERROR_CH("ch32f1 flash write: comm error\n"); \
return -1; \
} \
} while (!(sr & FLASH_SR_EOP));
#define CLEAR_EOP() target_mem_write32(t, FLASH_SR,FLASH_SR_EOP)
#define SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \
ct|=(bit); \
target_mem_write32(t, FLASH_CR, ct);}
#define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \
ct&=~(bit); \
target_mem_write32(t, FLASH_CR, ct);}
// Which one is the right value ?
#define MAGIC_WORD 0x100
// #define MAGIC_WORD 0x100
#define MAGIC(adr) { magic=target_mem_read32(t,(adr) ^ MAGIC_WORD); \
target_mem_write32(t, FLASH_MAGIC , magic); }
/**
\fn ch32f1_flash_unlock
\brief unlock ch32f103 in fast mode
*/
static int ch32f1_flash_unlock(target *t)
{
DEBUG_CH("CH32: flash unlock \n");
target_mem_write32(t, FLASH_KEYR , KEY1);
target_mem_write32(t, FLASH_KEYR , KEY2);
// fast mode
target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY1);
target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY2);
uint32_t cr = target_mem_read32(t, FLASH_CR);
if (cr & FLASH_CR_FLOCK_CH32)
{
ERROR_CH("Fast unlock failed, cr: 0x%08" PRIx32 "\n", cr);
return -1;
}
return 0;
}
static int ch32f1_flash_lock(target *t)
{
DEBUG_CH("CH32: flash lock \n");
SET_CR(FLASH_CR_LOCK);
return 0;
}
/**
\brief identify the ch32f1 chip
Actually grab all cortex m3 with designer = arm not caught earlier...
*/
bool ch32f1_probe(target *t)
{
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3)
return false;
if(t->idcode !=0x410) { // only ch32f103
return false;
}
// try to flock
ch32f1_flash_lock(t);
// if this fails it is not a CH32 chip
if(ch32f1_flash_unlock(t)) {
return false;
}
uint32_t signature= target_mem_read32(t, FLASHSIZE);
uint32_t flashSize=signature & 0xFFFF;
target_add_ram(t, 0x20000000, 0x5000);
ch32f1_add_flash(t, FLASH_BEGIN_ADDRESS_CH32, flashSize*1024, 128);
target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD/VL-LD/VL-MD");
t->driver = "CH32F1 medium density (stm32f1 clone)";
// make sure we have 2 wait states
//target_mem_write32(t, FLASH_ACR,2);
return true;
}
/**
\fn ch32f1_flash_erase
\brief fast erase of CH32
*/
int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len)
{
target *t = f->t;
DEBUG_CH("CH32: flash erase \n");
// Make sure we have 2 wait states, prefetch disabled
//target_mem_write32(t, FLASH_ACR , 2);
if (ch32f1_flash_unlock(t)) {
ERROR_CH("CH32: Unlock failed\n");
return -1;
}
// Fast Erase 128 bytes pages (ch32 mode)
while(len) {
SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER
/* write address to FMA */
target_mem_write32(t, FLASH_AR , addr);
/* Flash page erase start instruction */
SET_CR( FLASH_CR_STRT );
WAIT_EOP();
CLEAR_EOP();
CLEAR_CR( FLASH_CR_STRT );
// Magic
MAGIC(addr);
if (len > 128)
len -= 128;
else
len = 0;
addr += 128;
}
sr = target_mem_read32(t, FLASH_SR);
ch32f1_flash_lock(t);
if ((sr & SR_ERROR_MASK)) {
ERROR_CH("ch32f1 flash erase error 0x%" PRIx32 "\n", sr);
return -1;
}
return 0;
}
/**
\fn waitFlashReady
\brief poll the beginning of a block till it is fffff, meaning we can proceeed
*/
static bool waitFlashReady(target *t,uint32_t adr)
{
// Wait a bit
// the # of cycles needed to do N read access over SWD
// the actual number is around 10
// then check we do read ffff (/!\ even if we read ffff it does not mean its ok
// these are the data from the previous operation and they could be ffff)
uint32_t ff;
for(int i=0;i<32;i++) ff=target_mem_read32(t,adr);
if(ff!=0xffffffffUL) {
ERROR_CH("ch32f1 Not erased properly at %x or flash access issue\n",adr);
return false;
}
return true;
}
/**
\fn ch32f1_flash_write
\brief fast flash for ch32. Load 128 bytes chunk and then flash them
*/
static int upload(target *t, uint32_t dest, const void *src, uint32_t offset)
{
const uint32_t *ss=(const uint32_t *)(src+offset);
uint32_t dd=dest+offset;
SET_CR(FLASH_CR_FTPG_CH32);
target_mem_write32(t, dd+0,ss[0]);
target_mem_write32(t, dd+4,ss[1]);
target_mem_write32(t, dd+8,ss[2]);
target_mem_write32(t, dd+12,ss[3]);
SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */
WAIT_EOP();
CLEAR_EOP();
CLEAR_CR(FLASH_CR_FTPG_CH32);
MAGIC((dest+offset));
return 0;
}
/**
\fn ch32_buffer_clear
\brief clear the write buffer
*/
int ch32_buffer_clear(target *t)
{
SET_CR(FLASH_CR_FTPG_CH32); // Fast page program 4-
SET_CR(FLASH_CR_BUF_RESET_CH32); // BUF_RESET 5-
WAIT_BUSY(); // 6-
CLEAR_CR(FLASH_CR_FTPG_CH32); // Fast page program 4-
return 0;
}
#define CH32_VERIFY
/**
*/
static int ch32f1_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len)
{
target *t = f->t;
size_t length = len;
#ifdef CH32_VERIFY
target_addr orgDest=dest;
const void *orgSrc=src;
#endif
DEBUG_CH("CH32: flash write 0x%x ,size=%d\n",dest,len);
while(length>0)
{
if(ch32f1_flash_unlock(t)) {
ERROR_CH("ch32f1 cannot fast unlock\n");
return -1;
}
WAIT_BUSY();
// Buffer reset...
ch32_buffer_clear(t);
// Load 128 bytes to buffer
if(!waitFlashReady(t,dest)) {
return -1;
}
for(int i=0;i<8;i++) {
if(upload(t,dest,src, 16*i)) {
ERROR_CH("Cannot upload to buffer\n");
return -1;
}
}
// write buffer
SET_CR(FLASH_CR_FTPG_CH32);
target_mem_write32(t, FLASH_AR, dest); // 10
SET_CR(FLASH_CR_STRT); // 11 Start
WAIT_EOP(); // 12
CLEAR_EOP();
CLEAR_CR(FLASH_CR_FTPG_CH32);
MAGIC((dest));
// next
if(length>128)
length-=128;
else
length=0;
dest+=128;
src+=128;
sr = target_mem_read32(t, FLASH_SR); // 13
ch32f1_flash_lock(t);
if ((sr & SR_ERROR_MASK) ) {
ERROR_CH("ch32f1 flash write error 0x%" PRIx32 "\n", sr);
return -1;
}
}
#ifdef CH32_VERIFY
DEBUG_CH("Verifying\n");
int i=0;
for(i=0;i<(int)len;i+=4)
{
uint32_t mem=target_mem_read32(t, orgDest+i);
uint32_t mem2=*(uint32_t *)(orgSrc+i);
if(mem!=mem2)
{
ERROR_CH(">>>>write mistmatch at address 0x%x\n",orgDest+i);
ERROR_CH(">>>>expected 0x%x\n",mem2);
ERROR_CH(">>>>flash 0x%x\n",mem);
return -1;
}
}
#endif
return 0;
}
// EOF

View File

@ -110,6 +110,10 @@ static int stm32f4_flash_write(struct target_flash *f,
#define AXIM_BASE 0x8000000
#define ITCM_BASE 0x0200000
#define DBGMCU_CR_DBG_SLEEP (0x1U << 0U)
#define DBGMCU_CR_DBG_STOP (0x1U << 1U)
#define DBGMCU_CR_DBG_STANDBY (0x1U << 2U)
struct stm32f4_flash {
struct target_flash f;
enum align psize;
@ -117,6 +121,10 @@ struct stm32f4_flash {
uint8_t bank_split;
};
struct stm32f4_priv_s {
uint32_t dbgmcu_cr;
};
enum IDS_STM32F247 {
ID_STM32F20X = 0x411,
ID_STM32F40X = 0x413,
@ -194,10 +202,12 @@ static char *stm32f4_get_chip_name(uint32_t idcode)
}
}
static void stm32f7_detach(target *t)
static void stm32f4_detach(target *t)
{
ADIv5_AP_t *ap = cortexm_ap(t);
target_mem_write32(t, DBGMCU_CR, ap->ap_storage);
struct stm32f4_priv_s *ps = (struct stm32f4_priv_s*)t->target_storage;
/*reverse all changes to DBGMCU_CR*/
target_mem_write32(t, DBGMCU_CR, ps->dbgmcu_cr);
cortexm_detach(t);
}
@ -214,8 +224,6 @@ bool stm32f4_probe(target *t)
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
case ID_STM32F76X: /* F76x F77x RM0410 */
case ID_STM32F72X: /* F72x F73x RM0431 */
t->detach = stm32f7_detach;
/* fall through */
case ID_STM32F40X:
case ID_STM32F42X: /* 427/437 */
case ID_STM32F46X: /* 469/479 */
@ -226,6 +234,7 @@ bool stm32f4_probe(target *t)
case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
t->detach = stm32f4_detach;
t->driver = stm32f4_get_chip_name(t->idcode);
t->attach = stm32f4_attach;
target_add_commands(t, stm32f4_cmd_list, t->driver);
@ -295,6 +304,19 @@ static bool stm32f4_attach(target *t)
return false;
}
bool use_dual_bank = false;
/* Save DBGMCU_CR to restore it when detaching*/
struct stm32f4_priv_s *priv_storage = calloc(1, sizeof(*priv_storage));
if (!priv_storage) { /* calloc failed: heap exhaustion */
DEBUG_WARN("calloc: failed in %s\n", __func__);
return false;
}
priv_storage->dbgmcu_cr = target_mem_read32(t, DBGMCU_CR);
t->target_storage = (void*)priv_storage;
/* Enable debugging during all low power modes*/
target_mem_write32(t, DBGMCU_CR, priv_storage->dbgmcu_cr |
DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STANDBY | DBGMCU_CR_DBG_STOP);
/* Free previously loaded memory map */
target_mem_map_free(t);
if (is_f7) {
target_add_ram(t, 0x00000000, 0x4000); /* 16 k ITCM Ram */

View File

@ -173,6 +173,7 @@ int tc_system(target *t, target_addr cmd, size_t cmdlen);
/* Probe for various targets.
* Actual functions implemented in their respective drivers.
*/
bool ch32f1_probe(target *t); // will catch all the clones
bool gd32f1_probe(target *t);
bool stm32f1_probe(target *t);
bool stm32f4_probe(target *t);