nanonixos

Documentation
Login

We need to enable the RX function of the jz4740 pin for GPIO Port D for serial RX, instead of a keyboard line. But we need to do that at boot time, before kgdbwait.

I used this command line, enabling also kgdb in the kernel (also kdb):

CONFIG_CMDLINE="mem=32M console=tty0 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait kgdboc=ttyS0,57600 kgdbwait kgdbcon"

I had to build the kernel with a special patch, to enable the ttyS0 RX signal instead of the keyboard gpio line. It was this patch. I tried to guess what code would map to the PDFUNCS register described in the manual.

diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index f2d94c1..48289f5 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -442,6 +442,7 @@ static void __init board_gpio_setup(void)
         * drivers. Everything else is done by the drivers themselves. */
        jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N);
        jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD);
+       jz_gpio_set_function(JZ_GPIO_UART0_RXD, JZ_GPIO_FUNC_UART0_RXD);
 }

As explained in kgdb doc, kgdbcon allows me to see the printk in gdb. And kgdbwait blocks the boot at an early stage. Specifically, at this point:

NAND Secondary Program Loader

[U] pressed, goto USBBOOT mode
Ben NanoNote
GPIO, clocks, SDRAM, UART setup
now jump back to BOOT ROM...
ziess 80010000
Nkernel...
 the kernel...
[    0.000000] Linux version 3.2.0prova-86406-g986a58a-dirty (viric@bergamota) (collect2: ld returned 1 exit status) #12 PREEMPT Wed Jan 11 23:32:39 CET 2012
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU revision is: 0ad0024f (Ingenic JZRISC)
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 02000000 @ 00000000 (usable)
[    0.000000] User-defined physical RAM map:
[    0.000000]  memory: 02000000 @ 00000000 (usable)
[    0.000000] Zone PFN ranges:
[    0.000000]   Normal   0x00000000 -> 0x00002000
[    0.000000] Movable zone start PFN for each node
[    0.000000] early_node_map[1] active PFN ranges
[    0.000000]     0: 0x00000000 -> 0x00002000
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8128
[    0.000000] Kernel command line:  mem=32M console=tty0 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait kgdboc=ttyS0,57600 kgdbwait kgdbcon
[    0.000000] PID hash table entries: 128 (order: -3, 512 bytes)
[    0.000000] Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.000000] Primary instruction cache 16kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 32 bytes
[    0.000000] Memory: 27616k/32768k available (3140k kernel code, 5152k reserved, 1060k data, 176k init, 0k highmem)
[    0.000000] NR_IRQS:190
[    0.000000] Console: colour dummy device 80x25
[    0.000000] console [tty0] enabled, bootconsole disabled

Entering kdb (current=0x81c188c8, pid 1) due to Keyboard Entry
kdb>

Then we can start gdb:

$ mipsel-unknown-linux-gdb vmlinux
GNU gdb (GDB) 7.3.1
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=mipsel-unknown-linux".
---Type <return> to continue, or q <return> to quit---
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/viric/3rd/qi-kernel/vmlinux...
done.
(gdb) set remotebaud 57600
(gdb) target remote /dev/ttyUSB0
Remote debugging using /dev/ttyUSB0
0x8001cc68 in arch_kgdb_breakpoint () at arch/mips/kernel/kgdb.c:200
200             __asm__ __volatile__(
(gdb) break jz_nand_probe
Breakpoint 1 at 0x803192b0: file drivers/mtd/nand/jz4740_nand.c, line 404.
(gdb) c
Continuing.
[    0.600000] brd: module loaded

Breakpoint 1, jz_nand_probe (pdev=0x8040d850) at drivers/mtd/nand/jz4740_nand.c:404
404     {
(gdb)
.... listing ...
(gdb) 
459             /* We are going to autodetect NAND chips in the banks specified in the
460              * platform data. Although nand_scan_ident() can detect multiple chips,
461              * it requires those chips to be numbered consecuitively, which is not
462              * always the case for external memory banks. And a fixed chip-to-bank
463              * mapping is not practical either, since for example Dingoo units
464              * produced at different times have NAND chips in different banks.
465              */
466             chipnr = 0;
467             for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) {
468                     unsigned char bank;
(gdb) until 467
platform_set_drvdata (data=0x81cf2800, pdev=0x8040d850) at drivers/mtd/nand/jz4740_nand.c:467
467             for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) {
(gdb)

Usually there is no way to print local variables, because the kernel is built with -O2. This means that you have to rely on some static variables for debugging, or have a good virtual machine in your brain for the assembler gdb is going to show to you on 'disasm'.

A good explanation about the kernel built on -O2 (set on the root Makefile, KBUILD_CFLAGS += -1), you can find throughout this lkml thread - Building Kernel with -O0.

I don't know how to print local variables though. It looks like not working for me:

(gdb) print chip
No symbol "chip" in current context.
(gdb) print nand
No symbol "nand" in current context.
(gdb) print pdata
No symbol "pdata" in current context.

SYSRQ - sysreq - system request

Typing KEY_LEFTALT and KEY_SYSRQ at once brings you the sysrq possibilities. If you want to break at any point with an attached gdb, or you want to trigger kgdb, you can use the combination sysrq-g (Remember that sysrq-h shows the help).

I used this patch, that changes the KEY_F8 key for KEY_SYSRQ in the nanonote keyboard:

--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -200,7 +200,7 @@ static const uint32_t qi_lb60_keymap[] = {
        KEY(5, 5, KEY_QI_QI),   /* S47 */
        KEY(5, 6, KEY_RIGHTCTRL),       /* S48 */
        KEY(5, 7, KEY_LEFT),    /* S49 */
-       KEY(6, 0, KEY_F8),      /* S50 */
+       KEY(6, 0, KEY_SYSRQ),   /* S50 */
        KEY(6, 1, KEY_P),       /* S51 */
        KEY(6, 2, KEY_BACKSPACE),/* S52 */
        KEY(6, 3, KEY_ENTER),   /* S53 */

Then I could use ALT-F8 in the keyboard as a SYSRQ key. ALT-F8, and then H without releasing the ALT, showed the help in the console. In my case, tty0. ALT-F8, G started kgdb.

kgdb and kdb

If you compiled both in, typing "kgdb" in "kdb>" will make the kernel wait for a gdb to attach. If you know that the kernel is in kgdb mode, then you can type $3#33 (or check the proper manual for more information).