|
|
- /*
- *
- * PRU Debug Program
- * (c) Copyright 2011, 2013 by Arctica Technologies
- * Written by Steven Anderson
- *
- */
-
- #include <stdio.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 <sys/select.h>
-
- #include "prudbg.h"
-
- // breakpoint management
- int cmd_print_breakpoints()
- {
- int i;
-
- printf("## Address\n");
- for (i=0; i<MAX_BREAKPOINTS; i++) {
- if (bp[pru_num][i].state == BP_ACTIVE) {
- printf("%02u 0x%04x\n", i, bp[pru_num][i].address);
- } else {
- printf("%02u UNUSED\n", i);
- }
- }
- printf("\n");
- }
-
- // set breakpoint
- int cmd_set_breakpoint (unsigned int bpnum, unsigned int addr)
- {
- bp[pru_num][bpnum].state = BP_ACTIVE;
- bp[pru_num][bpnum].address = addr;
- }
-
- // clear breakpoint
- int cmd_clear_breakpoint (unsigned int bpnum)
- {
- bp[pru_num][bpnum].state = BP_UNUSED;
- }
-
- // dump data memory
- int cmd_d (int offset, int addr, int len)
- {
- int i, j;
-
- for (i=0; i<len; ) {
- printf ("[0x%04x] ", addr+i);
- for (j=0;(i<len)&&(j<4); i++,j++) printf ("0x%08x ", pru[offset+addr+i]);
- printf ("\n");
- }
- printf("\n");
- }
-
- // disassemble instruction memory
- int cmd_dis (int offset, int addr, int len)
- {
- int i, j;
- char inst_str[50];
- unsigned int status_reg;
- char *pc[] = {" ", ">>"};
- int pc_on = 0;
-
- status_reg = (pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG]) & 0xFFFF;
-
- for (i=0; i<len; i++) {
- if (status_reg == (addr + i)) pc_on = 1; else pc_on = 0;
- disassemble(inst_str, pru[offset+addr+i]);
- printf ("[0x%04x] 0x%08x %s %s\n", addr+i, pru[offset+addr+i], pc[pc_on], inst_str);
- }
- printf("\n");
- }
-
- // halt the current PRU
- void cmd_halt()
- {
- unsigned int ctrl_reg;
-
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- ctrl_reg &= ~PRU_REG_PROC_EN;
- pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
- printf("PRU%u Halted.\n", pru_num);
- }
-
- // load program into instruction memory
- int cmd_loadprog(unsigned int addr, char *fn)
- {
- int f, r;
- struct stat file_info;
-
- r = stat(fn, &file_info);
- if (r == -1) {
- printf("ERROR: could not open file\n");
- return 1;
- }
- if (((file_info.st_size/4)*4) != file_info.st_size) {
- printf("ERROR: file size is not evenly divisible by 4\n");
- } else {
- f = open(fn, O_RDONLY);
- if (f == -1) {
- printf("ERROR: could not open file 2\n");
- } else {
- read(f, &pru[pru_inst_base[pru_num] + addr], file_info.st_size);
- close(f);
- printf("Binary file of size %u bytes loaded into PRU%u instruction RAM.\n", file_info.st_size, pru_num);
- }
- }
- return 0;
- }
-
- // print current PRU registers
- void cmd_printregs()
- {
- unsigned int ctrl_reg, reset_pc, status_reg;
- char *run_state, *single_step, *cycle_cnt_en, *pru_sleep, *proc_en;
- unsigned int i;
- char inst_str[50];
-
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- status_reg = pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG];
- reset_pc = (ctrl_reg >> 16);
- if (ctrl_reg&PRU_REG_RUNSTATE)
- run_state = "RUNNING";
- else
- run_state = "STOPPED";
-
- if (ctrl_reg&PRU_REG_SINGLE_STEP)
- single_step = "SINGLE_STEP";
- else
- single_step = "FREE_RUN";
-
- if (ctrl_reg&PRU_REG_COUNT_EN)
- cycle_cnt_en = "COUNTER_ENABLED";
- else
- cycle_cnt_en = "COUNTER_DISABLED";
-
- if (ctrl_reg&PRU_REG_SLEEPING)
- pru_sleep = "SLEEPING";
- else
- pru_sleep = "NOT_SLEEPING";
-
- if (ctrl_reg&PRU_REG_PROC_EN)
- proc_en = "PROC_ENABLED";
- else
- proc_en = "PROC_DISABLED";
-
- printf("Register info for PRU%u\n", pru_num);
- printf(" Control register: 0x%08x\n", ctrl_reg);
- printf(" Reset PC:0x%04x %s, %s, %s, %s, %s\n\n", reset_pc, run_state, single_step, cycle_cnt_en, pru_sleep, proc_en);
-
- disassemble(inst_str, pru[pru_inst_base[pru_num] + (status_reg&0xFFFF)]);
- printf(" Program counter: 0x%04x\n", (status_reg&0xFFFF));
- printf(" Current instruction: %s\n\n", inst_str);
-
- if (ctrl_reg&PRU_REG_RUNSTATE) {
- printf(" Rxx registers not available since PRU is RUNNING.\n");
- } else {
- for (i=0; i<8; i++) printf(" R%02u: 0x%08x R%02u: 0x%08x R%02u: 0x%08x R%02u: 0x%08x\n", i, pru[pru_ctrl_base[pru_num] + PRU_INTGPR_REG + i], i+8, pru[pru_ctrl_base[pru_num] + PRU_INTGPR_REG + i + 8], i+16, pru[pru_ctrl_base[pru_num] + PRU_INTGPR_REG + i + 16], i+24, pru[pru_ctrl_base[pru_num] + PRU_INTGPR_REG + i + 24]);
- }
-
- printf("\n");
- }
-
- // start PRU running
- void cmd_run()
- {
- unsigned int ctrl_reg;
-
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- ctrl_reg |= PRU_REG_PROC_EN;
- pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
- }
-
- // run PRU in a single stepping mode - used for breakpoints and watch variables
- void cmd_runss()
- {
- unsigned int i, addr;
- unsigned int done = 0;
- unsigned int ctrl_reg;
- unsigned long t_cyc = 0;
- fd_set rd_fdset;
- struct timeval tv;
- int r;
-
- printf("Running (will run until a breakpoint is hit or a key is pressed)....\n");
-
- // enter single-step loop
- do {
- // prep some 'select' magic to detect keypress to escape
- FD_ZERO(&rd_fdset);
- FD_SET(STDIN_FILENO, &rd_fdset);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- // set single step mode and enable processor
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- ctrl_reg |= PRU_REG_PROC_EN | PRU_REG_SINGLE_STEP;
- pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
-
- // check if we've hit a breakpoint
- addr = pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG] & 0xFFFF;
- for (i=0; i<MAX_BREAKPOINTS; i++) if ((bp[pru_num][i].state == BP_ACTIVE) && (bp[pru_num][i].address == addr)) done = 1;
-
- // check if we've hit a watch point
- // addr = pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG] & 0xFFFF;
- for (i=0; i<MAX_WATCH; i++) {
- if ((wa[pru_num][i].state == WA_PRINT_ON_ANY) && (wa[pru_num][i].old_value != pru[pru_data_base[pru_num] + wa[pru_num][i].address])) {
- printf("[0x%04x] 0x%04x t=%lu\n", wa[pru_num][i].address, pru[pru_data_base[pru_num] + wa[pru_num][i].address], t_cyc);
- wa[pru_num][i].old_value = pru[pru_data_base[pru_num] + wa[pru_num][i].address];
- } else if ((wa[pru_num][i].state == WA_HALT_ON_VALUE) && (wa[pru_num][i].value == pru[pru_data_base[pru_num] + wa[pru_num][i].address])) {
- printf("[0x%04x] 0x%04x t=%lu\n", wa[pru_num][i].address, pru[pru_data_base[pru_num] + wa[pru_num][i].address], t_cyc);
- done = 1;
- }
- }
-
- // check if we are on a HALT instruction - if so, stop single step execution
- if (pru[pru_inst_base[pru_num] + addr] == 0x2a000000) {
- printf("\nHALT instruction hit.\n");
- done = 1;
- }
-
- // check if the user has attempted to stop execution of the PRU with a keypress
- r = select (STDIN_FILENO+1, &rd_fdset, NULL, NULL, &tv);
-
- // increase time
- t_cyc++;
- } while ((!done) && (r == 0));
-
- // if there is a character in the stdin queue, read the character
- if (r > 0) getchar();
-
- printf("\n");
-
- // print the registers
- cmd_printregs();
- }
-
- void cmd_single_step()
- {
- unsigned int ctrl_reg;
-
- // set single step mode and enable processor
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- ctrl_reg |= PRU_REG_PROC_EN | PRU_REG_SINGLE_STEP;
- pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
-
- // print the registers
- cmd_printregs();
-
- // disable single step mode and disable processor
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- ctrl_reg &= ~PRU_REG_PROC_EN;
- ctrl_reg &= ~PRU_REG_SINGLE_STEP;
- pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
- }
-
- void cmd_soft_reset()
- {
- unsigned int ctrl_reg;
-
- ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
- ctrl_reg &= ~PRU_REG_SOFT_RESET;
- pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
-
- printf("PRU%u reset.\n", pru_num);
- }
-
- // print list of watches
- void cmd_print_watch()
- {
- int i;
-
- printf("## Address Value\n");
- for (i=0; i<MAX_WATCH; i++) {
- if (wa[pru_num][i].state == WA_PRINT_ON_ANY) {
- printf("%02u 0x%04x Print on any\n", i, wa[pru_num][i].address);
- } else if (wa[pru_num][i].state == WA_HALT_ON_VALUE) {
- printf("%02u 0x%04x Halt = 0x%04x\n", i, wa[pru_num][i].address, wa[pru_num][i].value);
- } else {
- printf("%02u UNUSED\n", i);
- }
- }
- printf("\n");
- }
-
- // clear a watch from list
- void cmd_clear_watch (unsigned int wanum)
- {
- wa[pru_num][wanum].state = WA_UNUSED;
- }
-
- // set a watch for any change in value and no halt
- void cmd_set_watch_any (unsigned int wanum, unsigned int addr)
- {
- wa[pru_num][wanum].state = WA_PRINT_ON_ANY;
- wa[pru_num][wanum].address = addr;
- wa[pru_num][wanum].old_value = pru[pru_data_base[pru_num] + addr];
- }
-
- // set a watch for a specific value and halt
- void cmd_set_watch (unsigned int wanum, unsigned int addr, unsigned int value)
- {
- wa[pru_num][wanum].state = WA_HALT_ON_VALUE;
- wa[pru_num][wanum].address = addr;
- wa[pru_num][wanum].value = value;
- }
-
-
|