[U-Boot] U-BOOT kgdb support for ARM920T (s3c2440)

barbalace at igi.cnr.it barbalace at igi.cnr.it
Tue May 5 13:41:26 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