* rom68k-rom.c: New file. Replaces the old remote-mon.c and uses

the new generic ROM interface in monitor.c.
	* config/m68k/monitor.mt: Use new ROM support.
	* monitor.c: Add support for xmodem download protocol.
This commit is contained in:
Rob Savoye 1994-11-10 23:20:03 +00:00
parent f449d250be
commit 06b8f5e406
3 changed files with 497 additions and 159 deletions

View file

@ -1,3 +1,10 @@
Thu Nov 10 15:16:21 1994 Rob Savoye <rob@rtl.cygnus.com>
* rom68k-rom.c: New file. Replaces the old remote-mon.c and uses
the new generic ROM interface in monitor.c.
* config/m68k/monitor.mt: Use new ROM support.
* monitor.c: Add support for xmodem download protocol.
Wed Nov 9 18:46:24 1994 Stan Shebs (shebs@andros.cygnus.com)
* findvar.c (find_saved_register): Fix a frame variable name.

View file

@ -48,6 +48,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
# define TERMINAL struct sgttyb
#endif
extern void make_xmodem_packet();
extern void print_xmodem_packet();
struct monitor_ops *current_monitor;
extern struct cmd_list_element *setlist;
extern struct cmd_list_element *unsetlist;
@ -58,7 +61,6 @@ extern char *target_name;
static int hashmark; /* flag set by "set hash" */
/* FIXME: Replace with sr_get_debug (). */
#define LOG_FILE "monitor.log"
#if defined (LOG_FILE)
FILE *log_file;
@ -66,8 +68,9 @@ FILE *log_file;
static int timeout = 24;
/* Descriptor for I/O to remote machine. Initialize it to NULL so that
monitor_open knows that we don't have a file open when the program starts.
/*
* Descriptor for I/O to remote machine. Initialize it to NULL so that
* monitor_open knows that we don't have a file open when the program starts.
*/
static serial_t monitor_desc = NULL;
@ -78,6 +81,20 @@ static void set_loadtype_command();
static void monitor_load_srec();
static int monitor_write_srec();
/*
* these definitions are for xmodem protocol
*/
#define SOH 0x01
#define ACK 0x06
#define NAK 0x15
#define EOT 0x04
#define CANCEL 0x18
#define GETACK getacknak(ACK)
#define GETNAK getacknak(NAK)
#define XMODEM_DATASIZE 128 /* the data size is ALWAYS 128 */
#define XMODEM_PACKETSIZE 131 /* the packet size is ALWAYS 132 (zero based) */
#define XMODEM 1
/*
* set_loadtype_command -- set the type for downloading. Check to make
* sure you have a support protocol for this target.
@ -134,6 +151,21 @@ printf_monitor(va_alist)
if (SERIAL_WRITE(monitor_desc, buf, strlen(buf)))
fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
}
/*
* write_monitor -- send raw data to monitor.
*/
static void
write_monitor(data, len)
char data[];
int len;
{
if (SERIAL_WRITE(monitor_desc, data, len))
fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
*(data + len+1) = '\0';
debuglogs (1, "write_monitor(), Sending: \"%s\".", data);
}
/*
* debuglogs -- deal with debugging info to multiple sources. This takes
@ -155,7 +187,7 @@ debuglogs(va_alist)
level = va_arg(args, int); /* get the debug level */
if ((level <0) || (level > 100)) {
error ("Bad argument passed to debuglogs()");
error ("Bad argument passed to debuglogs(), needs debug level");
return;
}
@ -222,7 +254,7 @@ readchar(timeout)
c = SERIAL_READCHAR(monitor_desc, timeout);
if (sr_get_debug() > 4)
if (sr_get_debug() > 5)
putchar(c & 0x7f);
#ifdef LOG_FILE
@ -238,7 +270,7 @@ readchar(timeout)
return c; /* Polls shouldn't generate timeout errors */
error("Timeout reading from remote system.");
#ifdef LOG_FILE
fputc ("ERROR: Timeout reading from remote system", log_file);
fputs ("ERROR: Timeout reading from remote system", log_file);
#endif
}
perror_with_name("remote-monitor");
@ -300,11 +332,6 @@ static void
expect_prompt(discard)
int discard;
{
#if defined (LOG_FILE)
/* This is a convenient place to do this. The idea is to do it often
enough that we never lose much data if we terminate abnormally. */
fflush(log_file);
#endif
expect (PROMPT, discard);
}
@ -316,6 +343,7 @@ junk(ch)
char ch;
{
switch (ch) {
case '\0':
case ' ':
case '-':
case '\t':
@ -357,7 +385,7 @@ get_hex_digit(ignore)
;
else {
expect_prompt(1);
error("Invalid hex digit from remote system.");
error("Invalid hex digit from remote system. (0x%x)", ch);
}
}
}
@ -963,7 +991,8 @@ monitor_remove_breakpoint (addr, shadow)
/* monitor_load -- load a file. This file determines which of the
* supported formats to use. The current types are:
* FIXME: not all types supported yet.
* default - reads any file using bfd and writes it to memory.
* default - reads any file using bfd and writes it to memory. This
* is really slow.
* srec - reads binary file using bfd and writes it as an
* ascii srecord.
* xmodem-bin - reads a binary file using bfd, and downloads it
@ -990,7 +1019,7 @@ monitor_load (file, fromtty)
}
if (STREQ (loadtype_str, "srec")) { /* load an srecord by converting */
monitor_load_srec(file, fromtty); /* if from a binary */
monitor_load_srec(file, 0); /* if from a binary */
}
if (STREQ (loadtype_str, "ascii-srec")) { /* load an srecord file */
@ -998,7 +1027,7 @@ monitor_load (file, fromtty)
}
if (STREQ (loadtype_str, "xmodem-srec")) { /* load an srecord using the */
error ("This protocol is not implemented yet."); /* xmodem protocol */
monitor_load_srec(file, XMODEM);
}
}
@ -1024,7 +1053,7 @@ monitor_load_ascii_srec (file, fromtty)
}
printf_monitor (LOAD_CMD);
sleep(1);
while (!feof (download)) {
bytes_read = fread (buf, sizeof (char), DOWNLOAD_LINE_SIZE, download);
if (hashmark) {
@ -1083,17 +1112,41 @@ monitor_command (args, fromtty)
}
/*
* monitor_load_srec -- download a binary file by converting it to srecords.
* monitor_load_srec -- download a binary file by converting it to srecords. This
* will also use xmodem to download the resulting file.
*
* A download goes like this when using xmodem:
* Receiver: Sender
* NAK ---------->
* <-------- (packet) [SOH|1|1|data|SUM]
* ACK ---------->
* <-------- (packet) [SOH|2|2|data|SUM]
* ACK ---------->
* <-------- EOT
* ACK ---------->
*
* ACK = 0x06
* NAK = 0x15
* EOT = 0x04
*
*/
static void
monitor_load_srec (args, fromtty)
monitor_load_srec (args, protocol)
char *args;
int fromtty;
int protocol;
{
bfd *abfd;
asection *s;
char buffer[1024];
int srec_frame = SREC_SIZE;
char srec[1024];
char packet[XMODEM_PACKETSIZE];
int i;
int retries;
int type = 0; /* default to a type 0, header record */
int srec_frame = 57; /* FIXME: this must be 57 There is 12 bytes
of header, and 2 bytes of checksum at the end.
The problem is an xmodem packet holds exactly
128 bytes. */
abfd = bfd_openr (args, 0);
if (!abfd) {
@ -1106,176 +1159,311 @@ monitor_load_srec (args, fromtty)
return;
}
printf_monitor (LOAD_CMD); /* tell the monitor to load */
if (protocol == XMODEM) { /* get the NAK from the target */
if (GETNAK) {
debuglogs (3, "Got the NAK to start loading");
} else {
printf_monitor ("%c", EOT);
debuglogs (3, "Never got the NAK to start loading");
error ("Never got the NAK to start loading");
}
}
s = abfd->sections;
while (s != (asection *) NULL) {
srec_frame = SREC_SIZE;
if (s->flags & SEC_LOAD) {
int i;
char *buffer = xmalloc (srec_frame);
printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma, s->vma + s
->_raw_size);
printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma, s->vma + s->_raw_size);
fflush (stdout);
for (i = 0; i < s->_raw_size; i += srec_frame) {
if (srec_frame > s->_raw_size - i)
srec_frame = s->_raw_size - i;
bfd_get_section_contents (abfd, s, buffer, i, srec_frame);
monitor_write_srec (s->vma + i, buffer, srec_frame);
printf_filtered ("*");
monitor_make_srec (srec, type, s->vma + i, buffer, srec_frame);
if (protocol == XMODEM) { /* send a packet using xmodem */
make_xmodem_packet (packet, srec, XMODEM_DATASIZE);
write_monitor (packet, XMODEM_PACKETSIZE+1);
retries = 0;
while (retries++ <= 3) {
if (GETNAK) { /* Resend packet */
debuglogs (3, "Got a NAK, resending packet");
sleep(1);
write_monitor (packet, XMODEM_PACKETSIZE+1); /* send it again */
if (GETACK) /* ACKnowledged, get next data chunk */
break;
}
}
if (retries >= 4) { /* too many tries, must be hosed */
printf_monitor ("%c", EOT);
error ("Never got a ACK after sending an xmodem packet");
}
} else { /* no protocols at all */
printf_monitor ("%s\n", srec);
}
if (hashmark)
printf_filtered ("#");
type = 3; /* switch to a 4 byte address record */
fflush (stdout);
}
printf_filtered ("\n");
free (buffer);
} else {
debuglogs (3, "%s doesn't need to be loaded", s->name);
}
s = s->next;
}
sprintf (buffer, "rs ip %lx", (unsigned long) abfd->start_address);
printf_monitor (buffer);
/*
write a type 7 terminator record. no data for a type 7,
and there is no data, so len is 0.
*/
monitor_make_srec (srec, 7, abfd->start_address, "", 0);
printf_monitor ("%s\n", srec);
if (protocol == XMODEM) {
printf_monitor ("%c", EOT);
if (!GETACK)
error ("Never got ACK after sending EOT");
}
if (hashmark)
putchar ('\n');
expect_prompt ();
}
/*
* getacknak -- get an ACK or a NAK from the target.
* returns 1 (true) or 0 (false) This is
* for xmodem. ANy string starting with "***"
* is an error message from the target.
* Here's a few from the WinBond w89k "Cougar" PA board.
* *** Too many errors found.
* *** Bad command
* *** Command syntax error
*/
int
getacknak (byte)
int byte;
{
char character;
int i;
static int
monitor_write_srec (memaddr, myaddr, len)
i = 0;
while (i++ < 60) {
character = (char)readchar (0);
if (character == 0xfffffffe) { /* empty uart */
if (sr_get_debug() > 3)
putchar ('.');
fflush (stdout);
sleep (1);
continue;
}
if (character == CANCEL) { /* target aborted load */
expect_prompt (0);
error ("Got a CANCEL from the target.");
}
if (character == '*') { /* look for missed error message */
expect_prompt (0);
error ("Got an error message from the target");
}
debuglogs (3, "Got a %s (0x%x or \'%c\'), expecting a %s.\n",
(character == ACK) ? "ACK" : (character == NAK) ? "NAK" : "BOGUS",
character, character, (byte == ACK) ? "ACK" : "NAK");
if (character == byte) /* got what we wanted */
return 1;
if (character == ((byte == ACK) ? NAK : ACK)) { /* got the opposite */
debuglogs (3, "Got the opposite, wanted 0x%x, got a 0x%x", byte, character);
return 0;
}
sleep (1);
}
return 0;
}
/*
* monitor_make_srec -- make an srecord. This writes each line, one at a
* time, each with it's own header and trailer line.
* An srecord looks like this:
*
* byte count-+ address
* start ---+ | | data +- checksum
* | | | |
* S01000006F6B692D746573742E73726563E4
* S315000448600000000000000000FC00005900000000E9
* S31A0004000023C1400037DE00F023604000377B009020825000348D
* S30B0004485A0000000000004E
* S70500040000F6
*
* S<type><length><address><data><checksum>
*
* Where
* - length
* is the number of bytes following upto the checksum. Note that
* this is not the number of chars following, since it takes two
* chars to represent a byte.
* - type
* is one of:
* 0) header record
* 1) two byte address data record
* 2) three byte address data record
* 3) four byte address data record
* 7) four byte address termination record
* 8) three byte address termination record
* 9) two byte address termination record
*
* - address
* is the start address of the data following, or in the case of
* a termination record, the start address of the image
* - data
* is the data.
* - checksum
* is the sum of all the raw byte data in the record, from the length
* upwards, modulo 256 and subtracted from 255.
*/
int
monitor_make_srec (buffer, type, memaddr, myaddr, len)
char *buffer;
int type;
CORE_ADDR memaddr;
unsigned char *myaddr;
int len;
{
int done;
int checksum;
int x;
int retries;
int srec_bytes = 40;
int srec_max_retries = 3;
int srec_echo_pace = 0;
int srec_sleep = 0;
int srec_noise = 0;
char *buffer = alloca ((srec_bytes + 8) << 1);
retries = 0;
while (1) { /* FIXME !!! */
done = 0;
if (retries > srec_max_retries)
return(-1);
if (retries > 0) {
if (sr_get_debug() > 0)
printf("\n<retrying...>\n");
/* This gr_expect_prompt call is extremely important. Without
it, we will tend to resend our packet so fast that it
will arrive before the bug monitor is ready to receive
it. This would lead to a very ugly resend loop. */
gr_expect_prompt();
}
/* FIXME: this is just start_load pasted in... */
{ char *command;
command = (srec_echo_pace ? "lo 0 ;x" : "lo 0");
sr_write_cr (command);
sr_expect (command);
sr_expect ("\r\n");
#if 0
bug_srec_write_cr ("S0030000FC");
#endif
}
/* end of hack */
while (done < len) {
int thisgo;
int idx;
char *buf = buffer;
CORE_ADDR address;
int i;
char *buf;
buf = buffer;
debuglogs (4, "monitor_make_srec (buffer=0x%x, type=%d, memaddr=0x%x, len=%d",
buffer, type, memaddr, len);
checksum = 0;
thisgo = len - done;
if (thisgo > srec_bytes)
thisgo = srec_bytes;
address = memaddr + done;
sprintf (buf, "S3%02X%08X", thisgo + 4 + 1, address);
/*
create the header for the srec. 4 is the number of bytes in the address,
and 1 is the number of bytes in the count.
*/
if (type == 0) /* FIXME: type 0 is optional */
type = 3; /* so use data as it works */
sprintf (buf, "S%d%02X%08X", type, len + 4 + 1, memaddr);
buf += 12;
checksum += (thisgo + 4 + 1
+ (address & 0xff)
+ ((address >> 8) & 0xff)
+ ((address >> 16) & 0xff)
+ ((address >> 24) & 0xff));
checksum += (len + 4 + 1 /* calculate the checksum */
+ (memaddr & 0xff)
+ ((memaddr >> 8) & 0xff)
+ ((memaddr >> 16) & 0xff)
+ ((memaddr >> 24) & 0xff));
for (idx = 0; idx < thisgo; idx++) {
sprintf (buf, "%02X", myaddr[idx + done]);
checksum += myaddr[idx + done];
for (i = 0; i < len; i++) { /* build the srecord */
sprintf (buf, "%02X", myaddr[i]);
checksum += myaddr[i];
buf += 2;
}
if (srec_noise > 0) {
/* FIXME-NOW: insert a deliberate error every now and then.
This is intended for testing/debugging the error handling
stuff. */
static int counter = 0;
if (++counter > srec_noise) {
counter = 0;
++checksum;
}
}
sprintf(buf, "%02X", ~checksum & 0xff);
#if 0
bug_srec_write_cr (buffer);
#endif
if (srec_sleep != 0)
sleep(srec_sleep);
/* This pollchar is probably redundant to the gr_multi_scan
below. Trouble is, we can't be sure when or where an
error message will appear. Apparently, when running at
full speed from a typical sun4, error messages tend to
appear to arrive only *after* the s7 record. */
if ((x = sr_pollchar()) != 0) {
if (sr_get_debug() > 0)
printf("\n<retrying...>\n");
++retries;
/* flush any remaining input and verify that we are back
at the prompt level. */
gr_expect_prompt();
/* start all over again. */
/* FIXME: this is just start_load pasted in... */
{ char *command;
command = (srec_echo_pace ? "lo 0 ;x" : "lo 0");
sr_write_cr (command);
sr_expect (command);
sr_expect ("\r\n");
#if 0
bug_srec_write_cr ("S0030000FC");
#endif
}
/* end of hack */
done = 0;
continue;
}
done += thisgo;
}
#if 0
bug_srec_write_cr("S7060000000000F9");
#endif
++retries;
/* Having finished the load, we need to figure out whether we
had any errors. */
}
sprintf(buf, "%02X", ~checksum & 0xff); /* add the checksum */
debuglogs (3, "srec is \"%s\"", buffer);
return(0);
}
/*
* make_xmodem_packet -- this takes a 128 bytes of data and makes a packet
* out of it.
*
* Each packet looks like this:
* +-----+-------+-------+------+-----+
* | SOH | Seq1. | Seq2. | data | SUM |
* +-----+-------+-------+------+-----+
* SOH = 0x01
* Seq1 = The sequence number.
* Seq2 = The complement of the sequence number.
* Data = A 128 bytes of data.
* SUM = Add the contents of the 128 bytes and use the low-order
* 8 bits of the result.
*/
void
make_xmodem_packet (packet, data, len)
unsigned char packet[];
unsigned char *data;
int len;
{
static int sequence = 1;
int i, sum;
unsigned char *buf;
buf = data;
/* build the packet header */
packet[0] = SOH;
packet[1] = sequence;
packet[2] = 255 - sequence;
sequence++;
#if 0
packet[2] = ~sequence++; /* the complement is the sequence checksum */
#endif
sum = 0; /* calculate the data checksum */
for (i = 3; i <= len + 2; i++) {
packet[i] = *buf;
sum += *buf;
buf++;
}
for (i = len+1 ; i <= XMODEM_DATASIZE ; i++) { /* add padding for the rest of the packet */
packet[i] = '0';
}
packet[XMODEM_PACKETSIZE] = sum & 0xff; /* add the checksum */
if (sr_get_debug() > 4)
debuglogs (4, "The xmodem checksum is %d (0x%x)\n", sum & 0xff, sum & 0xff);
print_xmodem_packet (packet);
}
/*
* print_xmodem_packet -- print the packet as a debug check
*/
void
print_xmodem_packet(packet)
char packet[];
{
int i;
static int lastseq;
int sum;
/* take apart the packet header the packet header */
if (packet[0] == SOH) {
("SOH");
} else {
error ("xmodem: SOH is wrong");
}
/* check the sequence */
if (packet[1] != 0) {
lastseq = packet[1];
if (packet[2] != ~lastseq)
error ("xmodem: Sequence checksum is wrong");
else
printf_filtered (" %d %d", lastseq, ~lastseq);
}
/* check the data checksum */
sum = 0;
for (i = 3; i <= XMODEM_DATASIZE; i++) {
sum += packet[i];
}
/* ignore the data */
#if 0
printf (" [128 bytes of data] %d\n", sum & 0xff);
#endif
printf_filtered (" [%s] %d\n", packet, sum & 0xff);
if ((packet[XMODEM_PACKETSIZE] & 0xff) != (sum & 0xff)) {
debuglogs (4, "xmodem: data checksum wrong, got a %d", packet[XMODEM_PACKETSIZE] & 0xff);
}
putchar ('\n');
}
/*
* _initialize_remote_monitors -- setup a few addtitional commands that
* are usually only used by monitors.

143
gdb/rom68k-rom.c Normal file
View file

@ -0,0 +1,143 @@
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
#include "monitor.h"
extern int baud_rate;
void rom68k_open();
void monitor_open();
/*
* this array of registers need to match the indexes used by GDB. The
* whole reason this exists is cause the various ROM monitors use
* different strings than GDB does, and doesn't support all the
* registers either. So, typing "info reg sp" becomes a "r30".
*/
static char *rom68k_regnames[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1",
"a2", "a3", "a4", "a5", "a6", "usp", "ssp","pc", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", ""
};
/*
* Define the monitor command strings. Since these are passed directly
* through to a printf style function, we need can include formatting
* strings. We also need a CR or LF on the end.
*/
struct target_ops rom68k_ops = {
"rom68k",
"WinBond's debug monitor for the Rom68k Eval board",
"Debug on a Motorola IDP eval board running the ROM68K monitor.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).",
rom68k_open,
monitor_close,
monitor_attach,
monitor_detach,
monitor_resume,
monitor_wait,
monitor_fetch_register,
monitor_store_register,
monitor_prepare_to_store,
monitor_xfer_inferior_memory,
monitor_files_info,
monitor_insert_breakpoint,
monitor_remove_breakpoint, /* Breakpoints */
0,
0,
0,
0,
0, /* Terminal handling */
monitor_kill,
monitor_load, /* load */
0, /* lookup_symbol */
monitor_create_inferior,
monitor_mourn_inferior,
0, /* can_run */
0, /* notice_signals */
process_stratum,
0, /* next */
1,
1,
1,
1,
1, /* all mem, mem, stack, regs, exec */
0,
0, /* Section pointers */
OPS_MAGIC, /* Always the last thing */
};
struct monitor_ops rom68k_cmds = {
1, /* 1 for ASCII, 0 for binary */
"\n", /* monitor init string */
"go \n", /* execute or usually GO command */
"go \n", /* continue command */
"st \n", /* single step */
"db %x\n", /* set a breakpoint */
"cb %x\r", /* clear a breakpoint */
0, /* 0 for number, 1 for address */
{
"pm %x %x\r", /* set memory */
"=", /* delimiter */
"", /* the result */
},
{
"dm %x 1\r", /* get memory */
"", /* delimiter */
"", /* the result */
},
{
"pr %s %x\r", /* set a register */
"", /* delimiter between registers */
"", /* the result */
},
{
"pr %s\n", /* get a register */
":", /* delimiter between registers */
"", /* the result */
},
"dc\n", /* download command */
"ROM68K :->", /* monitor command prompt */
"=", /* end-of-command delimitor */
".\n", /* optional command terminator */
&rom68k_ops, /* target operations */
"srec,xmodem-ascii,xmodem-srec,default",/* load types */
rom68k_regnames /* registers names */
};
void
rom68k_open(args, from_tty)
char *args;
int from_tty;
{
target_preopen(from_tty);
push_target (&rom68k_ops);
push_monitor (&rom68k_cmds);
monitor_open (args, "rom68k", from_tty);
}
void
_initialize_rom68k ()
{
add_target (&rom68k_ops);
/* this is the default, since it's the only baud rate supported by the hardware */
baud_rate = 9600;
}