File indexing completed on 2025-05-11 08:22:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 #include <unistd.h>
0083
0084 #include <rtems/bspIo.h>
0085 #include <rtems/debugger/rtems-debugger-bsp.h>
0086
0087 #include "bspdebug.h"
0088
0089
0090
0091
0092 #define trace 0
0093 #define trace_reg 0
0094
0095
0096
0097
0098 #define has_tdo 0
0099
0100
0101
0102
0103 #define AM335x_PIN_CONF_TMS 116
0104 #define AM335x_PIN_CONF_TDI 117
0105 #define AM335x_PIN_CONF_TDO 118
0106 #define AM335x_PIN_CONF_TCK 119
0107 #define AM335x_PIN_CONF_TRSTN 120
0108 #define AM335x_PIN_CONF_EMU0 121
0109
0110
0111
0112
0113 #define AM335x_PRCM_CM_PER (0x44E00000)
0114 #define AM335x_PRCM_WKUP (AM335x_PRCM_CM_PER + 0x400)
0115 #define AM335x_CONTROL_MODULE (0x44E10000)
0116 #define AM335x_CONF_PIN (AM335x_CONTROL_MODULE + 0x800)
0117 #define AM335x_GPIO0 (0x44e07000)
0118 #define AM335x_GPIO1 (0x4804c000)
0119 #define AM335x_GPIO2 (0x481ac000)
0120 #define AM335x_GPIO3 (0x481ae000)
0121 #define AM335x_DEBUGSS_ETM (0x4B140000)
0122 #define AM335x_DEBUGSS_DEBUG (0x4B141000)
0123 #define AM335x_DEBUGSS_CTI (0x4B142000)
0124 #define AM335x_DEBUGSS_ICE (0x4B143000)
0125 #define AM335x_DEBUGSS_DRM (0x4B160000)
0126 #define AM335x_DEBUGSS_ETB (0x4B162000)
0127
0128
0129
0130
0131 #define AM335x_PRCM_CM_PER_GPIO3_CLKCTRL (0x0b4)
0132 #define AM335x_PRCM_WKUP_DEBUGSS_CLKCTRL (0x014)
0133
0134 #define AM335x_PRCM_CM_MODULEMODE_MASK (3)
0135 #define AM335x_PRCM_CM_MODULEMODE_DISABLE (0)
0136 #define AM335x_PRCM_CM_MODULEMODE_ENABLE (2)
0137 #define AM335x_PRCM_CM_IDLEST_MASK (3 << 16)
0138 #define AM335x_PRCM_CM_IDLEST_FUNC (0 << 16)
0139 #define AM335x_PRCM_CM_IDLEST_TRANS (1 << 16)
0140 #define AM335x_PRCM_CM_IDLEST_IDLE (2 << 16)
0141 #define AM335x_PRCM_CM_IDLEST_DISABLED (3 << 16)
0142
0143
0144
0145
0146 #define AM335x_PIN_IN_OFFSET (0x138)
0147 #define AM335x_PIN_SLEW_FAST (0 << 6)
0148 #define AM335x_PIN_SLEW_SLOW (1 << 6)
0149 #define AM335x_PIN_RX_DISABLE (0 << 5)
0150 #define AM335x_PIN_RX_ENABLE (1 << 5)
0151 #define AM335x_PIN_PULL_DIS (1 << 3)
0152 #define AM335x_PIN_PULL_EN (0 << 3)
0153 #define AM335x_PIN_PULL_UP ((1 << 4) | AM335x_PIN_PULL_EN)
0154 #define AM335x_PIN_PULL_DOWN ((0 << 4) | AM335x_PIN_PULL_EN)
0155
0156
0157
0158
0159 typedef enum {
0160 JTAG_RST,
0161 JTAG_COMMIT,
0162 JTAG_RUN,
0163 JTAG_DATA,
0164 JTAG_PAUSE
0165 } JTAG_STATE;
0166
0167 #define AM335x_JTAG_MASK (0x0fffffff)
0168 #define AM335x_JTAG_ID (0x0b94402f)
0169
0170
0171
0172
0173 #define AM335x_ICEPICK_IR_LEN (6)
0174 #define AM335x_ICEPICK_IR_BYPASS (0x3f)
0175 #define AM335x_ICEPICK_IR_PUB_CONNECT (0x07)
0176 #define AM335x_ICEPICK_IR_ROUTER (0x02)
0177
0178
0179
0180
0181 #define AM335x_DAP_ID (0x3ba00477)
0182 #define AM335x_DAP_IR_LEN (4)
0183 #define AM335x_DAP_IR_ABORT (0x08)
0184 #define AM335x_DAP_IR_DPACC (0x0a)
0185 #define AM335x_DAP_IR_APACC (0x0b)
0186 #define AM335x_DAP_IR_IDCODE (0x0e)
0187
0188
0189
0190
0191 #define AM335x_APB_DEBUG (0x80001000)
0192
0193
0194
0195
0196 static JTAG_STATE jtag_state;
0197
0198
0199
0200
0201 static const uint32_t am335x_icepick_init_regs[2] = {
0202 0x60002000,
0203 0x2c002100,
0204 };
0205
0206 #define AM335x_ICEPICK_INIT_REGS \
0207 (sizeof(am335x_icepick_init_regs) / sizeof(am335x_icepick_init_regs[0]))
0208
0209
0210
0211
0212 static void dbg_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
0213
0214 static void
0215 dbg_printk(const char* format, ...)
0216 {
0217 va_list ap;
0218 va_start(ap, format);
0219 if (trace) {
0220 vprintk(format, ap);
0221 }
0222 va_end(ap);
0223 }
0224
0225 static volatile uint32_t*
0226 arm_reg_addr(uint32_t base, uint32_t offset)
0227 {
0228 return (volatile uint32_t*) (base + offset);
0229 }
0230
0231 static uint32_t
0232 arm_reg_read(uint32_t base, uint32_t offset)
0233 {
0234 volatile uint32_t* addr = arm_reg_addr(base, offset);
0235 uint32_t val = *addr;
0236 if (trace_reg)
0237 printk("bbb: dbg: read: %08x -> %08x\n", (intptr_t) addr, val);
0238 return val;
0239 }
0240
0241 static void
0242 arm_reg_write(uint32_t base, uint32_t offset, uint32_t val)
0243 {
0244 volatile uint32_t* addr = arm_reg_addr(base, offset);
0245 if (trace_reg)
0246 printk("bbb: dbg: read: %08x <- %08x\n", (intptr_t) addr, val);
0247 *addr = val;
0248 }
0249
0250 static void
0251 arm_reg_set(uint32_t base, uint32_t offset, uint32_t mask, uint32_t val)
0252 {
0253 uint32_t rval = arm_reg_read(base, offset);
0254 rval &= ~mask;
0255 rval |= val;
0256 arm_reg_write(base, offset, rval);
0257 }
0258
0259 static void
0260 am335x_pin_config(int pin, uint32_t setting)
0261 {
0262 arm_reg_write(AM335x_CONF_PIN, pin * sizeof(uint32_t), setting);
0263 }
0264
0265 static void
0266 am335x_prcm_cm_enable(uint32_t clk)
0267 {
0268 arm_reg_set(AM335x_PRCM_CM_PER, clk,
0269 AM335x_PRCM_CM_MODULEMODE_MASK,
0270 AM335x_PRCM_CM_MODULEMODE_ENABLE);
0271 }
0272
0273 static bool
0274 am335x_prcm_cm_ready(uint32_t clk)
0275 {
0276 uint32_t val = arm_reg_read(AM335x_PRCM_CM_PER, clk) & AM335x_PRCM_CM_IDLEST_MASK;
0277 return val == AM335x_PRCM_CM_IDLEST_FUNC;
0278 }
0279
0280 static uint32_t
0281 bbb_sig_bank_addr(int pin)
0282 {
0283 static const uint32_t bank_addr[4] = {
0284 AM335x_GPIO0,
0285 AM335x_GPIO1,
0286 AM335x_GPIO2,
0287 AM335x_GPIO3
0288 };
0289 return bank_addr[(pin >> 5) & 3];
0290 }
0291
0292 static void
0293 bbb_sig_set(int pin, int level)
0294 {
0295 uint32_t val = (0 | AM335x_PIN_PULL_UP| AM335x_PIN_SLEW_FAST |
0296 ((level != 0) ? AM335x_PIN_RX_ENABLE : AM335x_PIN_RX_DISABLE));
0297 am335x_pin_config(pin, val);
0298 }
0299
0300 static uint32_t
0301 bbb_sig_get(int pin)
0302 {
0303 uint32_t in = arm_reg_read(bbb_sig_bank_addr(pin), AM335x_PIN_IN_OFFSET);
0304 return (in >> (32 - (pin & 31))) & 1;
0305 }
0306
0307 static void
0308 bbb_tdo_init(void)
0309 {
0310 if (has_tdo) {
0311 am335x_pin_config(AM335x_PIN_CONF_EMU0,
0312 7 | AM335x_PIN_PULL_UP |
0313 AM335x_PIN_RX_ENABLE | AM335x_PIN_SLEW_FAST);
0314 am335x_prcm_cm_enable(AM335x_PRCM_CM_PER_GPIO3_CLKCTRL);
0315 while (!am335x_prcm_cm_ready(AM335x_PRCM_CM_PER_GPIO3_CLKCTRL)) {}
0316 }
0317 }
0318
0319 static uint32_t
0320 bbb_sig_tdo(void)
0321 {
0322 return has_tdo && bbb_sig_get(AM335x_PIN_CONF_EMU0) == 1 ? 1 : 0;
0323 }
0324
0325 static void
0326 bbb_sig_trst(int level)
0327 {
0328 bbb_sig_set(AM335x_PIN_CONF_TRSTN, level);
0329 }
0330
0331 static void
0332 bbb_sig_tck(int level)
0333 {
0334 bbb_sig_set(AM335x_PIN_CONF_TCK, level);
0335 }
0336
0337 static void
0338 bbb_sig_tdi(int level)
0339 {
0340 bbb_sig_set(AM335x_PIN_CONF_TDI, level);
0341 }
0342
0343 static void
0344 bbb_sig_tms(int level)
0345 {
0346 bbb_sig_set(AM335x_PIN_CONF_TMS, level);
0347 }
0348
0349 static void
0350 bbb_nap(void)
0351 {
0352 volatile size_t count = 1000;
0353 while (count > 0)
0354 --count;
0355 }
0356
0357 static void
0358 bbb_sig_tck_pulse(void)
0359 {
0360 bbb_nap();
0361 bbb_sig_tck(1);
0362 bbb_nap();
0363 bbb_sig_tck(0);
0364 bbb_nap();
0365 }
0366
0367 static void
0368 bbb_jtag_cmd(size_t nbits, uint32_t data)
0369 {
0370 size_t b;
0371 for (b = 0; b < nbits; ++b, data >>= 1) {
0372 bbb_sig_tms(data & 1);
0373 bbb_sig_tck_pulse();
0374 }
0375 }
0376
0377 static void
0378 bbb_hw_init(void)
0379 {
0380 dbg_printk("]] HW reset\n");
0381
0382
0383
0384
0385 am335x_prcm_cm_enable(AM335x_PRCM_WKUP_DEBUGSS_CLKCTRL);
0386 while (!am335x_prcm_cm_ready(AM335x_PRCM_WKUP_DEBUGSS_CLKCTRL)) {}
0387 bbb_tdo_init();
0388 }
0389
0390 static void
0391 bbb_jtag_reset(void)
0392 {
0393 dbg_printk("]] JTAG reset\n");
0394 bbb_sig_trst(0);
0395 bbb_sig_tck(0);
0396 bbb_sig_tdi(1);
0397 bbb_jtag_cmd(7, 0x1f );
0398 }
0399
0400 static void
0401 bbb_jtag_commit(void)
0402 {
0403 if (jtag_state == JTAG_DATA) {
0404 dbg_printk("]] JTAG commit\n");
0405 bbb_jtag_cmd(2, 0x3 );
0406 jtag_state = JTAG_COMMIT;
0407 }
0408 }
0409
0410 static void
0411 bbb_jtag_run(size_t ncycles)
0412 {
0413 dbg_printk("]] JTAG run: %zu\n", ncycles);
0414 bbb_jtag_commit();
0415 bbb_jtag_cmd(ncycles, 0);
0416 jtag_state = JTAG_RUN;
0417 }
0418
0419 static uint32_t
0420 bbb_jtag_xfer(size_t nbits)
0421 {
0422 uint32_t in = 0;
0423 size_t b;
0424 dbg_printk("]] JTAG xfer: %zu\n", nbits);
0425 for (b = 0; b < nbits; ++b) {
0426 bbb_sig_tck_pulse();
0427 in |= bbb_sig_tdo() << b;
0428 }
0429 dbg_printk("]] JTAG xfer: in: %08x\n", in);
0430 return in;
0431 }
0432
0433 static uint32_t
0434 bbb_jtag_xfer_out(size_t nbits, uint32_t out)
0435 {
0436 uint32_t in = 0;
0437 size_t b;
0438 dbg_printk("]] JTAG xfer out: %zu %08x\n", nbits, out);
0439 for (b = 0; b < nbits; ++b, out >>= 1) {
0440 bbb_sig_tck_pulse();
0441 bbb_sig_tdi(out & 1);
0442 in |= bbb_sig_tdo() << b;
0443 }
0444 dbg_printk("]] JTAG xfer out: in: %08x\n", in);
0445 return in;
0446 }
0447
0448 static void
0449 bbb_jtag_dr(void)
0450 {
0451 dbg_printk("]] JTAG dr\n");
0452 bbb_jtag_commit();
0453 bbb_jtag_cmd(2, 0xb01);
0454 jtag_state = JTAG_DATA;
0455 }
0456
0457 static uint32_t
0458 bbb_jtag_dr_out(size_t nbits, uint32_t out)
0459 {
0460 uint32_t in;
0461 dbg_printk("]] JTAG dr out\n");
0462 bbb_jtag_dr();
0463 in = bbb_jtag_xfer_out(nbits, out);
0464 bbb_jtag_commit();
0465 return in;
0466 }
0467
0468 static void
0469 bbb_jtag_ir(void)
0470 {
0471 dbg_printk("]] JTAG ir\n");
0472 bbb_jtag_commit();
0473 bbb_jtag_cmd(3, 0x3 );
0474 jtag_state = JTAG_DATA;
0475 }
0476
0477 static uint32_t
0478 bbb_jtag_ir_out(size_t nbits, uint32_t out)
0479 {
0480 uint32_t in;
0481 dbg_printk("]] JTAG ir out\n");
0482 bbb_jtag_ir();
0483 in = bbb_jtag_xfer_out(nbits, out);
0484 bbb_jtag_commit();
0485 return in;
0486 }
0487
0488 static bool
0489 bbb_jtag_hw_init(void)
0490 {
0491 bool match = true;
0492 bbb_jtag_reset();
0493 bbb_sig_trst(1);
0494 bbb_jtag_run(100);
0495 if (has_tdo) {
0496 uint32_t id = bbb_jtag_dr_out(32, 0);
0497 match = (id & AM335x_JTAG_MASK) == AM335x_JTAG_ID;
0498 printk("bbb: dbg: JTAG Id: %08x (%s)\n",
0499 id, match ? "match" : "mismatch");
0500 }
0501 return match;
0502 }
0503
0504 static bool
0505 bbb_icepick_init(void)
0506 {
0507 size_t r;
0508 bbb_jtag_ir_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_PUB_CONNECT);
0509 bbb_jtag_dr_out(8, 0x89 );
0510 if (has_tdo && bbb_jtag_dr_out(8, 0) != 0x9 ) {
0511 printk("bbb: dbg: ICEPick connect failure\n");
0512 return false;
0513 }
0514 bbb_jtag_ir_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_ROUTER);
0515 for (r = 0; r < AM335x_ICEPICK_INIT_REGS; ++r) {
0516 uint32_t val = am335x_icepick_init_regs[r];
0517 bbb_jtag_dr_out(32, val | (1 << 31));
0518 if (has_tdo && ((bbb_jtag_dr_out(32, 0) >> 24) != (val >> 24))) {
0519 printk("bbb: dbg: ICEPick write failure\n");
0520 return false;
0521 }
0522 }
0523 bbb_jtag_ir_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_BYPASS);
0524 bbb_jtag_run(16);
0525 return true;
0526 }
0527
0528 static void
0529 bbb_dap_ir(uint32_t reg)
0530 {
0531 static uint32_t last_ir = AM335x_DAP_IR_IDCODE;
0532 if (reg != last_ir) {
0533 last_ir = reg;
0534 bbb_jtag_ir();
0535 bbb_jtag_xfer_out(AM335x_DAP_IR_LEN, reg);
0536 bbb_jtag_xfer_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_BYPASS);
0537 bbb_jtag_commit();
0538 }
0539 }
0540
0541 static uint32_t
0542 bbb_dap_op(uint32_t ir, uint32_t op, uint32_t arg)
0543 {
0544 uint32_t res;
0545 bbb_dap_ir(ir);
0546 bbb_jtag_dr();
0547 res = bbb_jtag_xfer_out(3, op);
0548 if (has_tdo && res != 0x2 ) {
0549 printk("bbb: dbg: DAP status code: %08x\n", res);
0550 }
0551 res = bbb_jtag_xfer_out(32, arg);
0552
0553
0554
0555 bbb_jtag_xfer(1);
0556
0557
0558
0559 bbb_jtag_run(1);
0560 return res;
0561 }
0562
0563 static uint32_t
0564 bbb_dap_csw(void)
0565 {
0566 return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x3 , 0);
0567 }
0568
0569 static uint32_t
0570 bbb_dap_set_csw(uint32_t val)
0571 {
0572 return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x2 , val);
0573 }
0574
0575 static uint32_t
0576 bbb_dap_set_sel(uint32_t val)
0577 {
0578 return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x4 , val);
0579 }
0580
0581 static uint32_t
0582 bbb_dap_nop(void)
0583 {
0584 return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x6 , 0);
0585 }
0586
0587 static uint32_t
0588 bbb_ap_set_csw(uint32_t val)
0589 {
0590 return bbb_dap_op(AM335x_DAP_IR_APACC, 0x0 , val);
0591 }
0592
0593 static uint32_t
0594 bbb_ap_set_addr(uint32_t val)
0595 {
0596 return bbb_dap_op(AM335x_DAP_IR_APACC, 0x2 , val);
0597 }
0598
0599 static uint32_t
0600 bbb_ap_data(void)
0601 {
0602 return bbb_dap_op(AM335x_DAP_IR_APACC, 0x7 , 0);
0603 }
0604
0605 static uint32_t
0606 bbb_ap_set_data(uint32_t val)
0607 {
0608 return bbb_dap_op(AM335x_DAP_IR_APACC, 0x6 , val);
0609 }
0610
0611 static uint32_t
0612 bbb_dap_check(void)
0613 {
0614 uint32_t data = bbb_dap_csw();
0615 uint32_t csw = bbb_dap_nop();
0616 if (has_tdo && csw != 0xf0000000) {
0617 printk("bbb: dbg: DP-CSW unexpected value: %08x\n", csw);
0618 }
0619 return data;
0620 }
0621
0622 static bool
0623 bbb_dap_init(void)
0624 {
0625 bool ok = true;
0626 if (has_tdo) {
0627 uint32_t id = bbb_jtag_dr_out(32, 0);
0628 ok = id == AM335x_DAP_ID;
0629 printk("bbb: dbg: DAP JTAG Id: %08x (%s)\n",
0630 id, ok ? "match" : "mismatch");
0631 }
0632 if (ok) {
0633
0634
0635
0636 bbb_dap_set_csw(0x50000032);
0637 bbb_dap_check();
0638
0639
0640
0641 bbb_dap_set_sel(1 << 24);
0642 bbb_ap_set_csw(0xe3000012);
0643 }
0644 return ok;
0645 }
0646
0647 static uint32_t
0648 bbb_ap_read(uint32_t addr)
0649 {
0650 uint32_t data;
0651 bbb_ap_set_addr(addr);
0652 bbb_ap_data();
0653 data = bbb_dap_check();
0654 if (has_tdo) {
0655 dbg_printk("bbb: dbg: read 0x%08x -> 0x%08x\n", addr, data);
0656 }
0657 return data;
0658 }
0659
0660 static uint32_t
0661 bbb_ap_write(uint32_t addr, uint32_t data)
0662 {
0663 bbb_ap_set_addr(addr);
0664 bbb_ap_set_data(data);
0665 return bbb_dap_check();
0666 }
0667
0668 static void
0669 bbb_show_auth_status(uint32_t addr)
0670 {
0671 if (has_tdo) {
0672 const char* privs[] = {
0673 "public invasive debug",
0674 "public non-invasive debug",
0675 "secure invasive debug",
0676 "secure non-invasive debug",
0677 };
0678 uint32_t val = bbb_ap_read(addr + 0xfb8);
0679 size_t s;
0680 printk("bbb: dbg: auth status: %08x\n", val);
0681 for (s = 0; s < (sizeof(privs) / sizeof(privs[0])); ++s, val >>= 2) {
0682 printk("bbb: dbg: %s: ", privs[s]);
0683 if ((val & 1) != 0)
0684 printk("granted");
0685 else if ((val & 2) != 0)
0686 printk("denied");
0687 printk("\n");
0688 }
0689 }
0690 }
0691
0692 static uint32_t
0693 bbb_debug_rx(void)
0694 {
0695
0696 uint32_t data;
0697 asm volatile("mrc p14, 0, %0, c0, c5, 0" : "=r" (data));
0698 return data;
0699 }
0700
0701 bool
0702 rtems_debugger_arm_debug_configure(void)
0703 {
0704 const uint32_t addr = (intptr_t) &rtems_debugger_arm_debug_configure;
0705 bbb_hw_init();
0706 if (!bbb_jtag_hw_init())
0707 return false;
0708 if (!bbb_icepick_init())
0709 return false;
0710 if (!bbb_dap_init())
0711 return false;
0712 bbb_show_auth_status(AM335x_APB_DEBUG);
0713 bbb_ap_read(AM335x_APB_DEBUG + 0x314);
0714 bbb_ap_read(AM335x_APB_DEBUG + 0x088);
0715 bbb_ap_write(AM335x_APB_DEBUG + 0x080, addr);
0716 usleep(1000);
0717 if (bbb_debug_rx() != addr) {
0718 printk("bbb: dbg: path test failure\n");
0719 return false;
0720 }
0721 return true;
0722 }
0723
0724 void*
0725 bbb_arm_debug_registers(void)
0726 {
0727 return (void*) AM335x_DEBUGSS_DEBUG;
0728 }
0729
0730 void*
0731 rtems_debugger_arm_debug_registers(void)
0732 {
0733 return bbb_arm_debug_registers();
0734 }