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

barbalace at igi.cnr.it barbalace at igi.cnr.it
Tue May 5 21:21:21 CEST 2009


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.


More information about the U-Boot mailing list