diff --git a/scripts/swolisten.c b/scripts/swolisten.c index 1ce141aa..f7408fd7 100644 --- a/scripts/swolisten.c +++ b/scripts/swolisten.c @@ -442,7 +442,10 @@ int usbFeeder(void) { unsigned char *c=cbw; if (options.dump) - printf(cbw); + { + cbw[size] = 0; + printf("%s", (char*)cbw); + } else while (size--) _protocolPump(c++); diff --git a/src/gdb_main.c b/src/gdb_main.c index af1edf92..c0575a6d 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -25,6 +25,7 @@ */ #include "general.h" +#include "ctype.h" #include "hex_utils.h" #include "gdb_if.h" #include "gdb_packet.h" @@ -429,9 +430,37 @@ handle_v_packet(char *packet, int plen) else 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. */ if(cur_target) { + target_set_cmdline(cur_target, cmdline); target_reset(cur_target); gdb_putpacketz("T05"); } 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 (cur_target) { + target_set_cmdline(cur_target, cmdline); target_reset(cur_target); gdb_putpacketz("T05"); } else gdb_putpacketz("E01"); diff --git a/src/include/target.h b/src/include/target.h index d052ab15..35102505 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -80,6 +80,7 @@ void target_reset(target *t); void target_halt_request(target *t); enum target_halt_reason target_halt_poll(target *t, target_addr *watch); void target_halt_resume(target *t, bool step); +void target_set_cmdline(target *t, char *cmdline); /* Break-/watchpoint functions */ enum target_breakwatch { diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index d45adb89..2ba76bfd 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -188,7 +188,7 @@ static const struct usb_endpoint_descriptor uart_data_endp[] = {{ .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0x03, .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, + .wMaxPacketSize = CDCACM_PACKET_SIZE / 2, .bInterval = 1, }, { .bLength = USB_DT_ENDPOINT_SIZE, diff --git a/src/platforms/libftdi/Makefile.inc b/src/platforms/libftdi/Makefile.inc index 9686050a..12c46966 100644 --- a/src/platforms/libftdi/Makefile.inc +++ b/src/platforms/libftdi/Makefile.inc @@ -8,5 +8,5 @@ else ifneq (, $(findstring cygwin, $(SYS))) LDFLAGS += -lusb-1.0 -lws2_32 endif VPATH += platforms/pc -SRC += timing.c cl_utils.c +SRC += timing.c cl_utils.c utils.c CFLAGS +=-I ./target -I./platforms/pc diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index 643304c9..8fad4ccd 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -290,34 +290,7 @@ int platform_buffer_read(uint8_t *data, int 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) { 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); -} - diff --git a/src/platforms/pc-hosted/Makefile.inc b/src/platforms/pc-hosted/Makefile.inc index 8a35408a..9493b0cf 100644 --- a/src/platforms/pc-hosted/Makefile.inc +++ b/src/platforms/pc-hosted/Makefile.inc @@ -1,14 +1,15 @@ TARGET=blackmagic_hosted SYS = $(shell $(CC) -dumpmachine) -CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG -I -CFLAGS += $(shell pkg-config --cflags libftdi1) +CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG CFLAGS +=-I ./target -I./platforms/pc -LDFLAGS += $(shell pkg-config --libs libftdi1) ifneq (, $(findstring mingw, $(SYS))) -LDFLAGS += -lusb-1.0 -lws2_32 -CFLAGS += -Wno-cast-function-type +SRC += serial_win.c +LDFLAGS += -lws2_32 else ifneq (, $(findstring cygwin, $(SYS))) -LDFLAGS += -lusb-1.0 -lws2_32 +SRC += serial_win.c +LDFLAGS += -lws2_32 +else +SRC += serial_unix.c endif VPATH += platforms/pc -SRC += cl_utils.c timing.c +SRC += cl_utils.c timing.c utils.c diff --git a/src/platforms/pc-hosted/jtagtap.c b/src/platforms/pc-hosted/jtagtap.c index cce1c71f..86e068d2 100644 --- a/src/platforms/pc-hosted/jtagtap.c +++ b/src/platforms/pc-hosted/jtagtap.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; /* 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); 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) { - for (unsigned int i = 1; i*8 <= (unsigned int)ticks; i++) - DO[i - 1] = remotehston(2 , (char *)&construct[s - (i * 2)]); + uint64_t DOl = remotehston(-1, (char *)&construct[1]); + *(uint64_t *)DO = DOl; } } diff --git a/src/platforms/pc-hosted/platform.c b/src/platforms/pc-hosted/platform.c index d543cfb7..361574d5 100644 --- a/src/platforms/pc-hosted/platform.c +++ b/src/platforms/pc-hosted/platform.c @@ -25,77 +25,16 @@ #include "remote.h" #include -#include #include -#include #include -#include -#include #include -#include #include -#include -#include #include "cl_utils.h" - -/* 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; -} - +static BMP_CL_OPTIONS_t cl_opts; /* Portable way to nullify the struct*/ void platform_init(int argc, char **argv) { - BMP_CL_OPTIONS_t cl_opts = {0}; cl_opts.opt_idstring = "Blackmagic Debug Probe Remote"; cl_init(&cl_opts, argc, argv); 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 " "\n\n"); - f=open(cl_opts.opt_serial,O_RDWR|O_SYNC|O_NOCTTY); - if (f<0) - { - 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); - } - + if (serial_open(&cl_opts)) + exit(-1); int c=snprintf(construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_START_STR); platform_buffer_write((uint8_t *)construct,c); 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); if (cl_opts.opt_tpwr) platform_target_set_power(0); - close(f); + serial_close(); exit(ret); } else { 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 #else # include #endif @@ -52,6 +53,9 @@ struct mmap_data { int fd; #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) { @@ -115,6 +119,7 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt) printf("Usage: %s [options]\n", argv[0]); printf("\t-h\t\t: This help.\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) " "serial number \"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_flash_start = 0x08000000; 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) { case 'c': if (optarg) @@ -155,7 +160,9 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) break; case 'v': if (optarg) - opt->opt_debuglevel = strtol(optarg, NULL, 0); + cl_debuglevel = strtol(optarg, NULL, 0); + else + cl_debuglevel = -1; break; case 'j': opt->opt_usejtag = true; @@ -166,6 +173,10 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) case 'n': opt->opt_no_wait = true; break; + case 'd': + if (optarg) + opt->opt_device = optarg; + break; case 's': if (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); if (opt->opt_mode == BMP_MODE_TEST) printf("Running in Test Mode\n"); + printf("Target voltage: %s Volt\n", platform_target_voltage()); if (opt->opt_usejtag) { num_targets = jtag_scan(NULL); } else { @@ -276,7 +288,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) goto target_detach; } int read_file = -1; - struct mmap_data map = {0}; if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) || (opt->opt_mode == BMP_MODE_FLASH_VERIFY)) { int mmap_res = bmp_mmap(opt->opt_flash_file, &map); diff --git a/src/platforms/pc/cl_utils.h b/src/platforms/pc/cl_utils.h index 850112b5..6e89656d 100644 --- a/src/platforms/pc/cl_utils.h +++ b/src/platforms/pc/cl_utils.h @@ -41,6 +41,7 @@ typedef struct BMP_CL_OPTIONS_s { bool opt_tpwr; bool opt_connect_under_reset; char *opt_flash_file; + char *opt_device; char *opt_serial; char *opt_cable; 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); int cl_execute(BMP_CL_OPTIONS_t *opt); +int serial_open(BMP_CL_OPTIONS_t *opt); +void serial_close(void); #endif diff --git a/src/platforms/pc/serial_unix.c b/src/platforms/pc/serial_unix.c new file mode 100644 index 00000000..cc186578 --- /dev/null +++ b/src/platforms/pc/serial_unix.c @@ -0,0 +1,214 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2019 Dave Marples + * 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 . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/platforms/pc/serial_win.c b/src/platforms/pc/serial_win.c new file mode 100644 index 00000000..a39d1a1a --- /dev/null +++ b/src/platforms/pc/serial_win.c @@ -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 . + */ + +#include +#include "general.h" +#include +#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; +} diff --git a/src/platforms/pc/utils.c b/src/platforms/pc/utils.c new file mode 100644 index 00000000..b74c8ae3 --- /dev/null +++ b/src/platforms/pc/utils.c @@ -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 + * 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 . + */ + +/* This file deduplicates codes used in several pc-hosted platforms + */ + +#include +#include +#include + +#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); +} diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index df976cf5..64216e90 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -39,6 +39,7 @@ uint8_t running_status; uint16_t led_idle_run; uint16_t srst_pin; static uint32_t rev; +static void adc_init(void); int platform_hwversion(void) { @@ -85,6 +86,7 @@ void platform_init(void) /* Don't enable UART if we're being debugged. */ if (!(SCS_DEMCR & SCS_DEMCR_TRCENA)) usbuart_init(); + adc_init(); } void platform_srst_set_val(bool assert) @@ -105,7 +107,52 @@ bool platform_srst_get_val() 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) { - 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; } diff --git a/src/platforms/stm32/timing_stm32.c b/src/platforms/stm32/timing_stm32.c index 234f039e..ca10de3f 100644 --- a/src/platforms/stm32/timing_stm32.c +++ b/src/platforms/stm32/timing_stm32.c @@ -20,7 +20,8 @@ #include "morse.h" #include -#include +#include +#include uint8_t running_status; static volatile uint32_t time_ms; @@ -29,9 +30,10 @@ void platform_timing_init(void) { /* Setup heartbeat timer */ systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); - systick_set_reload(900000); /* Interrupt us at 10 Hz */ - SCB_SHPR(11) &= ~((15 << 4) & 0xff); - SCB_SHPR(11) |= ((14 << 4) & 0xff); + /* Interrupt us at 10 Hz */ + systick_set_reload(rcc_ahb_frequency / (8 * 10) ); + /* SYSTICK_IRQ with low priority */ + nvic_set_priority(NVIC_SYSTICK_IRQ, 14 << 4); systick_interrupt_enable(); systick_counter_enable(); } diff --git a/src/remote.c b/src/remote.c index d54f0e22..dc44ff7d 100644 --- a/src/remote.c +++ b/src/remote.c @@ -61,7 +61,7 @@ static void _respond(char respCode, uint64_t param) /* Send response to far end */ { - char buf[34]; + char buf[35]; /*Response, code, EOM and 2*16 hex nibbles*/ char *p=buf; 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); /* Mask extra bits on return value... */ - DO&=(1<<(ticks+1))-1; + DO &= (1LL << (ticks + 1)) - 1; _respond(REMOTE_RESP_OK, DO); } diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 38f38e4e..7cccffa6 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -210,6 +210,7 @@ static const struct { {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? */ {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? */ {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; } +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) { (void) num_entry; addr &= ~3; - uint64_t pidr = 0; - uint32_t cidr = 0; + uint64_t pidr = adiv5_ap_read_pidr(ap, addr); + uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); bool res = false; #if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG) 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; #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)) { DEBUG("%sFault reading ID registers\n", indent); return false; @@ -376,7 +378,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, cortexm_probe(ap, false); break; case aa_cortexa: - DEBUG("%s-> cortexa_probe\n", indent + 1); + DEBUG("\n -> cortexa_probe\n"); cortexa_probe(ap, addr); break; default: diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 65f47197..60d89333 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -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_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len, enum align align); - +uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr); #endif diff --git a/src/target/cortexm.c b/src/target/cortexm.c index b81b4d1d..70e38d06 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -3,10 +3,10 @@ * * Copyright (C) 2012 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * and Koen De Vleeschauwer. * * 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. -he terms of the GNU General Public License as published by + * 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. * @@ -1009,11 +1009,14 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) #endif /* Semihosting support */ -/* ARM Semihosting syscall numbers, from ARM doc DUI0471C, Chapter 8 */ -#define SYS_CLOSE 0x02 +/* ARM Semihosting syscall numbers, from "Semihosting for AArch32 and AArch64 Version 3.0" */ + #define SYS_CLOCK 0x10 +#define SYS_CLOSE 0x02 #define SYS_ELAPSED 0x30 #define SYS_ERRNO 0x13 +#define SYS_EXIT 0x18 +#define SYS_EXIT_EXTENDED 0x20 #define SYS_FLEN 0x0C #define SYS_GET_CMDLINE 0x15 #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_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) { uint32_t arm_regs[t->regs_size]; @@ -1073,6 +1098,7 @@ static int cortexm_hostio_request(target *t) ret++; break; } + /* FIXME handle requests for special filename ':semihosting-features' */ ret = tc_open(t, params[0], params[2] + 1, pflag, 0644); if (ret != -1) @@ -1093,8 +1119,24 @@ static int cortexm_hostio_request(target *t) ret = params[2] - ret; break; case SYS_WRITEC: /* writec */ - ret = tc_write(t, 2, arm_regs[1], 1); + ret = tc_write(t, STDERR_FILENO, arm_regs[1], 1); 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 */ ret = tc_isatty(t, params[0] - 1); break; @@ -1112,17 +1154,102 @@ static int cortexm_hostio_request(target *t) ret = tc_system(t, params[0] - 1, params[1] + 1); break; - case SYS_FLEN: /* Not supported, fake success */ - t->tc->errno_ = 0; - break; + case SYS_FLEN: +#if defined(PC_HOSTED) + 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 */ ret = t->tc->errno_; break; - case SYS_TIME: /* gettimeofday */ - /* FIXME How do we use gdb's gettimeofday? */ + case SYS_EXIT: /* _exit() */ + tc_printf(t, "_exit(0x%x)\n", params[0]); + target_halt_resume(t, 1); + ret = 0; 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; diff --git a/src/target/lmi.c b/src/target/lmi.c index 14ae3495..fcb8a4f1 100644 --- a/src/target/lmi.c +++ b/src/target/lmi.c @@ -100,6 +100,13 @@ bool lmi_probe(target *t) lmi_add_flash(t, 0x10000); t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; 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; } diff --git a/src/target/lpc11xx.c b/src/target/lpc11xx.c index 43e6cd24..f93130ef 100644 --- a/src/target/lpc11xx.c +++ b/src/target/lpc11xx.c @@ -118,6 +118,11 @@ lpc11xx_probe(target *t) target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x1000); 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 0x3D00002B: t->driver = "LPC1343"; diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 41f3ffb2..aaaac10f 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -134,6 +134,7 @@ bool nrf51_probe(target *t) uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM); t->idcode = info_part; t->driver = "Nordic nRF52"; + t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; target_add_ram(t, 0x20000000, ram_size * 1024); nrf51_add_flash(t, 0, page_size * code_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 * there is later no usage.*/ 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, NRF51_UICR, page_size, page_size); target_add_commands(t, nrf51_cmd_list, "nRF51"); diff --git a/src/target/samd.c b/src/target/samd.c index 2a5c7e03..18da3bc4 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -113,10 +113,8 @@ const struct command_s samd_cmd_list[] = { #define SAMD_DSU_ADDRESS (SAMD_DSU_EXT_ACCESS + 0x4) #define SAMD_DSU_LENGTH (SAMD_DSU_EXT_ACCESS + 0x8) #define SAMD_DSU_DID (SAMD_DSU_EXT_ACCESS + 0x018) -#define SAMD_DSU_PID(n) (SAMD_DSU + 0x1FE0 + \ - (0x4 * (n % 4)) - (0x10 * (n / 4))) -#define SAMD_DSU_CID(n) (SAMD_DSU + 0x1FF0 + \ - (0x4 * (n % 4))) +#define SAMD_DSU_PID (SAMD_DSU + 0x1000) +#define SAMD_DSU_CID (SAMD_DSU + 0x1010) /* Control and Status Register (CTRLSTAT) */ #define SAMD_CTRL_CHIP_ERASE (1 << 4) @@ -221,35 +219,6 @@ static const struct samd_part samd_l22_parts[] = { {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 * 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]; bool samd_probe(target *t) { - uint32_t cid = samd_read_cid(t); - uint32_t pid = samd_read_pid(t); + ADIv5_AP_t *ap = cortexm_ap(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 */ if ((cid != SAMD_CID_VALUE) || diff --git a/src/target/samx5x.c b/src/target/samx5x.c index e23912c3..f8067bc3 100644 --- a/src/target/samx5x.c +++ b/src/target/samx5x.c @@ -169,11 +169,8 @@ const struct command_s samx5x_protected_cmd_list[] = { #define SAMX5X_DSU_LENGTH (SAMX5X_DSU_EXT_ACCESS + 0x08) #define SAMX5X_DSU_DATA (SAMX5X_DSU_EXT_ACCESS + 0x0C) #define SAMX5X_DSU_DID (SAMX5X_DSU_EXT_ACCESS + 0x18) -#define SAMX5X_DSU_PID(n) (SAMX5X_DSU + 0x1FE0 + \ - (0x4 * (n % 4)) - \ - (0x10 * (n / 4))) -#define SAMX5X_DSU_CID(n) (SAMX5X_DSU + 0x1FF0 + \ - (0x4 * (n % 4))) +#define SAMX5X_DSU_PID (SAMX5X_DSU + 0x1000) +#define SAMX5X_DSU_CID (SAMX5X_DSU + 0x1010) /* Control and Status Register (CTRLSTAT) */ #define SAMX5X_CTRL_CHIP_ERASE (1 << 4) @@ -219,23 +216,6 @@ const struct command_s samx5x_protected_cmd_list[] = { /* Component ID */ #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 * 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]; bool samx5x_probe(target *t) { - uint32_t cid = samx5x_read_cid(t); - uint32_t pid = samx5x_read_pid(t); + ADIv5_AP_t *ap = cortexm_ap(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 */ if ((cid != SAMX5X_CID_VALUE) || diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 68b37cdc..ff432682 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -159,31 +159,31 @@ static void stm32f4_add_flash(target *t, char *stm32f4_get_chip_name(uint32_t idcode) { switch(idcode){ - case ID_STM32F40X: + case ID_STM32F40X: /* F40XxE/G */ return "STM32F40x"; - case ID_STM32F42X: /* 427/437 */ + case ID_STM32F42X: /* F42XxG/I */ return "STM32F42x"; - case ID_STM32F46X: /* 469/479 */ + case ID_STM32F46X: /* 469/479 xG/I*/ return "STM32F47x"; - case ID_STM32F20X: /* F205 */ + case ID_STM32F20X: /* F205 xB/C/E/G*/ return "STM32F2"; - case ID_STM32F446: /* F446 */ + case ID_STM32F446: /* F446 xC/E*/ return "STM32F446"; case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */ return "STM32F401C"; - case ID_STM32F411: /* F411 RM0383 Rev.4 */ + case ID_STM32F411: /* F411 xC/E RM0383 Rev.4 */ 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"; case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */ 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"; - case ID_STM32F74X: /* F74x RM0385 Rev.4 */ + case ID_STM32F74X: /* F74XxG/I RM0385 Rev.4 */ return "STM32F74x"; - case ID_STM32F76X: /* F76x F77x RM0410 */ + case ID_STM32F76X: /* F76XxE/G F77x RM0410 */ return "STM32F76x"; - case ID_STM32F72X: /* F72x F73x RM0431 */ + case ID_STM32F72X: /* F72/3xC/E RM0431 */ return "STM32F72x"; default: return NULL; @@ -245,7 +245,7 @@ static bool stm32f4_attach(target *t) bool has_ccmram = false; bool is_f7 = false; bool large_sectors = false; - uint32_t flashsize_base = F4_FLASHSIZE; + uint16_t max_flashsize; if (!cortexm_attach(t)) return false; @@ -253,50 +253,53 @@ static bool stm32f4_attach(target *t) switch(t->idcode) { case ID_STM32F40X: has_ccmram = true; + max_flashsize = 1024; break; case ID_STM32F42X: /* 427/437 */ has_ccmram = true; dual_bank = true; + max_flashsize = 2048; break; case ID_STM32F46X: /* 469/479 */ has_ccmram = true; dual_bank = true; - break; - case ID_STM32F20X: /* F205 */ - break; - case ID_STM32F446: /* F446 */ + max_flashsize = 512; break; case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */ - break; - case ID_STM32F411: /* F411 RM0383 Rev.4 */ - break; - case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */ + max_flashsize = 256; break; 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; case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ + max_flashsize = 1536; break; case ID_STM32F74X: /* F74x RM0385 Rev.4 */ is_f7 = true; large_sectors = true; - flashsize_base = F7_FLASHSIZE; + max_flashsize = 1024; break; case ID_STM32F76X: /* F76x F77x RM0410 */ is_f7 = true; dual_bank = true; large_sectors = true; - flashsize_base = F7_FLASHSIZE; + max_flashsize = 2048; break; case ID_STM32F72X: /* F72x F73x RM0431 */ is_f7 = true; - flashsize_base = F72X_FLASHSIZE; + max_flashsize = 512; break; default: return false; } bool use_dual_bank = false; target_mem_map_free(t); - uint32_t flashsize = target_mem_read32(t, flashsize_base) & 0xffff; if (is_f7) { t->target_storage = target_mem_read32(t, DBGMCU_CR); 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 */ if (dual_bank) { use_dual_bank = true; - if (flashsize < 0x800) { + if (max_flashsize < 0x800) { /* Check Dual-bank on 1 Mbyte Flash memory devices*/ uint32_t optcr; optcr = target_mem_read32(t, FLASH_OPTCR); @@ -325,11 +328,11 @@ static bool stm32f4_attach(target *t) int split = 0; uint32_t banksize; if (use_dual_bank) { - banksize = flashsize << 9; /* flash split on two sectors. */ - split = (flashsize == 0x400) ? 8 : 12; + banksize = max_flashsize << 9; /* flash split on two sectors. */ + split = (max_flashsize == 0x400) ? 8 : 12; } else - banksize = flashsize << 10; + banksize = max_flashsize << 10; if (large_sectors) { uint32_t remains = banksize - 0x40000; /* 256 k in small sectors.*/ @@ -345,11 +348,6 @@ static bool stm32f4_attach(target *t) remains = banksize - 0x20000; /* 128 k in small sectors.*/ if (is_f7) { 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); if (banksize > 0x10000) { diff --git a/src/target/stm32h7.c b/src/target/stm32h7.c index f9e0ac1f..cc617934 100644 --- a/src/target/stm32h7.c +++ b/src/target/stm32h7.c @@ -213,14 +213,8 @@ static bool stm32h7_attach(target *t) target_add_ram(t, 0x38000000, 0x01000); /* AHB SRAM4, 32 k */ /* Add the flash to memory map. */ - uint32_t flashsize = target_mem_read32(t, FLASH_SIZE_REG); - flashsize &= 0xffff; - 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); - } + stm32h7_add_flash(t, 0x8000000, 0x100000, FLASH_SECTOR_SIZE); + stm32h7_add_flash(t, 0x8100000, 0x100000, FLASH_SECTOR_SIZE); return true; } diff --git a/src/target/target.c b/src/target/target.c index 56e54b0f..5c0ca574 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -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); } +/* 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 */ int target_breakwatch_set(target *t, enum target_breakwatch type, target_addr addr, size_t len) diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 15a47293..7be19ed2 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -72,6 +72,8 @@ struct breakwatch { uint32_t reserved[4]; /* for use by the implementing driver */ }; +#define MAX_CMDLINE 81 + struct target_s { bool attached; struct target_controller *tc; @@ -118,6 +120,7 @@ struct target_s { /* Other stuff */ const char *driver; const char *core; + char cmdline[MAX_CMDLINE]; struct target_command_s *commands; struct target_s *next;