diff options
| author | Bdale Garbee <bdale@gag.com> | 2009-08-18 14:40:54 -0600 | 
|---|---|---|
| committer | Bdale Garbee <bdale@gag.com> | 2009-08-18 14:40:54 -0600 | 
| commit | 7aa251970cbbb6b9d9678ed0721e28da3df9036b (patch) | |
| tree | 7e44c666040b1e8728510f2f5a99d6228ca3edd3 | |
| parent | 107055e969e89771d1e2f8ac8b1a4c5b4b9e9a48 (diff) | |
| parent | 1c2a0b6653623b689d68d7349a6b2dce3e20a4a6 (diff) | |
Merge branch 'master' into debian
| -rw-r--r-- | ao-tools/ao-dbg/ao-dbg-command.c | 654 | ||||
| -rw-r--r-- | ao-tools/ao-dbg/ao-dbg-main.c | 239 | ||||
| -rw-r--r-- | ao-tools/ao-dbg/ao-dbg-parse.c | 241 | ||||
| -rw-r--r-- | ao-tools/ao-dbg/ao-dbg.h | 123 | ||||
| -rw-r--r-- | ao-tools/ao-load/ao-load.c | 3 | 
5 files changed, 1260 insertions, 0 deletions
| diff --git a/ao-tools/ao-dbg/ao-dbg-command.c b/ao-tools/ao-dbg/ao-dbg-command.c new file mode 100644 index 00000000..eab7bc68 --- /dev/null +++ b/ao-tools/ao-dbg/ao-dbg-command.c @@ -0,0 +1,654 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-dbg.h" + +static uint16_t start_address; + +static enum command_result +parse_int(char *value, int *result) +{ +	char *endptr; + +	*result = strtol(value, &endptr, 0); +	if (endptr == value) +		return command_syntax; +	return command_success; +} + +static enum command_result +parse_uint16(char *value, uint16_t *uint16) +{ +	int	v; +	enum command_result result; + +	result = parse_int(value, &v); +	if (result != command_success) +		return command_error; +	if (v < 0 || v > 0xffff) +		return command_error; +	*uint16 = v; +	return command_success; +} + +static enum command_result +parse_uint8(char *value, uint8_t *uint8) +{ +	int	v; +	enum command_result result; + +	result = parse_int(value, &v); +	if (result != command_success) +		return command_error; +	if (v < 0 || v > 0xff) +		return command_error; +	*uint8 = v; +	return command_success; +} + +enum command_result +command_quit (int argc, char **argv) +{ +	ccdbg_reset(s51_dbg); +	exit(0); +	return command_error; +} + +static void +dump_bytes(uint8_t *memory, int length, uint16_t start, char *format) +{ +	int group, i; + +	for (group = 0; group < length; group += 8) { +		s51_printf(format, start + group); +		for (i = group; i < length && i < group + 8; i++) +			s51_printf("%02x ", memory[i]); +		for (; i < group + 8; i++) +			s51_printf("   "); +		for (i = group; i < length && i < group + 8; i++) { +			if (isascii(memory[i]) && isprint(memory[i])) +				s51_printf("%c", memory[i]); +			else +				s51_printf("."); +		} +		s51_printf("\n"); +	} +} + +enum command_result +command_di (int argc, char **argv) +{ +	uint16_t start, end; +	uint8_t	memory[65536]; +	uint8_t status; +	int length; + +	if (argc != 3) +		return command_error; +	if (parse_uint16(argv[1], &start) != command_success) +		return command_error; +	if (parse_uint16(argv[2], &end) != command_success) +		return command_error; +	length = (int) end - (int) start + 1; +	status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length); +	dump_bytes(memory, length, start, "0x%02x "); +	return command_success; +} + +enum command_result +command_ds (int argc, char **argv) +{ +	uint8_t start, end; +	uint8_t	memory[0x100]; +	uint8_t status; +	int length; + +	if (argc != 3) +		return command_error; +	if (parse_uint8(argv[1], &start) != command_success) +		return command_error; +	if (parse_uint8(argv[2], &end) != command_success) +		return command_error; +	length = (int) end - (int) start + 1; +	status = ccdbg_read_sfr(s51_dbg, start, memory, length); +	dump_bytes(memory, length, start, "0x%02x "); +	return command_success; +} + +enum command_result +command_dx (int argc, char **argv) +{ +	uint16_t start, end; +	uint8_t	memory[65536]; +	uint8_t status; +	int length; + +	if (argc != 3) +		return command_error; +	if (parse_uint16(argv[1], &start) != command_success) +		return command_error; +	if (parse_uint16(argv[2], &end) != command_success) +		return command_error; +	length = (int) end - (int) start + 1; +	status = ccdbg_read_memory(s51_dbg, start, memory, length); +	dump_bytes(memory, length, start, "0x%04x "); +	return command_success; +} + +enum command_result +command_set (int argc, char **argv) +{ +	uint16_t address; +	uint8_t *data; +	int len = argc - 3; +	int i; +	enum command_result ret = command_success; + +	if (len < 0) +		return command_error; +	if (parse_uint16(argv[2], &address) != command_success) +		return command_error; +	if (len == 0) +		return command_success; +	data = malloc(len); +	if (!data) +		return command_error; +	for (i = 0; i < len; i++) +		if (parse_uint8(argv[i+3], &data[i]) != command_success) +			return command_error; + +	if (strcmp(argv[1], "xram") == 0) { +		ccdbg_write_memory(s51_dbg, address, data, len); +	} else if (strcmp(argv[1], "iram") == 0) { +		ccdbg_write_memory(s51_dbg, address + 0xff00, data, len); +	} else if (strcmp(argv[1], "sfr") == 0) { +		ccdbg_write_sfr(s51_dbg, (uint8_t) address, data, len); +	} else +		ret = command_error; +	free(data); +	return ret; +} + +enum command_result +command_dump (int argc, char **argv) +{ +	if (argv[1]) { +		if (strcmp(argv[1], "rom") == 0 || +		    strcmp(argv[1], "xram") == 0) +			return command_dx(argc-1, argv+1); +		if (strcmp(argv[1], "iram") == 0) +			return command_di(argc-1, argv+1); +		if (strcmp(argv[1], "sfr") == 0) +			return command_ds(argc-1, argv+1); +	} +	return command_error; +} + +enum command_result +command_file (int argc, char **argv) +{ +	struct hex_file *hex; +	struct hex_image *image; +	FILE *file; + +	if (argc != 2) +		return command_error; +	file = fopen (argv[1], "r"); +	if (!file) +		return command_error; +	hex = ccdbg_hex_file_read(file, argv[1]); +	fclose(file); +	if (!hex) +		return command_error; +	if (hex->nrecord == 0) { +		ccdbg_hex_file_free(hex); +		return command_error; +	} +	image = ccdbg_hex_image_create(hex); +	ccdbg_hex_file_free(hex); +	start_address = image->address; +	ccdbg_set_rom(s51_dbg, image); +	return command_success; +} + +enum command_result +command_pc (int argc, char **argv) +{ +	uint16_t	pc; +	if (argv[1]) { +		enum command_result result; +		result = parse_uint16(argv[1], &pc); +		if (result != command_success) +			return result; +		ccdbg_set_pc(s51_dbg, pc); +	} else { +		pc = ccdbg_get_pc(s51_dbg); +		s51_printf("   0x%04x 00\n", pc); +	} +	return command_success; +} + +struct cc_break { +	int		enabled; +	int		temporary; +	uint16_t	address; +}; + +#define CC_NUM_BREAKPOINTS 4 + +static struct cc_break	breakpoints[CC_NUM_BREAKPOINTS]; + +static void +disable_breakpoint(int b) +{ +	uint8_t status; + +	status = ccdbg_set_hw_brkpnt(s51_dbg, b, 0, breakpoints[b].address); +	if (status != 0x00 && status != 0xff) +		s51_printf("disable_breakpoint status 0x%02x\n", status); +} + +static void +enable_breakpoint(int b) +{ +	uint8_t status; + +	status = ccdbg_set_hw_brkpnt(s51_dbg, b, 1, breakpoints[b].address); +	if (status != 0xff) +		s51_printf("enable_breakpoint status 0x%02x\n", status); +} + +static void +enable_breakpoints(void) +{ +	int b; +	for (b = 0; b < CC_NUM_BREAKPOINTS; b++) +		if (breakpoints[b].enabled) +			enable_breakpoint(b); +} + +enum command_result +set_breakpoint(uint16_t address, int temporary) +{ +	int b; +	uint8_t status; +	for (b = 0; b < CC_NUM_BREAKPOINTS; b++) { +		if (breakpoints[b].enabled == 0) +			break; +		if (breakpoints[b].address == address) +			break; +	} +	if (b == CC_NUM_BREAKPOINTS) { +		s51_printf("Error: too many breakpoints requested\n"); +		return command_success; +	} +	if (breakpoints[b].enabled == 0) { +		breakpoints[b].address = address; +		enable_breakpoint(b); +	} +	++breakpoints[b].enabled; +	s51_printf("Breakpoint %d at 0x%04x\n", b, address); +	breakpoints[b].temporary += temporary; +	return command_success; +} + +enum command_result +clear_breakpoint(uint16_t address, int temporary) +{ +	int b; +	uint8_t status; + +	for (b = 0; b < CC_NUM_BREAKPOINTS; b++) { +		if (breakpoints[b].enabled != 0 && +		    ((breakpoints[b].temporary != 0) == (temporary != 0)) && +		    breakpoints[b].address == address) +			break; +	} +	if (b == CC_NUM_BREAKPOINTS) { +		s51_printf("Error: no matching breakpoint found\n"); +		return command_success; +	} +	--breakpoints[b].enabled; +	breakpoints[b].temporary -= temporary; +	if (breakpoints[b].enabled == 0) { +		disable_breakpoint(b); +		breakpoints[b].address = -1; +	} +	return command_success; +} + + +int +find_breakpoint(uint16_t address) +{ +	int b; + +	for (b = 0; b < CC_NUM_BREAKPOINTS; b++) +		if (breakpoints[b].enabled && breakpoints[b].address == address) +			break; +	if (b == CC_NUM_BREAKPOINTS) +		return -1; +	return b; +} + +enum command_result +command_break (int argc, char **argv) +{ +	int b; +	uint16_t address; +	enum command_result result; + +	if (argc == 1) { +		for (b = 0; b < CC_NUM_BREAKPOINTS; b++) +			if (breakpoints[b].enabled) +				s51_printf("Breakpoint %d 0x%04x\n", +					b, breakpoints[b].address); +		return command_success; +	} +	if (argc != 2) +		return command_error; +	result = parse_uint16(argv[1], &address); +	if (result != command_success) +		return result; + +	return set_breakpoint(address, 0); +} + +enum command_result +command_clear (int argc, char **argv) +{ +	int b; +	uint16_t address; +	enum command_result result; + +	if (argc != 2) +		return command_error; +	result = parse_uint16(argv[1], &address); +	if (result != command_success) +		return result; +	return clear_breakpoint(address, 0); +} + +void +cc_stopped(uint8_t status) +{ +	uint16_t pc; +	int b; +	int code; +	char *reason; + +	pc = ccdbg_get_pc(s51_dbg); +	if (status & CC_STATUS_CPU_HALTED) { +		if ((status & CC_STATUS_HALT_STATUS) != 0) { +			pc = pc - 1; +			code = 104; +			reason = "Breakpoint"; +			b = find_breakpoint(pc); +			if (b != -1 && breakpoints[b].temporary) +				clear_breakpoint(pc, 1); +			ccdbg_set_pc(s51_dbg, pc); +		} else { +			code = 105; +			reason = "Interrupt"; +		} +		s51_printf("Stop at 0x%04x: (%d) %s\n", +			pc, code, reason); +	} +} + +uint8_t +cc_step(uint16_t pc) +{ +	int b; +	uint8_t status; + +	b = find_breakpoint(pc); +	if (b != -1) +		disable_breakpoint(b); +	status = ccdbg_step_instr(s51_dbg); +	if (b != -1) +		enable_breakpoint(b); +	return status; +} + +enum command_result +command_run (int argc, char **argv) +{ +	uint16_t start, end; +	enum command_result result; +	uint16_t pc; +	uint8_t status; +	int b; + +	if (argv[1]) { +		result = parse_uint16(argv[1], &start); +		if (result != command_success) +			return result; +		if (argv[2]) { +			result = parse_uint16(argv[2], &end); +			if (result != command_success) +				return result; +		} +		if (start_address && start == 0) { +			start = start_address; +			s51_printf("Starting at 0x%04x\n", start); +		} +		ccdbg_set_pc(s51_dbg, start); +	} +	else +		start = ccdbg_get_pc(s51_dbg); +	s51_printf("Resume at 0x%04x\n", start); +	pc = start; +	b = find_breakpoint(pc); +	if (b != -1) { +		cc_step(pc); +		pc = ccdbg_get_pc(s51_dbg); +		if (find_breakpoint(pc) != -1) { +			status = ccdbg_read_status(s51_dbg); +			cc_stopped(status); +			return command_success; +		} +	} +	ccdbg_resume(s51_dbg); +	result = cc_wait(); +	return result; +} + +enum command_result +command_next (int argc, char **argv) +{ +	return command_step(argc, argv); +} + +enum command_result +command_step (int argc, char **argv) +{ +	uint16_t pc; +	uint8_t	opcode; +	uint8_t a; + +	a = cc_step(ccdbg_get_pc(s51_dbg)); +	s51_printf(" ACC= 0x%02x\n", a); +	pc = ccdbg_get_pc(s51_dbg); +	ccdbg_read_memory(s51_dbg, pc, &opcode, 1); +	s51_printf(" ? 0x%04x %02x\n", pc, opcode); +	return command_success; +} + +enum command_result +command_load (int argc, char **argv) +{ +	char *filename = argv[1]; +	FILE *file; +	struct hex_file	*hex; +	struct hex_image *image; + +	if (!filename) +		return command_error; +	file = fopen(filename, "r"); +	if (!file) { +		perror(filename); +		return command_error; +	} +	hex = ccdbg_hex_file_read(file, filename); +	fclose(file); +	if (!hex) { +		return command_error; +	} +	image = ccdbg_hex_image_create(hex); +	ccdbg_hex_file_free(hex); +	if (!image) { +		fprintf(stderr, "image create failed\n"); +		return command_error; +	} +	if (image->address >= 0xf000) { +		printf("Loading %d bytes to RAM at 0x%04x\n", +		       image->length, image->address); +		ccdbg_write_hex_image(s51_dbg, image, 0); +	} else { +		fprintf(stderr, "Can only load to RAM\n"); +	} +	ccdbg_hex_image_free(image); +	return command_success; +} + +enum command_result +command_halt (int argc, char **argv) +{ +	uint16_t	pc; +	ccdbg_halt(s51_dbg); +	pc = ccdbg_get_pc(s51_dbg); +	s51_printf("Halted at 0x%04x\n", pc); +	return command_success; +} + +enum command_result +command_stop (int argc, char **argv) +{ +	return command_success; +} + +enum command_result +command_reset (int argc, char **argv) +{ +	ccdbg_debug_mode(s51_dbg); +	ccdbg_halt(s51_dbg); +	enable_breakpoints(); +	return command_success; +} + +enum command_result +command_status(int argc, char **argv) +{ +	uint8_t	status; + +	status = ccdbg_read_status(s51_dbg); +	if ((status & CC_STATUS_CHIP_ERASE_DONE) == 0) +		s51_printf("\tChip erase in progress\n"); +	if (status & CC_STATUS_PCON_IDLE) +		s51_printf("\tCPU is idle (clock gated)\n"); +	if (status & CC_STATUS_CPU_HALTED) +		s51_printf("\tCPU halted\n"); +	else +		s51_printf("\tCPU running\n"); +	if ((status & CC_STATUS_POWER_MODE_0) == 0) +		s51_printf("\tPower Mode 1-3 selected\n"); +	if (status & CC_STATUS_HALT_STATUS) +		s51_printf("\tHalted by software or hw breakpoint\n"); +	else +		s51_printf("\tHalted by debug command\n"); +	if (status & CC_STATUS_DEBUG_LOCKED) +		s51_printf("\tDebug interface is locked\n"); +	if ((status & CC_STATUS_OSCILLATOR_STABLE) == 0) +		s51_printf("\tOscillators are not stable\n"); +	if (status & CC_STATUS_STACK_OVERFLOW) +		s51_printf("\tStack overflow\n"); +	return command_success; +} + +static enum command_result +info_breakpoints(int argc, char **argv) +{ +	int b; +	uint16_t address; +	enum command_result result; + +	if (argc == 1) { +		s51_printf("Num Type       Disp Hit   Cnt   Address  What\n"); +		for (b = 0; b < CC_NUM_BREAKPOINTS; b++) +			if (breakpoints[b].enabled) { +				s51_printf("%-3d fetch      %s 1     1     0x%04x   uc::disass() unimplemented\n", +					   b, +					   breakpoints[b].temporary ? "del " : "keep", +					   breakpoints[b].address); +			} +		return command_success; +	} + +} + +static enum command_result +info_help(int argc, char **argv); + +static struct command_function infos[] = { +	{ "breakpoints", "b", info_breakpoints, "[b]reakpoints", +		"List current breakpoints\n" }, +	{ "help",   "?",  info_help,	"help", +		"Print this list\n" }, + +	{ NULL, NULL, NULL, NULL, NULL }, +}; + +static enum command_result +info_help(int argc, char **argv) +{ +	return command_function_help(infos, argc, argv); +} + +enum command_result +command_info(int argc, char **argv) +{ +	struct command_function *func; + +	if (argc < 2) +		return command_error; +	func = command_string_to_function(infos, argv[1]); +	if (!func) +		return command_syntax; +	return (*func->func)(argc-1, argv+1); +} + +enum command_result +cc_wait(void) +{ +	for(;;) { +		uint8_t status; +		status = ccdbg_read_status(s51_dbg); +		if (status & CC_STATUS_CPU_HALTED) { +			cc_stopped(status); +			return command_success; +		} +		if (s51_interrupted || s51_check_input()) { + +			ccdbg_halt(s51_dbg); +			status = ccdbg_read_status(s51_dbg); +			cc_stopped(status); +			return command_interrupt; +		} +	} +} diff --git a/ao-tools/ao-dbg/ao-dbg-main.c b/ao-tools/ao-dbg/ao-dbg-main.c new file mode 100644 index 00000000..72249a6b --- /dev/null +++ b/ao-tools/ao-dbg/ao-dbg-main.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-dbg.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <signal.h> +#include <stdarg.h> +#include <poll.h> + +static int s51_port = 0; +static char *cpu = "8051"; +static double freq = 11059200; +char *s51_prompt = "> "; +struct ccdbg *s51_dbg; +int s51_interrupted = 0; +int s51_monitor = 0; + +static FILE *s51_input; +static FILE *s51_output; + +static void +usage(void) +{ +	fprintf(stderr, "You're doing it wrong.\n"); +	exit(1); +} + +void s51_sigint() +{ +	s51_interrupted = 1; +} + +int +main(int argc, char **argv) +{ +	int flags, opt; +	char *endptr; +	struct sigvec vec, ovec; + +	while ((opt = getopt(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:")) != -1) { +		switch (opt) { +		case 't': +			cpu = optarg; +			break; +		case 'X': +			freq = strtod(optarg, &endptr); +			if (endptr == optarg) +				usage(); +			if (endptr[0] != '\0') { +				if (!strcmp(endptr, "k")) +					freq *= 1000; +				else if (!strcmp(endptr, "M") ) +					freq *= 1000000; +				else +					usage (); +			} +			break; +		case 'c': +			break; +		case 'r': +		case 'Z': +			s51_port = strtol(optarg, &endptr, 0); +			if (endptr == optarg || strlen(endptr) != 0) +				usage(); +			break; +		case 's': +			break; +		case 'S': +			break; +		case 'p': +			s51_prompt = optarg; +			break; +		case 'P': +			s51_prompt = NULL; +			break; +		case 'V': +			break; +		case 'v': +			break; +		case 'H': +			exit (0); +			break; +		case 'h': +			usage (); +			break; +		case 'm': +			s51_monitor = 1; +			break; +		} +	} +	if (s51_port) { +		int l, r, one = 1; +		int s; +		struct sockaddr_in in; + +		l = socket(AF_INET, SOCK_STREAM, 0); +		if (l < 0) { +			perror ("socket"); +			exit(1); +		} +		r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int)); +		if (r) { +			perror("setsockopt"); +			exit(1); +		} +		in.sin_family = AF_INET; +		in.sin_port = htons(s51_port); +		in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +		r = bind(l, (struct sockaddr *) &in, sizeof (in)); +		if (r) { +			perror("bind"); +			exit(1); +		} +		r = listen(l, 5); +		if (r) { +			perror("listen"); +			exit(1); +		} +		for (;;) { +			struct sockaddr_in client_addr; +			socklen_t client_len = sizeof (struct sockaddr_in); + +			s = accept(l, (struct sockaddr *) +				   &client_addr, &client_len); +			if (s < 0) { +				perror("accept"); +				exit(1); +			} +			s51_input = fdopen(s, "r"); +			s51_output = fdopen(s, "w"); +			if (!s51_input || !s51_output) { +				perror("fdopen"); +				exit(1); +			} +			vec.sv_handler = SIG_IGN; +			vec.sv_mask = 0; +			vec.sv_flags = 0; +			sigvec(SIGINT, &vec, &ovec); +			command_read(); +			sigvec(SIGINT, &ovec, NULL); +			fclose(s51_input); +			fclose(s51_output); +		} +	} else { +		s51_input = stdin; +		s51_output = stdout; +		vec.sv_handler = s51_sigint; +		vec.sv_mask = 0; +		vec.sv_flags = 0; +		sigvec(SIGINT, &vec, &ovec); +		command_read(); +	} +	exit(0); +} + +void +s51_printf(char *format, ...) +{ +	va_list	ap; + +	va_start(ap, format); +	vfprintf(s51_output, format, ap); +	if (s51_monitor) +		vfprintf(stdout, format, ap); +	va_end(ap); +} + +void +s51_putc(int c) +{ +	putc(c, s51_output); +} + +#include <readline/readline.h> +#include <readline/history.h> + +int +s51_read_line(char *line, int len) +{ +	int ret; +	if (s51_output == stdout && s51_input == stdin && s51_prompt) { +		char *r; + +		r = readline(s51_prompt); +		if (r == NULL) +			return 0; +		strncpy (line, r, len); +		line[len-1] = '\0'; +		add_history(r); +		return 1; +	} else { +		if (s51_prompt) +			s51_printf("%s", s51_prompt); +		else +			s51_putc('\0'); +		fflush(s51_output); +		ret = fgets(line, len, s51_input) != NULL; +		if (s51_monitor) +			printf("> %s", line); +		fflush(stdout); +	} +	return ret; +} + +int +s51_check_input(void) +{ +	struct pollfd	input; +	int r; +	int c; + +	input.fd = fileno(s51_input); +	input.events = POLLIN; +	r = poll(&input, 1, 0); +	if (r > 0) { +		char line[256]; +		(void) s51_read_line(line, sizeof (line)); +		return 1; +	} +	return 0; +} diff --git a/ao-tools/ao-dbg/ao-dbg-parse.c b/ao-tools/ao-dbg/ao-dbg-parse.c new file mode 100644 index 00000000..5db6c01c --- /dev/null +++ b/ao-tools/ao-dbg/ao-dbg-parse.c @@ -0,0 +1,241 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-dbg.h" + +static struct command_function functions[] = { +	{ "help",   "?",  command_help,	"help",		"Print this list\n" }, +	{ "quit",   "q",  command_quit,	"[q]uit",	"Quit\n" }, +	{ "di",	    "di", command_di,	"di <start> <end>", +		"Dump imem\n" }, +	{ "ds",	    "ds", command_ds,	"ds <start> <end>", +		"Dump sprs\n" }, +	{ "dx",	    "dx", command_dx,	"dx <start> <end>", +		"Dump xaddr\n" }, +	{ "set",    "t",  command_set,	"se[t] mem <prefix> <address> <data> ...", +		"Set mem {xram|rom|iram|sfr}\n" +		"set bit <addr>\n" }, +	{ "dump",   "d",  command_dump,	"[d]ump <prefix> <start> <end>", +		"Dump {xram|rom|iram|sfr} <start> <end>\n" }, +	{ "file", "file", command_file, "file <filename>", +		"Pretend to load executable from <filename>\n" }, +	{ "pc",	    "p",  command_pc, "[p]c [addr]", +		"Get or set pc value\n" }, +	{ "break",  "b",  command_break,"[b]reak <addr>", +		"Set break point\n" }, +	{ "clear",  "c",  command_clear,"[c]lear <addr>", +		"Clear break point\n" }, +	{ "run",    "r",  command_run, "[r]un [start] [stop]", +		"Run with optional start and temp breakpoint addresses\n" }, +	{ "go",     "g",  command_run, "[g]o [start] [stop]", +		"Run with optional start and temp breakpoint addresses\n" }, +	{ "next",   "n",  command_next, "[n]ext", +		"Step over one instruction, past any call\n" }, +	{ "step",   "s",  command_step, "[s]tep", +		"Single step\n" }, +	{ "load",   "l",  command_load, "[l]oad <file>", +		"Load a hex file into memory or flash" }, +	{ "halt",   "h",  command_halt, "[h]alt", +		"Halt the processor\n" }, +	{ "reset","res",command_reset,	"[res]et", +		"Reset the CPU\n" }, +	{ "status","status",command_status, "status", +		"Display CC1111 debug status\n" }, +	{ "info",   "i",  command_info, "[i]info", +		"Get information\n" }, +	{ "stop",  "stop", command_stop, "stop", +		"Ignored\n" }, +	{ NULL, NULL, NULL, NULL, NULL }, +}; + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +static int +string_to_int(char *s, int *v) +{ +	char *endptr; + +	if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') { +		*v = strtol(s, &endptr, 0); +		if (endptr == s) +			return FALSE; +	} else if (*s == '\'') { +		s++; +		if (*s == '\\') { +			s++; +			switch (*s) { +			case 'n': +				*v = '\n'; +				break; +			case 't': +				*v = '\t'; +				break; +			default: +				*v = (int) *s; +				break; +			} +		} else +			*v = (int) *s; +		s++; +		if (*s != '\'') +			return FALSE; +	} +	else +		return FALSE; +    return TRUE; +} + +struct command_function * +command_string_to_function(struct command_function *functions, char *name) +{ +	int i; +	for (i = 0; functions[i].name; i++) +		if (!strcmp(name, functions[i].name) || +		    !strcmp(name, functions[i].alias)) +			return &functions[i]; +	return NULL; +} + +enum command_result +command_function_help(struct command_function *functions, int argc, char **argv) +{ +	int i; +	struct command_function *func; + +	if (argc == 1) { +		for (i = 0; functions[i].name; i++) +			s51_printf("%-10s%s\n", functions[i].name, +			       functions[i].usage); +	} else { +		for (i = 1; i < argc; i++) { +			func = command_string_to_function(functions, argv[i]); +			if (!func) { +				s51_printf("%-10s unknown command\n", argv[i]); +				return command_syntax; +			} +			s51_printf("%-10s %s\n%s", func->name, +			       func->usage, func->help); +		} +	} +	return command_debug; +} + +static int +command_split_into_words(char *line, char **argv) +{ +	char quotechar; +	int argc; + +	argc = 0; +	while (*line) { +		while (isspace(*line)) +			line++; +		if (!*line) +			break; +		if (*line == '"') { +			quotechar = *line++; +			*argv++ = line; +			argc++; +			while (*line && *line != quotechar) +				line++; +			if (*line) +				*line++ = '\0'; +		} else { +			*argv++ = line; +			argc++; +			while (*line && !isspace(*line)) +				line++; +			if (*line) +				*line++ = '\0'; +		} +	} +	*argv = 0; +	return argc; +} + +enum command_result +command_help(int argc, char **argv) +{ +	return command_function_help(functions, argc, argv); +} + +void +command_syntax_error(int argc, char **argv) +{ +	s51_printf("Syntax error in:"); +	while (*argv) +		s51_printf(" %s", *argv++); +	s51_printf("\n"); +} + +void +command_read (void) +{ +	int argc; +	char line[1024]; +	char *argv[20]; +	enum command_result result; +	struct command_function *func; + +	s51_dbg = ccdbg_open (); +	if (!s51_dbg) { +		perror("ccdbg_open"); +		exit(1); +	} +	ccdbg_debug_mode(s51_dbg); +	ccdbg_halt(s51_dbg); +	s51_printf("Welcome to the non-simulated processor\n"); +	for (;;) { +		if (s51_read_line (line, sizeof line) == 0) +			break; +		s51_interrupted = 0; +		argc = command_split_into_words(line, argv); +		if (argc > 0) { +			func = command_string_to_function(functions, argv[0]); +			if (!func) +				command_syntax_error(argc, argv); +			else +			{ +				result = (*func->func)(argc, argv); +				if (s51_interrupted) +					result = command_interrupt; +				switch (result) { +				case command_syntax: +					command_syntax_error(argc, argv); +					break; +				case command_error: +					s51_printf("Error\n"); +					break; +				case command_success: +					break; +				case command_interrupt: +					ccdbg_halt(s51_dbg); +					s51_printf("Interrupted\n"); +					break; +				default: +					break; +				} +			} +		} +	} +	ccdbg_close(s51_dbg); +	s51_printf("...\n"); +} diff --git a/ao-tools/ao-dbg/ao-dbg.h b/ao-tools/ao-dbg/ao-dbg.h new file mode 100644 index 00000000..f4dcce66 --- /dev/null +++ b/ao-tools/ao-dbg/ao-dbg.h @@ -0,0 +1,123 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ccdbg.h> + +extern char *s51_prompt; +extern struct ccdbg *s51_dbg; +extern int s51_interrupted; +extern int s51_monitor; + +enum command_result { +	command_success, command_debug, command_syntax, command_interrupt, command_error, +}; + +struct command_function { +	char			*name; +	char			*alias; +	enum command_result	(*func)(int argc, char **argv); +	char			*usage; +	char			*help; +}; + +struct command_function * +command_string_to_function(struct command_function *functions, char *name); + +enum command_result +command_function_help(struct command_function *functions, int argc, char **argv); + +void +command_syntax_error(int argc, char **argv); + +enum command_result +command_quit (int argc, char **argv); + +enum command_result +command_help (int argc, char **argv); + +enum command_result +command_stop (int argc, char **argv); + +enum command_result +command_di (int argc, char **argv); + +enum command_result +command_ds (int argc, char **argv); + +enum command_result +command_dx (int argc, char **argv); + +enum command_result +command_set (int argc, char **argv); + +enum command_result +command_dump (int argc, char **argv); + +enum command_result +command_file (int argc, char **argv); + +enum command_result +command_pc (int argc, char **argv); + +enum command_result +command_break (int argc, char **argv); + +enum command_result +command_clear (int argc, char **argv); + +enum command_result +command_run (int argc, char **argv); + +enum command_result +command_next (int argc, char **argv); + +enum command_result +command_step (int argc, char **argv); + +enum command_result +command_load (int argc, char **argv); + +enum command_result +command_halt (int argc, char **argv); + +enum command_result +command_reset (int argc, char **argv); + +enum command_result +command_status (int argc, char **argv); + +enum command_result +command_info (int argc, char **argv); + +enum command_result +cc_wait(void); + +void +command_read (void); + +void +s51_printf(char *format, ...); + +void +s51_putc(int c); + +int +s51_check_input(void); + +int +s51_read_line(char *line, int len); diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index b84a88a6..6966dd3a 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -19,6 +19,8 @@  #include <stdlib.h>  #include <limits.h>  #include <stdint.h> +#include <unistd.h> +#include <getopt.h>  #include "ccdbg.h"  #define AO_USB_DESC_STRING		3 @@ -94,6 +96,7 @@ rewrite(struct hex_image *image, unsigned addr, char *data, int len)  	memcpy(image->data + addr - image->address, data, len);  } +static const struct option  int  main (int argc, char **argv)  { | 
