commands.c (9291B)
1 // Copyright 2023, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 #include <string.h> 5 6 #include "xdebug.h" 7 #include "transport.h" 8 #include "arm-v7-debug.h" 9 #include "arm-v7-system-control.h" 10 11 12 static uint32_t swd_clock_freq = 1000000; 13 14 int do_attach(DC* dc, CC* cc) { 15 uint32_t n; 16 dc_set_clock(dc, swd_clock_freq); 17 return dc_attach(dc, 0, 0, &n); 18 } 19 20 int do_setclock(DC* dc, CC* cc) { 21 uint32_t mhz; 22 if ((cmd_arg_u32(cc, 1, &mhz) < 0) || (mhz < 1) || (mhz > 20)) { 23 ERROR("setclock <mhz> -- between 1 and 20\n"); 24 return DBG_ERR; 25 } 26 swd_clock_freq = mhz * 1000000; 27 dc_set_clock(dc, swd_clock_freq); 28 return 0; 29 } 30 31 static uint32_t reglist[20] = { 32 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 33 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 34 }; 35 static uint32_t lastregs[20]; 36 37 static int read_show_regs(DC* dc) { 38 if (dc_core_reg_rd_list(dc, reglist, lastregs, 20)) { 39 return DBG_ERR; 40 } 41 INFO("r0 %08x r4 %08x r8 %08x ip %08x psr %08x\n", 42 lastregs[0], lastregs[4], lastregs[8], 43 lastregs[12], lastregs[16]); 44 INFO("r1 %08x r5 %08x r9 %08x sp %08x msp %08x\n", 45 lastregs[1], lastregs[5], lastregs[9], 46 lastregs[13], lastregs[17]); 47 INFO("r2 %08x r6 %08x 10 %08x lr %08x psp %08x\n", 48 lastregs[2], lastregs[6], lastregs[10], 49 lastregs[14], lastregs[18]); 50 INFO("r3 %08x r7 %08x 11 %08x pc %08x\n", 51 lastregs[3], lastregs[7], lastregs[11], 52 lastregs[15]); 53 INFO("control %02x faultmsk %02x basepri %02x primask %02x\n", 54 lastregs[20] >> 24, (lastregs[20] >> 16) & 0xFF, 55 (lastregs[20] >> 8) & 0xFF, lastregs[20] & 0xFF); 56 return 0; 57 } 58 59 int do_regs(DC* dc, CC* cc) { 60 return read_show_regs(dc); 61 } 62 63 static uint32_t lastaddr = 0x20000000; 64 static uint32_t lastcount = 0x40; 65 66 int do_dw(DC* dc, CC* cc) { 67 uint32_t data[1024]; 68 uint32_t addr; 69 uint32_t count; 70 unsigned n; 71 72 if (cmd_arg_u32_opt(cc, 1, &addr, lastaddr)) return DBG_ERR; 73 if (cmd_arg_u32_opt(cc, 2, &count, lastcount)) return DBG_ERR; 74 if (count > 1024) count = 1024; 75 lastaddr = addr; 76 lastcount = count; 77 78 if (addr & 3) { 79 ERROR("address is not word-aligned\n"); 80 return DBG_ERR; 81 } 82 count /= 4; 83 if (count < 1) return 0; 84 85 if (dc_mem_rd_words(dc, addr, count, data)) return DBG_ERR; 86 for (n = 0; count > 0; n += 4, addr += 16) { 87 switch (count) { 88 case 1: 89 count = 0; 90 INFO("%08x: %08x\n", addr, data[n]); 91 break; 92 case 2: 93 count = 0; 94 INFO("%08x: %08x %08x\n", 95 addr, data[n], data[n+1]); 96 break; 97 case 3: 98 count = 0; 99 INFO("%08x: %08x %08x %08x\n", 100 addr, data[n], data[n+1], data[n+2]); 101 break; 102 default: 103 count -= 4; 104 INFO("%08x: %08x %08x %08x %08x\n", 105 addr, data[n], data[n+1], data[n+2], data[n+3]); 106 break; 107 } 108 } 109 return 0; 110 } 111 112 int do_db(DC* dc, CC* cc) { 113 uint32_t data[1024 + 8]; 114 uint32_t addr, count, bytecount; 115 uint8_t *x; 116 unsigned n; 117 118 if (cmd_arg_u32_opt(cc, 1, &addr, lastaddr)) return DBG_ERR; 119 if (cmd_arg_u32_opt(cc, 2, &count, lastcount)) return DBG_ERR; 120 if (count > 1024) count = 1024; 121 lastaddr = addr; 122 lastcount = count; 123 124 bytecount = count; 125 x = (void*) data; 126 if (addr & 3) { 127 x += (addr & 3); 128 count += 4 - (addr & 3); 129 addr &= 3; 130 } 131 if (count & 3) { 132 count += 4 - (count & 3); 133 } 134 count /= 4; 135 if (count < 1) return 0; 136 137 if (dc_mem_rd_words(dc, addr, count, data)) return DBG_ERR; 138 139 while (bytecount > 0) { 140 n = (bytecount > 16) ? 16 : bytecount; 141 INFO("%08x:", addr); 142 bytecount -= n; 143 addr += n; 144 while (n-- > 0) { 145 INFO(" %02x", *x++); 146 } 147 INFO("\n"); 148 } 149 return 0; 150 } 151 152 int do_rd(DC* dc, CC* cc) { 153 uint32_t addr, val; 154 if (cmd_arg_u32(cc, 1, &addr)) return DBG_ERR; 155 int r = dc_mem_rd32(dc, addr, &val); 156 if (r < 0) { 157 INFO("%08x: ????????\n", addr); 158 } else { 159 INFO("%08x: %08x\n", addr, val); 160 } 161 return r; 162 } 163 164 int do_wr(DC* dc, CC* cc) { 165 uint32_t addr, val; 166 if (cmd_arg_u32(cc, 1, &addr)) return DBG_ERR; 167 if (cmd_arg_u32(cc, 2, &val)) return DBG_ERR; 168 int r; 169 if ((r = dc_mem_wr32(dc, addr, val)) == 0) { 170 INFO("%08x< %08x\n", addr, val); 171 } 172 return r; 173 } 174 175 int do_stop(DC* dc, CC* cc) { 176 int r; 177 if ((r = dc_core_halt(dc)) < 0) { 178 return r; 179 } 180 if ((r = dc_core_wait_halt(dc)) < 0) { 181 return r; 182 } 183 return read_show_regs(dc); 184 } 185 186 int do_resume(DC* dc, CC* cc) { 187 return dc_core_resume(dc); 188 } 189 190 int do_step(DC* dc, CC* cc) { 191 int r; 192 if ((r = dc_core_step(dc)) < 0) { 193 return r; 194 } 195 if ((r = dc_core_wait_halt(dc)) < 0) { 196 return r; 197 } 198 return read_show_regs(dc); 199 } 200 201 static uint32_t vcflags = 0; 202 203 int do_reset(DC* dc, CC* cc) { 204 int r; 205 if ((r = dc_core_halt(dc)) < 0) { 206 return r; 207 } 208 if ((r = dc_mem_wr32(dc, DEMCR, DEMCR_TRCENA | vcflags)) < 0) { 209 return r; 210 } 211 if ((r = dc_mem_wr32(dc, AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ)) < 0) { 212 return r; 213 } 214 return 0; 215 } 216 217 static int wait_for_stop(DC* dc) { 218 unsigned m = 0; 219 uint32_t val; 220 int r; 221 for (unsigned n = 0; n < 100; n++) { 222 if ((r = dc_mem_rd32(dc, DHCSR, &val)) < 0) { 223 dc_attach(dc, 0, 0, &val); 224 } else { 225 if (val & DHCSR_S_HALT) { 226 INFO("halt: CPU HALTED (%u,%u)\n", n, m); 227 uint32_t dfsr = -1, demcr = -1; 228 dc_mem_rd32(dc, DFSR, &dfsr); 229 dc_mem_rd32(dc, DEMCR, &demcr); 230 INFO("halt: DHCSR %08x, DFSR %08x, DEMCR %08x\n", val, dfsr, demcr); 231 return 0; 232 } 233 if (val & DHCSR_S_RESET_ST) { 234 m++; 235 } 236 dc_mem_wr32(dc, DHCSR, DHCSR_DBGKEY | DHCSR_C_HALT | DHCSR_C_DEBUGEN); 237 } 238 } 239 return DC_ERR_FAILED; 240 } 241 242 int do_reset_stop(DC* dc, CC* cc) { 243 int r; 244 if ((r = dc_core_halt(dc)) < 0) { 245 return r; 246 } 247 if ((r = wait_for_stop(dc)) < 0) { 248 return r; 249 } 250 if ((r = dc_mem_wr32(dc, DEMCR, DEMCR_VC_CORERESET | DEMCR_TRCENA | vcflags)) < 0) { 251 return r; 252 } 253 if ((r = dc_mem_wr32(dc, AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ)) < 0) { 254 return r; 255 } 256 if ((r = wait_for_stop(dc)) < 0) { 257 INFO("reset-stop: CPU DID NOT HALT\n"); 258 return r; 259 } 260 return 0; 261 } 262 263 static struct { 264 uint32_t flag; 265 const char* name; 266 const char* info; 267 } FLAGS[] = { 268 { DCF_POLL, "poll", "verify target state while attached" }, 269 { DCF_AUTO_ATTACH, "auto-attach", "automatically attach to target on command" }, 270 { DCF_AUTO_CONFIG, "auto-config", "set flags based on target probe on attach" }, 271 }; 272 273 #define NUMFLAGS (sizeof(FLAGS)/sizeof(FLAGS[0])) 274 275 static int text_to_flag(const char* s, uint32_t* flag) { 276 for (unsigned n = 0; n < NUMFLAGS; n++) { 277 if (!strcmp(FLAGS[n].name, s)) { 278 *flag = FLAGS[n].flag; 279 return 0; 280 } 281 } 282 return DBG_ERR; 283 } 284 285 int do_set(DC* dc, CC* cc) { 286 if (cmd_argc(cc) == 1) { 287 uint32_t set = dc_flags(dc, 0, 0); 288 for (unsigned n = 0; n < NUMFLAGS; n++) { 289 INFO("%c%-12s %s\n", set & FLAGS[n].flag ? '+' : '-', 290 FLAGS[n].name, FLAGS[n].info); 291 } 292 return 0; 293 } 294 int n = 1; 295 const char* s; 296 uint32_t clr = 0; 297 uint32_t set = 0; 298 while ((cmd_arg_str_opt(cc, n++, &s, NULL) == 0) && (s != NULL)){ 299 if (s[0] == '-') { 300 if (text_to_flag(s + 1, &clr)) { 301 ERROR("unknown flag '%s'\n", s + 1); 302 return DBG_ERR; 303 } 304 } else if (s[0] == '+') { 305 if (text_to_flag(s + 1, &clr)) { 306 ERROR("unknown flag '%s'\n", s + 1); 307 return DBG_ERR; 308 } 309 } else { 310 ERROR("set requires [+-]<feature> arguments\n"); 311 return DBG_ERR; 312 } 313 } 314 dc_flags(dc, clr, set); 315 return 0; 316 } 317 318 int do_exit(DC* dc, CC* cc) { 319 debugger_exit(); 320 return 0; 321 } 322 323 struct { 324 const char* name; 325 int (*func)(DC* dc, CC* cc); 326 const char* help; 327 } CMDS[] = { 328 { "attach", do_attach, "connect to target" }, 329 { "stop", do_stop, "halt core" }, 330 { "halt", do_stop, NULL }, 331 { "go", do_resume, NULL }, 332 { "resume", do_resume, "resume core" }, 333 { "step", do_step, "single-step core" }, 334 { "reset", do_reset, "reset core" }, 335 { "reset-stop", do_reset_stop, "reset core and halt" }, 336 { "dw", do_dw, "dump words dw <addr> [ <count> ]" }, 337 { "db", do_db, "dump bytes db <addr> [ <count> ]" }, 338 { "rd", do_rd, "read word rd <addr>" }, 339 { "dr", do_rd, NULL }, 340 { "wr", do_wr, "write word wr <addr> <val>" }, 341 { "regs", do_regs, "dump registers" }, 342 { "setarch", do_setarch, "select flash agent setarch <name>" }, 343 { "flash", do_flash, "write file to flash flash <file> <addr>" }, 344 { "erase", do_erase, "erase flash erase all | erase <addr> <len>" }, 345 { "download", do_download, "write file to memory download <file> <addr>" }, 346 { "upload", do_upload, "read memory to file upload <file> <addr> <len>" }, 347 { "setclock", do_setclock, "set SWD clock freq setclock <mhz>" }, 348 { "set", do_set, "adjust features set [+-]<feature>" }, 349 { "help", do_help, "list commands" }, 350 { "exit", do_exit, "exit debugger" }, 351 { "quit", do_exit, NULL }, 352 }; 353 354 int do_help(DC* dc, CC* cc) { 355 int w = 0; 356 for (int n = 0; n < sizeof(CMDS)/sizeof(CMDS[0]); n++) { 357 int len = strlen(CMDS[n].name); 358 if (len > w) w = len; 359 } 360 for (int n = 0; n < sizeof(CMDS)/sizeof(CMDS[0]); n++) { 361 if (CMDS[n].help == NULL) { 362 continue; 363 } 364 INFO("%-*s %s\n", w + 3, CMDS[n].name, CMDS[n].help); 365 } 366 return 0; 367 } 368 369 void debugger_command(DC* dc, CC* cc) { 370 const char* cmd = cmd_name(cc); 371 for (int n = 0; n < sizeof(CMDS)/sizeof(CMDS[0]); n++) { 372 if (!strcmp(cmd, CMDS[n].name)) { 373 CMDS[n].func(dc, cc); 374 return; 375 } 376 } 377 ERROR("unknown command '%s'\n", cmd); 378 } 379