[U-Boot] PATCH arm920t kgdb serial support

barbalace at igi.cnr.it barbalace at igi.cnr.it
Tue May 5 19:35:30 CEST 2009


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



More information about the U-Boot mailing list