1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Tomasz Malesinski
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
22 #include "usb_serial.h"
34 static char packet_buf
[BUFMAX
];
35 static char reply_buf
[BUFMAX
];
37 static const char hexchars
[] = "0123456789abcdef";
38 static int gdb_exception_no
, gdb_mem_access
;
39 static unsigned char watchdog_enabled
;
40 static unsigned long registers
[17];
42 void gdb_api_breakpoint(void);
43 static void gdb_api_log(char *msg
);
45 __attribute__((section(".gdbapi"))) struct gdb_api gdb_api
=
48 {gdb_api_breakpoint
, gdb_api_log
}
51 static void watchdog_enable(int on
)
53 (*(volatile unsigned long *)0x80002804) = on
;
54 watchdog_enabled
= on
;
57 static void watchdog_service(void)
61 (*(volatile unsigned long *)0x80002804) = 0;
62 (*(volatile unsigned long *)0x80002808) = 0;
63 (*(volatile unsigned long *)0x80002804) = 1;
67 static inline bool isxdigit(char c
)
69 return ((c
>= '0') && (c
<= '9'))
70 || ((c
>= 'a') && (c
<= 'f')) || ((c
>= 'A') && (c
<= 'F'));
73 static int hex(char ch
) {
74 if ((ch
>= 'a') && (ch
<= 'f'))
76 if ((ch
>= '0') && (ch
<= '9'))
78 if ((ch
>= 'A') && (ch
<= 'F'))
83 static void hex_byte(char *s
, int byte
) {
84 s
[0] = hexchars
[(byte
>> 4) & 0xf];
85 s
[1] = hexchars
[byte
& 0xf];
88 static void hex_word(char *s
, unsigned long val
) {
90 for (i
= 0; i
< 4; i
++)
91 hex_byte(s
+ i
* 2, (val
>> (i
* 8)) & 0xff);
94 static void hex_string(char *d
, char *s
) {
102 static int get_hex_byte(char *s
) {
103 return (hex(s
[0]) << 4) + hex(s
[1]);
106 static unsigned long get_hex_word(char *s
) {
109 for (i
= 3; i
>= 0; i
--)
110 r
= (r
<< 8) + get_hex_byte(s
+ i
* 2);
114 static void reply_error(int n
, char *reply
) {
116 hex_byte(reply
+ 1, n
);
120 static void reply_signal(int n
, char *reply
) {
136 hex_byte(reply
+ 1, signal
);
140 static void reply_ok(char *reply
) {
144 static int get_byte(void) {
146 while ((b
= usb_serial_try_get_byte()) < 0)
152 static void put_byte(unsigned char ch
) {
153 while (usb_serial_try_put_byte(ch
) < 0)
158 static void serial_write(unsigned char *buf
, int len
) {
160 for (i
= 0; i
< len
; i
++)
164 static void get_packet(char *buf
, int len
) {
165 int count
, checksum
, escaped
;
176 while (count
< len
) {
182 } else if (ch
== '#')
184 else if (ch
== 0x7d) {
195 buf
[count
] = ch
^ 0x20;
205 rchksum
= hex(ch
) << 4;
209 if ((checksum
& 0xff) != rchksum
)
219 static void put_packet(char *buf
) {
228 for (i
= 0; buf
[i
]; i
++)
231 serial_write(buf
, i
);
234 hex_byte(tmp
+ 1, checksum
& 0xff);
235 serial_write(tmp
, 3);
242 static inline unsigned long get_general_reg(int n
)
244 return registers
[n
+ 1];
247 static inline void set_general_reg(int n
, unsigned long v
)
249 registers
[n
+ 1] = v
;
252 static inline unsigned long get_cpsr(void)
257 static inline void set_cpsr(unsigned long v
)
262 static void g_reply(char *buf
) {
267 for (i
= 0; i
< 16; i
++) {
268 hex_word(p
, get_general_reg(i
));
272 for (i
= 0; i
< 8; i
++) {
279 hex_word(p
, get_cpsr());
283 static void cmd_get_register(char *args
, char *reply
) {
286 if (sscanf(args
, "%x", &r
) != 1) {
287 reply_error(0, reply
);
291 if (r
>= 0 && r
< 16) {
292 hex_word(reply
, get_general_reg(r
));
294 } else if (r
== 25) {
295 hex_word(reply
, get_cpsr());
303 static void cmd_set_register(char *args
, char *reply
) {
308 sscanf(args
, "%x=%n", &r
, &p
);
310 reply_error(0, reply
);
314 v
= get_hex_word(args
+ p
);
315 if (r
>= 0 && r
< 16)
316 set_general_reg(r
, v
);
322 static void cmd_set_registers(char *args
, char *reply
) {
329 for (i
= 0; i
< 16 && len
>= (i
+ 1) * 8; i
++) {
330 set_general_reg(i
, get_hex_word(p
));
334 if (len
>= 16 * 8 + 8 * 16 + 2 * 8)
337 set_cpsr(get_hex_word(p
));
343 static void cmd_get_memory(char *args
, char *reply
) {
344 unsigned long addr
, len
, i
;
346 if (sscanf(args
, "%lx,%lx", &addr
, &len
) != 2) {
347 reply_error(0, reply
);
351 if (len
> (BUFMAX
- 16) / 2) {
352 reply_error(1, reply
);
357 for (i
= 0; i
< len
; i
++)
358 hex_byte(reply
+ i
* 2, *((unsigned char *)(addr
+ i
)));
364 static void cmd_put_memory(char *args
, char *reply
) {
365 unsigned long addr
, len
, i
;
369 sscanf(args
, "%lx,%lx:%n", &addr
, &len
, &pos
);
371 reply_error(0, reply
);
376 for (i
= 0; i
< len
; i
++)
377 *((unsigned char *)(addr
+ i
)) = get_hex_byte(args
+ pos
+ i
* 2);
383 static void cmd_put_memory_binary(char *args
, char *reply
) {
384 unsigned long addr
, len
, i
;
388 sscanf(args
, "%lx,%lx:%n", &addr
, &len
, &pos
);
390 reply_error(0, reply
);
395 for (i
= 0; i
< len
; i
++)
396 *((unsigned char *)(addr
+ i
)) = args
[pos
+ i
];
402 static void parse_continue_args(char *args
) {
406 if (sscanf(args
, "%x;%lx", &sig
, &addr
) == 2) {
407 set_general_reg(15, addr
);
408 } else if (sscanf(args
, "%lx", &addr
) == 1) {
409 set_general_reg(15, addr
);
413 static void cmd_go(char *args
) {
414 parse_continue_args(args
);
418 " ldr r12, [r1], #4\n"
420 " and r0, r0, #0x1f\n"
423 " ldr r14, [r1, #60]\n"
424 " msr spsr_fsxc, r12\n"
425 " ldmia r1, {r0-r14}^\n"
428 " msr cpsr_fsxc, r12\n"
429 " ldmia r1, {r0-r15}\n"
430 : : "r" (registers
));
433 static void remote_cmd(char *cmd
, char *reply
) {
437 while ((cmd
[i
] >= 'a' && cmd
[i
] <= 'z') || cmd
[i
] == '_')
439 if (!strncmp(cmd
, "reboot", i
))
444 (*(volatile unsigned long *)0x80002804) = 1;
447 else if (!strncmp(cmd
, "power_off", i
))
455 else if (!strncmp(cmd
, "watchdog", i
))
458 if (sscanf(cmd
+ i
, "%d", &t
) == 1)
459 watchdog_enable(t
!= 0);
465 hex_string(reply
, "Unrecognized command\n");
467 reply_error(err
, reply
);
470 static void cmd_query(char *args
, char *reply
) {
471 if (!strncmp(args
, "Rcmd,", 5)) {
475 while (isxdigit(s
[0]) && isxdigit(s
[1]) && i
< sizeof(cmd
) - 1) {
476 cmd
[i
++] = get_hex_byte(s
);
480 remote_cmd(cmd
, reply
);
485 void gdb_loop(void) {
491 get_packet(packet_buf
, sizeof(packet_buf
) - 1);
494 switch (packet_buf
[0]) {
496 reply_signal(gdb_exception_no
, reply_buf
);
500 cmd_get_register(packet_buf
+ 1, reply_buf
);
504 cmd_set_register(packet_buf
+ 1, reply_buf
);
512 cmd_set_registers(packet_buf
+ 1, reply_buf
);
516 cmd_get_memory(packet_buf
+ 1, reply_buf
);
520 cmd_put_memory(packet_buf
+ 1, reply_buf
);
524 cmd_put_memory_binary(packet_buf
+ 1, reply_buf
);
528 cmd_query(packet_buf
+ 1, reply_buf
);
532 cmd_go(packet_buf
+ 1);
533 reply_error(1, reply_buf
);
537 /* cmd_go(packet_buf + 1); */
545 put_packet(reply_buf
);
549 extern void *vectors
[];
551 static void gdb_set_vector(int n
, void *p
)
556 void gdb_und_exc(void);
557 void gdb_swi_exc(void);
558 void gdb_pabt_exc(void);
559 void gdb_dabt_exc(void);
561 static void gdb_set_vectors(void)
563 gdb_set_vector(VEC_UND
, gdb_und_exc
);
564 gdb_set_vector(VEC_SWI
, gdb_swi_exc
);
565 gdb_set_vector(VEC_PABT
, gdb_pabt_exc
);
566 gdb_set_vector(VEC_DABT
, gdb_dabt_exc
);
569 void gdb_loop_from_exc(void)
572 reply_error(1, reply_buf
);
574 reply_signal(gdb_exception_no
, reply_buf
);
575 put_packet(reply_buf
);
579 #define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg)))
581 static inline unsigned long irq_read(int reg
)
592 #define IRQ_WRITE_WAIT(reg, val, cond) \
593 do { unsigned long v, v2; \
595 IRQ_REG(reg) = (val); \
598 } while ((v != v2) || !(cond)); \
605 static void system_init(void)
611 for (i
= 0; i
< 0x1c; i
++)
613 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x1e000001, (v
& 0x3010f) == 1);
614 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x4000000, (v
& 0x10000) == 0);
615 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x10000001, (v
& 0xf) == 1);
621 static void gdb_api_log(char *msg
)
627 while (*msg
&& i
+ 2 <= BUFMAX
- 1)
629 hex_byte(reply_buf
+ i
, *msg
++);
633 put_packet(reply_buf
);
642 gdb_api_breakpoint();
647 #define xstr(s) str(s)
651 " ldr sp, =_stub_stack\n"
652 " sub r14, r14, #4\n"
653 " stmfd sp!, {r0-r3, r12, r14}\n"
654 " mov r0, #" xstr(VEC_UND
) "\n"
655 " b gdb_handle_exception\n"
657 " ldr sp, =_stub_stack\n"
658 " stmfd sp!, {r0-r3, r12, r14}\n"
659 " mov r0, #" xstr(VEC_SWI
) "\n"
660 " b gdb_handle_exception\n"
662 " ldr sp, =_stub_stack\n"
663 " stmfd sp!, {r0-r3, r12, r14}\n"
664 " mov r0, #" xstr(VEC_PABT
) "\n"
665 " b gdb_handle_exception\n"
667 " ldr sp, =_stub_stack\n"
668 " sub r14, r14, #4\n"
669 " stmfd sp!, {r0-r3, r12, r14}\n"
670 " ldr r0, =gdb_mem_access\n"
673 " bne gdb_data_abort\n"
674 " mov r0, #" xstr(VEC_DABT
) "\n"
675 " b gdb_handle_exception\n"
676 "gdb_handle_exception:\n"
677 " ldr r1, =gdb_exception_no\n"
679 " ldr r0, =registers\n"
681 " str r12, [r0], #4\n"
682 " ldmfd sp!, {r2, r3}\n"
683 " stmia r0!, {r2, r3}\n"
684 " ldmfd sp!, {r2, r3, r12, r14}\n"
685 " str r14, [r0, #52]\n"
686 " stmia r0!, {r2-r12}\n"
688 " and r2, r1, #0x1f\n"
691 " stmia r0, {r13, r14}^\n"
692 " b gdb_data_abort\n"
695 " stmia r0, {r13, r14}\n"
697 " msr cpsr_c, #0xd3\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"
704 " str r1, [r0], #4\n"
706 " str r1, [r0], #4\n"
708 " str r1, [r0], #4\n"
709 " stmia r0!, {r2-r14}\n"
711 " msr cpsr_c, #0xd3\n"
712 " ldr sp, =_stub_stack\n"
713 " ldr r0, =gdb_exception_no\n"
716 " b gdb_loop_from_exc\n");