Merge commit 'd63e870e82ecbd73af2d14e6794d2985cb9bd0ad' into sam-update
This commit is contained in:
commit
41449370b4
@ -442,7 +442,10 @@ int usbFeeder(void)
|
|||||||
{
|
{
|
||||||
unsigned char *c=cbw;
|
unsigned char *c=cbw;
|
||||||
if (options.dump)
|
if (options.dump)
|
||||||
printf(cbw);
|
{
|
||||||
|
cbw[size] = 0;
|
||||||
|
printf("%s", (char*)cbw);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
while (size--)
|
while (size--)
|
||||||
_protocolPump(c++);
|
_protocolPump(c++);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
|
#include "ctype.h"
|
||||||
#include "hex_utils.h"
|
#include "hex_utils.h"
|
||||||
#include "gdb_if.h"
|
#include "gdb_if.h"
|
||||||
#include "gdb_packet.h"
|
#include "gdb_packet.h"
|
||||||
@ -429,9 +430,37 @@ handle_v_packet(char *packet, int plen)
|
|||||||
else
|
else
|
||||||
gdb_putpacketz("E01");
|
gdb_putpacketz("E01");
|
||||||
|
|
||||||
} else if (!strcmp(packet, "vRun;")) {
|
} else if (!strncmp(packet, "vRun", 4)) {
|
||||||
|
/* Parse command line for get_cmdline semihosting call */
|
||||||
|
char cmdline[83];
|
||||||
|
char *pbuf = cmdline;
|
||||||
|
char *tok = packet + 4;
|
||||||
|
if (*tok == ';') tok++;
|
||||||
|
*cmdline='\0';
|
||||||
|
while(*tok != '\0') {
|
||||||
|
if(strlen(cmdline)+3 >= sizeof(cmdline)) break;
|
||||||
|
if (*tok == ';') {
|
||||||
|
*pbuf++=' ';
|
||||||
|
*pbuf='\0';
|
||||||
|
tok++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isxdigit(*tok) && isxdigit(*(tok+1))) {
|
||||||
|
unhexify(pbuf, tok, 2);
|
||||||
|
if ((*pbuf == ' ') || (*pbuf == '\\')) {
|
||||||
|
*(pbuf+1)=*pbuf;
|
||||||
|
*pbuf++='\\';
|
||||||
|
}
|
||||||
|
pbuf++;
|
||||||
|
tok+=2;
|
||||||
|
*pbuf='\0';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* Run target program. For us (embedded) this means reset. */
|
/* 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);
|
target_reset(cur_target);
|
||||||
gdb_putpacketz("T05");
|
gdb_putpacketz("T05");
|
||||||
} else if(last_target) {
|
} else if(last_target) {
|
||||||
@ -440,6 +469,7 @@ handle_v_packet(char *packet, int plen)
|
|||||||
|
|
||||||
/* If we were able to attach to the target again */
|
/* If we were able to attach to the target again */
|
||||||
if (cur_target) {
|
if (cur_target) {
|
||||||
|
target_set_cmdline(cur_target, cmdline);
|
||||||
target_reset(cur_target);
|
target_reset(cur_target);
|
||||||
gdb_putpacketz("T05");
|
gdb_putpacketz("T05");
|
||||||
} else gdb_putpacketz("E01");
|
} else gdb_putpacketz("E01");
|
||||||
|
@ -80,6 +80,7 @@ void target_reset(target *t);
|
|||||||
void target_halt_request(target *t);
|
void target_halt_request(target *t);
|
||||||
enum target_halt_reason target_halt_poll(target *t, target_addr *watch);
|
enum target_halt_reason target_halt_poll(target *t, target_addr *watch);
|
||||||
void target_halt_resume(target *t, bool step);
|
void target_halt_resume(target *t, bool step);
|
||||||
|
void target_set_cmdline(target *t, char *cmdline);
|
||||||
|
|
||||||
/* Break-/watchpoint functions */
|
/* Break-/watchpoint functions */
|
||||||
enum target_breakwatch {
|
enum target_breakwatch {
|
||||||
|
@ -188,7 +188,7 @@ static const struct usb_endpoint_descriptor uart_data_endp[] = {{
|
|||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
.bEndpointAddress = 0x03,
|
.bEndpointAddress = 0x03,
|
||||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||||
.wMaxPacketSize = CDCACM_PACKET_SIZE,
|
.wMaxPacketSize = CDCACM_PACKET_SIZE / 2,
|
||||||
.bInterval = 1,
|
.bInterval = 1,
|
||||||
}, {
|
}, {
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
|
@ -8,5 +8,5 @@ else ifneq (, $(findstring cygwin, $(SYS)))
|
|||||||
LDFLAGS += -lusb-1.0 -lws2_32
|
LDFLAGS += -lusb-1.0 -lws2_32
|
||||||
endif
|
endif
|
||||||
VPATH += platforms/pc
|
VPATH += platforms/pc
|
||||||
SRC += timing.c cl_utils.c
|
SRC += timing.c cl_utils.c utils.c
|
||||||
CFLAGS +=-I ./target -I./platforms/pc
|
CFLAGS +=-I ./target -I./platforms/pc
|
||||||
|
@ -290,34 +290,7 @@ int platform_buffer_read(uint8_t *data, int size)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
#warning "This vasprintf() is dubious!"
|
|
||||||
int vasprintf(char **strp, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
int size = 128, ret = 0;
|
|
||||||
|
|
||||||
*strp = malloc(size);
|
|
||||||
while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
|
|
||||||
*strp = realloc(*strp, size <<= 1);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *platform_target_voltage(void)
|
const char *platform_target_voltage(void)
|
||||||
{
|
{
|
||||||
return "not supported";
|
return "not supported";
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_delay(uint32_t ms)
|
|
||||||
{
|
|
||||||
usleep(ms * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t platform_time_ms(void)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
TARGET=blackmagic_hosted
|
TARGET=blackmagic_hosted
|
||||||
SYS = $(shell $(CC) -dumpmachine)
|
SYS = $(shell $(CC) -dumpmachine)
|
||||||
CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG -I
|
CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG
|
||||||
CFLAGS += $(shell pkg-config --cflags libftdi1)
|
|
||||||
CFLAGS +=-I ./target -I./platforms/pc
|
CFLAGS +=-I ./target -I./platforms/pc
|
||||||
LDFLAGS += $(shell pkg-config --libs libftdi1)
|
|
||||||
ifneq (, $(findstring mingw, $(SYS)))
|
ifneq (, $(findstring mingw, $(SYS)))
|
||||||
LDFLAGS += -lusb-1.0 -lws2_32
|
SRC += serial_win.c
|
||||||
CFLAGS += -Wno-cast-function-type
|
LDFLAGS += -lws2_32
|
||||||
else ifneq (, $(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring cygwin, $(SYS)))
|
||||||
LDFLAGS += -lusb-1.0 -lws2_32
|
SRC += serial_win.c
|
||||||
|
LDFLAGS += -lws2_32
|
||||||
|
else
|
||||||
|
SRC += serial_unix.c
|
||||||
endif
|
endif
|
||||||
VPATH += platforms/pc
|
VPATH += platforms/pc
|
||||||
SRC += cl_utils.c timing.c
|
SRC += cl_utils.c timing.c utils.c
|
||||||
|
@ -98,7 +98,7 @@ void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI
|
|||||||
if(!ticks || !DI) return;
|
if(!ticks || !DI) return;
|
||||||
|
|
||||||
/* Reduce the length of DI according to the bits we're transmitting */
|
/* Reduce the length of DI according to the bits we're transmitting */
|
||||||
DIl&=(1L<<(ticks+1))-1;
|
DIl &= (1LL << (ticks + 1)) - 1;
|
||||||
|
|
||||||
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_TDIDO_STR,final_tms?REMOTE_TDITDO_TMS:REMOTE_TDITDO_NOTMS,ticks,DIl);
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_TDIDO_STR,final_tms?REMOTE_TDITDO_TMS:REMOTE_TDITDO_NOTMS,ticks,DIl);
|
||||||
platform_buffer_write(construct,s);
|
platform_buffer_write(construct,s);
|
||||||
@ -111,8 +111,8 @@ void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DO) {
|
if (DO) {
|
||||||
for (unsigned int i = 1; i*8 <= (unsigned int)ticks; i++)
|
uint64_t DOl = remotehston(-1, (char *)&construct[1]);
|
||||||
DO[i - 1] = remotehston(2 , (char *)&construct[s - (i * 2)]);
|
*(uint64_t *)DO = DOl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,77 +25,16 @@
|
|||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "cl_utils.h"
|
#include "cl_utils.h"
|
||||||
|
static BMP_CL_OPTIONS_t cl_opts; /* Portable way to nullify the struct*/
|
||||||
/* Allow 100mS for responses to reach us */
|
|
||||||
#define RESP_TIMEOUT (100)
|
|
||||||
|
|
||||||
/* Define this to see the transactions across the link */
|
|
||||||
//#define DUMP_TRANSACTIONS
|
|
||||||
|
|
||||||
static int f; /* File descriptor for connection to GDB remote */
|
|
||||||
|
|
||||||
int set_interface_attribs (int fd, int speed, int parity)
|
|
||||||
|
|
||||||
/* A nice routine grabbed from
|
|
||||||
* https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
struct termios tty;
|
|
||||||
memset (&tty, 0, sizeof tty);
|
|
||||||
if (tcgetattr (fd, &tty) != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"error %d from tcgetattr", errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfsetospeed (&tty, speed);
|
|
||||||
cfsetispeed (&tty, speed);
|
|
||||||
|
|
||||||
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
|
||||||
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
|
||||||
// as \000 chars
|
|
||||||
tty.c_iflag &= ~IGNBRK; // disable break processing
|
|
||||||
tty.c_lflag = 0; // no signaling chars, no echo,
|
|
||||||
// no canonical processing
|
|
||||||
tty.c_oflag = 0; // no remapping, no delays
|
|
||||||
tty.c_cc[VMIN] = 0; // read doesn't block
|
|
||||||
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
|
||||||
|
|
||||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
|
|
||||||
|
|
||||||
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
|
|
||||||
// enable reading
|
|
||||||
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
|
|
||||||
tty.c_cflag |= parity;
|
|
||||||
tty.c_cflag &= ~CSTOPB;
|
|
||||||
tty.c_cflag &= ~CRTSCTS;
|
|
||||||
|
|
||||||
if (tcsetattr (fd, TCSANOW, &tty) != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"error %d from tcsetattr", errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void platform_init(int argc, char **argv)
|
void platform_init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
BMP_CL_OPTIONS_t cl_opts = {0};
|
|
||||||
cl_opts.opt_idstring = "Blackmagic Debug Probe Remote";
|
cl_opts.opt_idstring = "Blackmagic Debug Probe Remote";
|
||||||
cl_init(&cl_opts, argc, argv);
|
cl_init(&cl_opts, argc, argv);
|
||||||
char construct[PLATFORM_MAX_MSG_SIZE];
|
char construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
@ -105,18 +44,8 @@ void platform_init(int argc, char **argv)
|
|||||||
printf("License GPLv3+: GNU GPL version 3 or later "
|
printf("License GPLv3+: GNU GPL version 3 or later "
|
||||||
"<http://gnu.org/licenses/gpl.html>\n\n");
|
"<http://gnu.org/licenses/gpl.html>\n\n");
|
||||||
|
|
||||||
f=open(cl_opts.opt_serial,O_RDWR|O_SYNC|O_NOCTTY);
|
if (serial_open(&cl_opts))
|
||||||
if (f<0)
|
exit(-1);
|
||||||
{
|
|
||||||
fprintf(stderr,"Couldn't open serial port %s\n", cl_opts.opt_serial);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set_interface_attribs (f, 115000, 0)<0)
|
|
||||||
{
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int c=snprintf(construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_START_STR);
|
int c=snprintf(construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_START_STR);
|
||||||
platform_buffer_write((uint8_t *)construct,c);
|
platform_buffer_write((uint8_t *)construct,c);
|
||||||
c=platform_buffer_read((uint8_t *)construct, PLATFORM_MAX_MSG_SIZE);
|
c=platform_buffer_read((uint8_t *)construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
@ -132,7 +61,7 @@ void platform_init(int argc, char **argv)
|
|||||||
int ret = cl_execute(&cl_opts);
|
int ret = cl_execute(&cl_opts);
|
||||||
if (cl_opts.opt_tpwr)
|
if (cl_opts.opt_tpwr)
|
||||||
platform_target_set_power(0);
|
platform_target_set_power(0);
|
||||||
close(f);
|
serial_close();
|
||||||
exit(ret);
|
exit(ret);
|
||||||
} else {
|
} else {
|
||||||
assert(gdb_if_init() == 0);
|
assert(gdb_if_init() == 0);
|
||||||
@ -217,110 +146,6 @@ void platform_buffer_flush(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int platform_buffer_write(const uint8_t *data, int size)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
|
|
||||||
#ifdef DUMP_TRANSACTIONS
|
|
||||||
printf("%s\n",data);
|
|
||||||
#endif
|
|
||||||
s=write(f,data,size);
|
|
||||||
if (s<0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Failed to write\n");
|
|
||||||
exit(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int platform_buffer_read(uint8_t *data, int maxsize)
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t *c;
|
|
||||||
int s;
|
|
||||||
int ret;
|
|
||||||
uint32_t endTime;
|
|
||||||
fd_set rset;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
c=data;
|
|
||||||
tv.tv_sec=0;
|
|
||||||
|
|
||||||
endTime=platform_time_ms()+RESP_TIMEOUT;
|
|
||||||
tv.tv_usec=1000*(endTime-platform_time_ms());
|
|
||||||
|
|
||||||
/* Look for start of response */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
FD_ZERO(&rset);
|
|
||||||
FD_SET(f, &rset);
|
|
||||||
|
|
||||||
ret = select(f + 1, &rset, NULL, NULL, &tv);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Failed on select\n");
|
|
||||||
exit(-4);
|
|
||||||
}
|
|
||||||
if(ret == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Timeout on read\n");
|
|
||||||
exit(-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
s=read(f,c,1);
|
|
||||||
}
|
|
||||||
while ((s>0) && (*c!=REMOTE_RESP));
|
|
||||||
|
|
||||||
/* Now collect the response */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
FD_ZERO(&rset);
|
|
||||||
FD_SET(f, &rset);
|
|
||||||
ret = select(f + 1, &rset, NULL, NULL, &tv);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Failed on select\n");
|
|
||||||
exit(-4);
|
|
||||||
}
|
|
||||||
if(ret == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Timeout on read\n");
|
|
||||||
exit(-3);
|
|
||||||
}
|
|
||||||
s=read(f,c,1);
|
|
||||||
if (*c==REMOTE_EOM)
|
|
||||||
{
|
|
||||||
*c=0;
|
|
||||||
#ifdef DUMP_TRANSACTIONS
|
|
||||||
printf(" %s\n",data);
|
|
||||||
#endif
|
|
||||||
return (c-data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
while ((s>=0) && (c-data<maxsize));
|
|
||||||
|
|
||||||
fprintf(stderr,"Failed to read\n");
|
|
||||||
exit(-3);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
#warning "This vasprintf() is dubious!"
|
|
||||||
int vasprintf(char **strp, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
int size = 128, ret = 0;
|
|
||||||
|
|
||||||
*strp = malloc(size);
|
|
||||||
while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
|
|
||||||
*strp = realloc(*strp, size <<= 1);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *platform_target_voltage(void)
|
const char *platform_target_voltage(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -340,15 +165,3 @@ const char *platform_target_voltage(void)
|
|||||||
|
|
||||||
return (char *)&construct[1];
|
return (char *)&construct[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_delay(uint32_t ms)
|
|
||||||
{
|
|
||||||
usleep(ms * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t platform_time_ms(void)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
|
||||||
}
|
|
||||||
|
@ -41,10 +41,12 @@
|
|||||||
#define SET_IDLE_STATE(state)
|
#define SET_IDLE_STATE(state)
|
||||||
#define SET_ERROR_STATE(state)
|
#define SET_ERROR_STATE(state)
|
||||||
|
|
||||||
|
/* Allow 100mS for responses to reach us */
|
||||||
|
#define RESP_TIMEOUT (100)
|
||||||
|
|
||||||
void platform_buffer_flush(void);
|
void platform_buffer_flush(void);
|
||||||
int platform_buffer_write(const uint8_t *data, int size);
|
int platform_buffer_write(const uint8_t *data, int size);
|
||||||
int platform_buffer_read(uint8_t *data, int size);
|
int platform_buffer_read(uint8_t *data, int size);
|
||||||
|
|
||||||
static inline int platform_hwversion(void)
|
static inline int platform_hwversion(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -9,5 +9,5 @@ else ifneq (, $(findstring cygwin, $(SYS)))
|
|||||||
LDFLAGS += -lws2_32
|
LDFLAGS += -lws2_32
|
||||||
endif
|
endif
|
||||||
VPATH += platforms/pc
|
VPATH += platforms/pc
|
||||||
SRC += timing.c stlinkv2.c cl_utils.c
|
SRC += timing.c stlinkv2.c cl_utils.c utils.c
|
||||||
OWN_HL = 1
|
OWN_HL = 1
|
||||||
|
@ -69,29 +69,3 @@ int platform_buffer_read(uint8_t *data, int size)
|
|||||||
(void) data;
|
(void) data;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
#warning "This vasprintf() is dubious!"
|
|
||||||
int vasprintf(char **strp, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
int size = 128, ret = 0;
|
|
||||||
|
|
||||||
*strp = malloc(size);
|
|
||||||
while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
|
|
||||||
*strp = realloc(*strp, size <<= 1);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void platform_delay(uint32_t ms)
|
|
||||||
{
|
|
||||||
usleep(ms * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t platform_time_ms(void)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
|
||||||
}
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
# include <windows.h>
|
||||||
#else
|
#else
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
@ -52,6 +53,9 @@ struct mmap_data {
|
|||||||
int fd;
|
int fd;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
int cl_debuglevel;
|
||||||
|
static struct mmap_data map; /* Portable way way to nullify the struct!*/
|
||||||
|
|
||||||
|
|
||||||
static int bmp_mmap(char *file, struct mmap_data *map)
|
static int bmp_mmap(char *file, struct mmap_data *map)
|
||||||
{
|
{
|
||||||
@ -115,6 +119,7 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
|
|||||||
printf("Usage: %s [options]\n", argv[0]);
|
printf("Usage: %s [options]\n", argv[0]);
|
||||||
printf("\t-h\t\t: This help.\n");
|
printf("\t-h\t\t: This help.\n");
|
||||||
printf("\t-v[1|2]\t\t: Increasing verbosity\n");
|
printf("\t-v[1|2]\t\t: Increasing verbosity\n");
|
||||||
|
printf("\t-d \"path\"\t: Use serial device at \"path\"\n");
|
||||||
printf("\t-s \"string\"\t: Use dongle with (partial) "
|
printf("\t-s \"string\"\t: Use dongle with (partial) "
|
||||||
"serial number \"string\"\n");
|
"serial number \"string\"\n");
|
||||||
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
|
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
|
||||||
@ -144,7 +149,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||||||
opt->opt_target_dev = 1;
|
opt->opt_target_dev = 1;
|
||||||
opt->opt_flash_start = 0x08000000;
|
opt->opt_flash_start = 0x08000000;
|
||||||
opt->opt_flash_size = 16 * 1024 *1024;
|
opt->opt_flash_size = 16 * 1024 *1024;
|
||||||
while((c = getopt(argc, argv, "Ehv::s:c:CnN:tVta:S:jprR")) != -1) {
|
while((c = getopt(argc, argv, "Ehv::d:s:c:CnN:tVta:S:jprR")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
@ -155,7 +160,9 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
opt->opt_debuglevel = strtol(optarg, NULL, 0);
|
cl_debuglevel = strtol(optarg, NULL, 0);
|
||||||
|
else
|
||||||
|
cl_debuglevel = -1;
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
opt->opt_usejtag = true;
|
opt->opt_usejtag = true;
|
||||||
@ -166,6 +173,10 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||||||
case 'n':
|
case 'n':
|
||||||
opt->opt_no_wait = true;
|
opt->opt_no_wait = true;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (optarg)
|
||||||
|
opt->opt_device = optarg;
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
opt->opt_serial = optarg;
|
opt->opt_serial = optarg;
|
||||||
@ -253,6 +264,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
|||||||
platform_srst_set_val(opt->opt_connect_under_reset);
|
platform_srst_set_val(opt->opt_connect_under_reset);
|
||||||
if (opt->opt_mode == BMP_MODE_TEST)
|
if (opt->opt_mode == BMP_MODE_TEST)
|
||||||
printf("Running in Test Mode\n");
|
printf("Running in Test Mode\n");
|
||||||
|
printf("Target voltage: %s Volt\n", platform_target_voltage());
|
||||||
if (opt->opt_usejtag) {
|
if (opt->opt_usejtag) {
|
||||||
num_targets = jtag_scan(NULL);
|
num_targets = jtag_scan(NULL);
|
||||||
} else {
|
} else {
|
||||||
@ -276,7 +288,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
|||||||
goto target_detach;
|
goto target_detach;
|
||||||
}
|
}
|
||||||
int read_file = -1;
|
int read_file = -1;
|
||||||
struct mmap_data map = {0};
|
|
||||||
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
|
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
|
||||||
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
|
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
|
||||||
int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
|
int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
|
||||||
|
@ -41,6 +41,7 @@ typedef struct BMP_CL_OPTIONS_s {
|
|||||||
bool opt_tpwr;
|
bool opt_tpwr;
|
||||||
bool opt_connect_under_reset;
|
bool opt_connect_under_reset;
|
||||||
char *opt_flash_file;
|
char *opt_flash_file;
|
||||||
|
char *opt_device;
|
||||||
char *opt_serial;
|
char *opt_serial;
|
||||||
char *opt_cable;
|
char *opt_cable;
|
||||||
int opt_debuglevel;
|
int opt_debuglevel;
|
||||||
@ -52,4 +53,6 @@ typedef struct BMP_CL_OPTIONS_s {
|
|||||||
|
|
||||||
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
|
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
|
||||||
int cl_execute(BMP_CL_OPTIONS_t *opt);
|
int cl_execute(BMP_CL_OPTIONS_t *opt);
|
||||||
|
int serial_open(BMP_CL_OPTIONS_t *opt);
|
||||||
|
void serial_close(void);
|
||||||
#endif
|
#endif
|
||||||
|
214
src/platforms/pc/serial_unix.c
Normal file
214
src/platforms/pc/serial_unix.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Dave Marples <dave@marples.net>
|
||||||
|
* with additions from Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "remote.h"
|
||||||
|
#include "cl_utils.h"
|
||||||
|
|
||||||
|
static int fd; /* File descriptor for connection to GDB remote */
|
||||||
|
extern int cl_debuglevel;
|
||||||
|
/* A nice routine grabbed from
|
||||||
|
* https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
|
||||||
|
*/
|
||||||
|
static int set_interface_attribs(void)
|
||||||
|
{
|
||||||
|
struct termios tty;
|
||||||
|
memset (&tty, 0, sizeof tty);
|
||||||
|
if (tcgetattr (fd, &tty) != 0) {
|
||||||
|
fprintf(stderr,"error %d from tcgetattr", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
||||||
|
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
||||||
|
// as \000 chars
|
||||||
|
tty.c_iflag &= ~IGNBRK; // disable break processing
|
||||||
|
tty.c_lflag = 0; // no signaling chars, no echo,
|
||||||
|
// no canonical processing
|
||||||
|
tty.c_oflag = 0; // no remapping, no delays
|
||||||
|
tty.c_cc[VMIN] = 0; // read doesn't block
|
||||||
|
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||||||
|
|
||||||
|
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
|
||||||
|
|
||||||
|
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
|
||||||
|
// enable reading
|
||||||
|
tty.c_cflag &= ~CSTOPB;
|
||||||
|
tty.c_cflag &= ~CRTSCTS;
|
||||||
|
|
||||||
|
if (tcsetattr (fd, TCSANOW, &tty) != 0) {
|
||||||
|
fprintf(stderr,"error %d from tcsetattr", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe"
|
||||||
|
#define DEVICE_BY_ID "/dev/serial/by-id/"
|
||||||
|
int serial_open(BMP_CL_OPTIONS_t *opt)
|
||||||
|
{
|
||||||
|
char name[4096];
|
||||||
|
if (!opt->opt_device) {
|
||||||
|
/* Try to find some BMP if0*/
|
||||||
|
struct dirent *dp;
|
||||||
|
DIR *dir = opendir(DEVICE_BY_ID);
|
||||||
|
if (!dir) {
|
||||||
|
fprintf(stderr, "No serial device found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int num_devices = 0;
|
||||||
|
int num_total = 0;
|
||||||
|
while ((dp = readdir(dir)) != NULL) {
|
||||||
|
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
|
||||||
|
(strstr(dp->d_name, "-if00"))) {
|
||||||
|
num_total++;
|
||||||
|
if (((opt->opt_serial) &&
|
||||||
|
(!strstr(dp->d_name, opt->opt_serial))))
|
||||||
|
continue;
|
||||||
|
num_devices++;
|
||||||
|
strcpy(name, DEVICE_BY_ID);
|
||||||
|
strncat(name, dp->d_name, sizeof(name) - strlen(name) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if ((num_devices == 0) && (num_total == 0)){
|
||||||
|
fprintf(stderr, "No BMP probe found\n");
|
||||||
|
return -1;
|
||||||
|
} else if (num_devices != 1) {
|
||||||
|
fprintf(stderr, "Available Probes:\n");
|
||||||
|
dir = opendir(DEVICE_BY_ID);
|
||||||
|
if (dir) {
|
||||||
|
while ((dp = readdir(dir)) != NULL) {
|
||||||
|
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
|
||||||
|
(strstr(dp->d_name, "-if00")))
|
||||||
|
fprintf(stderr, "%s\n", dp->d_name);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if (opt->opt_serial)
|
||||||
|
fprintf(stderr, "Do no match given serial \"%s\"\n", opt->opt_serial);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Select Probe with -s <(Partial) Serial Number\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Could not opendir %s: %s\n", name, strerror(errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strncpy(name, opt->opt_device, sizeof(name) - 1);
|
||||||
|
}
|
||||||
|
fd = open(name, O_RDWR | O_SYNC | O_NOCTTY);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr,"Couldn't open serial port %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* BMP only offers an USB-Serial connection with no real serial
|
||||||
|
* line in between. No need for baudrate or parity.!
|
||||||
|
*/
|
||||||
|
return set_interface_attribs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_close(void)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int platform_buffer_write(const uint8_t *data, int size)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("%s\n",data);
|
||||||
|
s = write(fd, data, size);
|
||||||
|
if (s < 0) {
|
||||||
|
fprintf(stderr, "Failed to write\n");
|
||||||
|
exit(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int platform_buffer_read(uint8_t *data, int maxsize)
|
||||||
|
{
|
||||||
|
uint8_t *c;
|
||||||
|
int s;
|
||||||
|
int ret;
|
||||||
|
uint32_t endTime;
|
||||||
|
fd_set rset;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
c = data;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
|
||||||
|
endTime = platform_time_ms() + RESP_TIMEOUT;
|
||||||
|
tv.tv_usec = 1000 * (endTime - platform_time_ms());
|
||||||
|
|
||||||
|
/* Look for start of response */
|
||||||
|
do {
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(fd, &rset);
|
||||||
|
|
||||||
|
ret = select(fd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr,"Failed on select\n");
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
if(ret == 0) {
|
||||||
|
fprintf(stderr,"Timeout on read RESP\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = read(fd, c, 1);
|
||||||
|
}
|
||||||
|
while ((s > 0) && (*c != REMOTE_RESP));
|
||||||
|
/* Now collect the response */
|
||||||
|
do {
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(fd, &rset);
|
||||||
|
ret = select(fd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr,"Failed on select\n");
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
if(ret == 0) {
|
||||||
|
fprintf(stderr,"Timeout on read\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
s = read(fd, c, 1);
|
||||||
|
if (*c==REMOTE_EOM) {
|
||||||
|
*c = 0;
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf(" %s\n",data);
|
||||||
|
return (c - data);
|
||||||
|
} else {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}while ((s >= 0) && ((c - data) < maxsize));
|
||||||
|
|
||||||
|
fprintf(stderr,"Failed to read\n");
|
||||||
|
exit(-3);
|
||||||
|
return 0;
|
||||||
|
}
|
139
src/platforms/pc/serial_win.c
Normal file
139
src/platforms/pc/serial_win.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "general.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include "remote.h"
|
||||||
|
#include "cl_utils.h"
|
||||||
|
|
||||||
|
HANDLE hComm;
|
||||||
|
extern int cl_debuglevel;
|
||||||
|
|
||||||
|
int serial_open(BMP_CL_OPTIONS_t *opt)
|
||||||
|
{
|
||||||
|
if (!opt->opt_device) {
|
||||||
|
fprintf(stderr,"Specify the serial device to use!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
char device[256];
|
||||||
|
if (strstr(opt->opt_device, "\\\\.\\")) {
|
||||||
|
strncpy(device, opt->opt_device, sizeof(device) - 1);
|
||||||
|
} else {
|
||||||
|
strcpy(device, "\\\\.\\");
|
||||||
|
strncat(device, opt->opt_device, sizeof(device) - strlen(device) - 1);
|
||||||
|
}
|
||||||
|
hComm = CreateFile(device, //port name
|
||||||
|
GENERIC_READ | GENERIC_WRITE, //Read/Write
|
||||||
|
0, // No Sharing
|
||||||
|
NULL, // No Security
|
||||||
|
OPEN_EXISTING,// Open existing port only
|
||||||
|
0, // Non Overlapped I/O
|
||||||
|
NULL); // Null for Comm Devices}
|
||||||
|
if (hComm == INVALID_HANDLE_VALUE) {
|
||||||
|
fprintf(stderr, "Could not open %s: %ld\n", device,
|
||||||
|
GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DCB dcbSerialParams;
|
||||||
|
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
|
||||||
|
if (!GetCommState(hComm, &dcbSerialParams)) {
|
||||||
|
fprintf(stderr, "GetCommState failed %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dcbSerialParams.ByteSize = 8;
|
||||||
|
if (!SetCommState(hComm, &dcbSerialParams)) {
|
||||||
|
fprintf(stderr, "SetCommState failed %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
COMMTIMEOUTS timeouts = {0};
|
||||||
|
timeouts.ReadIntervalTimeout = 10;
|
||||||
|
timeouts.ReadTotalTimeoutConstant = 10;
|
||||||
|
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||||
|
timeouts.WriteTotalTimeoutConstant = 10;
|
||||||
|
timeouts.WriteTotalTimeoutMultiplier = 10;
|
||||||
|
if (!SetCommTimeouts(hComm, &timeouts)) {
|
||||||
|
fprintf(stderr, "SetCommTimeouts failed %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_close(void)
|
||||||
|
{
|
||||||
|
CloseHandle(hComm);
|
||||||
|
}
|
||||||
|
|
||||||
|
int platform_buffer_write(const uint8_t *data, int size)
|
||||||
|
{
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("%s\n",data);
|
||||||
|
int s = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
DWORD written;
|
||||||
|
if (!WriteFile(hComm, data + s, size - s, &written, NULL)) {
|
||||||
|
fprintf(stderr, "Serial write failed %ld, written %d\n",
|
||||||
|
GetLastError(), s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s += written;
|
||||||
|
} while (s < size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int platform_buffer_read(uint8_t *data, int maxsize)
|
||||||
|
{
|
||||||
|
DWORD s;
|
||||||
|
uint8_t response = 0;
|
||||||
|
uint32_t startTime = platform_time_ms();
|
||||||
|
uint32_t endTime = platform_time_ms() + RESP_TIMEOUT;
|
||||||
|
do {
|
||||||
|
if (!ReadFile(hComm, &response, 1, &s, NULL)) {
|
||||||
|
fprintf(stderr,"ERROR on read RESP\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
if (platform_time_ms() > endTime) {
|
||||||
|
fprintf(stderr,"Timeout on read RESP\n");
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
} while (response != REMOTE_RESP);
|
||||||
|
uint8_t *c = data;
|
||||||
|
do {
|
||||||
|
if (!ReadFile(hComm, c, 1, &s, NULL)) {
|
||||||
|
fprintf(stderr,"Error on read\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
if (s > 0 ) {
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("%c", *c);
|
||||||
|
if (*c == REMOTE_EOM) {
|
||||||
|
*c = 0;
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("\n");
|
||||||
|
return (c - data);
|
||||||
|
} else {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (((c - data) < maxsize) && (platform_time_ms() < endTime));
|
||||||
|
fprintf(stderr,"Failed to read EOM at %d\n",
|
||||||
|
platform_time_ms() - startTime);
|
||||||
|
exit(-3);
|
||||||
|
return 0;
|
||||||
|
}
|
55
src/platforms/pc/utils.c
Normal file
55
src/platforms/pc/utils.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
|
* Base on code:
|
||||||
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
||||||
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* and others.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file deduplicates codes used in several pc-hosted platforms
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||||
|
#warning "This vasprintf() is dubious!"
|
||||||
|
int vasprintf(char **strp, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
int size = 128, ret = 0;
|
||||||
|
|
||||||
|
*strp = malloc(size);
|
||||||
|
while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
|
||||||
|
*strp = realloc(*strp, size <<= 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void platform_delay(uint32_t ms)
|
||||||
|
{
|
||||||
|
usleep(ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t platform_time_ms(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||||
|
}
|
@ -39,6 +39,7 @@ uint8_t running_status;
|
|||||||
uint16_t led_idle_run;
|
uint16_t led_idle_run;
|
||||||
uint16_t srst_pin;
|
uint16_t srst_pin;
|
||||||
static uint32_t rev;
|
static uint32_t rev;
|
||||||
|
static void adc_init(void);
|
||||||
|
|
||||||
int platform_hwversion(void)
|
int platform_hwversion(void)
|
||||||
{
|
{
|
||||||
@ -85,6 +86,7 @@ void platform_init(void)
|
|||||||
/* Don't enable UART if we're being debugged. */
|
/* Don't enable UART if we're being debugged. */
|
||||||
if (!(SCS_DEMCR & SCS_DEMCR_TRCENA))
|
if (!(SCS_DEMCR & SCS_DEMCR_TRCENA))
|
||||||
usbuart_init();
|
usbuart_init();
|
||||||
|
adc_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_srst_set_val(bool assert)
|
void platform_srst_set_val(bool assert)
|
||||||
@ -105,7 +107,52 @@ bool platform_srst_get_val()
|
|||||||
return gpio_get(SRST_PORT, srst_pin) == 0;
|
return gpio_get(SRST_PORT, srst_pin) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void adc_init(void)
|
||||||
|
{
|
||||||
|
rcc_periph_clock_enable(RCC_ADC1);
|
||||||
|
|
||||||
|
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
|
||||||
|
GPIO_CNF_INPUT_ANALOG, GPIO0);
|
||||||
|
|
||||||
|
adc_power_off(ADC1);
|
||||||
|
adc_disable_scan_mode(ADC1);
|
||||||
|
adc_set_single_conversion_mode(ADC1);
|
||||||
|
adc_disable_external_trigger_regular(ADC1);
|
||||||
|
adc_set_right_aligned(ADC1);
|
||||||
|
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
|
||||||
|
adc_enable_temperature_sensor();
|
||||||
|
adc_power_on(ADC1);
|
||||||
|
|
||||||
|
/* Wait for ADC starting up. */
|
||||||
|
for (int i = 0; i < 800000; i++) /* Wait a bit. */
|
||||||
|
__asm__("nop");
|
||||||
|
|
||||||
|
adc_reset_calibration(ADC1);
|
||||||
|
adc_calibrate(ADC1);
|
||||||
|
}
|
||||||
|
|
||||||
const char *platform_target_voltage(void)
|
const char *platform_target_voltage(void)
|
||||||
{
|
{
|
||||||
return "unknown";
|
static char ret[] = "0.00V";
|
||||||
|
const uint8_t channel = 0;
|
||||||
|
adc_set_regular_sequence(ADC1, 1, (uint8_t*)&channel);
|
||||||
|
adc_start_conversion_direct(ADC1);
|
||||||
|
/* Wait for end of conversion. */
|
||||||
|
while (!adc_eoc(ADC1));
|
||||||
|
uint32_t platform_adc_value = adc_read_regular(ADC1);
|
||||||
|
|
||||||
|
const uint8_t ref_channel = 17;
|
||||||
|
adc_set_regular_sequence(ADC1, 1, (uint8_t*)&ref_channel);
|
||||||
|
adc_start_conversion_direct(ADC1);
|
||||||
|
/* Wait for end of conversion. */
|
||||||
|
while (!adc_eoc(ADC1));
|
||||||
|
uint32_t vrefint_value = adc_read_regular(ADC1);
|
||||||
|
|
||||||
|
/* Value in mV*/
|
||||||
|
uint32_t val = (platform_adc_value * 2400) / vrefint_value;
|
||||||
|
ret[0] = '0' + val / 1000;
|
||||||
|
ret[2] = '0' + (val / 100) % 10;
|
||||||
|
ret[3] = '0' + (val / 10) % 10;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
#include <libopencm3/cm3/scb.h>
|
#include <libopencm3/cm3/nvic.h>
|
||||||
|
#include <libopencm3/stm32/rcc.h>
|
||||||
|
|
||||||
uint8_t running_status;
|
uint8_t running_status;
|
||||||
static volatile uint32_t time_ms;
|
static volatile uint32_t time_ms;
|
||||||
@ -29,9 +30,10 @@ void platform_timing_init(void)
|
|||||||
{
|
{
|
||||||
/* Setup heartbeat timer */
|
/* Setup heartbeat timer */
|
||||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
|
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
|
||||||
systick_set_reload(900000); /* Interrupt us at 10 Hz */
|
/* Interrupt us at 10 Hz */
|
||||||
SCB_SHPR(11) &= ~((15 << 4) & 0xff);
|
systick_set_reload(rcc_ahb_frequency / (8 * 10) );
|
||||||
SCB_SHPR(11) |= ((14 << 4) & 0xff);
|
/* SYSTICK_IRQ with low priority */
|
||||||
|
nvic_set_priority(NVIC_SYSTICK_IRQ, 14 << 4);
|
||||||
systick_interrupt_enable();
|
systick_interrupt_enable();
|
||||||
systick_counter_enable();
|
systick_counter_enable();
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ static void _respond(char respCode, uint64_t param)
|
|||||||
/* Send response to far end */
|
/* Send response to far end */
|
||||||
|
|
||||||
{
|
{
|
||||||
char buf[34];
|
char buf[35]; /*Response, code, EOM and 2*16 hex nibbles*/
|
||||||
char *p=buf;
|
char *p=buf;
|
||||||
|
|
||||||
gdb_if_putchar(REMOTE_RESP,0);
|
gdb_if_putchar(REMOTE_RESP,0);
|
||||||
@ -185,7 +185,7 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
|
|||||||
jtagtap_tdi_tdo_seq((void *)&DO, (packet[1]==REMOTE_TDITDO_TMS), (void *)&DI, ticks);
|
jtagtap_tdi_tdo_seq((void *)&DO, (packet[1]==REMOTE_TDITDO_TMS), (void *)&DI, ticks);
|
||||||
|
|
||||||
/* Mask extra bits on return value... */
|
/* Mask extra bits on return value... */
|
||||||
DO&=(1<<(ticks+1))-1;
|
DO &= (1LL << (ticks + 1)) - 1;
|
||||||
|
|
||||||
_respond(REMOTE_RESP_OK, DO);
|
_respond(REMOTE_RESP_OK, DO);
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,7 @@ static const struct {
|
|||||||
{0xc09, aa_cortexa, cidc_dc, PIDR_PN_BIT_STRINGS("Cortex-A9 Debug", "(Debug Unit)")},
|
{0xc09, aa_cortexa, cidc_dc, PIDR_PN_BIT_STRINGS("Cortex-A9 Debug", "(Debug Unit)")},
|
||||||
{0xc0f, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 Debug", "(Debug Unit)")}, /* support? */
|
{0xc0f, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 Debug", "(Debug Unit)")}, /* support? */
|
||||||
{0xc14, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-R4 Debug", "(Debug Unit)")}, /* support? */
|
{0xc14, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-R4 Debug", "(Debug Unit)")}, /* support? */
|
||||||
|
{0xcd0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Atmel DSU", "(Device Service Unit)")},
|
||||||
{0xd21, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M33", "()")}, /* support? */
|
{0xd21, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M33", "()")}, /* support? */
|
||||||
{0xfff, aa_end, cidc_unknown, PIDR_PN_BIT_STRINGS("end", "end")}
|
{0xfff, aa_end, cidc_unknown, PIDR_PN_BIT_STRINGS("end", "end")}
|
||||||
};
|
};
|
||||||
@ -252,12 +253,29 @@ static uint32_t adiv5_mem_read32(ADIv5_AP_t *ap, uint32_t addr)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t adiv5_ap_read_id(ADIv5_AP_t *ap, uint32_t addr)
|
||||||
|
{
|
||||||
|
uint32_t res = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
uint32_t x = adiv5_mem_read32(ap, addr + 4 * i);
|
||||||
|
res |= (x & 0xff) << (i * 8);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr)
|
||||||
|
{
|
||||||
|
uint64_t pidr = adiv5_ap_read_id(ap, addr + PIDR4_OFFSET);
|
||||||
|
pidr = pidr << 32 | adiv5_ap_read_id(ap, addr + PIDR0_OFFSET);
|
||||||
|
return pidr;
|
||||||
|
}
|
||||||
|
|
||||||
static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry)
|
static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry)
|
||||||
{
|
{
|
||||||
(void) num_entry;
|
(void) num_entry;
|
||||||
addr &= ~3;
|
addr &= ~3;
|
||||||
uint64_t pidr = 0;
|
uint64_t pidr = adiv5_ap_read_pidr(ap, addr);
|
||||||
uint32_t cidr = 0;
|
uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||||
bool res = false;
|
bool res = false;
|
||||||
#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG)
|
#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG)
|
||||||
char indent[recursion + 1];
|
char indent[recursion + 1];
|
||||||
@ -266,22 +284,6 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
|||||||
indent[recursion] = 0;
|
indent[recursion] = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Assemble logical Product ID register value. */
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
uint32_t x = adiv5_mem_read32(ap, addr + PIDR0_OFFSET + 4*i);
|
|
||||||
pidr |= (x & 0xff) << (i * 8);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
uint32_t x = adiv5_mem_read32(ap, addr + PIDR4_OFFSET);
|
|
||||||
pidr |= (uint64_t)x << 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assemble logical Component ID register value. */
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
uint32_t x = adiv5_mem_read32(ap, addr + CIDR0_OFFSET + 4*i);
|
|
||||||
cidr |= ((uint64_t)(x & 0xff)) << (i * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adiv5_dp_error(ap->dp)) {
|
if (adiv5_dp_error(ap->dp)) {
|
||||||
DEBUG("%sFault reading ID registers\n", indent);
|
DEBUG("%sFault reading ID registers\n", indent);
|
||||||
return false;
|
return false;
|
||||||
@ -376,7 +378,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
|||||||
cortexm_probe(ap, false);
|
cortexm_probe(ap, false);
|
||||||
break;
|
break;
|
||||||
case aa_cortexa:
|
case aa_cortexa:
|
||||||
DEBUG("%s-> cortexa_probe\n", indent + 1);
|
DEBUG("\n -> cortexa_probe\n");
|
||||||
cortexa_probe(ap, addr);
|
cortexa_probe(ap, addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -198,5 +198,5 @@ void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
|
|||||||
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
|
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
|
||||||
void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
|
void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
|
||||||
size_t len, enum align align);
|
size_t len, enum align align);
|
||||||
|
uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2012 Black Sphere Technologies Ltd.
|
* Copyright (C) 2012 Black Sphere Technologies Ltd.
|
||||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* and Koen De Vleeschauwer.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under tSchreibe Objekte: 100% (21/21), 3.20 KiB | 3.20 MiB/s, Fertig.
|
* it under the terms of the GNU General Public License as published by
|
||||||
he terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -1009,11 +1009,14 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Semihosting support */
|
/* Semihosting support */
|
||||||
/* ARM Semihosting syscall numbers, from ARM doc DUI0471C, Chapter 8 */
|
/* ARM Semihosting syscall numbers, from "Semihosting for AArch32 and AArch64 Version 3.0" */
|
||||||
#define SYS_CLOSE 0x02
|
|
||||||
#define SYS_CLOCK 0x10
|
#define SYS_CLOCK 0x10
|
||||||
|
#define SYS_CLOSE 0x02
|
||||||
#define SYS_ELAPSED 0x30
|
#define SYS_ELAPSED 0x30
|
||||||
#define SYS_ERRNO 0x13
|
#define SYS_ERRNO 0x13
|
||||||
|
#define SYS_EXIT 0x18
|
||||||
|
#define SYS_EXIT_EXTENDED 0x20
|
||||||
#define SYS_FLEN 0x0C
|
#define SYS_FLEN 0x0C
|
||||||
#define SYS_GET_CMDLINE 0x15
|
#define SYS_GET_CMDLINE 0x15
|
||||||
#define SYS_HEAPINFO 0x16
|
#define SYS_HEAPINFO 0x16
|
||||||
@ -1033,6 +1036,28 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
|||||||
#define SYS_WRITEC 0x03
|
#define SYS_WRITEC 0x03
|
||||||
#define SYS_WRITE0 0x04
|
#define SYS_WRITE0 0x04
|
||||||
|
|
||||||
|
#if !defined(PC_HOSTED)
|
||||||
|
/* probe memory access functions */
|
||||||
|
static void probe_mem_read(target *t __attribute__((unused)), void *probe_dest, target_addr target_src, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t *dst = (uint8_t *)probe_dest;
|
||||||
|
uint8_t *src = (uint8_t *)target_src;
|
||||||
|
|
||||||
|
DEBUG("probe_mem_read\n");
|
||||||
|
while (len--) *dst++=*src++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void probe_mem_write(target *t __attribute__((unused)), target_addr target_dest, const void *probe_src, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t *dst = (uint8_t *)target_dest;
|
||||||
|
uint8_t *src = (uint8_t *)probe_src;
|
||||||
|
|
||||||
|
DEBUG("probe_mem_write\n");
|
||||||
|
while (len--) *dst++=*src++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
static int cortexm_hostio_request(target *t)
|
static int cortexm_hostio_request(target *t)
|
||||||
{
|
{
|
||||||
uint32_t arm_regs[t->regs_size];
|
uint32_t arm_regs[t->regs_size];
|
||||||
@ -1073,6 +1098,7 @@ static int cortexm_hostio_request(target *t)
|
|||||||
ret++;
|
ret++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* FIXME handle requests for special filename ':semihosting-features' */
|
||||||
|
|
||||||
ret = tc_open(t, params[0], params[2] + 1, pflag, 0644);
|
ret = tc_open(t, params[0], params[2] + 1, pflag, 0644);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
@ -1093,8 +1119,24 @@ static int cortexm_hostio_request(target *t)
|
|||||||
ret = params[2] - ret;
|
ret = params[2] - ret;
|
||||||
break;
|
break;
|
||||||
case SYS_WRITEC: /* writec */
|
case SYS_WRITEC: /* writec */
|
||||||
ret = tc_write(t, 2, arm_regs[1], 1);
|
ret = tc_write(t, STDERR_FILENO, arm_regs[1], 1);
|
||||||
break;
|
break;
|
||||||
|
case SYS_WRITE0:{ /* write0 */
|
||||||
|
ret = -1;
|
||||||
|
target_addr str_begin = arm_regs[1];
|
||||||
|
target_addr str_end = str_begin;
|
||||||
|
while (target_mem_read8(t, str_end) != 0) {
|
||||||
|
if (target_check_error(t)) break;
|
||||||
|
str_end++;
|
||||||
|
}
|
||||||
|
int len = str_end - str_begin;
|
||||||
|
if (len != 0) {
|
||||||
|
int rc = tc_write(t, STDERR_FILENO, str_begin, len);
|
||||||
|
if (rc != len) break;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SYS_ISTTY: /* isatty */
|
case SYS_ISTTY: /* isatty */
|
||||||
ret = tc_isatty(t, params[0] - 1);
|
ret = tc_isatty(t, params[0] - 1);
|
||||||
break;
|
break;
|
||||||
@ -1112,17 +1154,102 @@ static int cortexm_hostio_request(target *t)
|
|||||||
ret = tc_system(t, params[0] - 1, params[1] + 1);
|
ret = tc_system(t, params[0] - 1, params[1] + 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYS_FLEN: /* Not supported, fake success */
|
case SYS_FLEN:
|
||||||
t->tc->errno_ = 0;
|
#if defined(PC_HOSTED)
|
||||||
break;
|
t->tc->errno_ = 0;
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
{ /* file length */
|
||||||
|
ret = -1;
|
||||||
|
uint32_t fio_stat[16]; /* same size as fio_stat in gdb/include/gdb/fileio.h */
|
||||||
|
//DEBUG("SYS_FLEN fio_stat addr %p\n", fio_stat);
|
||||||
|
void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len);
|
||||||
|
void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len);
|
||||||
|
saved_mem_read = t->mem_read;
|
||||||
|
saved_mem_write = t->mem_write;
|
||||||
|
t->mem_read = probe_mem_read;
|
||||||
|
t->mem_write = probe_mem_write;
|
||||||
|
int rc = tc_fstat(t, params[0] - 1, (target_addr)fio_stat); /* write fstat() result in fio_stat[] */
|
||||||
|
t->mem_read = saved_mem_read;
|
||||||
|
t->mem_write = saved_mem_write;
|
||||||
|
if (rc) break; /* tc_fstat() failed */
|
||||||
|
uint32_t fst_size_msw = fio_stat[7]; /* most significant 32 bits of fst_size in fio_stat */
|
||||||
|
uint32_t fst_size_lsw = fio_stat[8]; /* least significant 32 bits of fst_size in fio_stat */
|
||||||
|
if (fst_size_msw != 0) break; /* file size too large for uint32_t return type */
|
||||||
|
ret = __builtin_bswap32(fst_size_lsw); /* convert from bigendian to target order */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SYS_TIME: { /* gettimeofday */
|
||||||
|
ret = -1;
|
||||||
|
uint32_t fio_timeval[3]; /* same size as fio_timeval in gdb/include/gdb/fileio.h */
|
||||||
|
//DEBUG("SYS_TIME fio_timeval addr %p\n", fio_timeval);
|
||||||
|
void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len);
|
||||||
|
void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len);
|
||||||
|
saved_mem_read = t->mem_read;
|
||||||
|
saved_mem_write = t->mem_write;
|
||||||
|
t->mem_read = probe_mem_read;
|
||||||
|
t->mem_write = probe_mem_write;
|
||||||
|
int rc = tc_gettimeofday(t, (target_addr) fio_timeval, (target_addr) NULL); /* write gettimeofday() result in fio_timeval[] */
|
||||||
|
t->mem_read = saved_mem_read;
|
||||||
|
t->mem_write = saved_mem_write;
|
||||||
|
if (rc) break; /* tc_gettimeofday() failed */
|
||||||
|
uint32_t ftv_sec = fio_timeval[0]; /* time in seconds, first field in fio_timeval */
|
||||||
|
ret = __builtin_bswap32(ftv_sec); /* convert from bigendian to target order */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SYS_READC: { /* readc */
|
||||||
|
uint8_t ch;
|
||||||
|
//DEBUG("SYS_READC ch addr %p\n", &ch);
|
||||||
|
void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len);
|
||||||
|
void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len);
|
||||||
|
saved_mem_read = t->mem_read;
|
||||||
|
saved_mem_write = t->mem_write;
|
||||||
|
t->mem_read = probe_mem_read;
|
||||||
|
t->mem_write = probe_mem_write;
|
||||||
|
int rc = tc_read(t, params[0] - 1, (target_addr) &ch, 1); /* read a character in ch */
|
||||||
|
t->mem_read = saved_mem_read;
|
||||||
|
t->mem_write = saved_mem_write;
|
||||||
|
if (rc == 1) ret = ch;
|
||||||
|
else ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case SYS_ERRNO: /* Return last errno from GDB */
|
case SYS_ERRNO: /* Return last errno from GDB */
|
||||||
ret = t->tc->errno_;
|
ret = t->tc->errno_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYS_TIME: /* gettimeofday */
|
case SYS_EXIT: /* _exit() */
|
||||||
/* FIXME How do we use gdb's gettimeofday? */
|
tc_printf(t, "_exit(0x%x)\n", params[0]);
|
||||||
|
target_halt_resume(t, 1);
|
||||||
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SYS_GET_CMDLINE: { /* get_cmdline */
|
||||||
|
uint32_t retval[2];
|
||||||
|
ret = -1;
|
||||||
|
target_addr buf_ptr = params[0];
|
||||||
|
target_addr buf_len = params[1];
|
||||||
|
if (strlen(t->cmdline)+1 > buf_len) break;
|
||||||
|
if(target_mem_write(t, buf_ptr, t->cmdline, strlen(t->cmdline)+1)) break;
|
||||||
|
retval[0] = buf_ptr;
|
||||||
|
retval[1] = strlen(t->cmdline)+1;
|
||||||
|
if(target_mem_write(t, arm_regs[1], retval, sizeof(retval))) break;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not implemented yet:
|
||||||
|
case SYS_HEAPINFO: /* heapinfo */
|
||||||
|
case SYS_CLOCK: /* clock */
|
||||||
|
case SYS_ELAPSED: /* elapsed */
|
||||||
|
case SYS_ISERROR: /* iserror */
|
||||||
|
case SYS_TICKFREQ: /* tickfreq */
|
||||||
|
case SYS_TMPNAM: /* tmpnam */
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arm_regs[0] = ret;
|
arm_regs[0] = ret;
|
||||||
|
@ -100,6 +100,13 @@ bool lmi_probe(target *t)
|
|||||||
lmi_add_flash(t, 0x10000);
|
lmi_add_flash(t, 0x10000);
|
||||||
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case 0x101F: /* TM4C1294NCPDT */
|
||||||
|
t->driver = lmi_driver_str;
|
||||||
|
target_add_ram(t, 0x20000000, 0x40000);
|
||||||
|
lmi_add_flash(t, 0x100000);
|
||||||
|
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,11 @@ lpc11xx_probe(target *t)
|
|||||||
target_add_ram(t, 0x10000000, 0x1000);
|
target_add_ram(t, 0x10000000, 0x1000);
|
||||||
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x1000);
|
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x1000);
|
||||||
return true;
|
return true;
|
||||||
|
case 0x1000002b: // FX LPC11U6 32 kB SRAM/256 kB flash (max)
|
||||||
|
t->driver = "LPC11U6";
|
||||||
|
target_add_ram(t, 0x10000000, 0x8000);
|
||||||
|
lpc11xx_add_flash(t, 0x00000000, 0x40000, 0x1000);
|
||||||
|
return true;
|
||||||
case 0x3000002B:
|
case 0x3000002B:
|
||||||
case 0x3D00002B:
|
case 0x3D00002B:
|
||||||
t->driver = "LPC1343";
|
t->driver = "LPC1343";
|
||||||
|
@ -134,6 +134,7 @@ bool nrf51_probe(target *t)
|
|||||||
uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM);
|
uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM);
|
||||||
t->idcode = info_part;
|
t->idcode = info_part;
|
||||||
t->driver = "Nordic nRF52";
|
t->driver = "Nordic nRF52";
|
||||||
|
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||||
target_add_ram(t, 0x20000000, ram_size * 1024);
|
target_add_ram(t, 0x20000000, ram_size * 1024);
|
||||||
nrf51_add_flash(t, 0, page_size * code_size, page_size);
|
nrf51_add_flash(t, 0, page_size * code_size, page_size);
|
||||||
nrf51_add_flash(t, NRF51_UICR, page_size, page_size);
|
nrf51_add_flash(t, NRF51_UICR, page_size, page_size);
|
||||||
@ -145,6 +146,7 @@ bool nrf51_probe(target *t)
|
|||||||
* IDCODE is kept as '0', as deciphering is hard and
|
* IDCODE is kept as '0', as deciphering is hard and
|
||||||
* there is later no usage.*/
|
* there is later no usage.*/
|
||||||
target_add_ram(t, 0x20000000, 0x8000);
|
target_add_ram(t, 0x20000000, 0x8000);
|
||||||
|
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||||
nrf51_add_flash(t, 0, page_size * code_size, page_size);
|
nrf51_add_flash(t, 0, page_size * code_size, page_size);
|
||||||
nrf51_add_flash(t, NRF51_UICR, page_size, page_size);
|
nrf51_add_flash(t, NRF51_UICR, page_size, page_size);
|
||||||
target_add_commands(t, nrf51_cmd_list, "nRF51");
|
target_add_commands(t, nrf51_cmd_list, "nRF51");
|
||||||
|
@ -113,10 +113,8 @@ const struct command_s samd_cmd_list[] = {
|
|||||||
#define SAMD_DSU_ADDRESS (SAMD_DSU_EXT_ACCESS + 0x4)
|
#define SAMD_DSU_ADDRESS (SAMD_DSU_EXT_ACCESS + 0x4)
|
||||||
#define SAMD_DSU_LENGTH (SAMD_DSU_EXT_ACCESS + 0x8)
|
#define SAMD_DSU_LENGTH (SAMD_DSU_EXT_ACCESS + 0x8)
|
||||||
#define SAMD_DSU_DID (SAMD_DSU_EXT_ACCESS + 0x018)
|
#define SAMD_DSU_DID (SAMD_DSU_EXT_ACCESS + 0x018)
|
||||||
#define SAMD_DSU_PID(n) (SAMD_DSU + 0x1FE0 + \
|
#define SAMD_DSU_PID (SAMD_DSU + 0x1000)
|
||||||
(0x4 * (n % 4)) - (0x10 * (n / 4)))
|
#define SAMD_DSU_CID (SAMD_DSU + 0x1010)
|
||||||
#define SAMD_DSU_CID(n) (SAMD_DSU + 0x1FF0 + \
|
|
||||||
(0x4 * (n % 4)))
|
|
||||||
|
|
||||||
/* Control and Status Register (CTRLSTAT) */
|
/* Control and Status Register (CTRLSTAT) */
|
||||||
#define SAMD_CTRL_CHIP_ERASE (1 << 4)
|
#define SAMD_CTRL_CHIP_ERASE (1 << 4)
|
||||||
@ -221,35 +219,6 @@ static const struct samd_part samd_l22_parts[] = {
|
|||||||
{0xFF, 0, 0, 0}
|
{0xFF, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the SAM D20 Peripheral ID
|
|
||||||
*/
|
|
||||||
uint64_t samd_read_pid(target *t)
|
|
||||||
{
|
|
||||||
uint64_t pid = 0;
|
|
||||||
uint8_t i, j;
|
|
||||||
|
|
||||||
/* Five PID registers to read LSB first */
|
|
||||||
for (i = 0, j = 0; i < 5; i++, j += 8)
|
|
||||||
pid |= (target_mem_read32(t, SAMD_DSU_PID(i)) & 0xFF) << j;
|
|
||||||
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Reads the SAM D20 Component ID
|
|
||||||
*/
|
|
||||||
uint32_t samd_read_cid(target *t)
|
|
||||||
{
|
|
||||||
uint64_t cid = 0;
|
|
||||||
uint8_t i, j;
|
|
||||||
|
|
||||||
/* Four CID registers to read LSB first */
|
|
||||||
for (i = 0, j = 0; i < 4; i++, j += 8)
|
|
||||||
cid |= (target_mem_read32(t, SAMD_DSU_CID(i)) & 0xFF) << j;
|
|
||||||
|
|
||||||
return cid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overloads the default cortexm reset function with a version that
|
* Overloads the default cortexm reset function with a version that
|
||||||
* removes the target from extended reset where required.
|
* removes the target from extended reset where required.
|
||||||
@ -474,8 +443,9 @@ static void samd_add_flash(target *t, uint32_t addr, size_t length)
|
|||||||
char variant_string[60];
|
char variant_string[60];
|
||||||
bool samd_probe(target *t)
|
bool samd_probe(target *t)
|
||||||
{
|
{
|
||||||
uint32_t cid = samd_read_cid(t);
|
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||||
uint32_t pid = samd_read_pid(t);
|
uint32_t cid = adiv5_ap_read_pidr(ap, SAMD_DSU_CID);
|
||||||
|
uint32_t pid = adiv5_ap_read_pidr(ap, SAMD_DSU_PID);
|
||||||
|
|
||||||
/* Check the ARM Coresight Component and Perhiperal IDs */
|
/* Check the ARM Coresight Component and Perhiperal IDs */
|
||||||
if ((cid != SAMD_CID_VALUE) ||
|
if ((cid != SAMD_CID_VALUE) ||
|
||||||
|
@ -169,11 +169,8 @@ const struct command_s samx5x_protected_cmd_list[] = {
|
|||||||
#define SAMX5X_DSU_LENGTH (SAMX5X_DSU_EXT_ACCESS + 0x08)
|
#define SAMX5X_DSU_LENGTH (SAMX5X_DSU_EXT_ACCESS + 0x08)
|
||||||
#define SAMX5X_DSU_DATA (SAMX5X_DSU_EXT_ACCESS + 0x0C)
|
#define SAMX5X_DSU_DATA (SAMX5X_DSU_EXT_ACCESS + 0x0C)
|
||||||
#define SAMX5X_DSU_DID (SAMX5X_DSU_EXT_ACCESS + 0x18)
|
#define SAMX5X_DSU_DID (SAMX5X_DSU_EXT_ACCESS + 0x18)
|
||||||
#define SAMX5X_DSU_PID(n) (SAMX5X_DSU + 0x1FE0 + \
|
#define SAMX5X_DSU_PID (SAMX5X_DSU + 0x1000)
|
||||||
(0x4 * (n % 4)) - \
|
#define SAMX5X_DSU_CID (SAMX5X_DSU + 0x1010)
|
||||||
(0x10 * (n / 4)))
|
|
||||||
#define SAMX5X_DSU_CID(n) (SAMX5X_DSU + 0x1FF0 + \
|
|
||||||
(0x4 * (n % 4)))
|
|
||||||
|
|
||||||
/* Control and Status Register (CTRLSTAT) */
|
/* Control and Status Register (CTRLSTAT) */
|
||||||
#define SAMX5X_CTRL_CHIP_ERASE (1 << 4)
|
#define SAMX5X_CTRL_CHIP_ERASE (1 << 4)
|
||||||
@ -219,23 +216,6 @@ const struct command_s samx5x_protected_cmd_list[] = {
|
|||||||
/* Component ID */
|
/* Component ID */
|
||||||
#define SAMX5X_CID_VALUE 0xB105100D
|
#define SAMX5X_CID_VALUE 0xB105100D
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the SAM D5x/E5x Peripheral ID
|
|
||||||
*
|
|
||||||
* (Reuses the SAM D1x/2x implementation as it is identical)
|
|
||||||
*/
|
|
||||||
extern uint64_t samd_read_pid(target *t);
|
|
||||||
#define samx5x_read_pid samd_read_pid
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the SAM D5x/E5x Component ID
|
|
||||||
*
|
|
||||||
* (Reuses the SAM D1x/2x implementation as it is identical)
|
|
||||||
*/
|
|
||||||
extern uint32_t samd_read_cid(target *t);
|
|
||||||
#define samx5x_read_cid samd_read_cid
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overloads the default cortexm reset function with a version that
|
* Overloads the default cortexm reset function with a version that
|
||||||
* removes the target from extended reset where required.
|
* removes the target from extended reset where required.
|
||||||
@ -367,8 +347,9 @@ static void samx5x_add_flash(target *t, uint32_t addr, size_t length,
|
|||||||
char variant_string[60];
|
char variant_string[60];
|
||||||
bool samx5x_probe(target *t)
|
bool samx5x_probe(target *t)
|
||||||
{
|
{
|
||||||
uint32_t cid = samx5x_read_cid(t);
|
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||||
uint32_t pid = samx5x_read_pid(t);
|
uint32_t cid = adiv5_ap_read_pidr(ap, SAMX5X_DSU_CID);
|
||||||
|
uint32_t pid = adiv5_ap_read_pidr(ap, SAMX5X_DSU_PID);
|
||||||
|
|
||||||
/* Check the ARM Coresight Component and Perhiperal IDs */
|
/* Check the ARM Coresight Component and Perhiperal IDs */
|
||||||
if ((cid != SAMX5X_CID_VALUE) ||
|
if ((cid != SAMX5X_CID_VALUE) ||
|
||||||
|
@ -159,31 +159,31 @@ static void stm32f4_add_flash(target *t,
|
|||||||
char *stm32f4_get_chip_name(uint32_t idcode)
|
char *stm32f4_get_chip_name(uint32_t idcode)
|
||||||
{
|
{
|
||||||
switch(idcode){
|
switch(idcode){
|
||||||
case ID_STM32F40X:
|
case ID_STM32F40X: /* F40XxE/G */
|
||||||
return "STM32F40x";
|
return "STM32F40x";
|
||||||
case ID_STM32F42X: /* 427/437 */
|
case ID_STM32F42X: /* F42XxG/I */
|
||||||
return "STM32F42x";
|
return "STM32F42x";
|
||||||
case ID_STM32F46X: /* 469/479 */
|
case ID_STM32F46X: /* 469/479 xG/I*/
|
||||||
return "STM32F47x";
|
return "STM32F47x";
|
||||||
case ID_STM32F20X: /* F205 */
|
case ID_STM32F20X: /* F205 xB/C/E/G*/
|
||||||
return "STM32F2";
|
return "STM32F2";
|
||||||
case ID_STM32F446: /* F446 */
|
case ID_STM32F446: /* F446 xC/E*/
|
||||||
return "STM32F446";
|
return "STM32F446";
|
||||||
case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */
|
case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */
|
||||||
return "STM32F401C";
|
return "STM32F401C";
|
||||||
case ID_STM32F411: /* F411 RM0383 Rev.4 */
|
case ID_STM32F411: /* F411 xC/E RM0383 Rev.4 */
|
||||||
return "STM32F411";
|
return "STM32F411";
|
||||||
case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */
|
case ID_STM32F412: /* F412 xG/I RM0402 Rev.4, 256 kB Ram */
|
||||||
return "STM32F412";
|
return "STM32F412";
|
||||||
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
||||||
return "STM32F401E";
|
return "STM32F401E";
|
||||||
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
case ID_STM32F413: /* F413xG/H RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
||||||
return "STM32F413";
|
return "STM32F413";
|
||||||
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
|
case ID_STM32F74X: /* F74XxG/I RM0385 Rev.4 */
|
||||||
return "STM32F74x";
|
return "STM32F74x";
|
||||||
case ID_STM32F76X: /* F76x F77x RM0410 */
|
case ID_STM32F76X: /* F76XxE/G F77x RM0410 */
|
||||||
return "STM32F76x";
|
return "STM32F76x";
|
||||||
case ID_STM32F72X: /* F72x F73x RM0431 */
|
case ID_STM32F72X: /* F72/3xC/E RM0431 */
|
||||||
return "STM32F72x";
|
return "STM32F72x";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -245,7 +245,7 @@ static bool stm32f4_attach(target *t)
|
|||||||
bool has_ccmram = false;
|
bool has_ccmram = false;
|
||||||
bool is_f7 = false;
|
bool is_f7 = false;
|
||||||
bool large_sectors = false;
|
bool large_sectors = false;
|
||||||
uint32_t flashsize_base = F4_FLASHSIZE;
|
uint16_t max_flashsize;
|
||||||
|
|
||||||
if (!cortexm_attach(t))
|
if (!cortexm_attach(t))
|
||||||
return false;
|
return false;
|
||||||
@ -253,50 +253,53 @@ static bool stm32f4_attach(target *t)
|
|||||||
switch(t->idcode) {
|
switch(t->idcode) {
|
||||||
case ID_STM32F40X:
|
case ID_STM32F40X:
|
||||||
has_ccmram = true;
|
has_ccmram = true;
|
||||||
|
max_flashsize = 1024;
|
||||||
break;
|
break;
|
||||||
case ID_STM32F42X: /* 427/437 */
|
case ID_STM32F42X: /* 427/437 */
|
||||||
has_ccmram = true;
|
has_ccmram = true;
|
||||||
dual_bank = true;
|
dual_bank = true;
|
||||||
|
max_flashsize = 2048;
|
||||||
break;
|
break;
|
||||||
case ID_STM32F46X: /* 469/479 */
|
case ID_STM32F46X: /* 469/479 */
|
||||||
has_ccmram = true;
|
has_ccmram = true;
|
||||||
dual_bank = true;
|
dual_bank = true;
|
||||||
break;
|
max_flashsize = 512;
|
||||||
case ID_STM32F20X: /* F205 */
|
|
||||||
break;
|
|
||||||
case ID_STM32F446: /* F446 */
|
|
||||||
break;
|
break;
|
||||||
case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */
|
case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */
|
||||||
break;
|
max_flashsize = 256;
|
||||||
case ID_STM32F411: /* F411 RM0383 Rev.4 */
|
|
||||||
break;
|
|
||||||
case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */
|
|
||||||
break;
|
break;
|
||||||
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
||||||
|
case ID_STM32F411: /* F411 RM0383 Rev.4 */
|
||||||
|
case ID_STM32F446: /* F446 */
|
||||||
|
max_flashsize = 512;
|
||||||
|
break;
|
||||||
|
case ID_STM32F20X: /* F205xB/C/E/G */
|
||||||
|
case ID_STM32F412: /* F412xE/G RM0402 Rev.4, 256 kB Ram */
|
||||||
|
max_flashsize = 1024;
|
||||||
break;
|
break;
|
||||||
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
||||||
|
max_flashsize = 1536;
|
||||||
break;
|
break;
|
||||||
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
|
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
|
||||||
is_f7 = true;
|
is_f7 = true;
|
||||||
large_sectors = true;
|
large_sectors = true;
|
||||||
flashsize_base = F7_FLASHSIZE;
|
max_flashsize = 1024;
|
||||||
break;
|
break;
|
||||||
case ID_STM32F76X: /* F76x F77x RM0410 */
|
case ID_STM32F76X: /* F76x F77x RM0410 */
|
||||||
is_f7 = true;
|
is_f7 = true;
|
||||||
dual_bank = true;
|
dual_bank = true;
|
||||||
large_sectors = true;
|
large_sectors = true;
|
||||||
flashsize_base = F7_FLASHSIZE;
|
max_flashsize = 2048;
|
||||||
break;
|
break;
|
||||||
case ID_STM32F72X: /* F72x F73x RM0431 */
|
case ID_STM32F72X: /* F72x F73x RM0431 */
|
||||||
is_f7 = true;
|
is_f7 = true;
|
||||||
flashsize_base = F72X_FLASHSIZE;
|
max_flashsize = 512;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool use_dual_bank = false;
|
bool use_dual_bank = false;
|
||||||
target_mem_map_free(t);
|
target_mem_map_free(t);
|
||||||
uint32_t flashsize = target_mem_read32(t, flashsize_base) & 0xffff;
|
|
||||||
if (is_f7) {
|
if (is_f7) {
|
||||||
t->target_storage = target_mem_read32(t, DBGMCU_CR);
|
t->target_storage = target_mem_read32(t, DBGMCU_CR);
|
||||||
target_mem_write32(t, DBGMCU_CR, DBG_SLEEP);
|
target_mem_write32(t, DBGMCU_CR, DBG_SLEEP);
|
||||||
@ -314,7 +317,7 @@ static bool stm32f4_attach(target *t)
|
|||||||
target_add_ram(t, 0x20000000, 0x50000); /* 320 k RAM */
|
target_add_ram(t, 0x20000000, 0x50000); /* 320 k RAM */
|
||||||
if (dual_bank) {
|
if (dual_bank) {
|
||||||
use_dual_bank = true;
|
use_dual_bank = true;
|
||||||
if (flashsize < 0x800) {
|
if (max_flashsize < 0x800) {
|
||||||
/* Check Dual-bank on 1 Mbyte Flash memory devices*/
|
/* Check Dual-bank on 1 Mbyte Flash memory devices*/
|
||||||
uint32_t optcr;
|
uint32_t optcr;
|
||||||
optcr = target_mem_read32(t, FLASH_OPTCR);
|
optcr = target_mem_read32(t, FLASH_OPTCR);
|
||||||
@ -325,11 +328,11 @@ static bool stm32f4_attach(target *t)
|
|||||||
int split = 0;
|
int split = 0;
|
||||||
uint32_t banksize;
|
uint32_t banksize;
|
||||||
if (use_dual_bank) {
|
if (use_dual_bank) {
|
||||||
banksize = flashsize << 9; /* flash split on two sectors. */
|
banksize = max_flashsize << 9; /* flash split on two sectors. */
|
||||||
split = (flashsize == 0x400) ? 8 : 12;
|
split = (max_flashsize == 0x400) ? 8 : 12;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
banksize = flashsize << 10;
|
banksize = max_flashsize << 10;
|
||||||
if (large_sectors) {
|
if (large_sectors) {
|
||||||
uint32_t remains = banksize - 0x40000;
|
uint32_t remains = banksize - 0x40000;
|
||||||
/* 256 k in small sectors.*/
|
/* 256 k in small sectors.*/
|
||||||
@ -345,11 +348,6 @@ static bool stm32f4_attach(target *t)
|
|||||||
remains = banksize - 0x20000; /* 128 k in small sectors.*/
|
remains = banksize - 0x20000; /* 128 k in small sectors.*/
|
||||||
if (is_f7) {
|
if (is_f7) {
|
||||||
stm32f4_add_flash(t, ITCM_BASE, 0x10000, 0x4000, 0, split);
|
stm32f4_add_flash(t, ITCM_BASE, 0x10000, 0x4000, 0, split);
|
||||||
if (banksize > 0x10000) {
|
|
||||||
/* STM32F730 has only 64 kiB flash! */
|
|
||||||
stm32f4_add_flash(t, 0x0210000, 0x10000, 0x10000, 4, split);
|
|
||||||
stm32f4_add_flash(t, 0x0220000, remains, 0x20000, 5, split);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0, split);
|
stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0, split);
|
||||||
if (banksize > 0x10000) {
|
if (banksize > 0x10000) {
|
||||||
|
@ -213,14 +213,8 @@ static bool stm32h7_attach(target *t)
|
|||||||
target_add_ram(t, 0x38000000, 0x01000); /* AHB SRAM4, 32 k */
|
target_add_ram(t, 0x38000000, 0x01000); /* AHB SRAM4, 32 k */
|
||||||
|
|
||||||
/* Add the flash to memory map. */
|
/* Add the flash to memory map. */
|
||||||
uint32_t flashsize = target_mem_read32(t, FLASH_SIZE_REG);
|
stm32h7_add_flash(t, 0x8000000, 0x100000, FLASH_SECTOR_SIZE);
|
||||||
flashsize &= 0xffff;
|
stm32h7_add_flash(t, 0x8100000, 0x100000, FLASH_SECTOR_SIZE);
|
||||||
if (flashsize == 128) { /* H750 has only 128 kByte!*/
|
|
||||||
stm32h7_add_flash(t, 0x8000000, FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE);
|
|
||||||
} else {
|
|
||||||
stm32h7_add_flash(t, 0x8000000, 0x100000, FLASH_SECTOR_SIZE);
|
|
||||||
stm32h7_add_flash(t, 0x8100000, 0x100000, FLASH_SECTOR_SIZE);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,6 +401,15 @@ enum target_halt_reason target_halt_poll(target *t, target_addr *watch)
|
|||||||
|
|
||||||
void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); }
|
void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); }
|
||||||
|
|
||||||
|
/* Command line for semihosting get_cmdline */
|
||||||
|
void target_set_cmdline(target *t, char *cmdline) {
|
||||||
|
uint32_t len_dst;
|
||||||
|
len_dst = sizeof(t->cmdline)-1;
|
||||||
|
strncpy(t->cmdline, cmdline, len_dst -1);
|
||||||
|
t->cmdline[strlen(t->cmdline)]='\0';
|
||||||
|
DEBUG("cmdline: >%s<\n", t->cmdline);
|
||||||
|
}
|
||||||
|
|
||||||
/* Break-/watchpoint functions */
|
/* Break-/watchpoint functions */
|
||||||
int target_breakwatch_set(target *t,
|
int target_breakwatch_set(target *t,
|
||||||
enum target_breakwatch type, target_addr addr, size_t len)
|
enum target_breakwatch type, target_addr addr, size_t len)
|
||||||
|
@ -72,6 +72,8 @@ struct breakwatch {
|
|||||||
uint32_t reserved[4]; /* for use by the implementing driver */
|
uint32_t reserved[4]; /* for use by the implementing driver */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_CMDLINE 81
|
||||||
|
|
||||||
struct target_s {
|
struct target_s {
|
||||||
bool attached;
|
bool attached;
|
||||||
struct target_controller *tc;
|
struct target_controller *tc;
|
||||||
@ -118,6 +120,7 @@ struct target_s {
|
|||||||
/* Other stuff */
|
/* Other stuff */
|
||||||
const char *driver;
|
const char *driver;
|
||||||
const char *core;
|
const char *core;
|
||||||
|
char cmdline[MAX_CMDLINE];
|
||||||
struct target_command_s *commands;
|
struct target_command_s *commands;
|
||||||
|
|
||||||
struct target_s *next;
|
struct target_s *next;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user