Initial Commit - Copy from Altus Metrum AltOS
This commit is contained in:
1
ao-tools/ao-dbg/.gitignore
vendored
Normal file
1
ao-tools/ao-dbg/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
s51
|
12
ao-tools/ao-dbg/Makefile.am
Normal file
12
ao-tools/ao-dbg/Makefile.am
Normal file
@@ -0,0 +1,12 @@
|
||||
bin_PROGRAMS=ao-dbg
|
||||
|
||||
AM_CFLAGS=$(WARN_CFLAGS) -I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
|
||||
AO_DBG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
|
||||
|
||||
man_MANS = ao-dbg.1
|
||||
|
||||
ao_dbg_DEPENDENCIES = $(AO_DBG_LIBS)
|
||||
|
||||
ao_dbg_LDADD=$(AO_DBG_LIBS) $(LIBUSB_LIBS) $(LIBREADLINE)
|
||||
|
||||
ao_dbg_SOURCES = ao-dbg-parse.c ao-dbg-command.c ao-dbg-main.c
|
652
ao-tools/ao-dbg/ao-dbg-command.c
Normal file
652
ao-tools/ao-dbg/ao-dbg-command.c
Normal file
@@ -0,0 +1,652 @@
|
||||
/*
|
||||
* 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);
|
||||
(void) status;
|
||||
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);
|
||||
(void) status;
|
||||
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);
|
||||
(void) status;
|
||||
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 ao_hex_file *hex;
|
||||
struct ao_hex_image *image;
|
||||
FILE *file;
|
||||
|
||||
if (argc != 2)
|
||||
return command_error;
|
||||
file = fopen (argv[1], "r");
|
||||
if (!file)
|
||||
return command_error;
|
||||
hex = ao_hex_file_read(file, argv[1]);
|
||||
fclose(file);
|
||||
if (!hex)
|
||||
return command_error;
|
||||
if (hex->nrecord == 0) {
|
||||
ao_hex_file_free(hex);
|
||||
return command_error;
|
||||
}
|
||||
image = ao_hex_image_create(hex);
|
||||
ao_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);
|
||||
}
|
||||
|
||||
static enum command_result
|
||||
set_breakpoint(uint16_t address, int temporary)
|
||||
{
|
||||
int b;
|
||||
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;
|
||||
}
|
||||
|
||||
static enum command_result
|
||||
clear_breakpoint(uint16_t address, int temporary)
|
||||
{
|
||||
int b;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
}
|
||||
|
||||
static 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 ao_hex_file *hex;
|
||||
struct ao_hex_image *image;
|
||||
|
||||
if (!filename)
|
||||
return command_error;
|
||||
file = fopen(filename, "r");
|
||||
if (!file) {
|
||||
perror(filename);
|
||||
return command_error;
|
||||
}
|
||||
hex = ao_hex_file_read(file, filename);
|
||||
fclose(file);
|
||||
if (!hex) {
|
||||
return command_error;
|
||||
}
|
||||
image = ao_hex_image_create(hex);
|
||||
ao_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");
|
||||
}
|
||||
ao_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;
|
||||
|
||||
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;
|
||||
}
|
||||
return command_syntax;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
256
ao-tools/ao-dbg/ao-dbg-main.c
Normal file
256
ao-tools/ao-dbg/ao-dbg-main.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#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>
|
||||
#include <getopt.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;
|
||||
char *s51_tty = NULL;
|
||||
char *s51_device = NULL;
|
||||
|
||||
static FILE *s51_input;
|
||||
static FILE *s51_output;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "You're doing it wrong.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
s51_sigint(int signum)
|
||||
{
|
||||
s51_interrupted = 1;
|
||||
}
|
||||
|
||||
static const struct option options[] = {
|
||||
{ .name = "tty", .has_arg = 1, .val = 'T' },
|
||||
{ .name = "device", .has_arg = 1, .val = 'D' },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
char *endptr;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:T:", options, NULL)) != -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;
|
||||
case 'T':
|
||||
s51_tty = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
s51_device = optarg;
|
||||
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);
|
||||
}
|
||||
signal(SIGINT, SIG_IGN);
|
||||
command_read();
|
||||
signal(SIGINT, SIG_DFL);
|
||||
fclose(s51_input);
|
||||
fclose(s51_output);
|
||||
}
|
||||
} else {
|
||||
s51_input = stdin;
|
||||
s51_output = stdout;
|
||||
signal(SIGINT, s51_sigint);
|
||||
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);
|
||||
}
|
||||
|
||||
#if HAVE_LIBREADLINE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
s51_read_line(char *line, int len)
|
||||
{
|
||||
int ret;
|
||||
#if HAVE_LIBREADLINE
|
||||
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
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
209
ao-tools/ao-dbg/ao-dbg-parse.c
Normal file
209
ao-tools/ao-dbg/ao-dbg-parse.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
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;
|
||||
|
||||
if (!s51_tty) {
|
||||
if (!s51_device)
|
||||
s51_device = getenv("AO_DBG_DEVICE");
|
||||
s51_tty = cc_usbdevs_find_by_arg(s51_device, "TeleDongle");
|
||||
}
|
||||
s51_dbg = ccdbg_open (s51_tty);
|
||||
if (!s51_dbg)
|
||||
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");
|
||||
}
|
235
ao-tools/ao-dbg/ao-dbg.1
Normal file
235
ao-tools/ao-dbg/ao-dbg.1
Normal file
@@ -0,0 +1,235 @@
|
||||
.\"
|
||||
.\" Copyright © 2009 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.
|
||||
.\"
|
||||
.\"
|
||||
.TH AO-DBG 1 "ao-dbg" ""
|
||||
.SH NAME
|
||||
ao-dbg \- hex debugger for cc1111 processors
|
||||
.SH SYNOPSIS
|
||||
.B "ao-dbg"
|
||||
[\-t \fIcpu-type\fP]
|
||||
[\-X \fIfrequency\fP]
|
||||
[\-c]
|
||||
[\-r \fIlisten-port\fP]
|
||||
[\-Z \fIlisten-port\fP]
|
||||
[\-s]
|
||||
[\-S]
|
||||
[\-p \fIprompt\fP]
|
||||
[\-V]
|
||||
[\-v]
|
||||
[\-H]
|
||||
[\-h]
|
||||
[\-m]
|
||||
[\-T \fItty-device\fP]
|
||||
[\--tty \fItty-device\fP]
|
||||
[\-D \fIaltos-device\fP]
|
||||
[\--device \fIaltos-device\fP]
|
||||
.SH DESCRIPTION
|
||||
.I ao-dbg
|
||||
connects to a cc1111 processor through either a suitable cc1111 board
|
||||
or a cp2103 usb to serial converter board, using the GPIO pins
|
||||
available on that chip. It provides an interface compatible with the
|
||||
8051 emulator from sdcc called s51, but communicating with the real
|
||||
chip instead of an emulation. Using a modified version of the SDCC
|
||||
debugger (sdcdb), you can control program execution on the target
|
||||
machine at source-level.
|
||||
|
||||
.SH OPTIONS
|
||||
The command line options are designed to be compatible with the 8051
|
||||
emulator so that it can be used with sdcdb. As such, they're all one letter
|
||||
long.
|
||||
.IP "\-t \fIcpu-type\fP"
|
||||
The 8051 emulator can operate as one of several different chips. Oddly, the
|
||||
real hardware cannot, so this option is ignored.
|
||||
.IP "\-X \fIfrequency\fP"
|
||||
Similarly, the emulator can pretend to run at an arbitrary frequency
|
||||
which the real hardware cannot do. Ignored.
|
||||
.IP "\-c"
|
||||
.IP "\-s"
|
||||
.IP "\-S"
|
||||
.IP "\-v"
|
||||
.IP "\-V"
|
||||
All ignored.
|
||||
.IP "\-r \fIlisten-port\fP, -Z \fIlisten-port\fP"
|
||||
The emulator and sdcdb communicate through a network socket. This option
|
||||
switches the debugger from communicating through stdin/stdout to listening
|
||||
on a specific network port instead. Once a connection is made, the debugger
|
||||
continues on, using that network port for command input and output. The
|
||||
debugger uses port 9756, and attempts to connect before launching ao-dbg, so if
|
||||
ao-dbg is listening on this port before sdcdb is started, sdcdb will end up
|
||||
talking to the existing ao-dbg instance. That's often useful for debugging ao-dbg
|
||||
itself.
|
||||
.IP "\-p \fIprompt\fP"
|
||||
This sets the command prompt to the specified string.
|
||||
.IP "\-P"
|
||||
This sets the command prompt to a single NUL character. This is for use by
|
||||
sdcdb.
|
||||
.IP "\-h"
|
||||
This should print a usage message, but does nothing useful currently.
|
||||
.IP "\-m"
|
||||
This option is not present in the original 8051 emulator, and causes ao-dbg to
|
||||
dump all commands and replies that are received from and sent to sdcdb.
|
||||
.TP
|
||||
\-T tty-device | --tty tty-device
|
||||
This selects which tty device the debugger uses to communicate with
|
||||
the target device. The special name 'BITBANG' directs ao-dbg to use
|
||||
the cp2103 connection, otherwise this should be a usb serial port
|
||||
connected to a suitable cc1111 debug node.
|
||||
.TP
|
||||
\-D AltOS-device | --device AltOS-device
|
||||
Search for a connected device. This requires an argument of one of the
|
||||
following forms:
|
||||
.IP
|
||||
TeleMetrum:2
|
||||
.br
|
||||
TeleMetrum
|
||||
.br
|
||||
2
|
||||
.IP
|
||||
Leaving out the product name will cause the tool to select a suitable
|
||||
product, leaving out the serial number will cause the tool to match
|
||||
one of the available devices.
|
||||
.SH COMMANDS
|
||||
Once started, ao-dbg connects to the cc1111 and then reads and
|
||||
executes commands, either from stdin, or the network connection to
|
||||
sdcdb.
|
||||
.PP
|
||||
Unlike the command line, ao-dbg contains built-in help for each of these
|
||||
commands, via the 'help' command. Most of the commands are available in a
|
||||
long form and a single character short form. Below, the short form follows
|
||||
the long form after a comma.
|
||||
.IP "help, ? {command}"
|
||||
Without arguments, prints a list of available commands. With an argument
|
||||
prints more detail about the specific command
|
||||
.IP "quit, q"
|
||||
Terminates the application, without changing the state of the target
|
||||
processor.
|
||||
.IP "di [start] [end]"
|
||||
Dumps imem (256 bytes of "internal" memory) from start to end (inclusive).
|
||||
.IP "ds [start] [end]"
|
||||
Dumps sprs from start to end (inclusive). Note that while most sprs are
|
||||
visible in the global address space, some are not, so use this command
|
||||
instead of "dx" to read them.
|
||||
.IP "dx [start] [end]"
|
||||
Dump external (global) memory from start to end (inclusive).
|
||||
.IP "set, t <prefix> [start] {data ...}"
|
||||
Store to the memory space specified by prefix where prefix is one of "xram",
|
||||
"rom", "iram", or "sfr". Store bytes starting at start.
|
||||
.IP "dump, d <prefix> [start] [end]"
|
||||
Dump from the memory space specified by prefix, where prefix is one of
|
||||
"xram", "rom", "iram" or "sfr". Dumps from start to end (inclusive).
|
||||
.IP "file [filename]"
|
||||
Specifies an intel-format hex file (ihx) that contains the contents of the
|
||||
rom area loaded into the cc1111. This is used to respond to requests to dump
|
||||
rom memory contents without getting them from the cc1111 (which is slow).
|
||||
.IP "pc, p {address}"
|
||||
If the address argument is given, this sets the program counter to the
|
||||
specified value. Otherwise, the current program counter value is displayed.
|
||||
.IP "break, b [address]"
|
||||
Sets a breakpoint at the specified address. This uses the built-in hardware
|
||||
breakpoint support in the cc1111. As a result, it supports no more than four
|
||||
breakpoints at once. You must therefore use a modified version of sdcdb which
|
||||
changes how program execution is controlled to work within this limit.
|
||||
.IP "clear, c [address]"
|
||||
Clear a breakpoint from the specified address.
|
||||
.IP "run, r, go, g {start} {stop}"
|
||||
Resumes execution of the program. If the start argument is present, then it
|
||||
begins at that address, otherwise it continues running at the current pc. If
|
||||
a stop argument is present, then a temporary breakpoint is set at that
|
||||
address. This temporary breakpoint will be removed when execution hits it.
|
||||
.IP "next, n"
|
||||
Step one instruction. In the original s51 program this would ignore
|
||||
subroutines, but as sdcdb doesn't require this functionality, it's not
|
||||
available here.
|
||||
.IP "step, s"
|
||||
Step one instruction.
|
||||
.IP "load, l [filename]"
|
||||
This is not implemented, but it is supposed to load a hex file into flash.
|
||||
Use the ccload program instead.
|
||||
.IP "halt, h"
|
||||
Halt the processor. This is the only command which can be sent while the
|
||||
program is running. It is ignored at other times.
|
||||
.IP "reset, res"
|
||||
Reset the processor. This pulls the reset pin low and re-enables debug mode.
|
||||
Check the cc1111 documentation to see precisely what this does.
|
||||
.IP "status"
|
||||
This dumps the cc1111 debug status register.
|
||||
.IP "info, i breakpoints, b"
|
||||
List the current breakpoints.
|
||||
.IP "info, i help, ?"
|
||||
List the things you can get info on.
|
||||
.IP "stop"
|
||||
This doesn't do anything and is present only to retain compatibility with
|
||||
the original 8051 emulator.
|
||||
.SH "BOARD BRINGUP DEBUGGING"
|
||||
.PP
|
||||
While the original purpose for this program was to connect the source
|
||||
debugger with the hardware, it can also be used as a low-level hex debugger
|
||||
all on its own. In particular, all of the cc1111 peripherals can be
|
||||
manipulated directly from the ao-dbg command line.
|
||||
.IP "Starting ao-dbg"
|
||||
First ensure that the target cc1111 device and intermediate cp2103 or
|
||||
cc111 board are all hooked up correctly.
|
||||
.IP
|
||||
$ ao-dbg
|
||||
.br
|
||||
Welcome to the non-simulated processor
|
||||
.br
|
||||
> status
|
||||
.br
|
||||
CPU halted
|
||||
.br
|
||||
Halted by debug command
|
||||
.br
|
||||
>
|
||||
.IP "Turning on LEDs"
|
||||
Two of the cc1111 GPIO pins, P1_0 and P1_1 are capable of driving external
|
||||
LEDs. To control these, set the Port 1 direction bits to make these output
|
||||
pins and then change the Port 1 data to set them high or low:
|
||||
.IP
|
||||
> set sfr 0xfe 0x02 # set P1DIR to 0x2
|
||||
.br
|
||||
> set sfr 0x90 0x02 # set P1_1 to high
|
||||
.br
|
||||
> set sfr 0x90 0x00 # set P1_1 to low
|
||||
.IP "Reading the A/D converters"
|
||||
The six A/D converter inputs can each be connected to any of the P0 pins,
|
||||
ground, the A/D voltage reference, an internal temperature sensor or VDD/3.
|
||||
To read one of these values, select an A/D converter to use then start the
|
||||
conversion process. The cc1111 manual has the table for selecting the input
|
||||
on page 144.
|
||||
.IP
|
||||
To configure one of the P0 pins for use by the A/D unit, we program the
|
||||
ADCCFG register, setting the bits in that which match the pins desired:
|
||||
.IP
|
||||
> set sfr 0xf2 0x3f # enable all 6 A/D inputs
|
||||
.IP
|
||||
To trigger a single conversion, we ask the A/D unit to perform an 'extra'
|
||||
conversion, which means to do a single conversion not a whole sequence of
|
||||
conversions. This is controlled by the ADCCON3 register at 0xB6:
|
||||
.IP
|
||||
> set sfr 0xb6 0xb2 # sample P0_2 using 12 bits of precision
|
||||
.br
|
||||
> ds 0xba 0xbb # dump the ADC data low and high regs
|
||||
.br
|
||||
> set sfr 0xb6 0xbe # sample internal temperature sensor
|
||||
.br
|
||||
> ds 0xba 0xbb # dump the ADC data low and high regs
|
||||
.SH "SEE ALSO"
|
||||
sdcdb(1), ccload(1)
|
||||
.SH AUTHOR
|
||||
Keith Packard
|
127
ao-tools/ao-dbg/ao-dbg.h
Normal file
127
ao-tools/ao-dbg/ao-dbg.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <cc.h>
|
||||
#include <ctype.h>
|
||||
|
||||
extern char *s51_prompt;
|
||||
extern struct ccdbg *s51_dbg;
|
||||
extern int s51_interrupted;
|
||||
extern int s51_monitor;
|
||||
extern char *s51_tty;
|
||||
extern char *s51_device;
|
||||
|
||||
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);
|
60
ao-tools/ao-dbg/commands
Normal file
60
ao-tools/ao-dbg/commands
Normal file
@@ -0,0 +1,60 @@
|
||||
Listens on port 9756 for a command stream.
|
||||
|
||||
Dump commands:
|
||||
di <start> <end> - dump imem
|
||||
ds <start> <end> - dump sprs
|
||||
dx <start> <end> - dump xaddr
|
||||
|
||||
Returns a string of hex pairs, each preceded by a space,
|
||||
with 8 pairs per line
|
||||
|
||||
Memory access commands:
|
||||
set mem <prefix> <start> <end>
|
||||
dump <prefix> <start> <end>
|
||||
|
||||
<prefix> is one of:
|
||||
|
||||
xram - external ram or external stack
|
||||
rom - code space
|
||||
iram - internal ram or stack
|
||||
sfr - special function register
|
||||
|
||||
|
||||
dump <addr>
|
||||
set bit <addr>
|
||||
|
||||
bit addressable space
|
||||
|
||||
Set PC:
|
||||
|
||||
pc <addr>
|
||||
|
||||
Sets PC to specified address
|
||||
|
||||
pc
|
||||
|
||||
Returns current PC
|
||||
|
||||
Breakpoints
|
||||
|
||||
break <addr>
|
||||
clear <addr>
|
||||
|
||||
Load a file
|
||||
|
||||
file "<filename>"
|
||||
|
||||
Execution control:
|
||||
|
||||
run <start> - run starting at <start>
|
||||
run <start> <stop> - set temporary bp at <stop>
|
||||
run - continue
|
||||
next - step over calls(?)
|
||||
step - step one instruction
|
||||
|
||||
reset - reset the simulator
|
||||
res - synonym?
|
||||
|
||||
Error messages:
|
||||
|
||||
start with "Error:"
|
Reference in New Issue
Block a user