KISS Data Aquisition and Control System
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
8.5 KiB

  1. /*
  2. *
  3. * PRU Debug Program
  4. * (c) Copyright 2011, 2013 by Arctica Technologies
  5. * Written by Steven Anderson
  6. *
  7. */
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #include <sys/mman.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <errno.h>
  15. #include <termios.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/select.h>
  18. #include "prudbg.h"
  19. // breakpoint management
  20. int cmd_print_breakpoints()
  21. {
  22. int i;
  23. printf("## Address\n");
  24. for (i=0; i<MAX_BREAKPOINTS; i++) {
  25. if (bp[pru_num][i].state == BP_ACTIVE) {
  26. printf("%02u 0x%04x\n", i, bp[pru_num][i].address);
  27. } else {
  28. printf("%02u UNUSED\n", i);
  29. }
  30. }
  31. printf("\n");
  32. }
  33. // set breakpoint
  34. int cmd_set_breakpoint (unsigned int bpnum, unsigned int addr)
  35. {
  36. bp[pru_num][bpnum].state = BP_ACTIVE;
  37. bp[pru_num][bpnum].address = addr;
  38. }
  39. // clear breakpoint
  40. int cmd_clear_breakpoint (unsigned int bpnum)
  41. {
  42. bp[pru_num][bpnum].state = BP_UNUSED;
  43. }
  44. // dump data memory
  45. int cmd_d (int offset, int addr, int len)
  46. {
  47. int i, j;
  48. for (i=0; i<len; ) {
  49. printf ("[0x%04x] ", addr+i);
  50. for (j=0;(i<len)&&(j<4); i++,j++) printf ("0x%08x ", pru[offset+addr+i]);
  51. printf ("\n");
  52. }
  53. printf("\n");
  54. }
  55. // disassemble instruction memory
  56. int cmd_dis (int offset, int addr, int len)
  57. {
  58. int i, j;
  59. char inst_str[50];
  60. unsigned int status_reg;
  61. char *pc[] = {" ", ">>"};
  62. int pc_on = 0;
  63. status_reg = (pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG]) & 0xFFFF;
  64. for (i=0; i<len; i++) {
  65. if (status_reg == (addr + i)) pc_on = 1; else pc_on = 0;
  66. disassemble(inst_str, pru[offset+addr+i]);
  67. printf ("[0x%04x] 0x%08x %s %s\n", addr+i, pru[offset+addr+i], pc[pc_on], inst_str);
  68. }
  69. printf("\n");
  70. }
  71. // halt the current PRU
  72. void cmd_halt()
  73. {
  74. unsigned int ctrl_reg;
  75. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  76. ctrl_reg &= ~PRU_REG_PROC_EN;
  77. pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
  78. printf("PRU%u Halted.\n", pru_num);
  79. }
  80. // load program into instruction memory
  81. int cmd_loadprog(unsigned int addr, char *fn)
  82. {
  83. int f, r;
  84. struct stat file_info;
  85. r = stat(fn, &file_info);
  86. if (r == -1) {
  87. printf("ERROR: could not open file\n");
  88. return 1;
  89. }
  90. if (((file_info.st_size/4)*4) != file_info.st_size) {
  91. printf("ERROR: file size is not evenly divisible by 4\n");
  92. } else {
  93. f = open(fn, O_RDONLY);
  94. if (f == -1) {
  95. printf("ERROR: could not open file 2\n");
  96. } else {
  97. read(f, &pru[pru_inst_base[pru_num] + addr], file_info.st_size);
  98. close(f);
  99. printf("Binary file of size %u bytes loaded into PRU%u instruction RAM.\n", file_info.st_size, pru_num);
  100. }
  101. }
  102. return 0;
  103. }
  104. // print current PRU registers
  105. void cmd_printregs()
  106. {
  107. unsigned int ctrl_reg, reset_pc, status_reg;
  108. char *run_state, *single_step, *cycle_cnt_en, *pru_sleep, *proc_en;
  109. unsigned int i;
  110. char inst_str[50];
  111. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  112. status_reg = pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG];
  113. reset_pc = (ctrl_reg >> 16);
  114. if (ctrl_reg&PRU_REG_RUNSTATE)
  115. run_state = "RUNNING";
  116. else
  117. run_state = "STOPPED";
  118. if (ctrl_reg&PRU_REG_SINGLE_STEP)
  119. single_step = "SINGLE_STEP";
  120. else
  121. single_step = "FREE_RUN";
  122. if (ctrl_reg&PRU_REG_COUNT_EN)
  123. cycle_cnt_en = "COUNTER_ENABLED";
  124. else
  125. cycle_cnt_en = "COUNTER_DISABLED";
  126. if (ctrl_reg&PRU_REG_SLEEPING)
  127. pru_sleep = "SLEEPING";
  128. else
  129. pru_sleep = "NOT_SLEEPING";
  130. if (ctrl_reg&PRU_REG_PROC_EN)
  131. proc_en = "PROC_ENABLED";
  132. else
  133. proc_en = "PROC_DISABLED";
  134. printf("Register info for PRU%u\n", pru_num);
  135. printf(" Control register: 0x%08x\n", ctrl_reg);
  136. 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);
  137. disassemble(inst_str, pru[pru_inst_base[pru_num] + (status_reg&0xFFFF)]);
  138. printf(" Program counter: 0x%04x\n", (status_reg&0xFFFF));
  139. printf(" Current instruction: %s\n\n", inst_str);
  140. if (ctrl_reg&PRU_REG_RUNSTATE) {
  141. printf(" Rxx registers not available since PRU is RUNNING.\n");
  142. } else {
  143. 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]);
  144. }
  145. printf("\n");
  146. }
  147. // start PRU running
  148. void cmd_run()
  149. {
  150. unsigned int ctrl_reg;
  151. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  152. ctrl_reg |= PRU_REG_PROC_EN;
  153. pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
  154. }
  155. // run PRU in a single stepping mode - used for breakpoints and watch variables
  156. void cmd_runss()
  157. {
  158. unsigned int i, addr;
  159. unsigned int done = 0;
  160. unsigned int ctrl_reg;
  161. unsigned long t_cyc = 0;
  162. fd_set rd_fdset;
  163. struct timeval tv;
  164. int r;
  165. printf("Running (will run until a breakpoint is hit or a key is pressed)....\n");
  166. // enter single-step loop
  167. do {
  168. // prep some 'select' magic to detect keypress to escape
  169. FD_ZERO(&rd_fdset);
  170. FD_SET(STDIN_FILENO, &rd_fdset);
  171. tv.tv_sec = 0;
  172. tv.tv_usec = 0;
  173. // set single step mode and enable processor
  174. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  175. ctrl_reg |= PRU_REG_PROC_EN | PRU_REG_SINGLE_STEP;
  176. pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
  177. // check if we've hit a breakpoint
  178. addr = pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG] & 0xFFFF;
  179. for (i=0; i<MAX_BREAKPOINTS; i++) if ((bp[pru_num][i].state == BP_ACTIVE) && (bp[pru_num][i].address == addr)) done = 1;
  180. // check if we've hit a watch point
  181. // addr = pru[pru_ctrl_base[pru_num] + PRU_STATUS_REG] & 0xFFFF;
  182. for (i=0; i<MAX_WATCH; i++) {
  183. 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])) {
  184. 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);
  185. wa[pru_num][i].old_value = pru[pru_data_base[pru_num] + wa[pru_num][i].address];
  186. } 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])) {
  187. 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);
  188. done = 1;
  189. }
  190. }
  191. // check if we are on a HALT instruction - if so, stop single step execution
  192. if (pru[pru_inst_base[pru_num] + addr] == 0x2a000000) {
  193. printf("\nHALT instruction hit.\n");
  194. done = 1;
  195. }
  196. // check if the user has attempted to stop execution of the PRU with a keypress
  197. r = select (STDIN_FILENO+1, &rd_fdset, NULL, NULL, &tv);
  198. // increase time
  199. t_cyc++;
  200. } while ((!done) && (r == 0));
  201. // if there is a character in the stdin queue, read the character
  202. if (r > 0) getchar();
  203. printf("\n");
  204. // print the registers
  205. cmd_printregs();
  206. }
  207. void cmd_single_step()
  208. {
  209. unsigned int ctrl_reg;
  210. // set single step mode and enable processor
  211. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  212. ctrl_reg |= PRU_REG_PROC_EN | PRU_REG_SINGLE_STEP;
  213. pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
  214. // print the registers
  215. cmd_printregs();
  216. // disable single step mode and disable processor
  217. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  218. ctrl_reg &= ~PRU_REG_PROC_EN;
  219. ctrl_reg &= ~PRU_REG_SINGLE_STEP;
  220. pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
  221. }
  222. void cmd_soft_reset()
  223. {
  224. unsigned int ctrl_reg;
  225. ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
  226. ctrl_reg &= ~PRU_REG_SOFT_RESET;
  227. pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;
  228. printf("PRU%u reset.\n", pru_num);
  229. }
  230. // print list of watches
  231. void cmd_print_watch()
  232. {
  233. int i;
  234. printf("## Address Value\n");
  235. for (i=0; i<MAX_WATCH; i++) {
  236. if (wa[pru_num][i].state == WA_PRINT_ON_ANY) {
  237. printf("%02u 0x%04x Print on any\n", i, wa[pru_num][i].address);
  238. } else if (wa[pru_num][i].state == WA_HALT_ON_VALUE) {
  239. printf("%02u 0x%04x Halt = 0x%04x\n", i, wa[pru_num][i].address, wa[pru_num][i].value);
  240. } else {
  241. printf("%02u UNUSED\n", i);
  242. }
  243. }
  244. printf("\n");
  245. }
  246. // clear a watch from list
  247. void cmd_clear_watch (unsigned int wanum)
  248. {
  249. wa[pru_num][wanum].state = WA_UNUSED;
  250. }
  251. // set a watch for any change in value and no halt
  252. void cmd_set_watch_any (unsigned int wanum, unsigned int addr)
  253. {
  254. wa[pru_num][wanum].state = WA_PRINT_ON_ANY;
  255. wa[pru_num][wanum].address = addr;
  256. wa[pru_num][wanum].old_value = pru[pru_data_base[pru_num] + addr];
  257. }
  258. // set a watch for a specific value and halt
  259. void cmd_set_watch (unsigned int wanum, unsigned int addr, unsigned int value)
  260. {
  261. wa[pru_num][wanum].state = WA_HALT_ON_VALUE;
  262. wa[pru_num][wanum].address = addr;
  263. wa[pru_num][wanum].value = value;
  264. }