580 lines
16 KiB
C
580 lines
16 KiB
C
|
/*
|
||
|
*
|
||
|
* PRU Debug Program
|
||
|
* (c) Copyright 2011, 2013 by Arctica Technologies
|
||
|
* Written by Steven Anderson
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/mman.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <errno.h>
|
||
|
#include <termios.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
|
||
|
#include "prudbg.h"
|
||
|
#include "uio.h"
|
||
|
|
||
|
|
||
|
// global variable definitions
|
||
|
unsigned int *pru;
|
||
|
unsigned int pru_inst_base[MAX_NUM_OF_PRUS];
|
||
|
unsigned int pru_ctrl_base[MAX_NUM_OF_PRUS];
|
||
|
unsigned int pru_data_base[MAX_NUM_OF_PRUS];
|
||
|
unsigned int pru_num = 0;
|
||
|
unsigned int last_offset, last_addr, last_len, last_cmd;
|
||
|
struct breakpoints bp[MAX_NUM_OF_PRUS][MAX_BREAKPOINTS];
|
||
|
struct watchvariable wa[MAX_NUM_OF_PRUS][MAX_WATCH];
|
||
|
|
||
|
// processor database
|
||
|
typedef struct offsets_tag {
|
||
|
unsigned int pruss_inst;
|
||
|
unsigned int pruss_data;
|
||
|
unsigned int pruss_ctrl;
|
||
|
} offsets_t;
|
||
|
|
||
|
struct pdb_tag {
|
||
|
char processor[MAX_PROC_NAME];
|
||
|
char short_name[MAX_PROC_NAME];
|
||
|
unsigned int pruss_address;
|
||
|
unsigned int pruss_len;
|
||
|
unsigned int num_of_pruss;
|
||
|
const offsets_t offsets[MAX_NUM_OF_PRUS];
|
||
|
} pdb[] = {
|
||
|
|
||
|
// The following is a "database" of available processors.
|
||
|
// To add another processor please copy one of the existing structures to
|
||
|
// the end before the END MARKER structure. "processor" is the long name
|
||
|
// for the processor (used for displaying info), "short_name" is used to
|
||
|
// select a processor at the command prompt (should be short and no spaces),
|
||
|
// "pruss_address" is the byte address of the beginning of the PRUSS memory
|
||
|
// space on the ARM, "pruss_len" is the memory allocated starting at the
|
||
|
// pruss_address address, "num_of_pruss" is the number of PRUs in the ARM
|
||
|
// processor (currently 2 is the only valid value), and "offsets" is an
|
||
|
// array of 32-bit word address/index values used to locate the instruction,
|
||
|
// data, and control memory locations for a specific PRU. This offsets
|
||
|
// array much contain num_of_pruss entries. If you add a processor to
|
||
|
// this structure then you should also add a DEFINE to the beginning of
|
||
|
// the prudbg.h file to represent the processor index in the structure
|
||
|
// array. This is only used for the DEFAULT_PROCESSOR_INDEX in the
|
||
|
// prudbg.h file (this sets the processor used if none is selected
|
||
|
// on the command line).
|
||
|
|
||
|
{
|
||
|
.processor = "AM1707",
|
||
|
.short_name = "AM1707",
|
||
|
.pruss_address = 0x01C30000,
|
||
|
.pruss_len = 0x20000,
|
||
|
.num_of_pruss = 2,
|
||
|
.offsets = {
|
||
|
{
|
||
|
.pruss_inst = 0x2000,
|
||
|
.pruss_data = 0x0000,
|
||
|
.pruss_ctrl = 0x1C00
|
||
|
},
|
||
|
{
|
||
|
.pruss_inst = 0x3000,
|
||
|
.pruss_data = 0x0800,
|
||
|
.pruss_ctrl = 0x1E00
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.processor = "AM335x",
|
||
|
.short_name = "AM335X",
|
||
|
.pruss_address = 0x4A300000,
|
||
|
.pruss_len = 0x40000,
|
||
|
.num_of_pruss = 2,
|
||
|
.offsets = {
|
||
|
{
|
||
|
.pruss_inst = 0xD000,
|
||
|
.pruss_data = 0x0000,
|
||
|
.pruss_ctrl = 0x8800
|
||
|
},
|
||
|
{
|
||
|
.pruss_inst = 0xE000,
|
||
|
.pruss_data = 0x0800,
|
||
|
.pruss_ctrl = 0x9000
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
{ // end marker
|
||
|
.processor = "NONE",
|
||
|
.short_name = "NONE",
|
||
|
.num_of_pruss = 0
|
||
|
}
|
||
|
};
|
||
|
|
||
|
int strcmpci(char *str1, char *str2, int m) {
|
||
|
unsigned int i;
|
||
|
char c1, c2;
|
||
|
int r;
|
||
|
|
||
|
r = 1;
|
||
|
for (i=0; str1[i] != 0 && i<m; i++) {
|
||
|
c1 = str1[i];
|
||
|
c2 = str2[i];
|
||
|
if (c1>96 && c1<123) c1 = c1 - 32;
|
||
|
if (c2>96 && c2<123) c2 = c2 - 32;
|
||
|
if (c1 != c2) r = 0;
|
||
|
}
|
||
|
if ((i==m) || (str2[i] != 0)) r = 0;
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
// main entry point for program
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
int fd;
|
||
|
char prompt_str[20];
|
||
|
char cmd[MAX_CMD_LEN], cmdargs[MAX_CMDARGS_LEN];
|
||
|
unsigned int argptrs[MAX_ARGS], numargs;
|
||
|
struct termios oldT, newT;
|
||
|
unsigned int i;
|
||
|
unsigned int addr, len, bpnum, offset, wanum, value;
|
||
|
int opt;
|
||
|
unsigned long opt_pruss_addr;
|
||
|
int pru_access_mode, pi, pitemp;
|
||
|
char uio_dev_file[50];
|
||
|
|
||
|
// say hello
|
||
|
printf ("PRU Debugger v0.25\n");
|
||
|
printf ("(C) Copyright 2011, 2013 by Arctica Technologies. All rights reserved.\n");
|
||
|
printf ("Written by Steven Anderson\n");
|
||
|
printf ("\n");
|
||
|
|
||
|
// get command line options
|
||
|
opt_pruss_addr = 0;
|
||
|
pru_access_mode = ACCESS_GUESS;
|
||
|
pi = DEFAULT_PROCESSOR_INDEX;
|
||
|
while ((opt = getopt(argc, argv, "?a:p:um")) != -1) {
|
||
|
switch (opt) {
|
||
|
case 'a':
|
||
|
opt_pruss_addr = strtol(optarg, NULL, 0);
|
||
|
break;
|
||
|
|
||
|
case 'u':
|
||
|
pru_access_mode = ACCESS_UIO;
|
||
|
break;
|
||
|
|
||
|
case 'm':
|
||
|
pru_access_mode = ACCESS_MEM;
|
||
|
break;
|
||
|
|
||
|
case 'p':
|
||
|
pitemp = -1;
|
||
|
for(i=0; pdb[i].num_of_pruss != 0; i++) if (strcmpci(optarg, pdb[i].short_name, MAX_PROC_NAME)) pitemp = i;
|
||
|
|
||
|
if (pitemp == -1) {
|
||
|
printf("WARNING: unrecognized processor - will use the compiled-in default processor.\n\n");
|
||
|
} else {
|
||
|
pi = pitemp;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case '?':
|
||
|
default: /* '?' */
|
||
|
printf("Usage: prudebug [-a pruss-address] [-u] [-m] [-p processor]\n");
|
||
|
printf(" -a - pruss-address is the memory address of the PRU in ARM memory space\n");
|
||
|
printf(" -u - force the use of UIO to map PRU memory space\n");
|
||
|
printf(" -m - force the use of /dev/mem to map PRU memory space\n");
|
||
|
printf(" if neither the -u or -m options are used then it will try the UIO first\n");
|
||
|
|
||
|
printf(" -p - select processor to use (sets the PRU memory locations)\n");
|
||
|
for(i=0; pdb[i].num_of_pruss != 0; i++) {
|
||
|
printf(" %s - %s\n", pdb[i].short_name, pdb[i].processor);
|
||
|
}
|
||
|
|
||
|
return(-1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// setup PRU memory offsets
|
||
|
for (i=0; i<pdb[pi].num_of_pruss ;i++) {
|
||
|
pru_inst_base[i] = pdb[pi].offsets[i].pruss_inst;
|
||
|
pru_data_base[i] = pdb[pi].offsets[i].pruss_data;
|
||
|
pru_ctrl_base[i] = pdb[pi].offsets[i].pruss_ctrl;
|
||
|
}
|
||
|
|
||
|
// if user hasn't requested a different PRU base address on the CLI, then use the PRU DB address
|
||
|
if (opt_pruss_addr == 0) opt_pruss_addr = pdb[pi].pruss_address;
|
||
|
|
||
|
// determine how to obtain the PRU base memory pointer (/dev/mem or a UIO PRUSS driver file - /dev/uio*)
|
||
|
if (pru_access_mode == ACCESS_GUESS || pru_access_mode == ACCESS_UIO) {
|
||
|
// get the UIO info (a UIO device file for the PRUSS)
|
||
|
uio_getprussfile(uio_dev_file);
|
||
|
if (uio_dev_file[0] != 0) {
|
||
|
// there is a valid UIO/PRUSS file so open it and use the pointer
|
||
|
fd = open (uio_dev_file, O_RDWR | O_SYNC);
|
||
|
if (fd == -1) {
|
||
|
printf ("ERROR: could not open /dev/mem.\n\n");
|
||
|
return 1;
|
||
|
}
|
||
|
pru = mmap (0, pdb[pi].pruss_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||
|
if (pru == MAP_FAILED) {
|
||
|
printf ("ERROR: could not map memory.\n\n");
|
||
|
return 1;
|
||
|
}
|
||
|
close(fd);
|
||
|
printf ("Using UIO PRUSS device.\n");
|
||
|
} else if (pru_access_mode == ACCESS_UIO) {
|
||
|
// user wanted only UIO device and none found - generate an error and exit
|
||
|
printf ("ERROR: UIO PRUSS device requested and none found.\n\n");
|
||
|
return (1);
|
||
|
} else {
|
||
|
// no valid UIO device file and user wants a guess so open /dev/mem
|
||
|
fd = open ("/dev/mem", O_RDWR | O_SYNC);
|
||
|
if (fd == -1) {
|
||
|
printf ("ERROR: could not open /dev/mem.\n\n");
|
||
|
return 1;
|
||
|
}
|
||
|
pru = mmap (0, pdb[pi].pruss_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, opt_pruss_addr);
|
||
|
if (pru == MAP_FAILED) {
|
||
|
printf ("ERROR: could not map memory.\n\n");
|
||
|
return 1;
|
||
|
}
|
||
|
close(fd);
|
||
|
printf ("Using /dev/mem device.\n");
|
||
|
}
|
||
|
} else {
|
||
|
// user requested the use of /dev/mem
|
||
|
fd = open ("/dev/mem", O_RDWR | O_SYNC);
|
||
|
if (fd == -1) {
|
||
|
printf ("ERROR: could not open /dev/mem.\n\n");
|
||
|
return 1;
|
||
|
}
|
||
|
pru = mmap (0, pdb[pi].pruss_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, opt_pruss_addr);
|
||
|
if (pru == MAP_FAILED) {
|
||
|
printf ("ERROR: could not map memory.\n\n");
|
||
|
return 1;
|
||
|
}
|
||
|
close(fd);
|
||
|
printf ("Using /dev/mem device.\n");
|
||
|
}
|
||
|
|
||
|
// get memory pointer for PRU from /dev/mem
|
||
|
|
||
|
// clear breakpoints
|
||
|
for (i=0; i<MAX_BREAKPOINTS; i++) {
|
||
|
bp[pru_num][i].state = BP_UNUSED;
|
||
|
}
|
||
|
|
||
|
// clear watch variables
|
||
|
for (i=0; i<MAX_WATCH; i++) {
|
||
|
wa[pru_num][i].state = WA_UNUSED;
|
||
|
}
|
||
|
|
||
|
// print some useful info
|
||
|
printf("Processor type %s\n", pdb[pi].processor);
|
||
|
printf("PRUSS memory address 0x%08x\n", opt_pruss_addr);
|
||
|
printf("PRUSS memory length 0x%08x\n\n", pdb[pi].pruss_len);
|
||
|
printf(" offsets below are in 32-bit word addresses (not ARM byte addresses)\n");
|
||
|
printf(" PRU Instruction Data Ctrl\n");
|
||
|
for (i=0; i<pdb[pi].num_of_pruss; i++) {
|
||
|
printf(" %-15d0x%08x 0x%08x 0x%08x\n", i, pdb[pi].offsets[i].pruss_inst, pdb[pi].offsets[i].pruss_data, pdb[pi].offsets[i].pruss_ctrl);
|
||
|
}
|
||
|
printf("\n");
|
||
|
|
||
|
// setup the terminal for more flexible IO
|
||
|
ioctl(0,TCGETS,&oldT);
|
||
|
newT=oldT;
|
||
|
newT.c_lflag &= ~ECHO;
|
||
|
newT.c_lflag &= ~ICANON;
|
||
|
ioctl(0,TCSETS,&newT);
|
||
|
|
||
|
|
||
|
// Command prompt handler
|
||
|
do {
|
||
|
// get command from user
|
||
|
sprintf(prompt_str, "PRU%u> ", pru_num);
|
||
|
cmd_input(prompt_str, cmd, cmdargs, argptrs, &numargs);
|
||
|
|
||
|
// do something with command info
|
||
|
if (!strcmp(cmd, "?") || !strcmp(cmd, "HELP")) { // HELP - help command
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
printhelp();
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "HB")) { // brief HELP
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
printhelpbrief();
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "BR")) { // BR - Breakpoint command
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs == 0) {
|
||
|
cmd_print_breakpoints();
|
||
|
} else if (numargs == 1) {
|
||
|
bpnum = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
if (bpnum < MAX_BREAKPOINTS) {
|
||
|
cmd_clear_breakpoint (bpnum);
|
||
|
} else {
|
||
|
printf("ERROR: breakpoint number must be equal to or between 0 and %u\n", MAX_BREAKPOINTS-1);
|
||
|
}
|
||
|
} else if (numargs == 2) {
|
||
|
bpnum = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
addr = strtol(&cmdargs[argptrs[1]], NULL, 0);
|
||
|
if (bpnum < MAX_BREAKPOINTS) {
|
||
|
cmd_set_breakpoint (bpnum, addr);
|
||
|
} else {
|
||
|
printf("ERROR: breakpoint number must be equal to or between 0 and %u\n", MAX_BREAKPOINTS-1);
|
||
|
}
|
||
|
} else {
|
||
|
printf("ERROR: invalid breakpoint command\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if ((!strcmp(cmd, "D")) || (!strcmp(cmd, "DD")) || (!strcmp(cmd, "DI"))) { // D - Dump command
|
||
|
if (numargs > 2) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else {
|
||
|
if (numargs == 2) {
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
len = strtol(&cmdargs[argptrs[1]], NULL, 0);
|
||
|
} else if (numargs == 0) {
|
||
|
addr = 0;
|
||
|
len = 16;
|
||
|
} else {
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
len = 16;
|
||
|
}
|
||
|
if ((addr < 0) || (addr > MAX_PRU_MEM - 1) || (len < 0) || (addr+len > MAX_PRU_MEM)) {
|
||
|
printf("ERROR: arguments out of range.\n");
|
||
|
} else if (numargs > 2) {
|
||
|
printf("ERROR: Incorrect format. Please use help command to get command details.\n");
|
||
|
} else {
|
||
|
if (!strcmp(cmd, "DD")) {
|
||
|
offset = pru_data_base[pru_num];
|
||
|
last_cmd = LAST_CMD_DD;
|
||
|
} else if (!strcmp(cmd, "DI")) {
|
||
|
offset = pru_inst_base[pru_num];
|
||
|
last_cmd = LAST_CMD_DI;
|
||
|
} else {
|
||
|
offset = 0;
|
||
|
last_cmd = LAST_CMD_D;
|
||
|
}
|
||
|
last_offset = offset;
|
||
|
last_addr = addr + len;
|
||
|
last_len = len;
|
||
|
printf ("Absolute addr = 0x%04x, offset = 0x%04x, Len = %u\n", addr + offset, addr, len);
|
||
|
cmd_d(offset, addr, len);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "DIS")) { // DIS - disassemble command
|
||
|
if (numargs > 2) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else {
|
||
|
if (numargs == 2) {
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
len = strtol(&cmdargs[argptrs[1]], NULL, 0);
|
||
|
} else if (numargs == 0) {
|
||
|
addr = 0;
|
||
|
len = 16;
|
||
|
} else {
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
len = 16;
|
||
|
}
|
||
|
if ((addr < 0) || (addr > MAX_PRU_MEM - 1) || (len < 0) || (addr+len > MAX_PRU_MEM)) {
|
||
|
printf("ERROR: arguments out of range.\n");
|
||
|
} else if (numargs > 2) {
|
||
|
printf("ERROR: Incorrect format. Please use help command to get command details.\n");
|
||
|
} else {
|
||
|
offset = pru_inst_base[pru_num];
|
||
|
last_cmd = LAST_CMD_DIS;
|
||
|
|
||
|
last_offset = offset;
|
||
|
last_addr = addr + len;
|
||
|
last_len = len;
|
||
|
printf ("Absolute addr = 0x%04x, offset = 0x%04x, Len = %u\n", addr + offset, addr, len);
|
||
|
cmd_dis(offset, addr, len);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "G")) { // G - Start program
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs > 1) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else if (numargs == 0) {
|
||
|
// start processor
|
||
|
cmd_run();
|
||
|
} else {
|
||
|
// set instruction pointer
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
|
||
|
// start processor
|
||
|
// cmd_run_at(addr);
|
||
|
printf("NOT IMPLEMENTED YET.\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "GSS")) { // GSS - Start program using single stepping to provde BP/Watch
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs > 0) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else {
|
||
|
// halt the processor
|
||
|
cmd_runss();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "HALT")) { // HALT - Halt PRU
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs > 0) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else {
|
||
|
// halt the processor
|
||
|
cmd_halt();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "L")) { // L - Load PRU program
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs != 2) {
|
||
|
printf("ERROR: incorrect number of arguments\n");
|
||
|
} else {
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
cmd_loadprog(addr, &cmdargs[argptrs[1]]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "PRU")) { // PRU - Select the active PRU
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs != 1) {
|
||
|
printf("ERROR: incorrect number of arguments\n");
|
||
|
} else {
|
||
|
pru_num = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
printf("Active PRU is PRU%u.\n\n", pru_num);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "R")) { // R - Print PRU registers
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs != 0) {
|
||
|
printf("ERROR: incorrect number of arguments\n");
|
||
|
} else {
|
||
|
cmd_printregs();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "RESET")) { // RESET - Reset PRU
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs > 0) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else {
|
||
|
// reset the processor
|
||
|
cmd_soft_reset();
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "SS")) { // SS - Single step
|
||
|
last_cmd = LAST_CMD_SS;
|
||
|
if (numargs > 0) {
|
||
|
printf("ERROR: too many arguments\n");
|
||
|
} else {
|
||
|
// reset the processor
|
||
|
cmd_single_step();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "WA")) { // WA - Watch command
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
if (numargs == 0) {
|
||
|
cmd_print_watch();
|
||
|
} else if (numargs == 1) {
|
||
|
wanum = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
if (wanum < MAX_WATCH) {
|
||
|
cmd_clear_watch (wanum);
|
||
|
} else {
|
||
|
printf("ERROR: breakpoint number must be equal to or between 0 and %u\n", MAX_WATCH-1);
|
||
|
}
|
||
|
} else if (numargs == 2) {
|
||
|
wanum = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
addr = strtol(&cmdargs[argptrs[1]], NULL, 0);
|
||
|
if (wanum < MAX_WATCH) {
|
||
|
cmd_set_watch_any (wanum, addr);
|
||
|
} else {
|
||
|
printf("ERROR: breakpoint number must be equal to or between 0 and %u\n", MAX_WATCH-1);
|
||
|
}
|
||
|
} else if (numargs == 3) {
|
||
|
wanum = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
addr = strtol(&cmdargs[argptrs[1]], NULL, 0);
|
||
|
value = strtol(&cmdargs[argptrs[2]], NULL, 0);
|
||
|
if (wanum < MAX_WATCH) {
|
||
|
cmd_set_watch (wanum, addr, value);
|
||
|
} else {
|
||
|
printf("ERROR: breakpoint number must be equal to or between 0 and %u\n", MAX_WATCH-1);
|
||
|
}
|
||
|
} else {
|
||
|
printf("ERROR: invalid breakpoint command\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if ((!strcmp(cmd, "WR")) || (!strcmp(cmd, "WRD")) || (!strcmp(cmd, "WRI"))) { // WR - Write Raw
|
||
|
last_cmd = LAST_CMD_NONE;
|
||
|
addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
|
||
|
if (numargs < 2) {
|
||
|
printf("ERROR: too few arguments\n");
|
||
|
} else {
|
||
|
if ((addr < 0) || (addr > MAX_PRU_MEM - 1)) {
|
||
|
printf("ERROR: arguments out of range.\n");
|
||
|
} else {
|
||
|
if (!strcmp(cmd, "WRD")) {
|
||
|
offset = pru_data_base[pru_num];
|
||
|
} else if (!strcmp(cmd, "WRI")) {
|
||
|
offset = pru_inst_base[pru_num];
|
||
|
} else {
|
||
|
offset = 0;
|
||
|
}
|
||
|
printf("Write to absolute address 0x%04x\n", offset+addr);
|
||
|
for (i=1; i<numargs; i++) pru[offset+addr+i-1] = (unsigned int) (strtoll(&cmdargs[argptrs[i]], NULL, 0) & 0xFFFFFFFF);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "Q")) { // dummy so it's a valid command
|
||
|
}
|
||
|
|
||
|
else if (!strcmp(cmd, "")) { // repeat display command option
|
||
|
switch(last_cmd) {
|
||
|
case LAST_CMD_D:
|
||
|
case LAST_CMD_DD:
|
||
|
case LAST_CMD_DI:
|
||
|
printf ("Absolute addr = 0x%04x, offset = 0x%04x, Len = %u\n", last_addr + last_offset, last_addr, last_len);
|
||
|
cmd_d(last_offset, last_addr, last_len);
|
||
|
last_addr += last_len;
|
||
|
break;
|
||
|
|
||
|
case LAST_CMD_SS:
|
||
|
cmd_single_step();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
printf("Invalid command.\n\n");
|
||
|
}
|
||
|
|
||
|
} while (strcmp(cmd, "Q"));
|
||
|
|
||
|
printf("\nGoodbye.\n\n");
|
||
|
|
||
|
// restore terminal IO settings
|
||
|
ioctl(0,TCSETS,&oldT);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|