1 /* Remote target communications for the Macraigor Systems BDM Wiggler
2 Copyright 1996 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "gdb_string.h"
32 #include "gdb-stabs.h"
37 #include <sys/types.h>
43 /* Wiggler serial protocol definitions */
45 #define DLE 020 /* Quote char */
46 #define SYN 026 /* Start of packet */
47 #define RAW_SYN ((026 << 8) | 026) /* get_quoted_char found a naked SYN */
51 #define WIGGLER_FLAG_RESET 0x01 /* Target is being reset */
52 #define WIGGLER_FLAG_STOPPED 0x02 /* Target is halted */
53 #define WIGGLER_FLAG_BDM 0x04 /* Target is in BDM */
54 #define WIGGLER_FLAG_PWF 0x08 /* Power failed */
55 #define WIGGLER_FLAG_CABLE_DISC 0x10 /* BDM cable disconnected */
57 #define WIGGLER_AYT 0x0 /* Are you there? */
58 #define WIGGLER_GET_VERSION 0x1 /* Get Version */
59 #define WIGGLER_SET_BAUD_RATE 0x2 /* Set Baud Rate */
60 #define WIGGLER_INIT 0x10 /* Initialize Wiggler */
61 #define WIGGLER_SET_SPEED 0x11 /* Set Speed */
62 #define WIGGLER_GET_STATUS_MASK 0x12 /* Get Status Mask */
63 #define WIGGLER_GET_CTRS 0x13 /* Get Error Counters */
64 #define WIGGLER_SET_FUNC_CODE 0x14 /* Set Function Code */
65 #define WIGGLER_SET_CTL_FLAGS 0x15 /* Set Control Flags */
66 #define WIGGLER_SET_BUF_ADDR 0x16 /* Set Register Buffer Address */
67 #define WIGGLER_RUN 0x20 /* Run Target from PC */
68 #define WIGGLER_RUN_ADDR 0x21 /* Run Target from Specified Address */
69 #define WIGGLER_STOP 0x22 /* Stop Target */
70 #define WIGGLER_RESET_RUN 0x23 /* Reset Target and Run */
71 #define WIGGLER_RESET 0x24 /* Reset Target and Halt */
72 #define WIGGLER_STEP 0x25 /* Single step */
73 #define WIGGLER_READ_REGS 0x30 /* Read Registers */
74 #define WIGGLER_WRITE_REGS 0x31 /* Write Registers */
75 #define WIGGLER_READ_MEM 0x32 /* Read Memory */
76 #define WIGGLER_WRITE_MEM 0x33 /* Write Memory */
77 #define WIGGLER_FILL_MEM 0x34 /* Fill Memory */
78 #define WIGGLER_MOVE_MEM 0x35 /* Move Memory */
80 #define WIGGLER_READ_INT_MEM 0x80 /* Read Internal Memory */
81 #define WIGGLER_WRITE_INT_MEM 0x81 /* Write Internal Memory */
82 #define WIGGLER_JUMP 0x82 /* Jump to Subroutine */
84 #define WIGGLER_ERASE_FLASH 0x90 /* Erase flash memory */
85 #define WIGGLER_PROGRAM_FLASH 0x91 /* Write flash memory */
86 #define WIGGLER_EXIT_MON 0x93 /* Exit the flash programming monitor */
87 #define WIGGLER_ENTER_MON 0x94 /* Enter the flash programming monitor */
89 #define WIGGLER_SET_STATUS 0x0a /* Set status */
90 #define WIGGLER_FLAG_STOP 0x0 /* Stop the target, enter BDM */
91 #define WIGGLER_FLAG_START 0x01 /* Start the target at PC */
92 #define WIGGLER_FLAG_RETURN_STATUS 0x04 /* Return async status */
94 /* Stuff that should be in tm-xxx files. */
96 #define BDM_NUM_REGS 24
97 #define BDM_REGMAP 0, 1, 2, 3, 4, 5, 6, 7, /* d0 -> d7 */ \
98 8, 9, 10, 11, 12, 13, 14, 15, /* a0 -> a7 */ \
99 18, 16, /* ps, pc */ \
100 -1, -1, -1, -1, -1, -1, -1, -1, /* fp0 -> fp7 */ \
101 -1, -1, -1, -1, -1 /* fpcontrol, fpstatus, fpiaddr, fpcode, fpflags */
102 #define BDM_BREAKPOINT 0x4a, 0xfa /* BGND insn */
104 #define BDM_NUM_REGS 24
105 #define BDM_REGMAP 8, 9, 10, 11, 12, 13, 14, 15, /* d0 -> d7 */ \
106 16, 17, 18, 19, 20, 21, 22, 23, /* a0 -> a7 */ \
108 -1, -1, -1, -1, -1, -1, -1, -1, /* fp0 -> fp7 */ \
109 -1, -1, -1, -1, -1 /* fpcontrol, fpstatus, fpiaddr, fpcode, fpflags */
113 /* Prototypes for local functions */
115 static void wiggler_stop
PARAMS ((void));
117 static void put_packet
PARAMS ((unsigned char *packet
, int pktlen
));
118 static unsigned char * get_packet
PARAMS ((int cmd
, int *pktlen
, int timeout
));
120 static int wiggler_write_bytes
PARAMS ((CORE_ADDR memaddr
,
121 char *myaddr
, int len
));
123 static int wiggler_read_bytes
PARAMS ((CORE_ADDR memaddr
,
124 char *myaddr
, int len
));
126 static void wiggler_files_info
PARAMS ((struct target_ops
*ignore
));
128 static int wiggler_xfer_memory
PARAMS ((CORE_ADDR memaddr
, char *myaddr
,
129 int len
, int should_write
,
130 struct target_ops
*target
));
132 static void wiggler_prepare_to_store
PARAMS ((void));
134 static void wiggler_fetch_registers
PARAMS ((int regno
));
136 static void wiggler_resume
PARAMS ((int pid
, int step
,
137 enum target_signal siggnal
));
139 static int wiggler_start_remote
PARAMS ((char *dummy
));
141 static void wiggler_open
PARAMS ((char *name
, int from_tty
));
143 static void wiggler_close
PARAMS ((int quitting
));
145 static void wiggler_store_registers
PARAMS ((int regno
));
147 static void wiggler_mourn
PARAMS ((void));
149 static int readchar
PARAMS ((int timeout
));
151 static void reset_packet
PARAMS ((void));
153 static void output_packet
PARAMS ((void));
155 static int get_quoted_char
PARAMS ((int timeout
));
157 static void put_quoted_char
PARAMS ((int c
));
159 static int wiggler_wait
PARAMS ((int pid
, struct target_waitstatus
*status
));
161 static void wiggler_kill
PARAMS ((void));
163 static void wiggler_detach
PARAMS ((char *args
, int from_tty
));
165 static void wiggler_interrupt
PARAMS ((int signo
));
167 static void wiggler_interrupt_twice
PARAMS ((int signo
));
169 static void interrupt_query
PARAMS ((void));
171 static unsigned char * do_command
PARAMS ((int cmd
, int *statusp
, int *lenp
));
173 static unsigned char * read_bdm_registers
PARAMS ((int first_bdm_regno
,
177 extern struct target_ops wiggler_ops
; /* Forward decl */
179 static int last_run_status
;
181 /* This was 5 seconds, which is a long time to sit and wait.
182 Unless this is going though some terminal server or multiplexer or
183 other form of hairy serial connection, I would think 2 seconds would
186 /* Changed to allow option to set timeout value.
187 was static int remote_timeout = 2; */
188 extern int remote_timeout
;
190 /* Descriptor for I/O to remote machine. Initialize it to NULL so that
191 wiggler_open knows that we don't have a file open when the program
193 serial_t wiggler_desc
= NULL
;
196 wiggler_error (s
, error_code
)
202 fputs_filtered (s
, gdb_stderr
);
203 fputs_filtered (" ", gdb_stderr
);
207 case 0x1: s
= "Unknown fault"; break;
208 case 0x2: s
= "Power failed"; break;
209 case 0x3: s
= "Cable disconnected"; break;
210 case 0x4: s
= "Couldn't enter BDM"; break;
211 case 0x5: s
= "Target stuck in reset"; break;
212 case 0x6: s
= "Port not configured"; break;
213 case 0x7: s
= "Write verify failed"; break;
214 case 0x11: s
= "Bus error"; break;
215 case 0x12: s
= "Checksum error"; break;
216 case 0x13: s
= "Illegal command"; break;
217 case 0x14: s
= "Parameter error"; break;
218 case 0x15: s
= "Internal error"; break;
219 case 0x16: s
= "Register buffer error"; break;
220 case 0x80: s
= "Flash erase error"; break;
222 sprintf (buf
, "Unknown error code %d", error_code
);
229 /* Return nonzero if the thread TH is still alive on the remote system. */
232 wiggler_thread_alive (th
)
238 /* Clean up connection to a remote debugger. */
242 wiggler_close (quitting
)
246 SERIAL_CLOSE (wiggler_desc
);
250 /* Stub for catch_errors. */
253 wiggler_start_remote (dummy
)
256 unsigned char buf
[10], *p
;
262 immediate_quit
= 1; /* Allow user to interrupt it */
264 SERIAL_SEND_BREAK (wiggler_desc
); /* Wake up the wiggler */
266 do_command (WIGGLER_AYT
, &status
, &pktlen
);
268 p
= do_command (WIGGLER_GET_VERSION
, &status
, &pktlen
);
270 printf_unfiltered ("[Wiggler version %x.%x, capability 0x%x]\n",
271 p
[0], p
[1], (p
[2] << 16) | p
[3]);
274 speed
= 80; /* Divide clock by 4000 */
276 buf
[0] = WIGGLER_INIT
;
278 buf
[2] = speed
& 0xff;
279 buf
[3] = 0; /* CPU32 for now */
280 put_packet (buf
, 4); /* Init Wiggler params */
281 p
= get_packet (buf
[0], &pktlen
, remote_timeout
);
284 error ("Truncated response packet from Wiggler");
290 wiggler_error ("WIGGLER_INIT:", error_code
);
294 /* Reset the target */
296 do_command (WIGGLER_RESET_RUN
, &status
, &pktlen
);
297 /* do_command (WIGGLER_RESET, &status, &pktlen);*/
300 /* If processor is still running, stop it. */
302 if (!(status
& WIGGLER_FLAG_BDM
))
306 buf
[0] = WIGGLER_SET_CTL_FLAGS
;
308 buf
[2] = 1; /* Asynchronously return status when target stops */
311 p
= get_packet (buf
[0], &pktlen
, remote_timeout
);
314 error ("Truncated response packet from Wiggler");
320 wiggler_error ("WIGGLER_SET_CTL_FLAGS:", error_code
);
325 /* This is really the job of start_remote however, that makes an assumption
326 that the target is about to print out a status message of some sort. That
327 doesn't happen here (in fact, it may not be possible to get the monitor to
328 send the appropriate packet). */
330 flush_cached_frames ();
331 registers_changed ();
332 stop_pc
= read_pc ();
333 set_current_frame (create_new_frame (read_fp (), stop_pc
));
334 select_frame (get_current_frame (), 0);
335 print_stack_frame (selected_frame
, -1, 1);
340 /* Open a connection to a remote debugger.
341 NAME is the filename used for communication. */
343 static DCACHE
*wiggler_dcache
;
346 wiggler_open (name
, from_tty
)
351 error ("To open a Wiggler connection, you need to specify what serial\n\
352 device the Wiggler is attached to (e.g. /dev/ttya).");
354 target_preopen (from_tty
);
356 unpush_target (&wiggler_ops
);
358 wiggler_dcache
= dcache_init (wiggler_read_bytes
, wiggler_write_bytes
);
360 wiggler_desc
= SERIAL_OPEN (name
);
362 perror_with_name (name
);
366 if (SERIAL_SETBAUDRATE (wiggler_desc
, baud_rate
))
368 SERIAL_CLOSE (wiggler_desc
);
369 perror_with_name (name
);
373 SERIAL_RAW (wiggler_desc
);
375 /* If there is something sitting in the buffer we might take it as a
376 response to a command, which would be bad. */
377 SERIAL_FLUSH_INPUT (wiggler_desc
);
381 puts_filtered ("Remote target wiggler connected to ");
382 puts_filtered (name
);
383 puts_filtered ("\n");
385 push_target (&wiggler_ops
); /* Switch to using remote target now */
387 /* Without this, some commands which require an active target (such as kill)
388 won't work. This variable serves (at least) double duty as both the pid
389 of the target process (if it has such), and as a flag indicating that a
390 target is active. These functions should be split out into seperate
391 variables, especially since GDB will someday have a notion of debugging
392 several processes. */
394 inferior_pid
= 42000;
395 /* Start the remote connection; if error (0), discard this target.
396 In particular, if the user quits, be sure to discard it
397 (we'd be in an inconsistent state otherwise). */
398 if (!catch_errors (wiggler_start_remote
, (char *)0,
399 "Couldn't establish connection to remote target\n", RETURN_MASK_ALL
))
403 /* This takes a program previously attached to and detaches it. After
404 this is done, GDB can be used to debug some other program. We
405 better not have left any breakpoints in the target program or it'll
406 die when it hits one. */
409 wiggler_detach (args
, from_tty
)
414 error ("Argument given to \"detach\" when remotely debugging.");
418 puts_filtered ("Ending remote debugging.\n");
421 /* Tell the remote machine to resume. */
424 wiggler_resume (pid
, step
, siggnal
)
426 enum target_signal siggnal
;
430 dcache_flush (wiggler_dcache
);
433 do_command (WIGGLER_STEP
, &last_run_status
, &pktlen
);
435 do_command (WIGGLER_RUN
, &last_run_status
, &pktlen
);
444 do_command (WIGGLER_STOP
, &status
, &pktlen
);
446 if (!(status
& WIGGLER_FLAG_BDM
))
447 error ("Can't stop target via BDM");
450 static volatile int wiggler_interrupt_flag
;
452 /* Send ^C to target to halt it. Target will respond, and send us a
456 wiggler_interrupt (signo
)
459 /* If this doesn't work, try more severe steps. */
460 signal (signo
, wiggler_interrupt_twice
);
463 printf_unfiltered ("wiggler_interrupt called\n");
469 buf
[0] = WIGGLER_AYT
;
471 wiggler_interrupt_flag
= 1;
475 static void (*ofunc
)();
477 /* The user typed ^C twice. */
479 wiggler_interrupt_twice (signo
)
482 signal (signo
, ofunc
);
486 signal (signo
, wiggler_interrupt
);
489 /* Ask the user what to do when an interrupt is received. */
494 target_terminal_ours ();
496 if (query ("Interrupted while waiting for the program.\n\
497 Give up (and stop debugging it)? "))
499 target_mourn_inferior ();
500 return_to_top_level (RETURN_QUIT
);
503 target_terminal_inferior ();
506 /* If nonzero, ignore the next kill. */
507 static int kill_kludge
;
509 /* Wait until the remote machine stops, then return,
510 storing status in STATUS just as `wait' would.
511 Returns "pid" (though it's not clear what, if anything, that
512 means in the case of this target). */
515 wiggler_wait (pid
, target_status
)
517 struct target_waitstatus
*target_status
;
520 int error_code
, status
;
523 wiggler_interrupt_flag
= 0;
525 target_status
->kind
= TARGET_WAITKIND_STOPPED
;
526 target_status
->value
.sig
= TARGET_SIGNAL_TRAP
;
528 /* Target may already be stopped by the time we get here. */
530 if (!(last_run_status
& WIGGLER_FLAG_BDM
))
532 ofunc
= (void (*)()) signal (SIGINT
, wiggler_interrupt
);
534 p
= get_packet (WIGGLER_AYT
, &pktlen
, -1);
536 signal (SIGINT
, ofunc
);
539 error ("Truncated response packet from Wiggler");
545 wiggler_error ("target_wait:", error_code
);
547 if (status
& WIGGLER_FLAG_PWF
)
548 error ("Wiggler lost VCC at BDM interface.");
549 else if (status
& WIGGLER_FLAG_CABLE_DISC
)
550 error ("BDM cable appears to have been disconnected.");
552 if (!(status
& WIGGLER_FLAG_BDM
))
553 error ("Wiggler woke up, but wasn't stopped: 0x%x", status
);
555 if (wiggler_interrupt_flag
)
556 target_status
->value
.sig
= TARGET_SIGNAL_INT
;
559 /* This test figures out if we just executed a BGND insn, and if it's one of
560 our breakpoints. If so, then we back up PC. N.B. When a BGND insn is
561 executed, the PC points at the loc just after the insn (ie: it's always
562 two bytes *after* the BGND). So, it's not sufficient to just see if PC-2
563 is a BGND insn because we could have gotten there via a jump. We dis-
564 ambiguate this case by examining the ATEMP register (which is only
565 accessible from BDM). This will tell us if we entered BDM because we
566 executed a BGND insn. */
568 if (breakpoint_inserted_here_p (read_pc () - 2)) /* One of our breakpoints? */
569 { /* Yes, see if we actually executed it */
570 #if 0 /* Temporarily disabled until atemp reading is fixed. */
574 p
= read_bdm_registers (23, 23, &numregs
);
575 atemp
= extract_unsigned_integer (p
, 4);
577 if (atemp
== 1) /* And, did we hit a breakpoint insn? */
579 write_pc (read_pc () - 2); /* Yes, then back up PC */
585 /* Read the remote registers into the block REGS. */
586 /* Currently we just read all the registers, so we don't use regno. */
589 static unsigned char *
590 read_bdm_registers (first_bdm_regno
, last_bdm_regno
, numregs
)
595 unsigned char buf
[10];
599 int error_code
, status
;
602 buf
[0] = WIGGLER_READ_REGS
;
603 buf
[1] = first_bdm_regno
>> 8;
604 buf
[2] = first_bdm_regno
& 0xff;
605 buf
[3] = last_bdm_regno
>> 8;
606 buf
[4] = last_bdm_regno
& 0xff;
609 p
= get_packet (WIGGLER_READ_REGS
, &pktlen
, remote_timeout
);
612 error ("Truncated response packet from Wiggler");
618 wiggler_error ("read_bdm_registers:", error_code
);
626 error ("Register block size bad: %d", i
);
642 regs
= read_bdm_registers (0, BDM_NUM_REGS
- 1, &numregs
);
644 printf_unfiltered ("rpc = 0x%x ",
645 (int)extract_unsigned_integer (regs
, 4));
647 printf_unfiltered ("usp = 0x%x ",
648 (int)extract_unsigned_integer (regs
, 4));
650 printf_unfiltered ("ssp = 0x%x ",
651 (int)extract_unsigned_integer (regs
, 4));
653 printf_unfiltered ("vbr = 0x%x ",
654 (int)extract_unsigned_integer (regs
, 4));
656 printf_unfiltered ("sr = 0x%x ",
657 (int)extract_unsigned_integer (regs
, 4));
659 printf_unfiltered ("sfc = 0x%x ",
660 (int)extract_unsigned_integer (regs
, 4));
662 printf_unfiltered ("dfc = 0x%x ",
663 (int)extract_unsigned_integer (regs
, 4));
665 printf_unfiltered ("atemp = 0x%x ",
666 (int)extract_unsigned_integer (regs
, 4));
668 printf_unfiltered ("\n");
670 for (i
= 0; i
<= 7; i
++)
671 printf_unfiltered ("d%i = 0x%x ", i
,
672 (int)extract_unsigned_integer (regs
+ i
* 4, 4));
674 printf_unfiltered ("\n");
676 for (i
= 0; i
<= 7; i
++)
677 printf_unfiltered ("a%i = 0x%x ", i
,
678 (int)extract_unsigned_integer (regs
+ i
* 4, 4));
679 printf_unfiltered ("\n");
682 static int bdm_regmap
[] = {BDM_REGMAP
};
684 /* Read the remote registers into the block REGS. */
685 /* Currently we just read all the registers, so we don't use regno. */
688 wiggler_fetch_registers (regno
)
693 int first_regno
, last_regno
;
694 int first_bdm_regno
, last_bdm_regno
;
700 last_regno
= NUM_REGS
- 1;
703 last_bdm_regno
= BDM_NUM_REGS
- 1;
710 first_bdm_regno
= bdm_regmap
[regno
];
711 last_bdm_regno
= bdm_regmap
[regno
];
714 if (first_bdm_regno
== -1)
716 supply_register (first_regno
, NULL
);
717 return; /* Unsupported register */
720 regs
= read_bdm_registers (first_bdm_regno
, last_bdm_regno
, &numregs
);
722 for (i
= first_regno
; i
<= last_regno
; i
++)
724 int bdm_regno
, regoffset
;
726 bdm_regno
= bdm_regmap
[i
];
729 regoffset
= bdm_regno
- first_bdm_regno
;
731 if (regoffset
>= numregs
)
734 supply_register (i
, regs
+ 4 * regoffset
);
737 supply_register (i
, NULL
); /* Unsupported register */
742 wiggler_prepare_to_store ()
746 /* Store register REGNO, or all registers if REGNO == -1, from the contents
747 of REGISTERS. FIXME: ignores errors. */
750 wiggler_store_registers (regno
)
753 unsigned char buf
[10 + 256];
756 int error_code
, status
;
758 int first_regno
, last_regno
;
759 int first_bdm_regno
, last_bdm_regno
;
764 last_regno
= NUM_REGS
- 1;
767 last_bdm_regno
= BDM_NUM_REGS
- 1;
774 first_bdm_regno
= bdm_regmap
[regno
];
775 last_bdm_regno
= bdm_regmap
[regno
];
778 if (first_bdm_regno
== -1)
779 return; /* Unsupported register */
781 buf
[0] = WIGGLER_WRITE_REGS
;
784 for (i
= first_regno
; i
<= last_regno
; i
++)
788 bdm_regno
= bdm_regmap
[i
];
790 buf
[1] = bdm_regno
>> 8;
791 buf
[2] = bdm_regno
& 0xff;
793 memcpy (&buf
[4], ®isters
[REGISTER_BYTE (i
)], 4);
794 put_packet (buf
, 4 + 4);
795 p
= get_packet (WIGGLER_WRITE_REGS
, &pktlen
, remote_timeout
);
798 error ("Truncated response packet from Wiggler");
804 wiggler_error ("wiggler_store_registers:", error_code
);
808 /* Write memory data directly to the remote machine.
809 This does not inform the data cache; the data cache uses this.
810 MEMADDR is the address in the remote memory space.
811 MYADDR is the address of the buffer in our space.
812 LEN is the number of bytes.
814 Returns number of bytes transferred, or 0 for error. */
817 wiggler_write_bytes (memaddr
, myaddr
, len
)
828 buf
[0] = WIGGLER_WRITE_MEM
;
829 buf
[5] = 1; /* Write as bytes */
830 buf
[6] = 0; /* Don't verify */
836 int status
, error_code
;
838 numbytes
= min (len
, 256 - 8);
840 buf
[1] = memaddr
>> 24;
841 buf
[2] = memaddr
>> 16;
842 buf
[3] = memaddr
>> 8;
847 memcpy (&buf
[8], myaddr
, numbytes
);
848 put_packet (buf
, 8 + numbytes
);
849 p
= get_packet (WIGGLER_WRITE_MEM
, &pktlen
, remote_timeout
);
851 error ("Truncated response packet from Wiggler");
856 if (error_code
== 0x11) /* Got a bus error? */
858 CORE_ADDR error_address
;
860 error_address
= p
[3] << 24;
861 error_address
|= p
[4] << 16;
862 error_address
|= p
[5] << 8;
863 error_address
|= p
[6];
864 numbytes
= error_address
- memaddr
;
872 else if (error_code
!= 0)
873 wiggler_error ("wiggler_write_bytes:", error_code
);
880 return origlen
- len
;
883 /* Read memory data directly from the remote machine.
884 This does not use the data cache; the data cache uses this.
885 MEMADDR is the address in the remote memory space.
886 MYADDR is the address of the buffer in our space.
887 LEN is the number of bytes.
889 Returns number of bytes transferred, or 0 for error. */
892 wiggler_read_bytes (memaddr
, myaddr
, len
)
903 buf
[0] = WIGGLER_READ_MEM
;
904 buf
[5] = 1; /* Read as bytes */
910 int status
, error_code
;
912 numbytes
= min (len
, 256 - 7);
914 buf
[1] = memaddr
>> 24;
915 buf
[2] = memaddr
>> 16;
916 buf
[3] = memaddr
>> 8;
922 p
= get_packet (WIGGLER_READ_MEM
, &pktlen
, remote_timeout
);
924 error ("Truncated response packet from Wiggler");
929 if (error_code
== 0x11) /* Got a bus error? */
931 CORE_ADDR error_address
;
933 error_address
= p
[3] << 24;
934 error_address
|= p
[4] << 16;
935 error_address
|= p
[5] << 8;
936 error_address
|= p
[6];
937 numbytes
= error_address
- memaddr
;
945 else if (error_code
!= 0)
946 wiggler_error ("wiggler_read_bytes:", error_code
);
948 memcpy (myaddr
, &p
[4], numbytes
);
955 return origlen
- len
;
958 /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
959 to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
960 nonzero. Returns length of data written or read; 0 for error. */
964 wiggler_xfer_memory (memaddr
, myaddr
, len
, should_write
, target
)
969 struct target_ops
*target
; /* ignored */
971 return dcache_xfer_memory (wiggler_dcache
, memaddr
, myaddr
, len
, should_write
);
975 wiggler_files_info (ignore
)
976 struct target_ops
*ignore
;
978 puts_filtered ("Debugging a target over a serial line.\n");
981 /* Stuff for dealing with the packets which are part of this protocol.
982 See comment at top of file for details. */
984 /* Read a single character from the remote side, handling wierd errors. */
992 ch
= SERIAL_READCHAR (wiggler_desc
, timeout
);
997 error ("Remote connection closed");
999 perror_with_name ("Remote communication error");
1000 case SERIAL_TIMEOUT
:
1007 /* Read a character from the data stream, dequoting as necessary. SYN is
1008 treated special. Any SYNs appearing in the data stream are returned as the
1009 distinct value RAW_SYN (which has a value > 8 bits and therefore cannot be
1010 mistaken for real data). */
1013 get_quoted_char (timeout
)
1018 ch
= readchar (timeout
);
1022 case SERIAL_TIMEOUT
:
1023 error ("Timeout in mid-packet, aborting");
1027 ch
= readchar (timeout
);
1036 static unsigned char pkt
[256 * 2 + 10], *pktp
; /* Worst case */
1047 if (SERIAL_WRITE (wiggler_desc
, pkt
, pktp
- pkt
))
1048 perror_with_name ("output_packet: write failed");
1053 /* Output a quoted character. SYNs and DLEs are quoted. Everything else goes
1054 through untouched. */
1071 /* Send a packet to the Wiggler. The packet framed by a SYN character, a byte
1072 count and a checksum. The byte count only counts the number of bytes
1073 between the count and the checksum. A count of zero actually means 256.
1074 Any SYNs within the packet (including the checksum and count) must be
1075 quoted. The quote character must be quoted as well. Quoting is done by
1076 replacing the character with the two-character sequence DLE, {char} | 0100.
1077 Note that the quoting mechanism has no effect on the byte count.
1081 stu_put_packet (buf
, len
)
1085 unsigned char checksum
;
1088 if (len
== 0 || len
> 256)
1089 abort (); /* Can't represent 0 length packet */
1095 put_quoted_char (RAW_SYN
);
1103 put_quoted_char (c
);
1109 put_quoted_char (-checksum
& 0xff);
1116 /* Send a packet to the Wiggler. The packet framed by a SYN character, a byte
1117 count and a checksum. The byte count only counts the number of bytes
1118 between the count and the checksum. A count of zero actually means 256.
1119 Any SYNs within the packet (including the checksum and count) must be
1120 quoted. The quote character must be quoted as well. Quoting is done by
1121 replacing the character with the two-character sequence DLE, {char} | 0100.
1122 Note that the quoting mechanism has no effect on the byte count.
1126 put_packet (buf
, len
)
1130 unsigned char checksum
;
1132 unsigned char *packet
, *packet_ptr
;
1134 packet
= alloca (len
+ 1 + 1); /* packet + SYN + checksum */
1135 packet_ptr
= packet
;
1139 *packet_ptr
++ = 0x55;
1149 *packet_ptr
++ = -checksum
;
1150 if (SERIAL_WRITE (wiggler_desc
, packet
, packet_ptr
- packet
))
1151 perror_with_name ("output_packet: write failed");
1156 /* Get a packet from the Wiggler. Timeout is only enforced for the first byte
1157 of the packet. Subsequent bytes are expected to arrive in time <=
1158 remote_timeout. Returns a pointer to a static buffer containing the payload
1159 of the packet. *LENP contains the length of the packet.
1162 static unsigned char *
1163 stu_get_packet (cmd
, lenp
, timeout
)
1169 static unsigned char buf
[256 + 10], *p
;
1170 unsigned char checksum
;
1174 ch
= get_quoted_char (timeout
);
1177 error ("get_packet (readchar): %d", ch
);
1182 found_syn
: /* Found the start of a packet */
1187 len
= get_quoted_char (remote_timeout
);
1197 len
++; /* Include checksum */
1201 ch
= get_quoted_char (remote_timeout
);
1213 error ("Response phase error. Got 0x%x, expected 0x%x", buf
[0], cmd
);
1215 *lenp
= p
- buf
- 1;
1221 /* Get a packet from the Wiggler. Timeout is only enforced for the first byte
1222 of the packet. Subsequent bytes are expected to arrive in time <=
1223 remote_timeout. Returns a pointer to a static buffer containing the payload
1224 of the packet. *LENP contains the length of the packet.
1227 static unsigned char *
1228 get_packet (cmd
, lenp
, timeout
)
1235 static unsigned char packet
[512];
1236 unsigned char *packet_ptr
;
1237 unsigned char checksum
;
1241 ch
= readchar (timeout
);
1244 error ("get_packet (readchar): %d", ch
);
1249 /* Found the start of a packet */
1251 packet_ptr
= packet
;
1254 /* Read command char. That sort of tells us how long the packet is. */
1256 ch
= readchar (timeout
);
1259 error ("get_packet (readchar): %d", ch
);
1266 ch
= readchar (timeout
);
1269 error ("get_packet (readchar): %d", ch
);
1273 /* Get error code. */
1275 ch
= readchar (timeout
);
1278 error ("get_packet (readchar): %d", ch
);
1282 switch (ch
) /* Figure out length of packet */
1284 case 0x7: /* Write verify error? */
1285 len
= 8; /* write address, value read back */
1287 case 0x11: /* Bus error? */
1288 /* write address, read flag */
1289 case 0x15: /* Internal error */
1290 len
= 5; /* error code, vector */
1292 default: /* Error w/no params */
1294 case 0x0: /* Normal result */
1297 case WIGGLER_AYT
: /* Are You There? */
1298 case WIGGLER_SET_BAUD_RATE
: /* Set Baud Rate */
1299 case WIGGLER_INIT
: /* Initialize wiggler */
1300 case WIGGLER_SET_SPEED
: /* Set Speed */
1301 case WIGGLER_SET_FUNC_CODE
: /* Set Function Code */
1302 case WIGGLER_SET_CTL_FLAGS
: /* Set Control Flags */
1303 case WIGGLER_SET_BUF_ADDR
: /* Set Register Buffer Address */
1304 case WIGGLER_RUN
: /* Run Target from PC */
1305 case WIGGLER_RUN_ADDR
: /* Run Target from Specified Address */
1306 case WIGGLER_STOP
: /* Stop Target */
1307 case WIGGLER_RESET_RUN
: /* Reset Target and Run */
1308 case WIGGLER_RESET
: /* Reset Target and Halt */
1309 case WIGGLER_STEP
: /* Single Step */
1310 case WIGGLER_WRITE_REGS
: /* Write Register */
1311 case WIGGLER_WRITE_MEM
: /* Write Memory */
1312 case WIGGLER_FILL_MEM
: /* Fill Memory */
1313 case WIGGLER_MOVE_MEM
: /* Move Memory */
1314 case WIGGLER_WRITE_INT_MEM
: /* Write Internal Memory */
1315 case WIGGLER_JUMP
: /* Jump to Subroutine */
1316 case WIGGLER_ERASE_FLASH
: /* Erase flash memory */
1317 case WIGGLER_PROGRAM_FLASH
: /* Write flash memory */
1318 case WIGGLER_EXIT_MON
: /* Exit the flash programming monitor */
1319 case WIGGLER_ENTER_MON
: /* Enter the flash programming monitor */
1322 case WIGGLER_GET_VERSION
: /* Get Version */
1325 case WIGGLER_GET_STATUS_MASK
: /* Get Status Mask */
1328 case WIGGLER_GET_CTRS
: /* Get Error Counters */
1329 case WIGGLER_READ_REGS
: /* Read Register */
1330 case WIGGLER_READ_MEM
: /* Read Memory */
1331 case WIGGLER_READ_INT_MEM
: /* Read Internal Memory */
1335 fprintf_filtered (gdb_stderr
, "Unknown packet type 0x%x\n", ch
);
1340 if (len
== 257) /* Byte stream? */
1341 { /* Yes, byte streams contain the length */
1342 ch
= readchar (timeout
);
1345 error ("get_packet (readchar): %d", ch
);
1353 while (len
-- >= 0) /* Do rest of packet and checksum */
1355 ch
= readchar (timeout
);
1358 error ("get_packet (readchar): %d", ch
);
1366 if (cmd
!= -1 && cmd
!= packet
[0])
1367 error ("Response phase error. Got 0x%x, expected 0x%x", packet
[0], cmd
);
1369 *lenp
= packet_ptr
- packet
- 1; /* Subtract checksum byte */
1374 /* Execute a simple (one-byte) command. Returns a pointer to the data
1375 following the error code. */
1377 static unsigned char *
1378 do_command (cmd
, statusp
, lenp
)
1383 unsigned char buf
[100], *p
;
1384 int status
, error_code
;
1388 put_packet (buf
, 1); /* Send command */
1389 p
= get_packet (*buf
, lenp
, remote_timeout
);
1392 error ("Truncated response packet from Wiggler");
1397 if (error_code
!= 0)
1399 sprintf (errbuf
, "do_command (0x%x):", cmd
);
1400 wiggler_error (errbuf
, error_code
);
1403 if (status
& WIGGLER_FLAG_PWF
)
1404 error ("Wiggler can't detect VCC at BDM interface.");
1405 else if (status
& WIGGLER_FLAG_CABLE_DISC
)
1406 error ("BDM cable appears to be disconnected.");
1416 /* For some mysterious reason, wait_for_inferior calls kill instead of
1417 mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
1421 target_mourn_inferior ();
1425 /* Don't wait for it to die. I'm not really sure it matters whether
1427 target_mourn_inferior ();
1433 unpush_target (&wiggler_ops
);
1434 generic_mourn_inferior ();
1437 /* All we actually do is set the PC to the start address of exec_bfd, and start
1438 the program at that point. */
1441 wiggler_create_inferior (exec_file
, args
, env
)
1446 if (args
&& (*args
!= '\000'))
1447 error ("Args are not supported by BDM.");
1449 clear_proceed_status ();
1450 proceed (bfd_get_start_address (exec_bfd
), TARGET_SIGNAL_0
, 0);
1454 wiggler_load (args
, from_tty
)
1458 generic_load (args
, from_tty
);
1462 /* This is necessary because many things were based on the PC at the time that
1463 we attached to the monitor, which is no longer valid now that we have loaded
1464 new code (and just changed the PC). Another way to do this might be to call
1465 normal_stop, except that the stack may not be valid, and things would get
1466 horribly confused... */
1468 clear_symtab_users ();
1471 /* BDM (at least on CPU32) uses a different breakpoint */
1474 wiggler_insert_breakpoint (addr
, contents_cache
)
1476 char *contents_cache
;
1478 static char break_insn
[] = {BDM_BREAKPOINT
};
1481 val
= target_read_memory (addr
, contents_cache
, sizeof break_insn
);
1484 val
= target_write_memory (addr
, break_insn
, sizeof break_insn
);
1490 bdm_command (args
, from_tty
)
1494 error ("bdm command must be followed by `reset'");
1498 bdm_reset_command (args
, from_tty
)
1505 error ("Not connected to wiggler.");
1507 do_command (WIGGLER_RESET
, &status
, &pktlen
);
1508 dcache_flush (wiggler_dcache
);
1509 registers_changed ();
1513 bdm_restart_command (args
, from_tty
)
1520 error ("Not connected to wiggler.");
1522 do_command (WIGGLER_RESET_RUN
, &status
, &pktlen
);
1523 last_run_status
= status
;
1524 clear_proceed_status ();
1525 wait_for_inferior ();
1530 flash_xfer_memory (memaddr
, myaddr
, len
, should_write
, target
)
1535 struct target_ops
*target
; /* ignored */
1546 buf
[0] = WIGGLER_PROGRAM_FLASH
;
1552 int status
, error_code
;
1554 numbytes
= min (len
, 256 - 6);
1556 buf
[1] = memaddr
>> 24;
1557 buf
[2] = memaddr
>> 16;
1558 buf
[3] = memaddr
>> 8;
1563 memcpy (&buf
[6], myaddr
, numbytes
);
1564 put_packet (buf
, 6 + numbytes
);
1565 p
= get_packet (WIGGLER_PROGRAM_FLASH
, &pktlen
, remote_timeout
);
1567 error ("Truncated response packet from Wiggler");
1572 if (error_code
!= 0)
1573 wiggler_error ("flash_xfer_memory:", error_code
);
1576 memaddr
+= numbytes
;
1580 return origlen
- len
;
1584 bdm_update_flash_command (args
, from_tty
)
1589 struct cleanup
*old_chain
;
1592 error ("Not connected to wiggler.");
1595 error ("Must specify file containing new Wiggler code.");
1597 /* old_chain = make_cleanup (flash_cleanup, 0);*/
1599 do_command (WIGGLER_ENTER_MON
, &status
, &pktlen
);
1601 do_command (WIGGLER_ERASE_FLASH
, &status
, &pktlen
);
1603 wiggler_ops
.to_xfer_memory
= flash_xfer_memory
;
1605 generic_load (args
, from_tty
);
1607 wiggler_ops
.to_xfer_memory
= wiggler_xfer_memory
;
1609 do_command (WIGGLER_EXIT_MON
, &status
, &pktlen
);
1611 /* discard_cleanups (old_chain);*/
1614 /* Define the target subroutine names */
1616 struct target_ops wiggler_ops
= {
1617 "wiggler", /* to_shortname */
1618 "", /* to_longname */
1620 wiggler_open
, /* to_open */
1621 wiggler_close
, /* to_close */
1622 NULL
, /* to_attach */
1623 wiggler_detach
, /* to_detach */
1624 wiggler_resume
, /* to_resume */
1625 wiggler_wait
, /* to_wait */
1626 wiggler_fetch_registers
, /* to_fetch_registers */
1627 wiggler_store_registers
, /* to_store_registers */
1628 wiggler_prepare_to_store
, /* to_prepare_to_store */
1629 wiggler_xfer_memory
, /* to_xfer_memory */
1630 wiggler_files_info
, /* to_files_info */
1631 wiggler_insert_breakpoint
, /* to_insert_breakpoint */
1632 memory_remove_breakpoint
, /* to_remove_breakpoint */
1633 NULL
, /* to_terminal_init */
1634 NULL
, /* to_terminal_inferior */
1635 NULL
, /* to_terminal_ours_for_output */
1636 NULL
, /* to_terminal_ours */
1637 NULL
, /* to_terminal_info */
1638 wiggler_kill
, /* to_kill */
1639 wiggler_load
, /* to_load */
1640 NULL
, /* to_lookup_symbol */
1641 wiggler_create_inferior
, /* to_create_inferior */
1642 wiggler_mourn
, /* to_mourn_inferior */
1644 0, /* to_notice_signals */
1645 wiggler_thread_alive
, /* to_thread_alive */
1647 process_stratum
, /* to_stratum */
1649 1, /* to_has_all_memory */
1650 1, /* to_has_memory */
1651 1, /* to_has_stack */
1652 1, /* to_has_registers */
1653 1, /* to_has_execution */
1654 NULL
, /* sections */
1655 NULL
, /* sections_end */
1656 OPS_MAGIC
/* to_magic */
1660 _initialize_remote_wiggler ()
1662 extern struct cmd_list_element
*cmdlist
;
1663 static struct cmd_list_element
*bdm_cmd_list
= NULL
;
1665 add_target (&wiggler_ops
);
1667 add_show_from_set (add_set_cmd ("remotetimeout", no_class
,
1668 var_integer
, (char *)&remote_timeout
,
1669 "Set timeout value for remote read.\n", &setlist
),
1672 add_prefix_cmd ("bdm", class_obscure
, bdm_command
, "", &bdm_cmd_list
, "bdm ",
1675 add_cmd ("reset", class_obscure
, bdm_reset_command
, "", &bdm_cmd_list
);
1676 add_cmd ("restart", class_obscure
, bdm_restart_command
, "", &bdm_cmd_list
);
1677 add_cmd ("update-flash", class_obscure
, bdm_update_flash_command
, "", &bdm_cmd_list
);