[U-Boot] [PATCH] arm920t kgdb serial support

This patch add kgdb to ARM920T cpus (full support to s3c2440). The patch lets debugging remote ARM targets using the serial line and GDB.
Signed-off-by: Antonio Barbalace <antonio.barbalace at igi.cnr.it>
diff -r -u u-boot/common/kgdb.c u-boot-UniPd-denx.de/common/kgdb.c --- u-boot/common/kgdb.c 2007-11-06 18:07:07.000000000 +0100 +++ u-boot-UniPd-denx.de/common/kgdb.c 2009-05-05 18:44:25.000000000 +0200 @@ -458,6 +458,7 @@
goto doexit;
+#ifdef _PPC case 'S': /* SSS single step with signal SS */ *ptr = '\0'; /* ignore the signal number for now */ /* fall through */ @@ -469,7 +470,7 @@ kd.exaddr = addr; kd.extype |= KGDBEXIT_WITHADDR; } - +#endif doexit: /* Need to flush the instruction cache here, as we may have deposited a * breakpoint, and the icache probably has no way of knowing that a data ref to @@ -496,8 +497,13 @@ } else { kgdb_error(KGDBERR_BADPARAMS); } + + case 'q': + if (!(strcmp(ptr, "Supported"))) { + sprintf(remcomOutBuffer, "PacketSize=%d", BUFMAX); + } break; - } /* switch */ + } /* switch */
if (errnum != 0) sprintf(remcomOutBuffer, "E%02d", errnum); diff -r -u u-boot/cpu/arm920t/Makefile u-boot-UniPd-denx.de/cpu/arm920t/Makefile --- u-boot/cpu/arm920t/Makefile 2007-11-07 17:18:30.000000000 +0100 +++ u-boot-UniPd-denx.de/cpu/arm920t/Makefile 2009-01-15 17:01:58.000000000 +0100 @@ -26,7 +26,8 @@ LIB = $(obj)lib$(CPU).a
START = start.o -COBJS = cpu.o interrupts.o +COBJS = cpu.o interrupts.o +SOBJS = kgdb.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) diff -r -u u-boot/cpu/arm920t/interrupts.c u-boot-UniPd-denx.de/cpu/arm920t/interrupts.c --- u-boot/cpu/arm920t/interrupts.c 2007-11-06 18:11:29.000000000 +0100 +++ u-boot-UniPd-denx.de/cpu/arm920t/interrupts.c 2009-05-05 18:52:15.000000000 +0200 @@ -33,6 +33,10 @@ #include <arm920t.h> #include <asm/proc-armv/ptrace.h>
+#if defined(CONFIG_CMD_KGDB) +int (*debugger_exception_handler)(struct pt_regs *) = 0; +#endif + #ifdef CONFIG_USE_IRQ /* enable IRQ interrupts */ void enable_interrupts (void) @@ -119,9 +123,16 @@
void do_undefined_instruction (struct pt_regs *pt_regs) { +#if defined(CONFIG_CMD_KGDB) + pt_regs->ARM_pc -= 4; + if (debugger_exception_handler && (*debugger_exception_handler)(pt_regs)) { + return; + } +#else printf ("undefined instruction\n"); show_regs (pt_regs); bad_mode (); +#endif }
void do_software_interrupt (struct pt_regs *pt_regs) diff -r -u u-boot/cpu/arm920t/s3c24x0/serial.c u-boot-UniPd-denx.de/cpu/arm920t/s3c24x0/serial.c --- u-boot/cpu/arm920t/s3c24x0/serial.c 2007-11-06 18:13:13.000000000 +0100 +++ u-boot-UniPd-denx.de/cpu/arm920t/s3c24x0/serial.c 2009-05-05 19:00:14.000000000 +0200 @@ -306,6 +306,114 @@
#endif /* CONFIG_SERIAL_MULTI */
+#if defined(CONFIG_CMD_KGDB) +/* + according to CONFIG_KGDB_SER_INDEX kgdb uses serial port + number 0 or number 1 + - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 : + configuration has been already done + - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 : + configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE +*/ +#if (CONFIG_KGDB_SER_INDEX & 2) +void kgdb_serial_init (void) +{ + volatile char val; + unsigned short br_reg; + + get_clocks (); + br_reg = (((((gd->cpu_clk / 16) / 18) * 10) / CONFIG_KGDB_BAUDRATE) + + 5) / 10; + /* + * Init onboard 16550 UART + */ + out8 (ACTING_UART1_BASE + UART_LCR, 0x80); /* set DLAB bit */ + out8 (ACTING_UART1_BASE + UART_DLL, (br_reg & 0x00ff)); /* set divisor for 9600 baud */ + out8 (ACTING_UART1_BASE + UART_DLM, ((br_reg & 0xff00) >> 8)); /* set divisor for 9600 baud */ + out8 (ACTING_UART1_BASE + UART_LCR, 0x03); /* line control 8 bits no parity */ + out8 (ACTING_UART1_BASE + UART_FCR, 0x00); /* disable FIFO */ + out8 (ACTING_UART1_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ + val = in8 (ACTING_UART1_BASE + UART_LSR); /* clear line status */ + val = in8 (ACTING_UART1_BASE + UART_RBR); /* read receive buffer */ + out8 (ACTING_UART1_BASE + UART_SCR, 0x00); /* set scratchpad */ + out8 (ACTING_UART1_BASE + UART_IER, 0x00); /* set interrupt enable reg */ +} + +void putDebugChar (const char c) +{ + if (c == '\n') + serial_putc ('\r'); + + out8 (ACTING_UART1_BASE + UART_THR, c); /* put character out */ + + /* check THRE bit, wait for transfer done */ + while ((in8 (ACTING_UART1_BASE + UART_LSR) & 0x20) != 0x20); +} + +void putDebugStr (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int getDebugChar (void) +{ + unsigned char status = 0; + + while (1) { + status = in8 (ACTING_UART1_BASE + UART_LSR); + if ((status & asyncLSRDataReady1) != 0x0) { + break; + } + if ((status & ( asyncLSRFramingError1 | + asyncLSROverrunError1 | + asyncLSRParityError1 | + asyncLSRBreakInterrupt1 )) != 0) { + out8 (ACTING_UART1_BASE + UART_LSR, + asyncLSRFramingError1 | + asyncLSROverrunError1 | + asyncLSRParityError1 | + asyncLSRBreakInterrupt1); + } + } + return (0x000000ff & (int) in8 (ACTING_UART1_BASE)); +} + +void kgdb_interruptible (int yes) +{ + return; +} + +#else /* ! (CONFIG_KGDB_SER_INDEX & 2) */ + +void kgdb_serial_init (void) +{ + serial_printf ("[on serial] "); +} + +void putDebugChar (int c) +{ + serial_putc (c); +} + +void putDebugStr (const char *str) +{ + serial_puts (str); +} + +int getDebugChar (void) +{ + return serial_getc (); +} + +void kgdb_interruptible (int yes) +{ + return; +} +#endif /* (CONFIG_KGDB_SER_INDEX & 2) */ +#endif + #endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined (CONFIG_S3C2442) || defined (CONFIG_TRAB) */ diff -r -u u-boot/cpu/arm920t/start.S u-boot-UniPd-denx.de/cpu/arm920t/start.S --- u-boot/cpu/arm920t/start.S 2008-01-21 11:27:32.000000000 +0100 +++ u-boot-UniPd-denx.de/cpu/arm920t/start.S 2009-05-05 19:15:15.000000000 +0200 @@ -780,7 +780,7 @@ sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 add r7, sp, #S_PC - stmdb r7, {sp, lr}^ @ Calling SP, LR + stmdb r7, {sp, lr}^ @ NOTE: Save USER SP and LR str lr, [r7, #0] @ Save calling PC mrs r6, spsr str r6, [r7, #4] @ Save CPSR @@ -788,6 +788,56 @@ mov r0, sp .endm
+#if defined (CONFIG_CMD_KGDB) + /* + * U-BOOT runs in SVC32 mode and so is not simple to access SVC's sp and + * lr registers, there isn't an appropriate instruction like in ARM11. + * kgdb needs the exact content of this registers to work. + * ARM9 guarantee access to USR32 mode registers from any other mode but + * there is no direct way to access SVC, UND, etc.. registers from other + * privileged modes. + * This solution work well with SVC <-> UND doesn't work with USR <-> UND + * because writing mode bits is a privileged action and can't return. + */ + .macro und_save_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r7, sp, #S_PC + str lr, [r7, #0] @ Save calling PC + mrs r6, spsr + str r6, [r7, #4] @ Save CPSR + str r0, [r7, #8] @ Save OLD_R0 + + mrs r0, cpsr @ move cpsr in r0 + msr cpsr_c, r6 @ move in the previous mode and save sp and lr in + mov r1, sp @ r1 and + mov r2, lr @ r2 then + msr cpsr_c, r0 @ return in the correct mode and + + stmdb r7, {r1, r2} @ save registers on the stack + mov r0, sp + .endm + + .macro und_restore_regs + add r7, sp, #S_PC @ set r7 to point program counter + ldr r6, [r7, #4] @ load spsr in r6 + ldmdb r7, {r1, r2} @ load sp in r1 and lr in r2 + + mrs r0, cpsr @ move cpsr in r0 + msr cpsr_c, r6 @ move in the previous mode and restore r1 and r2 in + mov sp, r1 @ sp and + mov lr, r2 @ lr then + msr cpsr_c, r0 @ return in the correct mode and + + ldmia sp, {r0 - r12} @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + movs pc, lr @ return & move spsr_svc into cpsr + .endm + +#endif /* CONFIG_CMD_KGDB */ + .macro irq_restore_user_regs ldmia sp, {r0 - lr}^ @ Calling r0 - lr mov r0, r0 @@ -823,12 +873,24 @@ /* * exception handlers */ + +#if defined(CONFIG_CMD_KGDB) + .align 5 +undefined_instruction: + get_irq_stack + und_save_regs + bl do_undefined_instruction + und_restore_regs + +#else /* CONFIG_CMD_KGDB */ .align 5 undefined_instruction: get_bad_stack bad_save_user_regs bl do_undefined_instruction
+#endif /* CONFIG_CMD_KGDB */ + .align 5 software_interrupt: get_bad_stack @@ -854,7 +916,6 @@ bl do_not_used
#ifdef CONFIG_USE_IRQ - .align 5 irq: get_irq_stack @@ -871,7 +932,6 @@ irq_restore_user_regs
#else - .align 5 irq: get_bad_stack diff -r -u u-boot/include/_exports.h u-boot-UniPd-denx.de/include/_exports.h --- u-boot/include/_exports.h 2007-11-06 18:07:07.000000000 +0100 +++ u-boot-UniPd-denx.de/include/_exports.h 2009-05-05 19:19:56.000000000 +0200 @@ -24,3 +24,6 @@ EXPORT_FUNC(i2c_write) EXPORT_FUNC(i2c_read) #endif +#ifdef CONFIG_CMD_KGDB +EXPORT_FUNC(kgdb_breakpoint) +#endif diff -r -u u-boot/include/exports.h u-boot-UniPd-denx.de/include/exports.h --- u-boot/include/exports.h 2007-11-06 18:07:07.000000000 +0100 +++ u-boot-UniPd-denx.de/include/exports.h 2009-05-05 19:17:07.000000000 +0200 @@ -25,6 +25,9 @@ void setenv (char *varname, char *varvalue); long simple_strtol(const char *cp,char **endp,unsigned int base); int strcmp(const char * cs,const char * ct); +#ifdef CONFIG_CMD_KGDB +void kgdb_breakpoint(int argc, char *argv[]); +#endif #ifdef CONFIG_HAS_UID void forceenv (char *varname, char *varvalue); #endif @@ -45,7 +48,7 @@ XF_MAX };
-#define XF_VERSION 4 +#define XF_VERSION 5
#if defined(CONFIG_I386) extern gd_t *global_data; diff -r -u u-boot/lib_arm/Makefile u-boot-UniPd-denx.de/lib_arm/Makefile --- u-boot/lib_arm/Makefile 2007-11-06 18:07:08.000000000 +0100 +++ u-boot-UniPd-denx.de/lib_arm/Makefile 2009-01-15 13:03:04.000000000 +0100 @@ -28,7 +28,7 @@ SOBJS = _ashldi3.o _ashrdi3.o _divsi3.o _modsi3.o _udivsi3.o _umodsi3.o
COBJS = armlinux.o board.o \ - cache.o div0.o + cache.o div0.o kgdb.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff -r -u u-boot/lib_arm/board.c u-boot-UniPd-denx.de/lib_arm/board.c --- u-boot/lib_arm/board.c 2007-11-06 18:07:08.000000000 +0100 +++ u-boot-UniPd-denx.de/lib_arm/board.c 2009-05-05 19:18:01.000000000 +0200 @@ -345,6 +345,11 @@ serial_initialize(); #endif
+#if defined(CONFIG_CMD_KGDB) + puts ("KGDB: "); + kgdb_init (); +#endif + /* IP Address */ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.

barbalace@igi.cnr.it wrote:
This patch add kgdb to ARM920T cpus (full support to s3c2440). The patch lets debugging remote ARM targets using the serial line and GDB.
Signed-off-by: Antonio Barbalace <antonio.barbalace at igi.cnr.it>
diff -r -u u-boot/common/kgdb.c u-boot-UniPd-denx.de/common/kgdb.c --- u-boot/common/kgdb.c 2007-11-06 18:07:07.000000000 +0100 +++ u-boot-UniPd-denx.de/common/kgdb.c 2009-05-05 18:44:25.000000000 +0200 @@ -458,6 +458,7 @@
goto doexit;
+#ifdef _PPC
CONFIG_PPC -- and explain in a comment why this is powerpc-specific (and keep in mind that ARM and PowerPC are not the only possibilities), and what happens on other architectures if those commands are used.
@@ -496,8 +497,13 @@ } else { kgdb_error(KGDBERR_BADPARAMS); }
case 'q':
if (!(strcmp(ptr, "Supported"))) {
sprintf(remcomOutBuffer, "PacketSize=%d", BUFMAX);
} break;
Explain what this change does -- what does it have to do with arm920t?
-Scott
participants (2)
-
barbalaceļ¼ igi.cnr.it
-
Scott Wood