Merge commit 'a3feae60aab1fb85fe44b33123e020a9d7c8e18c' into sam-update
This commit is contained in:
commit
e43b07172b
154
src/gdb_main.c
154
src/gdb_main.c
@ -51,12 +51,10 @@ enum gdb_signal {
|
||||
typedef struct
|
||||
{
|
||||
const char *cmd_prefix;
|
||||
void (*func)(const char *packet,int len);
|
||||
}cmd_executer;
|
||||
void (*func)(const char *packet, int len);
|
||||
} cmd_executer;
|
||||
|
||||
|
||||
|
||||
static char pbuf[BUF_SIZE+1];
|
||||
static char pbuf[BUF_SIZE + 1];
|
||||
|
||||
static target *cur_target;
|
||||
static target *last_target;
|
||||
@ -119,7 +117,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)),
|
||||
sizeof(arm_regs) * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 'm': { /* 'm addr,len': Read len bytes from addr */
|
||||
uint32_t addr, len;
|
||||
ERROR_IF_NO_TARGET();
|
||||
@ -134,9 +132,9 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
if (target_mem_read(cur_target, mem, addr, len))
|
||||
gdb_putpacketz("E01");
|
||||
else
|
||||
gdb_putpacket(hexify(pbuf, mem, len), len*2);
|
||||
gdb_putpacket(hexify(pbuf, mem, len), len * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 'G': { /* 'G XX': Write general registers */
|
||||
ERROR_IF_NO_TARGET();
|
||||
uint8_t arm_regs[target_regs_size(cur_target)];
|
||||
@ -144,7 +142,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
target_regs_write(cur_target, arm_regs);
|
||||
gdb_putpacketz("OK");
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 'M': { /* 'M addr,len:XX': Write len bytes to addr */
|
||||
uint32_t addr, len;
|
||||
int hex;
|
||||
@ -163,7 +161,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
else
|
||||
gdb_putpacketz("OK");
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 's': /* 's [addr]': Single step [start at addr] */
|
||||
single_step = true;
|
||||
/* fall through */
|
||||
@ -217,7 +215,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
gdb_putpacket_f("T%02X", GDB_SIGTRAP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Optional GDB packet support */
|
||||
case 'p': { /* Read single register */
|
||||
@ -226,32 +224,31 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
sscanf(pbuf, "p%" SCNx32, ®);
|
||||
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 */
|
||||
ERROR_IF_NO_TARGET();
|
||||
uint32_t reg;
|
||||
int n;
|
||||
sscanf(pbuf, "P%" SCNx32 "=%n", ®, &n);
|
||||
uint8_t val[strlen(&pbuf[n])/2];
|
||||
// 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("");
|
||||
}
|
||||
@ -309,12 +306,12 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
}
|
||||
DEBUG_GDB("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
|
||||
addr, len);
|
||||
if (target_mem_write(cur_target, addr, pbuf+bin, len))
|
||||
if (target_mem_write(cur_target, addr, pbuf + bin, len))
|
||||
gdb_putpacketz("E01");
|
||||
else
|
||||
gdb_putpacketz("OK");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case 'q': /* General query packet */
|
||||
handle_q_packet(pbuf, size);
|
||||
@ -337,35 +334,36 @@ 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);
|
||||
if(!strncmp(packet,exec->cmd_prefix,l)) {
|
||||
exec->func(packet+l,len-l);
|
||||
while (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;
|
||||
}
|
||||
|
||||
static void exec_q_rcmd(const char *packet,int len)
|
||||
{
|
||||
char *data;
|
||||
int datalen;
|
||||
char *data;
|
||||
int datalen;
|
||||
|
||||
/* calculate size and allocate buffer for command */
|
||||
datalen = len/ 2;
|
||||
data = alloca(datalen+1);
|
||||
datalen = len / 2;
|
||||
data = alloca(datalen + 1);
|
||||
/* dehexify command */
|
||||
unhexify(data, packet, datalen);
|
||||
data[datalen] = 0; /* add terminating null */
|
||||
|
||||
int c = command_process(cur_target, data);
|
||||
if(c < 0)
|
||||
if (c < 0)
|
||||
gdb_putpacketz("");
|
||||
else if(c == 0)
|
||||
else if (c == 0)
|
||||
gdb_putpacketz("OK");
|
||||
else
|
||||
gdb_putpacket(hexify(pbuf, "Failed\n", strlen("Failed\n")),
|
||||
@ -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;
|
||||
gdb_putpacket2("m",1,str+addr,output_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;
|
||||
@ -400,12 +401,12 @@ static void exec_q_supported(const char *packet, int len)
|
||||
gdb_putpacket_f("PacketSize=%X;qXfer:memory-map:read+;qXfer:features:read+", BUF_SIZE);
|
||||
}
|
||||
|
||||
static void exec_q_memory_map(const char *packet,int len)
|
||||
static void exec_q_memory_map(const char *packet, int len)
|
||||
{
|
||||
(void)packet;
|
||||
(void)len;
|
||||
/* Read target XML memory map */
|
||||
if((!cur_target) && last_target) {
|
||||
if ((!cur_target) && last_target) {
|
||||
/* Attach to last target if detached. */
|
||||
cur_target = target_attach(last_target,
|
||||
&gdb_controller);
|
||||
@ -423,7 +424,7 @@ static void exec_q_feature_read(const char *packet, int len)
|
||||
{
|
||||
(void)len;
|
||||
/* Read target description */
|
||||
if((!cur_target) && last_target) {
|
||||
if ((!cur_target) && last_target) {
|
||||
/* Attach to last target if detached. */
|
||||
cur_target = target_attach(last_target, &gdb_controller);
|
||||
}
|
||||
@ -431,7 +432,7 @@ static void exec_q_feature_read(const char *packet, int len)
|
||||
gdb_putpacketz("E01");
|
||||
return;
|
||||
}
|
||||
handle_q_string_reply(target_tdesc(cur_target), packet );
|
||||
handle_q_string_reply(target_tdesc(cur_target), packet);
|
||||
}
|
||||
|
||||
static void exec_q_crc(const char *packet, int len)
|
||||
@ -439,7 +440,7 @@ static void exec_q_crc(const char *packet, int len)
|
||||
(void)len;
|
||||
uint32_t addr, alen;
|
||||
if (sscanf(packet, "%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) {
|
||||
if(!cur_target) {
|
||||
if (!cur_target) {
|
||||
gdb_putpacketz("E01");
|
||||
return;
|
||||
}
|
||||
@ -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},
|
||||
{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,35 +493,37 @@ 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++ = ' ';
|
||||
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++='\\';
|
||||
pcmdline[1] = *pcmdline;
|
||||
*pcmdline++ = '\\';
|
||||
}
|
||||
pcmdline++;
|
||||
tok+=2;
|
||||
*pcmdline='\0';
|
||||
tok += 2;
|
||||
pcmdline[0] = '\0';
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Run target program. For us (embedded) this means reset. */
|
||||
if(cur_target) {
|
||||
if (cur_target) {
|
||||
target_set_cmdline(cur_target, cmdline);
|
||||
target_reset(cur_target);
|
||||
gdb_putpacketz("T05");
|
||||
} else if(last_target) {
|
||||
} else if (last_target) {
|
||||
cur_target = target_attach(last_target,
|
||||
&gdb_controller);
|
||||
|
||||
@ -531,24 +533,29 @@ 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) {
|
||||
if (!flash_mode) {
|
||||
/* Reset target if first flash command! */
|
||||
/* This saves us if we're interrupted in IRQ context */
|
||||
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,13 +598,12 @@ 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)
|
||||
|
105
src/gdb_packet.c
105
src/gdb_packet.c
@ -37,7 +37,7 @@ int gdb_getpacket(char *packet, int size)
|
||||
char recv_csum[3];
|
||||
int i;
|
||||
|
||||
while(1) {
|
||||
while (1) {
|
||||
/* Wait for packet start */
|
||||
do {
|
||||
/* Spin waiting for a start of packet character - either a gdb
|
||||
@ -45,38 +45,39 @@ 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) {
|
||||
if (packet[0] == REMOTE_SOM) {
|
||||
/* This is probably a remote control packet
|
||||
* - get and handle it */
|
||||
i=0;
|
||||
bool gettingRemotePacket=true;
|
||||
i = 0;
|
||||
bool gettingRemotePacket = true;
|
||||
while (gettingRemotePacket) {
|
||||
c=gdb_if_getchar();
|
||||
c = gdb_if_getchar();
|
||||
switch (c) {
|
||||
case REMOTE_SOM: /* Oh dear, packet restarts */
|
||||
i=0;
|
||||
i = 0;
|
||||
break;
|
||||
|
||||
case REMOTE_EOM: /* Complete packet for processing */
|
||||
packet[i]=0;
|
||||
remotePacketProcess(i,packet);
|
||||
gettingRemotePacket=false;
|
||||
packet[i] = 0;
|
||||
remotePacketProcess(i, packet);
|
||||
gettingRemotePacket = false;
|
||||
break;
|
||||
|
||||
case '$': /* A 'real' gdb packet, best stop squatting now */
|
||||
packet[0]='$';
|
||||
gettingRemotePacket=false;
|
||||
packet[0] = '$';
|
||||
gettingRemotePacket = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i<size) {
|
||||
packet[i++]=c;
|
||||
if (i < size) {
|
||||
packet[i++] = c;
|
||||
} else {
|
||||
/* Who knows what is going on...return to normality */
|
||||
gettingRemotePacket=false;
|
||||
gettingRemotePacket = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -91,18 +92,20 @@ 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()) != '#') {
|
||||
while ((c = gdb_if_getchar()) != '#') {
|
||||
|
||||
if(i == size) break; /* Oh shit */
|
||||
if (i == size) /* Oh shit */
|
||||
break;
|
||||
|
||||
if(c == '$') { /* Restart capture */
|
||||
if (c == '$') { /* Restart capture */
|
||||
i = 0;
|
||||
csum = 0;
|
||||
continue;
|
||||
}
|
||||
if(c == '}') { /* escaped char */
|
||||
if (c == '}') { /* escaped char */
|
||||
c = gdb_if_getchar();
|
||||
csum += c + '}';
|
||||
packet[i++] = c ^ 0x20;
|
||||
@ -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 */
|
||||
@ -140,23 +144,24 @@ int gdb_getpacket(char *packet, int size)
|
||||
|
||||
static void gdb_next_char(char c, unsigned char *csum)
|
||||
{
|
||||
#if PC_HOSTED == 1
|
||||
if ((c >= 32) && (c < 127))
|
||||
DEBUG_GDB_WIRE("%c", c);
|
||||
else
|
||||
DEBUG_GDB_WIRE("\\x%02X", c);
|
||||
#endif
|
||||
if((c == '$') || (c == '#') || (c == '}') || (c == '*')) {
|
||||
gdb_if_putchar('}', 0);
|
||||
gdb_if_putchar(c ^ 0x20, 0);
|
||||
*csum += '}' + (c ^ 0x20);
|
||||
} else {
|
||||
gdb_if_putchar(c, 0);
|
||||
*csum += c;
|
||||
}
|
||||
#if PC_HOSTED == 1
|
||||
if ((c >= 32) && (c < 127))
|
||||
DEBUG_GDB_WIRE("%c", c);
|
||||
else
|
||||
DEBUG_GDB_WIRE("\\x%02X", c);
|
||||
#endif
|
||||
if ((c == '$') || (c == '#') || (c == '}') || (c == '*')) {
|
||||
gdb_if_putchar('}', 0);
|
||||
gdb_if_putchar(c ^ 0x20, 0);
|
||||
*csum += '}' + (c ^ 0x20);
|
||||
}
|
||||
else {
|
||||
gdb_if_putchar(c, 0);
|
||||
*csum += c;
|
||||
}
|
||||
}
|
||||
|
||||
void gdb_putpacket2(const char *packet1, int size1,const char *packet2, int size2)
|
||||
void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int size2)
|
||||
{
|
||||
int i;
|
||||
unsigned char csum;
|
||||
@ -168,18 +173,19 @@ 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++)
|
||||
gdb_next_char( packet1[i],&csum);
|
||||
for(i = 0; i < size2; i++)
|
||||
gdb_next_char( packet2[i],&csum);
|
||||
for (i = 0; i < size1; ++i)
|
||||
gdb_next_char(packet1[i], &csum);
|
||||
for (i = 0; i < size2; ++i)
|
||||
gdb_next_char(packet2[i], &csum);
|
||||
|
||||
gdb_if_putchar('#', 0);
|
||||
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
|
||||
gdb_if_putchar(xmit_csum[0], 0);
|
||||
gdb_if_putchar(xmit_csum[1], 1);
|
||||
DEBUG_GDB_WIRE("\n");
|
||||
} while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
|
||||
} while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
|
||||
}
|
||||
|
||||
void gdb_putpacket(const char *packet, int size)
|
||||
{
|
||||
int i;
|
||||
@ -191,14 +197,14 @@ 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++)
|
||||
gdb_next_char(packet[i],&csum);
|
||||
for (i = 0; i < size; ++i)
|
||||
gdb_next_char(packet[i], &csum);
|
||||
gdb_if_putchar('#', 0);
|
||||
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
|
||||
gdb_if_putchar(xmit_csum[0], 0);
|
||||
gdb_if_putchar(xmit_csum[1], 1);
|
||||
DEBUG_GDB_WIRE("\n");
|
||||
} while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
|
||||
} while ((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
|
||||
}
|
||||
|
||||
void gdb_putpacket_f(const char *fmt, ...)
|
||||
@ -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);
|
||||
int l = strlen(buf);
|
||||
char *hexdata = calloc(1, 2 * l + 1);
|
||||
if (!hexdata)
|
||||
return;
|
||||
hexify(hexdata, buf, l);
|
||||
gdb_putpacket2("O",1,hexdata, 2*l);
|
||||
gdb_putpacket2("O", 1, hexdata, 2 * l);
|
||||
free(hexdata);
|
||||
}
|
||||
|
||||
void gdb_voutf(const char *fmt, va_list ap)
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
int gdb_getpacket(char *packet, int size);
|
||||
void gdb_putpacket(const char *packet, int size);
|
||||
void gdb_putpacket2(const char *packet1, int size1,const char *packet2, int size2);
|
||||
void gdb_putpacket2(const char *packet1, int size1, const char *packet2, int size2);
|
||||
#define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet))
|
||||
void gdb_putpacket_f(const char *packet, ...);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
338
src/target/stm32f1_ch32.c
Normal 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
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user