Addition of pc-hosted variant and extensions to other targets to support it.
This commit is contained in:
parent
8a1d8bfba3
commit
90df8172ca
4
Makefile
4
Makefile
|
@ -13,6 +13,10 @@ ifeq ($(PROBE_HOST), pc-stlinkv2)
|
||||||
PC_HOSTED = true
|
PC_HOSTED = true
|
||||||
NO_LIBOPENCM3 = true
|
NO_LIBOPENCM3 = true
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(PROBE_HOST), pc-hosted)
|
||||||
|
PC_HOSTED = true
|
||||||
|
NO_LIBOPENCM3 = true
|
||||||
|
endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
ifndef NO_LIBOPENCM3
|
ifndef NO_LIBOPENCM3
|
||||||
|
|
|
@ -46,7 +46,7 @@ SRC = \
|
||||||
nxpke04.c \
|
nxpke04.c \
|
||||||
platform.c \
|
platform.c \
|
||||||
sam3x.c \
|
sam3x.c \
|
||||||
sam4l.c \
|
sam4l.c \
|
||||||
samd.c \
|
samd.c \
|
||||||
stm32f1.c \
|
stm32f1.c \
|
||||||
stm32f4.c \
|
stm32f4.c \
|
||||||
|
@ -71,6 +71,9 @@ endif
|
||||||
|
|
||||||
ifndef OWN_HL
|
ifndef OWN_HL
|
||||||
SRC += jtag_scan.c jtagtap.c swdptap.c
|
SRC += jtag_scan.c jtagtap.c swdptap.c
|
||||||
|
SRC += remote.c
|
||||||
|
else
|
||||||
|
CFLAGS += -DOWN_HL
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJ = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC)))
|
OBJ = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC)))
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "gdb_if.h"
|
#include "gdb_if.h"
|
||||||
#include "gdb_packet.h"
|
#include "gdb_packet.h"
|
||||||
#include "hex_utils.h"
|
#include "hex_utils.h"
|
||||||
|
#include "remote.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -37,9 +38,52 @@ int gdb_getpacket(char *packet, int size)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
/* Wait for packet start */
|
/* Wait for packet start */
|
||||||
while((packet[0] = gdb_if_getchar()) != '$')
|
do {
|
||||||
if(packet[0] == 0x04) return 1;
|
/* Spin waiting for a start of packet character - either a gdb
|
||||||
|
* start ('$') or a BMP remote packet start ('!').
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
packet[0] = gdb_if_getchar();
|
||||||
|
if (packet[0]==0x04) return 1;
|
||||||
|
} while ((packet[0] != '$') && (packet[0] != REMOTE_SOM));
|
||||||
|
#ifndef OWN_HL
|
||||||
|
if (packet[0]==REMOTE_SOM) {
|
||||||
|
/* This is probably a remote control packet
|
||||||
|
* - get and handle it */
|
||||||
|
i=0;
|
||||||
|
bool gettingRemotePacket=true;
|
||||||
|
while (gettingRemotePacket) {
|
||||||
|
c=gdb_if_getchar();
|
||||||
|
switch (c) {
|
||||||
|
case REMOTE_SOM: /* Oh dear, packet restarts */
|
||||||
|
i=0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_EOM: /* Complete packet for processing */
|
||||||
|
packet[i]=0;
|
||||||
|
remotePacketProcess(i,packet);
|
||||||
|
gettingRemotePacket=false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '$': /* A 'real' gdb packet, best stop squatting now */
|
||||||
|
packet[0]='$';
|
||||||
|
gettingRemotePacket=false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (i<size) {
|
||||||
|
packet[i++]=c;
|
||||||
|
} else {
|
||||||
|
/* Who knows what is going on...return to normality */
|
||||||
|
gettingRemotePacket=false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} while (packet[0] != '$');
|
||||||
|
|
||||||
i = 0; csum = 0;
|
i = 0; csum = 0;
|
||||||
/* Capture packet data into buffer */
|
/* Capture packet data into buffer */
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
TARGET=blackmagic_hosted
|
||||||
|
SYS = $(shell $(CC) -dumpmachine)
|
||||||
|
CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG
|
||||||
|
LDFLAGS += -lftdi1
|
||||||
|
ifneq (, $(findstring mingw, $(SYS)))
|
||||||
|
LDFLAGS += -lusb-1.0 -lws2_32
|
||||||
|
CFLAGS += -Wno-cast-function-type
|
||||||
|
else ifneq (, $(findstring cygwin, $(SYS)))
|
||||||
|
LDFLAGS += -lusb-1.0 -lws2_32
|
||||||
|
endif
|
||||||
|
VPATH += platforms/pc
|
||||||
|
SRC += timing.c \
|
|
@ -0,0 +1,40 @@
|
||||||
|
PC Hosted variant
|
||||||
|
|
||||||
|
THIS IS INCOMPLETE - ONLY SUPPORTS SWD AT THE MOMENT
|
||||||
|
|
||||||
|
This variant will use any BMP probe with recent firmware as a remote
|
||||||
|
actuator, with the actual probe code running on the PC. The BMP itself
|
||||||
|
is 'dumb' and doesn't do anything (although any secondary serial port
|
||||||
|
remains available).
|
||||||
|
|
||||||
|
To use it, compile for the pc-hosted target and then connect to your normal
|
||||||
|
BMP GDB port;
|
||||||
|
|
||||||
|
src/blackmagic -s /dev/ttyACM0
|
||||||
|
|
||||||
|
...you can then connect your gdb session to localhost:2000 for all your
|
||||||
|
debugging goodness;
|
||||||
|
|
||||||
|
$arm-eabi-none-gdb
|
||||||
|
(gdb) monitor swdp_scan
|
||||||
|
Target voltage: not supported
|
||||||
|
Available Targets:
|
||||||
|
No. Att Driver
|
||||||
|
1 STM32F1 medium density M3/M4
|
||||||
|
(gdb) attach 1
|
||||||
|
Attaching to program: Builds/blackmagic/src/blackmagic, Remote target
|
||||||
|
0x08001978 in ?? ()
|
||||||
|
(gdb) file src/blackmagic
|
||||||
|
A program is being debugged already.
|
||||||
|
Are you sure you want to change the file? (y or n) y
|
||||||
|
Load new symbol table from "src/blackmagic"? (y or n) y
|
||||||
|
Reading symbols from src/blackmagic...
|
||||||
|
(gdb) load
|
||||||
|
Loading section .text, size 0x1201c lma 0x8002000
|
||||||
|
Loading section .data, size 0xd8 lma 0x801401c
|
||||||
|
Start address 0x800d9fc, load size 73972
|
||||||
|
Transfer rate: 2 KB/sec, 960 bytes/write.
|
||||||
|
(gdb)
|
||||||
|
|
||||||
|
...note that the speed of the probe in this way is about 10 times less than
|
||||||
|
running native. This build is intended for debug and development only.
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Black Sphere Technologies Ltd.
|
||||||
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* Modified by Dave Marples <dave@marples.net>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Low level JTAG implementation using FT2232 with libftdi.
|
||||||
|
*
|
||||||
|
* Issues:
|
||||||
|
* Should share interface with swdptap.c or at least clean up...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "remote.h"
|
||||||
|
#include "jtagtap.h"
|
||||||
|
|
||||||
|
/* See remote.c/.h for protocol information */
|
||||||
|
|
||||||
|
int jtagtap_init(void)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_JTAG_INIT_STR);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"jtagtap_init failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jtagtap_reset(void)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_JTAG_RESET_STR);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"jtagtap_reset failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jtagtap_tms_seq(uint32_t MS, int ticks)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_TMS_STR,ticks,MS);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"jtagtap_tms_seq failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
uint64_t DIl=*(uint64_t *)DI;
|
||||||
|
uint64_t *DOl=(uint64_t *)DO;
|
||||||
|
|
||||||
|
if(!ticks) return;
|
||||||
|
if (!DI && !DO) return;
|
||||||
|
|
||||||
|
/* Reduce the length of DI according to the bits we're transmitting */
|
||||||
|
DIl&=(1L<<(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);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"jtagtap_tms_seq failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DO)
|
||||||
|
*DOl=remotehston(-1,(char *)&construct[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
|
||||||
|
|
||||||
|
{
|
||||||
|
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_NEXT,dTMS?'1':'0',dTDI?'1':'0');
|
||||||
|
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"jtagtap_next failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return remotehston(-1,(char *)&construct[1]);
|
||||||
|
}
|
|
@ -0,0 +1,352 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
||||||
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* Additions by Dave Marples <dave@marples.net>
|
||||||
|
*
|
||||||
|
* 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 "general.h"
|
||||||
|
#include "gdb_if.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "platform.h"
|
||||||
|
#include "remote.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void platform_init(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
char construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
char *serial = NULL;
|
||||||
|
while((c = getopt(argc, argv, "s:")) != -1) {
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
serial = optarg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nBlack Magic Probe (" FIRMWARE_VERSION ")\n");
|
||||||
|
printf("Copyright (C) 2019 Black Sphere Technologies Ltd.\n");
|
||||||
|
printf("License GPLv3+: GNU GPL version 3 or later "
|
||||||
|
"<http://gnu.org/licenses/gpl.html>\n\n");
|
||||||
|
|
||||||
|
assert(gdb_if_init() == 0);
|
||||||
|
|
||||||
|
f=open(serial,O_RDWR|O_SYNC|O_NOCTTY);
|
||||||
|
if (f<0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Couldn't open serial port %s\n",serial);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_interface_attribs (f, 115000, 0)<0)
|
||||||
|
{
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if ((!c) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Remote Start failed, error %s\n",c?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Remote is %s\n",&construct[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool platform_target_get_power(void)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_PWR_GET_STR);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"platform_target_get_power failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (construct[1]=='1');
|
||||||
|
}
|
||||||
|
|
||||||
|
void platform_target_set_power(bool power)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_PWR_SET_STR,power?'1':'0');
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"platform_target_set_power failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void platform_srst_set_val(bool assert)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_SRST_SET_STR,assert?'1':'0');
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"platform_srst_set_val failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool platform_srst_get_val(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_SRST_GET_STR);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"platform_srst_set_val failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (construct[1]=='1');
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
{
|
||||||
|
static uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_VOLTAGE_STR);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"platform_target_voltage failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-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);
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
||||||
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* Additions by Dave Marples <dave@marples.net>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PLATFORM_H
|
||||||
|
#define __PLATFORM_H
|
||||||
|
|
||||||
|
#include "timing.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
# include <alloca.h>
|
||||||
|
#else
|
||||||
|
# ifndef alloca
|
||||||
|
# define alloca __builtin_alloca
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PLATFORM_HAS_DEBUG
|
||||||
|
#define PLATFORM_HAS_POWER_SWITCH
|
||||||
|
#define PLATFORM_MAX_MSG_SIZE (256)
|
||||||
|
#define PLATFORM_IDENT "PC-HOSTED"
|
||||||
|
#define BOARD_IDENT PLATFORM_IDENT
|
||||||
|
#define SET_RUN_STATE(state)
|
||||||
|
#define SET_IDLE_STATE(state)
|
||||||
|
#define SET_ERROR_STATE(state)
|
||||||
|
|
||||||
|
void platform_buffer_flush(void);
|
||||||
|
int platform_buffer_write(const uint8_t *data, int size);
|
||||||
|
int platform_buffer_read(uint8_t *data, int size);
|
||||||
|
|
||||||
|
static inline int platform_hwversion(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* Modified by Dave Marples <dave@marples.net>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* MPSSE bit-banging SW-DP interface over FTDI with loop unrolled.
|
||||||
|
* Speed is sensible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "swdptap.h"
|
||||||
|
#include "remote.h"
|
||||||
|
|
||||||
|
int swdptap_init(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=sprintf((char *)construct,"%s",REMOTE_SWDP_INIT_STR);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"swdptap_init failed, error %s\n",s?(char *)&(construct[1]):"unknown");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=sprintf((char *)construct,REMOTE_SWDP_IN_PAR_STR,ticks);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((s<2) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"swdptap_seq_in_parity failed, error %s\n",s?(char *)&(construct[1]):"short response");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*res=remotehston(-1,(char *)&construct[1]);
|
||||||
|
return (construct[0]!=REMOTE_RESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t swdptap_seq_in(int ticks)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=sprintf((char *)construct,REMOTE_SWDP_IN_STR,ticks);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((s<2) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"swdptap_seq_in failed, error %s\n",s?(char *)&(construct[1]):"short response");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return remotehston(-1,(char *)&construct[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swdptap_seq_out(uint32_t MS, int ticks)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=sprintf((char *)construct,REMOTE_SWDP_OUT_STR,ticks,MS);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((s<1) || (construct[0]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"swdptap_seq_out failed, error %s\n",s?(char *)&(construct[1]):"short response");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void swdptap_seq_out_parity(uint32_t MS, int ticks)
|
||||||
|
{
|
||||||
|
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s=sprintf((char *)construct,REMOTE_SWDP_OUT_PAR_STR,ticks,MS);
|
||||||
|
platform_buffer_write(construct,s);
|
||||||
|
|
||||||
|
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
|
if ((s<1) || (construct[1]==REMOTE_RESP_ERR))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"swdptap_seq_out_parity failed, error %s\n",s?(char *)&(construct[2]):"short response");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,276 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Black Sphere Technologies Ltd.
|
||||||
|
* Written by Dave Marples <dave@marples.net>
|
||||||
|
*
|
||||||
|
* 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 "general.h"
|
||||||
|
#include "remote.h"
|
||||||
|
#include "gdb_packet.h"
|
||||||
|
#include "swdptap.h"
|
||||||
|
#include "jtagtap.h"
|
||||||
|
#include "gdb_if.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NTOH(x) ((x<=9)?x+'0':'a'+x-10)
|
||||||
|
#define HTON(x) ((x<='9')?x-'0':((TOUPPER(x))-'A'+10))
|
||||||
|
#define TOUPPER(x) ((((x)>='a') && ((x)<='z'))?((x)-('a'-'A')):(x))
|
||||||
|
#define ISHEX(x) ( \
|
||||||
|
(((x)>='0') && ((x)<='9')) || \
|
||||||
|
(((x)>='A') && ((x)<='F')) || \
|
||||||
|
(((x)>='a') && ((x)<='f')) \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t remotehston(uint32_t limit, char *s)
|
||||||
|
|
||||||
|
/* Return numeric version of string, until illegal hex digit, or limit */
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t ret=0L;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (limit--) {
|
||||||
|
c=*s++;
|
||||||
|
if (!ISHEX(c))
|
||||||
|
return ret;
|
||||||
|
ret=(ret<<4)|HTON(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _respond(char respCode, uint64_t param)
|
||||||
|
|
||||||
|
/* Send response to far end */
|
||||||
|
|
||||||
|
{
|
||||||
|
char buf[34];
|
||||||
|
char *p=buf;
|
||||||
|
|
||||||
|
gdb_if_putchar(REMOTE_RESP,0);
|
||||||
|
gdb_if_putchar(respCode,0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
*p++=NTOH((param&0x0f));
|
||||||
|
param>>=4;
|
||||||
|
}
|
||||||
|
while (param);
|
||||||
|
|
||||||
|
/* At this point the number to print is the buf, but backwards, so spool it out */
|
||||||
|
do {
|
||||||
|
gdb_if_putchar(*--p,0);
|
||||||
|
} while (p>buf);
|
||||||
|
gdb_if_putchar(REMOTE_EOM,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _respondS(char respCode, const char *s)
|
||||||
|
/* Send response to far end */
|
||||||
|
{
|
||||||
|
gdb_if_putchar(REMOTE_RESP,0);
|
||||||
|
gdb_if_putchar(respCode,0);
|
||||||
|
while (*s) {
|
||||||
|
/* Just clobber illegal characters so they don't disturb the protocol */
|
||||||
|
if ((*s=='$') || (*s==REMOTE_SOM) || (*s==REMOTE_EOM))
|
||||||
|
gdb_if_putchar(' ', 0);
|
||||||
|
else
|
||||||
|
gdb_if_putchar(*s, 0);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
gdb_if_putchar(REMOTE_EOM,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remotePacketProcessSWD(uint8_t i, char *packet)
|
||||||
|
{
|
||||||
|
uint8_t ticks;
|
||||||
|
uint32_t param;
|
||||||
|
bool badParity;
|
||||||
|
|
||||||
|
switch (packet[1]) {
|
||||||
|
case REMOTE_INIT: /* SS = initialise ================================= */
|
||||||
|
if (i==2) {
|
||||||
|
swdptap_init();
|
||||||
|
_respond(REMOTE_RESP_OK, 0);
|
||||||
|
} else {
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_IN_PAR: /* = In parity ================================== */
|
||||||
|
ticks=remotehston(2,&packet[2]);
|
||||||
|
badParity=swdptap_seq_in_parity(¶m, ticks);
|
||||||
|
_respond(badParity?REMOTE_RESP_PARERR:REMOTE_RESP_OK,param);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_IN: /* = In ========================================= */
|
||||||
|
ticks=remotehston(2,&packet[2]);
|
||||||
|
param=swdptap_seq_in(ticks);
|
||||||
|
_respond(REMOTE_RESP_OK,param);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_OUT: /* = Out ======================================== */
|
||||||
|
ticks=remotehston(2,&packet[2]);
|
||||||
|
param=remotehston(-1, &packet[4]);
|
||||||
|
swdptap_seq_out(param, ticks);
|
||||||
|
_respond(REMOTE_RESP_OK, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_OUT_PAR: /* = Out parity ================================= */
|
||||||
|
ticks=remotehston(2,&packet[2]);
|
||||||
|
param=remotehston(-1, &packet[4]);
|
||||||
|
swdptap_seq_out_parity(param, ticks);
|
||||||
|
_respond(REMOTE_RESP_OK, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remotePacketProcessJTAG(uint8_t i, char *packet)
|
||||||
|
{
|
||||||
|
uint32_t MS;
|
||||||
|
uint64_t DO;
|
||||||
|
uint8_t ticks;
|
||||||
|
uint64_t DI;
|
||||||
|
|
||||||
|
switch (packet[1]) {
|
||||||
|
case REMOTE_INIT: /* = initialise ================================= */
|
||||||
|
jtagtap_init();
|
||||||
|
_respond(REMOTE_RESP_OK, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_RESET: /* = reset ================================= */
|
||||||
|
jtagtap_reset();
|
||||||
|
_respond(REMOTE_RESP_OK, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_TMS: /* = TMS Sequence ================================== */
|
||||||
|
ticks=remotehston(2,&packet[2]);
|
||||||
|
MS=remotehston(2,&packet[4]);
|
||||||
|
|
||||||
|
if (i<4) {
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||||
|
} else {
|
||||||
|
jtagtap_tms_seq( MS, ticks);
|
||||||
|
_respond(REMOTE_RESP_OK, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_TDITDO_TMS: /* = TDI/TDO ========================================= */
|
||||||
|
case REMOTE_TDITDO_NOTMS:
|
||||||
|
|
||||||
|
if (i<5) {
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||||
|
} else {
|
||||||
|
ticks=remotehston(2,&packet[2]);
|
||||||
|
DI=remotehston(-1,&packet[4]);
|
||||||
|
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;
|
||||||
|
|
||||||
|
_respond(REMOTE_RESP_OK, DO);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_NEXT: /* = NEXT ======================================== */
|
||||||
|
if (i!=4) {
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||||
|
} else {
|
||||||
|
uint32_t dat=jtagtap_next( (packet[2]=='1'), (packet[3]=='1'));
|
||||||
|
_respond(REMOTE_RESP_OK,dat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remotePacketProcessGEN(uint8_t i, char *packet)
|
||||||
|
|
||||||
|
{
|
||||||
|
(void)i;
|
||||||
|
switch (packet[1]) {
|
||||||
|
case REMOTE_VOLTAGE:
|
||||||
|
_respondS(REMOTE_RESP_OK,platform_target_voltage());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_SRST_SET:
|
||||||
|
platform_srst_set_val(packet[2]=='1');
|
||||||
|
_respond(REMOTE_RESP_OK,0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_SRST_GET:
|
||||||
|
_respond(REMOTE_RESP_OK,platform_srst_get_val());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_PWR_SET:
|
||||||
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
||||||
|
platform_target_set_power(packet[2]=='1');
|
||||||
|
_respond(REMOTE_RESP_OK,0);
|
||||||
|
#else
|
||||||
|
_respond(REMOTE_RESP_NOTSUP,0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_PWR_GET:
|
||||||
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
||||||
|
_respond(REMOTE_RESP_OK,platform_target_get_power());
|
||||||
|
#else
|
||||||
|
_respond(REMOTE_RESP_NOTSUP,0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if !defined(BOARD_IDENT) && defined(PLATFORM_IDENT)
|
||||||
|
# define BOARD_IDENT PLATFORM_IDENT
|
||||||
|
#endif
|
||||||
|
case REMOTE_START:
|
||||||
|
_respondS(REMOTE_RESP_OK, BOARD_IDENT " " FIRMWARE_VERSION);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remotePacketProcess(uint8_t i, char *packet)
|
||||||
|
{
|
||||||
|
switch (packet[0]) {
|
||||||
|
case REMOTE_SWDP_PACKET:
|
||||||
|
remotePacketProcessSWD(i,packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_JTAG_PACKET:
|
||||||
|
remotePacketProcessJTAG(i,packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOTE_GEN_PACKET:
|
||||||
|
remotePacketProcessGEN(i,packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* Oh dear, unrecognised, return an error */
|
||||||
|
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Black Sphere Technologies Ltd.
|
||||||
|
* Written by Dave Marples <dave@marples.net>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REMOTE_
|
||||||
|
#define _REMOTE_
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commands to remote end, and responses
|
||||||
|
* =====================================
|
||||||
|
*
|
||||||
|
* All commands as sent as ASCII and begin with !, ending with #.
|
||||||
|
* Parameters are hex digits and format is per command.
|
||||||
|
*
|
||||||
|
* !<CMD><PARAM>#
|
||||||
|
* <CMD> - 2 digit ASCII value
|
||||||
|
* <PARAM> - x digits (according to command) ASCII value
|
||||||
|
*
|
||||||
|
* So, for example;
|
||||||
|
*
|
||||||
|
* SI - swdptap_seq_in_parity
|
||||||
|
* tt - Ticks
|
||||||
|
* e.g. SI21 : Request input with parity, 33 ticks
|
||||||
|
* resp: K<PARAM> - hex value returned.
|
||||||
|
* resp: F<PARAM> - hex value returned, bad parity.
|
||||||
|
* X<err> - error occured
|
||||||
|
*
|
||||||
|
* The whole protocol is defined in this header file. Parameters have
|
||||||
|
* to be marshalled in remote.c, swdptap.c and jtagtap.c, so be
|
||||||
|
* careful to ensure the parameter handling matches the protocol
|
||||||
|
* definition when anything is changed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Protocol error messages */
|
||||||
|
#define REMOTE_ERROR_UNRECOGNISED 1
|
||||||
|
#define REMOTE_ERROR_WRONGLEN 2
|
||||||
|
|
||||||
|
/* Start and end of message identifiers */
|
||||||
|
#define REMOTE_SOM '!'
|
||||||
|
#define REMOTE_EOM '#'
|
||||||
|
#define REMOTE_RESP '&'
|
||||||
|
|
||||||
|
/* Generic protocol elements */
|
||||||
|
#define REMOTE_START 'A'
|
||||||
|
#define REMOTE_TDITDO_TMS 'D'
|
||||||
|
#define REMOTE_TDITDO_NOTMS 'd'
|
||||||
|
#define REMOTE_IN_PAR 'I'
|
||||||
|
#define REMOTE_IN 'i'
|
||||||
|
#define REMOTE_NEXT 'N'
|
||||||
|
#define REMOTE_OUT_PAR 'O'
|
||||||
|
#define REMOTE_OUT 'o'
|
||||||
|
#define REMOTE_PWR_SET 'P'
|
||||||
|
#define REMOTE_PWR_GET 'p'
|
||||||
|
#define REMOTE_RESET 'R'
|
||||||
|
#define REMOTE_INIT 'S'
|
||||||
|
#define REMOTE_TMS 'T'
|
||||||
|
#define REMOTE_VOLTAGE 'V'
|
||||||
|
#define REMOTE_SRST_SET 'Z'
|
||||||
|
#define REMOTE_SRST_GET 'z'
|
||||||
|
|
||||||
|
/* Protocol response options */
|
||||||
|
#define REMOTE_RESP_OK 'K'
|
||||||
|
#define REMOTE_RESP_PARERR 'P'
|
||||||
|
#define REMOTE_RESP_ERR 'E'
|
||||||
|
#define REMOTE_RESP_NOTSUP 'N'
|
||||||
|
|
||||||
|
/* Generic protocol elements */
|
||||||
|
#define REMOTE_GEN_PACKET 'G'
|
||||||
|
|
||||||
|
#define REMOTE_START_STR (char []){ '+', REMOTE_EOM, REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_START, REMOTE_EOM, 0 }
|
||||||
|
#define REMOTE_VOLTAGE_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_VOLTAGE, REMOTE_EOM, 0 }
|
||||||
|
#define REMOTE_SRST_SET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_SRST_SET, '%', 'c', REMOTE_EOM, 0 }
|
||||||
|
#define REMOTE_SRST_GET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_SRST_GET, REMOTE_EOM, 0 }
|
||||||
|
#define REMOTE_PWR_SET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_PWR_SET, '%', 'c', REMOTE_EOM, 0 }
|
||||||
|
#define REMOTE_PWR_GET_STR (char []){ REMOTE_SOM, REMOTE_GEN_PACKET, REMOTE_PWR_GET, REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
/* SWDP protocol elements */
|
||||||
|
#define REMOTE_SWDP_PACKET 'S'
|
||||||
|
#define REMOTE_SWDP_INIT_STR (char []){ REMOTE_SOM, REMOTE_SWDP_PACKET, REMOTE_INIT, REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_SWDP_IN_PAR_STR (char []){ REMOTE_SOM, REMOTE_SWDP_PACKET, REMOTE_IN_PAR, \
|
||||||
|
'%','0','2','x',REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_SWDP_IN_STR (char []){ REMOTE_SOM, REMOTE_SWDP_PACKET, REMOTE_IN, \
|
||||||
|
'%','0','2','x',REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_SWDP_OUT_STR (char []){ REMOTE_SOM, REMOTE_SWDP_PACKET, REMOTE_OUT, \
|
||||||
|
'%','0','2','x','%','x',REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_SWDP_OUT_PAR_STR (char []){ REMOTE_SOM, REMOTE_SWDP_PACKET, REMOTE_OUT_PAR, \
|
||||||
|
'%','0','2','x','%','x',REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
/* JTAG protocol elements */
|
||||||
|
#define REMOTE_JTAG_PACKET 'J'
|
||||||
|
|
||||||
|
#define REMOTE_JTAG_INIT_STR (char []){ '+',REMOTE_EOM, REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_INIT, REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_JTAG_RESET_STR (char []){ '+',REMOTE_EOM, REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_RESET, REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_JTAG_TMS_STR (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_TMS, \
|
||||||
|
'%','0','2','x','%','x',REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_JTAG_TDIDO_STR (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET, '%', 'c', \
|
||||||
|
'%','0','2','x','%','l', 'x', REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
#define REMOTE_JTAG_NEXT (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_NEXT, \
|
||||||
|
'%','c','%','c',REMOTE_EOM, 0 }
|
||||||
|
|
||||||
|
uint64_t remotehston(uint32_t limit, char *s);
|
||||||
|
void remotePacketProcess(uint8_t i, char *packet);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue