1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Tomasz Malesinski
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
24 #include "ifp_usb_serial.h"
36 static char packet_buf
[BUFMAX
];
37 static char reply_buf
[BUFMAX
];
39 static const char hexchars
[] = "0123456789abcdef";
40 static int gdb_exception_no
, gdb_mem_access
;
41 static unsigned char watchdog_enabled
;
42 static unsigned long registers
[17];
44 void gdb_api_breakpoint(void);
45 static void gdb_api_log(char *msg
);
47 __attribute__((section(".gdbapi"))) struct gdb_api gdb_api
=
50 {gdb_api_breakpoint
, gdb_api_log
}
53 static void watchdog_enable(int on
)
55 (*(volatile unsigned long *)0x80002804) = on
;
56 watchdog_enabled
= on
;
59 static void watchdog_service(void)
63 (*(volatile unsigned long *)0x80002804) = 0;
64 (*(volatile unsigned long *)0x80002808) = 0;
65 (*(volatile unsigned long *)0x80002804) = 1;
69 static inline bool isxdigit(char c
)
71 return ((c
>= '0') && (c
<= '9'))
72 || ((c
>= 'a') && (c
<= 'f')) || ((c
>= 'A') && (c
<= 'F'));
75 static int hex(char ch
) {
76 if ((ch
>= 'a') && (ch
<= 'f'))
78 if ((ch
>= '0') && (ch
<= '9'))
80 if ((ch
>= 'A') && (ch
<= 'F'))
85 static void hex_byte(char *s
, int byte
) {
86 s
[0] = hexchars
[(byte
>> 4) & 0xf];
87 s
[1] = hexchars
[byte
& 0xf];
90 static void hex_word(char *s
, unsigned long val
) {
92 for (i
= 0; i
< 4; i
++)
93 hex_byte(s
+ i
* 2, (val
>> (i
* 8)) & 0xff);
96 static void hex_string(char *d
, char *s
) {
104 static int get_hex_byte(char *s
) {
105 return (hex(s
[0]) << 4) + hex(s
[1]);
108 static unsigned long get_hex_word(char *s
) {
111 for (i
= 3; i
>= 0; i
--)
112 r
= (r
<< 8) + get_hex_byte(s
+ i
* 2);
116 static void reply_error(int n
, char *reply
) {
118 hex_byte(reply
+ 1, n
);
122 static void reply_signal(int n
, char *reply
) {
138 hex_byte(reply
+ 1, signal
);
142 static void reply_ok(char *reply
) {
146 static int get_byte(void) {
148 while ((b
= usb_serial_try_get_byte()) < 0)
154 static void put_byte(unsigned char ch
) {
155 while (usb_serial_try_put_byte(ch
) < 0)
160 static void serial_write(unsigned char *buf
, int len
) {
162 for (i
= 0; i
< len
; i
++)
166 static void get_packet(char *buf
, int len
) {
167 int count
, checksum
, escaped
;
178 while (count
< len
) {
184 } else if (ch
== '#')
186 else if (ch
== 0x7d) {
197 buf
[count
] = ch
^ 0x20;
207 rchksum
= hex(ch
) << 4;
211 if ((checksum
& 0xff) != rchksum
)
221 static void put_packet(char *buf
) {
230 for (i
= 0; buf
[i
]; i
++)
233 serial_write(buf
, i
);
236 hex_byte(tmp
+ 1, checksum
& 0xff);
237 serial_write(tmp
, 3);
244 static inline unsigned long get_general_reg(int n
)
246 return registers
[n
+ 1];
249 static inline void set_general_reg(int n
, unsigned long v
)
251 registers
[n
+ 1] = v
;
254 static inline unsigned long get_cpsr(void)
259 static inline void set_cpsr(unsigned long v
)
264 static void g_reply(char *buf
) {
269 for (i
= 0; i
< 16; i
++) {
270 hex_word(p
, get_general_reg(i
));
274 for (i
= 0; i
< 8; i
++) {
281 hex_word(p
, get_cpsr());
285 static void cmd_get_register(char *args
, char *reply
) {
288 if (sscanf(args
, "%x", &r
) != 1) {
289 reply_error(0, reply
);
293 if (r
>= 0 && r
< 16) {
294 hex_word(reply
, get_general_reg(r
));
296 } else if (r
== 25) {
297 hex_word(reply
, get_cpsr());
305 static void cmd_set_register(char *args
, char *reply
) {
310 sscanf(args
, "%x=%n", &r
, &p
);
312 reply_error(0, reply
);
316 v
= get_hex_word(args
+ p
);
317 if (r
>= 0 && r
< 16)
318 set_general_reg(r
, v
);
324 static void cmd_set_registers(char *args
, char *reply
) {
331 for (i
= 0; i
< 16 && len
>= (i
+ 1) * 8; i
++) {
332 set_general_reg(i
, get_hex_word(p
));
336 if (len
>= 16 * 8 + 8 * 16 + 2 * 8)
339 set_cpsr(get_hex_word(p
));
345 static void cmd_get_memory(char *args
, char *reply
) {
346 unsigned long addr
, len
, i
;
348 if (sscanf(args
, "%lx,%lx", &addr
, &len
) != 2) {
349 reply_error(0, reply
);
353 if (len
> (BUFMAX
- 16) / 2) {
354 reply_error(1, reply
);
359 for (i
= 0; i
< len
; i
++)
360 hex_byte(reply
+ i
* 2, *((unsigned char *)(addr
+ i
)));
366 static void cmd_put_memory(char *args
, char *reply
) {
367 unsigned long addr
, len
, i
;
371 sscanf(args
, "%lx,%lx:%n", &addr
, &len
, &pos
);
373 reply_error(0, reply
);
378 for (i
= 0; i
< len
; i
++)
379 *((unsigned char *)(addr
+ i
)) = get_hex_byte(args
+ pos
+ i
* 2);
385 static void cmd_put_memory_binary(char *args
, char *reply
) {
386 unsigned long addr
, len
, i
;
390 sscanf(args
, "%lx,%lx:%n", &addr
, &len
, &pos
);
392 reply_error(0, reply
);
397 for (i
= 0; i
< len
; i
++)
398 *((unsigned char *)(addr
+ i
)) = args
[pos
+ i
];
404 static void parse_continue_args(char *args
) {
408 if (sscanf(args
, "%x;%lx", &sig
, &addr
) == 2) {
409 set_general_reg(15, addr
);
410 } else if (sscanf(args
, "%lx", &addr
) == 1) {
411 set_general_reg(15, addr
);
415 static void cmd_go(char *args
) {
416 parse_continue_args(args
);
420 " ldr r12, [r1], #4\n"
422 " and r0, r0, #0x1f\n"
425 " ldr r14, [r1, #60]\n"
426 " msr spsr_fsxc, r12\n"
427 " ldmia r1, {r0-r14}^\n"
430 " msr cpsr_fsxc, r12\n"
431 " ldmia r1, {r0-r15}\n"
432 : : "r" (registers
));
435 static void remote_cmd(char *cmd
, char *reply
) {
439 while ((cmd
[i
] >= 'a' && cmd
[i
] <= 'z') || cmd
[i
] == '_')
441 if (!strncmp(cmd
, "reboot", i
))
446 (*(volatile unsigned long *)0x80002804) = 1;
449 else if (!strncmp(cmd
, "power_off", i
))
457 else if (!strncmp(cmd
, "watchdog", i
))
460 if (sscanf(cmd
+ i
, "%d", &t
) == 1)
461 watchdog_enable(t
!= 0);
467 hex_string(reply
, "Unrecognized command\n");
469 reply_error(err
, reply
);
472 static void cmd_query(char *args
, char *reply
) {
473 if (!strncmp(args
, "Rcmd,", 5)) {
477 while (isxdigit(s
[0]) && isxdigit(s
[1]) && i
< sizeof(cmd
) - 1) {
478 cmd
[i
++] = get_hex_byte(s
);
482 remote_cmd(cmd
, reply
);
487 void gdb_loop(void) {
493 get_packet(packet_buf
, sizeof(packet_buf
) - 1);
496 switch (packet_buf
[0]) {
498 reply_signal(gdb_exception_no
, reply_buf
);
502 cmd_get_register(packet_buf
+ 1, reply_buf
);
506 cmd_set_register(packet_buf
+ 1, reply_buf
);
514 cmd_set_registers(packet_buf
+ 1, reply_buf
);
518 cmd_get_memory(packet_buf
+ 1, reply_buf
);
522 cmd_put_memory(packet_buf
+ 1, reply_buf
);
526 cmd_put_memory_binary(packet_buf
+ 1, reply_buf
);
530 cmd_query(packet_buf
+ 1, reply_buf
);
534 cmd_go(packet_buf
+ 1);
535 reply_error(1, reply_buf
);
539 /* cmd_go(packet_buf + 1); */
547 put_packet(reply_buf
);
551 extern void *vectors
[];
553 static void gdb_set_vector(int n
, void *p
)
558 void gdb_und_exc(void);
559 void gdb_swi_exc(void);
560 void gdb_pabt_exc(void);
561 void gdb_dabt_exc(void);
563 static void gdb_set_vectors(void)
565 gdb_set_vector(VEC_UND
, gdb_und_exc
);
566 gdb_set_vector(VEC_SWI
, gdb_swi_exc
);
567 gdb_set_vector(VEC_PABT
, gdb_pabt_exc
);
568 gdb_set_vector(VEC_DABT
, gdb_dabt_exc
);
571 void gdb_loop_from_exc(void)
574 reply_error(1, reply_buf
);
576 reply_signal(gdb_exception_no
, reply_buf
);
577 put_packet(reply_buf
);
581 #define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg)))
583 static inline unsigned long irq_read(int reg
)
594 #define IRQ_WRITE_WAIT(reg, val, cond) \
595 do { unsigned long v, v2; \
597 IRQ_REG(reg) = (val); \
600 } while ((v != v2) || !(cond)); \
607 static void system_init(void)
613 for (i
= 0; i
< 0x1c; i
++)
615 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x1e000001, (v
& 0x3010f) == 1);
616 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x4000000, (v
& 0x10000) == 0);
617 IRQ_WRITE_WAIT(0x404 + i
* 4, 0x10000001, (v
& 0xf) == 1);
623 static void gdb_api_log(char *msg
)
629 while (*msg
&& i
+ 2 <= BUFMAX
- 1)
631 hex_byte(reply_buf
+ i
, *msg
++);
635 put_packet(reply_buf
);
644 gdb_api_breakpoint();
649 #define xstr(s) str(s)
653 " ldr sp, =_stub_stack\n"
654 " sub r14, r14, #4\n"
655 " stmfd sp!, {r0-r3, r12, r14}\n"
656 " mov r0, #" xstr(VEC_UND
) "\n"
657 " b gdb_handle_exception\n"
659 " ldr sp, =_stub_stack\n"
660 " stmfd sp!, {r0-r3, r12, r14}\n"
661 " mov r0, #" xstr(VEC_SWI
) "\n"
662 " b gdb_handle_exception\n"
664 " ldr sp, =_stub_stack\n"
665 " stmfd sp!, {r0-r3, r12, r14}\n"
666 " mov r0, #" xstr(VEC_PABT
) "\n"
667 " b gdb_handle_exception\n"
669 " ldr sp, =_stub_stack\n"
670 " sub r14, r14, #4\n"
671 " stmfd sp!, {r0-r3, r12, r14}\n"
672 " ldr r0, =gdb_mem_access\n"
675 " bne gdb_data_abort\n"
676 " mov r0, #" xstr(VEC_DABT
) "\n"
677 " b gdb_handle_exception\n"
678 "gdb_handle_exception:\n"
679 " ldr r1, =gdb_exception_no\n"
681 " ldr r0, =registers\n"
683 " str r12, [r0], #4\n"
684 " ldmfd sp!, {r2, r3}\n"
685 " stmia r0!, {r2, r3}\n"
686 " ldmfd sp!, {r2, r3, r12, r14}\n"
687 " str r14, [r0, #52]\n"
688 " stmia r0!, {r2-r12}\n"
690 " and r2, r1, #0x1f\n"
693 " stmia r0, {r13, r14}^\n"
694 " b gdb_data_abort\n"
697 " stmia r0, {r13, r14}\n"
699 " msr cpsr_c, #0xd3\n"
700 " ldr sp, =_stub_stack\n"
701 " b gdb_loop_from_exc\n"
702 "gdb_api_breakpoint:\n"
703 " stmfd sp!, {r0-r1}\n"
704 " ldr r0, =registers\n"
706 " str r1, [r0], #4\n"
708 " str r1, [r0], #4\n"
710 " str r1, [r0], #4\n"
711 " stmia r0!, {r2-r14}\n"
713 " msr cpsr_c, #0xd3\n"
714 " ldr sp, =_stub_stack\n"
715 " ldr r0, =gdb_exception_no\n"
718 " b gdb_loop_from_exc\n");