/* * * PRU Debug Program * (c) Copyright 2011, 2013 by Arctica Technologies * Written by Steven Anderson * */ #include #include #include #include #include #include #include #include #include #include #include "prudbg.h" // breakpoint management int cmd_print_breakpoints() { int i; printf("## Address\n"); for (i=0; i>"}; int pc_on = 0; status_reg = (pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG]) & 0xFFFF; for (i=0; i> 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; } // start PRU running at address void cmd_run_at(int addr) { unsigned int ctrl_reg; ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG]; ctrl_reg &= 0xfffe; ctrl_reg |= addr << 16; 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 0) getchar(); printf("\n"); // print the registers cmd_printregs(); } void cmd_single_step(int addr) { unsigned int ctrl_reg; // set single step mode and enable processor ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG]; if (addr != -1) { ctrl_reg &= 0xfffe; ctrl_reg |= addr << 16; } 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