public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] arm920t kgdb serial support
@ 2009-05-05 19:21 barbalace at igi.cnr.it
  2009-05-05 19:30 ` Scott Wood
  0 siblings, 1 reply; 4+ messages in thread
From: barbalace at igi.cnr.it @ 2009-05-05 19:21 UTC (permalink / raw)
  To: u-boot

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@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.

^ permalink raw reply	[flat|nested] 4+ messages in thread
* [U-Boot] PATCH arm920t kgdb serial support
@ 2009-05-05 17:35 barbalace at igi.cnr.it
  2009-05-05 18:53 ` Wolfgang Denk
  0 siblings, 1 reply; 4+ messages in thread
From: barbalace at igi.cnr.it @ 2009-05-05 17:35 UTC (permalink / raw)
  To: u-boot

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 */

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");
 
Signed-off-by: Eng. Antonio Barbalace

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-05-05 19:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-05 19:21 [U-Boot] [PATCH] arm920t kgdb serial support barbalace at igi.cnr.it
2009-05-05 19:30 ` Scott Wood
  -- strict thread matches above, loose matches on Subject: below --
2009-05-05 17:35 [U-Boot] PATCH " barbalace at igi.cnr.it
2009-05-05 18:53 ` Wolfgang Denk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox