[U-Boot] U-BOOT kgdb support for ARM920T (s3c2440)
barbalace at igi.cnr.it
barbalace at igi.cnr.it
Tue May 5 13:47:28 CEST 2009
I've just written and tested this kgdb patch for ARM920T cpus.
The development was aimed at providing a low-cost cross-debugging
environment for a Samsung ARM board produced from SERP (www.serp.it)
used in an Computer Architecture course taught at the university of
Padova (IT) (www.dei.unipd.it).
It works with gdb software breakpoint (on the host computer). Also
with an arm-linux- toolchain.
Eng. Antonio Barbalace
Istituto Gas Ionizzati del CNR
Consorzio RFX - Associazione EURATOM/ENEA sulla Fusione
Corso Stati Uniti 4, 35127 Padova - Italy
antonio.barbalace at igi.cnr.it, http://www.igi.cnr.it
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
-------------- next part --------------
diff -r -u u-boot/common/kgdb.c u-boot-UniPd/common/kgdb.c
--- u-boot/common/kgdb.c 2007-11-06 18:07:07.000000000 +0100
+++ u-boot-UniPd/common/kgdb.c 2009-02-23 16:47:31.000000000 +0100
@@ -322,7 +322,7 @@
kgdb_interruptible(0);
- printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
+// printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
if (kgdb_setjmp((long*)error_jmp_buf) != 0)
panic("kgdb: error or fault in entry init!\n");
@@ -457,10 +457,11 @@
}
goto doexit;
-
- case 'S': /* SSS single step with signal SS */
- *ptr = '\0'; /* ignore the signal number for now */
- /* fall through */
+/*
+#ifdef _PPC
+ case 'S': // SSS single step with signal SS
+ *ptr = '\0'; // ignore the signal number for now
+ // fall through
case 's':
kd.extype = KGDBEXIT_SINGLE;
@@ -469,7 +470,8 @@
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 +498,12 @@
} else {
kgdb_error(KGDBERR_BADPARAMS);
}
- break;
- } /* switch */
+ case 'q':
+ if (!(strcmp(ptr, "Supported"))) {
+ sprintf(remcomOutBuffer, "PacketSize=%d", BUFMAX);
+ }
+ break;
+ } /* switch */
if (errnum != 0)
sprintf(remcomOutBuffer, "E%02d", errnum);
diff -r -u u-boot/cpu/arm920t/Makefile u-boot-UniPd/cpu/arm920t/Makefile
--- u-boot/cpu/arm920t/Makefile 2007-11-07 17:18:30.000000000 +0100
+++ u-boot-UniPd/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/cpu/arm920t/interrupts.c
--- u-boot/cpu/arm920t/interrupts.c 2007-11-06 18:11:29.000000000 +0100
+++ u-boot-UniPd/cpu/arm920t/interrupts.c 2009-01-19 22:55:29.000000000 +0100
@@ -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,13 +123,26 @@
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)
{
+/*
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(pt_regs))
+ return;
+#endif
+*/
printf ("software interrupt\n");
show_regs (pt_regs);
bad_mode ();
@@ -133,13 +150,24 @@
void do_prefetch_abort (struct pt_regs *pt_regs)
{
+/*
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(pt_regs))
+ return;
+#endif
+*/
printf ("prefetch abort\n");
show_regs (pt_regs);
bad_mode ();
}
void do_data_abort (struct pt_regs *pt_regs)
-{
+{/*
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(pt_regs))
+ return;
+#endif
+*/
printf ("data abort\n");
show_regs (pt_regs);
bad_mode ();
@@ -154,6 +182,12 @@
void do_fiq (struct pt_regs *pt_regs)
{
+/*
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(pt_regs))
+ return;
+#endif
+*/
printf ("fast interrupt request\n");
show_regs (pt_regs);
bad_mode ();
@@ -161,19 +195,27 @@
void do_irq (struct pt_regs *pt_regs)
{
-#if defined (CONFIG_USE_IRQ)
-#if defined (ARM920_IRQ_CALLBACK)
- ARM920_IRQ_CALLBACK();
- return;
-#elif defined (CONFIG_ARCH_INTEGRATOR)
+//#if defined (CONFIG_USE_IRQ)
+//#if defined (ARM920_IRQ_CALLBACK)
+// ARM920_IRQ_CALLBACK();
+// return;
+//#elif defined (CONFIG_ARCH_INTEGRATOR)
/* ASSUMED to be a timer interrupt */
/* Just clear it - count handled in */
/* integratorap.c */
- *(volatile ulong *)(CFG_TIMERBASE + 0x0C) = 0;
-#endif /* ARCH_INTEGRATOR */
-#else
+// *(volatile ulong *)(CFG_TIMERBASE + 0x0C) = 0;
+//#endif /* ARCH_INTEGRATOR */
+//#else
+
+/*
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(pt_regs))
+ return;
+#endif
+*/
printf ("interrupt request\n");
show_regs (pt_regs);
bad_mode ();
-#endif
+
+//#endif
}
diff -r -u u-boot/cpu/arm920t/s3c24x0/serial.c u-boot-UniPd/cpu/arm920t/s3c24x0/serial.c
--- u-boot/cpu/arm920t/s3c24x0/serial.c 2007-11-06 18:13:13.000000000 +0100
+++ u-boot-UniPd/cpu/arm920t/s3c24x0/serial.c 2009-01-15 17:29:24.000000000 +0100
@@ -306,6 +306,114 @@
#endif /* CONFIG_SERIAL_MULTI */
+#if defined(CONFIG_CMD_KGDB)
+/*
+ AS HARNOIS : 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/cpu/arm920t/start.S
--- u-boot/cpu/arm920t/start.S 2008-01-21 11:27:32.000000000 +0100
+++ u-boot-UniPd/cpu/arm920t/start.S 2009-01-21 16:21:13.000000000 +0100
@@ -160,6 +160,8 @@
*/
start_code:
+#define START_SVC32 1
+#if defined (START_SVC32)
/*
* set the cpu to SVC32 mode
*/
@@ -167,6 +169,8 @@
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
+#else
+#endif
#if defined (CONFIG_S3C2440) && defined (CFG_UART0_EARLY_INIT)
# setup GPIOs
@@ -757,8 +761,8 @@
#define I_BIT 0x80
/*
- * use bad_save_user_regs for abort/prefetch/undef/swi ...
- * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ * use bad_save_user_regs for abort/prefetch/undef/swi
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/
.macro bad_save_user_regs
@@ -780,7 +784,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 +792,57 @@
mov r0, sp
.endm
+#if defined (CONFIG_CMD_KGDB)
+#if defined (START_SVC32)
+ /*
+ * if u-boot run in SVC32 mode is not so simple to access SVC sp and lr
+ * registers and kgdb need the exact content of this registers. ^ guarantee
+ * access to user registers but there is no simple way like sp_svc to access
+ * those registers. This solution work well with SVC <-> UND. doesn't work
+ * with USR <-> UND because writing mode bits is a privileged action.
+ * Probably more appropriate und_save_svc_regs/und_save_svc_regs will be written...
+ */
+ .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
+#else
+#endif /* START_SVC32 */
+
+#endif /* CONFIG_CMD_KGDB */
+
.macro irq_restore_user_regs
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
mov r0, r0
@@ -823,12 +878,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 +921,6 @@
bl do_not_used
#ifdef CONFIG_USE_IRQ
-
.align 5
irq:
get_irq_stack
@@ -871,7 +937,6 @@
irq_restore_user_regs
#else
-
.align 5
irq:
get_bad_stack
diff -r -u u-boot/examples/Makefile u-boot-UniPd/examples/Makefile
--- u-boot/examples/Makefile 2007-11-06 18:07:07.000000000 +0100
+++ u-boot-UniPd/examples/Makefile 2009-01-15 19:54:59.000000000 +0100
@@ -30,7 +30,7 @@
endif
ifeq ($(ARCH),arm)
-LOAD_ADDR = 0xc100000
+LOAD_ADDR = 0x30000000
endif
ifeq ($(ARCH),mips)
diff -r -u u-boot/examples/hello_world.c u-boot-UniPd/examples/hello_world.c
--- u-boot/examples/hello_world.c 2007-11-06 18:07:07.000000000 +0100
+++ u-boot-UniPd/examples/hello_world.c 2009-01-19 15:14:08.000000000 +0100
@@ -49,6 +49,14 @@
/* consume input */
(void) getc();
- printf ("\n\n");
+// asm volatile ("\t.long 0xe7f001f0\n");
+ kgdb_breakpoint(argc, argv);
+
+ printf ("break0 test\n\n");
+ printf ("break1 test\n\n");
+ printf ("break2 test\n\n");
+
+// asm volatile ("\t.long 0xef9f0001\n");
+
return (0);
}
diff -r -u u-boot/include/_exports.h u-boot-UniPd/include/_exports.h
--- u-boot/include/_exports.h 2007-11-06 18:07:07.000000000 +0100
+++ u-boot-UniPd/include/_exports.h 2009-01-19 15:16:07.000000000 +0100
@@ -24,3 +24,6 @@
EXPORT_FUNC(i2c_write)
EXPORT_FUNC(i2c_read)
#endif
+#ifdef CONFIG_CMD_KGDB
+EXPORT_FUNC(kgdb_breakpoint)
+#endif
\ No newline at end of file
diff -r -u u-boot/include/configs/serp.h u-boot-UniPd/include/configs/serp.h
--- u-boot/include/configs/serp.h 2007-12-05 15:12:22.000000000 +0100
+++ u-boot-UniPd/include/configs/serp.h 2009-01-15 12:59:37.000000000 +0100
@@ -111,6 +111,7 @@
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_LICENSE
#define CONFIG_CMD_TERMINAL
+#define CONFIG_CMD_KGDB
#define CONFIG_BOOTDELAY 10
#define CONFIG_BOOTARGS ""
@@ -119,7 +120,6 @@
#define CONFIG_DOS_PARTITION 1
#if defined(CONFIG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
-/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
diff -r -u u-boot/include/exports.h u-boot-UniPd/include/exports.h
--- u-boot/include/exports.h 2007-11-06 18:07:07.000000000 +0100
+++ u-boot-UniPd/include/exports.h 2009-01-19 15:14:12.000000000 +0100
@@ -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
diff -r -u u-boot/lib_arm/Makefile u-boot-UniPd/lib_arm/Makefile
--- u-boot/lib_arm/Makefile 2007-11-06 18:07:08.000000000 +0100
+++ u-boot-UniPd/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/lib_arm/board.c
--- u-boot/lib_arm/board.c 2007-11-06 18:07:08.000000000 +0100
+++ u-boot-UniPd/lib_arm/board.c 2009-01-15 20:48:37.000000000 +0100
@@ -284,6 +284,8 @@
}
}
+
+
#ifndef CFG_NO_FLASH
/* configure available FLASH banks */
size = flash_init ();
@@ -345,6 +347,11 @@
serial_initialize();
#endif
+#if defined(CONFIG_CMD_KGDB)
+ puts ("KGDB: ");
+ kgdb_init ();
+#endif
+
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
More information about the U-Boot
mailing list