summaryrefslogtreecommitdiff
path: root/gdb/arm-stub.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arm-stub.c')
-rw-r--r--gdb/arm-stub.c194
1 files changed, 168 insertions, 26 deletions
diff --git a/gdb/arm-stub.c b/gdb/arm-stub.c
index 68b24a7457..0717af49c3 100644
--- a/gdb/arm-stub.c
+++ b/gdb/arm-stub.c
@@ -21,6 +21,8 @@
21#include <string.h> 21#include <string.h>
22#include "usb_serial.h" 22#include "usb_serial.h"
23#include "sscanf.h" 23#include "sscanf.h"
24#include "pnx0101.h"
25#include "gdb_api.h"
24 26
25#define BUFMAX 1024 27#define BUFMAX 1024
26 28
@@ -34,8 +36,34 @@ static char reply_buf[BUFMAX];
34 36
35static const char hexchars[] = "0123456789abcdef"; 37static const char hexchars[] = "0123456789abcdef";
36static int gdb_exception_no, gdb_mem_access; 38static int gdb_exception_no, gdb_mem_access;
39static unsigned char watchdog_enabled;
37static unsigned long registers[17]; 40static unsigned long registers[17];
38 41
42void gdb_api_breakpoint(void);
43static void gdb_api_log(char *msg);
44
45__attribute__((section(".gdbapi"))) struct gdb_api gdb_api =
46{
47 GDB_API_MAGIC,
48 {gdb_api_breakpoint, gdb_api_log}
49};
50
51static void watchdog_enable(int on)
52{
53 (*(volatile unsigned long *)0x80002804) = on;
54 watchdog_enabled = on;
55}
56
57static void watchdog_service(void)
58{
59 if (watchdog_enabled)
60 {
61 (*(volatile unsigned long *)0x80002804) = 0;
62 (*(volatile unsigned long *)0x80002808) = 0;
63 (*(volatile unsigned long *)0x80002804) = 1;
64 }
65}
66
39static inline bool isxdigit(char c) 67static inline bool isxdigit(char c)
40{ 68{
41 return ((c >= '0') && (c <= '9')) 69 return ((c >= '0') && (c <= '9'))
@@ -113,33 +141,58 @@ static void reply_ok(char *reply) {
113 strcpy(reply, "OK"); 141 strcpy(reply, "OK");
114} 142}
115 143
144static int get_byte(void) {
145 int b;
146 while ((b = usb_serial_try_get_byte()) < 0)
147 watchdog_service();
148 watchdog_service();
149 return b;
150}
151
152static void put_byte(unsigned char ch) {
153 while (usb_serial_try_put_byte(ch) < 0)
154 watchdog_service();
155 watchdog_service();
156}
157
116static void serial_write(unsigned char *buf, int len) { 158static void serial_write(unsigned char *buf, int len) {
117 int i; 159 int i;
118 for (i = 0; i < len; i++) 160 for (i = 0; i < len; i++)
119 usb_serial_put_byte(buf[i]); 161 put_byte(buf[i]);
120} 162}
121 163
122static void get_packet(char *buf, int len) { 164static void get_packet(char *buf, int len) {
123 int count, checksum; 165 int count, checksum, escaped;
124 int ch; 166 int ch;
125 167
126 while (1) { 168 while (1) {
127 do { 169 do {
128 ch = usb_serial_get_byte(); 170 ch = get_byte();
129 } while (ch != '$'); 171 } while (ch != '$');
130 172
131 checksum = 0; 173 checksum = 0;
132 count = 0; 174 count = 0;
175 escaped = 0;
133 while (count < len) { 176 while (count < len) {
134 ch = usb_serial_get_byte(); 177 ch = get_byte();
135 if (ch == '$') { 178 if (!escaped) {
136 checksum = 0; 179 if (ch == '$') {
137 count = 0; 180 checksum = 0;
138 } else if (ch == '#') 181 count = 0;
139 break; 182 } else if (ch == '#')
140 else { 183 break;
184 else if (ch == 0x7d) {
185 escaped = 1;
186 checksum += ch;
187 } else {
188 checksum += ch;
189 buf[count] = ch;
190 count++;
191 }
192 } else {
193 escaped = 0;
141 checksum += ch; 194 checksum += ch;
142 buf[count] = ch; 195 buf[count] = ch ^ 0x20;
143 count++; 196 count++;
144 } 197 }
145 } 198 }
@@ -148,15 +201,15 @@ static void get_packet(char *buf, int len) {
148 if (ch == '#') { 201 if (ch == '#') {
149 int rchksum; 202 int rchksum;
150 203
151 ch = usb_serial_get_byte(); 204 ch = get_byte();
152 rchksum = hex(ch) << 4; 205 rchksum = hex(ch) << 4;
153 ch = usb_serial_get_byte(); 206 ch = get_byte();
154 rchksum += hex(ch); 207 rchksum += hex(ch);
155 208
156 if ((checksum & 0xff) != rchksum) 209 if ((checksum & 0xff) != rchksum)
157 usb_serial_put_byte('-'); 210 put_byte('-');
158 else { 211 else {
159 usb_serial_put_byte('+'); 212 put_byte('+');
160 return; 213 return;
161 } 214 }
162 } 215 }
@@ -169,7 +222,7 @@ static void put_packet(char *buf) {
169 char tmp[3]; 222 char tmp[3];
170 223
171 do { 224 do {
172 usb_serial_put_byte('$'); 225 put_byte('$');
173 226
174 checksum = 0; 227 checksum = 0;
175 for (i = 0; buf[i]; i++) 228 for (i = 0; buf[i]; i++)
@@ -181,7 +234,7 @@ static void put_packet(char *buf) {
181 hex_byte(tmp + 1, checksum & 0xff); 234 hex_byte(tmp + 1, checksum & 0xff);
182 serial_write(tmp, 3); 235 serial_write(tmp, 3);
183 236
184 ch = usb_serial_get_byte(); 237 ch = get_byte();
185 238
186 } while (ch != '+'); 239 } while (ch != '+');
187} 240}
@@ -327,6 +380,25 @@ static void cmd_put_memory(char *args, char *reply) {
327 reply_ok(reply); 380 reply_ok(reply);
328} 381}
329 382
383static void cmd_put_memory_binary(char *args, char *reply) {
384 unsigned long addr, len, i;
385 int pos;
386
387 pos = -1;
388 sscanf(args, "%lx,%lx:%n", &addr, &len, &pos);
389 if (pos == -1) {
390 reply_error(0, reply);
391 return;
392 }
393
394 gdb_mem_access = 1;
395 for (i = 0; i < len; i++)
396 *((unsigned char *)(addr + i)) = args[pos + i];
397 gdb_mem_access = 0;
398
399 reply_ok(reply);
400}
401
330static void parse_continue_args(char *args) { 402static void parse_continue_args(char *args) {
331 int sig; 403 int sig;
332 unsigned long addr; 404 unsigned long addr;
@@ -359,8 +431,40 @@ static void cmd_go(char *args) {
359} 431}
360 432
361static void remote_cmd(char *cmd, char *reply) { 433static void remote_cmd(char *cmd, char *reply) {
362 (void)cmd; 434 int i, err;
363 hex_string(reply, "Unrecognized command\n"); 435 i = 0;
436 err = 0;
437 while ((cmd[i] >= 'a' && cmd[i] <= 'z') || cmd[i] == '_')
438 i++;
439 if (!strncmp(cmd, "reboot", i))
440 {
441 reply_ok(reply);
442 put_packet(reply);
443 watchdog_enable(1);
444 (*(volatile unsigned long *)0x80002804) = 1;
445 while (1);
446 }
447 else if (!strncmp(cmd, "power_off", i))
448 {
449 reply_ok(reply);
450 put_packet(reply);
451 GPIO1_CLR = 1 << 16;
452 GPIO2_SET = 1;
453 while (1);
454 }
455 else if (!strncmp(cmd, "watchdog", i))
456 {
457 int t;
458 if (sscanf(cmd + i, "%d", &t) == 1)
459 watchdog_enable(t != 0);
460 else
461 err = 1;
462 reply_ok(reply);
463 }
464 else
465 hex_string(reply, "Unrecognized command\n");
466 if (err)
467 reply_error(err, reply);
364} 468}
365 469
366static void cmd_query(char *args, char *reply) { 470static void cmd_query(char *args, char *reply) {
@@ -416,6 +520,10 @@ void gdb_loop(void) {
416 cmd_put_memory(packet_buf + 1, reply_buf); 520 cmd_put_memory(packet_buf + 1, reply_buf);
417 break; 521 break;
418 522
523 case 'X':
524 cmd_put_memory_binary(packet_buf + 1, reply_buf);
525 break;
526
419 case 'q': 527 case 'q':
420 cmd_query(packet_buf + 1, reply_buf); 528 cmd_query(packet_buf + 1, reply_buf);
421 break; 529 break;
@@ -468,8 +576,6 @@ void gdb_loop_from_exc(void)
468 gdb_loop(); 576 gdb_loop();
469} 577}
470 578
471#define GPIO3_CLR (*(volatile unsigned long *)0x800030d8)
472
473#define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg))) 579#define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg)))
474 580
475static inline unsigned long irq_read(int reg) 581static inline unsigned long irq_read(int reg)
@@ -492,12 +598,15 @@ static inline unsigned long irq_read(int reg)
492 } while ((v != v2) || !(cond)); \ 598 } while ((v != v2) || !(cond)); \
493 } while (0); 599 } while (0);
494 600
601void fiq(void)
602{
603}
604
495static void system_init(void) 605static void system_init(void)
496{ 606{
497 int i; 607 int i;
498 608
499 /* turn off watchdog */ 609 watchdog_enable(0);
500 (*(volatile unsigned long *)0x80002804) = 0;
501 610
502 for (i = 0; i < 0x1c; i++) 611 for (i = 0; i < 0x1c; i++)
503 { 612 {
@@ -509,13 +618,29 @@ static void system_init(void)
509 GPIO3_CLR = 1; 618 GPIO3_CLR = 1;
510} 619}
511 620
621static void gdb_api_log(char *msg)
622{
623 int i;
624
625 reply_buf[0] = 'O';
626 i = 1;
627 while (*msg && i + 2 <= BUFMAX - 1)
628 {
629 hex_byte(reply_buf + i, *msg++);
630 i += 2;
631 }
632 reply_buf[i] = 0;
633 put_packet(reply_buf);
634}
635
512void main(void) 636void main(void)
513{ 637{
514 system_init(); 638 system_init();
515 usb_serial_init(); 639 usb_serial_init();
516 gdb_exception_no = VEC_SWI; 640 gdb_mem_access = 0;
517 gdb_set_vectors(); 641 gdb_set_vectors();
518 gdb_loop(); 642 gdb_api_breakpoint();
643 while (1);
519} 644}
520 645
521#define str(s) #s 646#define str(s) #s
@@ -571,4 +696,21 @@ asm (".text\n"
571 "gdb_data_abort:\n" 696 "gdb_data_abort:\n"
572 " msr cpsr_c, #0xd3\n" 697 " msr cpsr_c, #0xd3\n"
573 " ldr sp, =_stub_stack\n" 698 " ldr sp, =_stub_stack\n"
699 " b gdb_loop_from_exc\n"
700 "gdb_api_breakpoint:\n"
701 " stmfd sp!, {r0-r1}\n"
702 " ldr r0, =registers\n"
703 " mrs r1, cpsr\n"
704 " str r1, [r0], #4\n"
705 " ldmfd sp!, {r1}\n"
706 " str r1, [r0], #4\n"
707 " ldmfd sp!, {r1}\n"
708 " str r1, [r0], #4\n"
709 " stmia r0!, {r2-r14}\n"
710 " str r14, [r0]\n"
711 " msr cpsr_c, #0xd3\n"
712 " ldr sp, =_stub_stack\n"
713 " ldr r0, =gdb_exception_no\n"
714 " mov r1, #5\n"
715 " str r1, [r0]\n"
574 " b gdb_loop_from_exc\n"); 716 " b gdb_loop_from_exc\n");