2013年9月29日 星期日

OpenOCD + Eclipse + Jtag debug on Uboot & Linux

OpenOCD debugging is the most efficient than KGDB. (fit for Freescale & TI chip)

1.
Seeedstudio Bus Blaster price is less than 40 US$ on Ebay. Very cheap.
bus blaster v3 or v3c or v4 or v4.1 connect to i.mx6dq jtag pings.(Vtg, Vcc disconnect)
Blaster      - I.Mx6dq
TRST         - TRSTn
TDI            - TDI
TMS          - TMS
TCK          - TCK
TDO          - TDO
TSRST      - nSRST
GND         - GND

http://dangerousprototypes.com/docs/Bus_Blaster
http://www.mediafire.com/view/ozh1f11zx8s2g5s/BusBlaster_jtag.png#
http://www.mediafire.com/view/9tbesr2g5j1bp82/IMX6dq_jtag.png#

2. arm-eabi-gdb dependency lib
add-apt-repository ppa:fkrull/deadsnakes
apt-get update
apt-get install python2.6 python2.6-dev

3. openocd lib
apt-get update
apt-get install libftdi-dev
apt-get install libusb-1.0-0-dev
apt-get install automake autoconf libtool pkg-config

4.
http://sourceforge.net/projects/openocd/files/openocd/0.9.0
download file openocd-0.9.0.tar.gz
extract to
[~home]/openocd-0.9.0
or
open terminal window -> git clone git://git.code.sf.net/p/openocd/code

5.
//i.mx6 only have hardware breakpoint.
//Hit the soft breakpoint can not continue debug, bug fixed.
function gdb_breakpoint_watchpoint_packet of openocd-0.9.0/src/server/gdb_server.c
bp_type = BKPT_SOFT;
change to
bp_type = BKPT_HARD;

6. //auto switch AHB APB source
in function cortex_a_post_debug_entry(struct target *target)
after code
cortex_a->curr_mode = armv7a->arm.core_mode;
add new
armv7a->memory_ap = armv7a->armv7a_mmu.mmu_enabled; //0-AHB 1-APB

here explain how AHB and APB work
http://arttools.blogspot.tw/2009/09/debugging-on-cortex-a8-system.html

7. //APB force use slow path
gedit /root/openocd-0.9.0/src/target/cortex_a.c
//in function cortex_a_read_apb_ab_memory
if (size == 4 && (address % 4) == 0)
//change to
if( 0 )

//in function cortex_a_write_apb_ab_memory
if (size == 4 && (address % 4) == 0)
//change to
if( 0 )

8. //speed up openocd to debug (OPTION)
gedit /root/openocd-0.9.0/src/target/target.h
//in struct target
after
int32_t coreid;
add new
bool cp15_entry_switch; //by stone

gedit /root/openocd-0.9.0/src/server/gdb_server.c
//in gdb_new_connection(struct connection *connection)
after
command_set_output_handler(connection->cmd_ctx, gdb_output, connection);
add
gdb_service->target->cp15_entry_switch = true; //by stone, when new connect cp15 read

gedit /root/openocd-0.9.0/src/target/cortex_a.c
//in cortex_a_debug_entry(struct target *target)
if (armv7a->post_debug_entry) {
...
...
//change to
if (armv7a->post_debug_entry && target->cp15_entry_switch) {
    retval = armv7a->post_debug_entry(target);
    if (retval != ERROR_OK)
            return retval;
    target->cp15_entry_switch = false;
}

gedit /root/openocd-0.9.0/src/target/cortex_a.c
//in cortex_a_post_debug_entry(struct target *target)
after
armv7a->memory_ap = armv7a->armv7a_mmu.mmu_enabled; //0-AHB 1-APB
add new
LOG_INFO("memory bus type %d", armv7a->memory_ap);

9. Avoid gdb infinite request
gedit /root/openocd-0.9.0/src/server/gdb_server.c
//add
static int gdb_rmpacket_times = 0;

//in static int gdb_read_memory_packet
if ((retval != ERROR_OK) && !gdb_report_data_abort)
//change to
if ( (retval != ERROR_OK && !gdb_report_data_abort) || gdb_rmpacket_times >= 180 )

//in static int gdb_input_inner
if (packet_size > 0)
{
...
...
//add this section
if( packet[0] == 'm' )
    gdb_rmpacket_times++;
else
    gdb_rmpacket_times = 0;

/* if a packet handler returned an error, exit input loop */
if (retval != ERROR_OK)
    return retval;
}

10.
cd [~home]/openocd-0.9.0
./configure --prefix=/opt/openocd --enable-maintainer-mode --enable-ftdi
make && make install

//If build openocd 0.10.0
./configure --prefix=/opt/openocd --enable-maintainer-mode --enable-ftdi --enable-target64

11.
gedit /etc/environment
add this
/opt/openocd/bin

then reboot

///////////// Agent-proxy terminal, No minicom
1.
git clone git://git.kernel.org/pub/scm/utils/kernel/kgdb/agent-proxy.git
cd agent-proxy
make
~#./agent-proxy 4440^4441 0 /dev/ttyUSB0,115200

2.
open another terminal
~# telnet localhost 4440    //now connect to target console

////////////u-boot console debug
1. //Load code and boot-up
because add 2 events in our imx6d-1gb.cfg
$_TARGETNAME configure -event reset-assert
$_TARGETNAME configure -event reset-end

please compare mx6d1G_4x_mt41j128.cfg with imx6d-512mb-oocd-0.8.0.cfg
mx6d1G_4x_mt41j128.cfg at /root/project_board/free_imx/myandroid/bootable/bootloader/uboot-imx/board/freescale/imx/ddr
imx6d-512mb-oocd-0.8.0.cfg at http://www.voipac.com/downloads/imx/jtag

replace correct define on clock, ddr, cache, "set" address and "mww phys" write value in imx6d-512mb-oocd-0.8.0.cfg
save to /opt/openocd/share/openocd/scripts/target/imx6d-1gb.cfg

2.
gedit ~/myandroid/bootable/bootloader/uboot-imx/Kconfig
find [config CC_OPTIMIZE_FOR_SIZE]
default y
//to
default n

3. //u-boot
gedit /root/project_board/free_imx/myandroid/bootable/bootloader/uboot-imx/Makefile
modify
KBUILD_CFLAGS    += -O2
to
KBUILD_CFLAGS    += -O0 -g -fno-omit-frame-pointer -fno-optimize-sibling-calls

4. avoid call stack infinite
gedit /root/project_board/free_imx/myandroid/bootable/bootloader/uboot-imx/arch/arm/lib/crt0.S
in ENTRY(_main)
...
...
//sub    sp, sp, #GD_SIZE
to
subs    sp, sp, #GD_SIZE

Let me explain why use [subs]:
build gdb-7.10 source code first
./configure --target=arm-linux-androideabi
make

when target breakpoint at
//$home/myandroid/bootable/bootloader/uboot-imx/arch/arm/lib/crt0.S
sub        sp, sp, #GD_SIZE    /* allocate one GD above SP */
or
//$home/myandroid/kernel_imx/arch/arm/kernel/entry-armv.S
sub        sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)

//attach debug process arm-linux-androideabi-gdb
//$home/gdb-7.10/gdb/mi/mi-cmd-stack.c
void mi_cmd_stack_info_depth (...)
{
...
for (i = 0, fi = get_current_frame ();
       fi && (i < frame_high || frame_high == -1);
       i++, fi = get_prev_frame (fi))   //--->here will always dead looping
    QUIT;
...
}

//trace into
//$home/gdb-7.10/gdb/arm-tdep.c
static CORE_ADDR arm_analyze_prologue(...)
{
...
...
 //ARM_SP_REGNUM = 13
 else if ((insn & 0xfff00000) == 0xe2400000    /* sub Rd, Rn, #n */
                    &&
                    pv_is_register (regs[bits (insn, 16, 19)], ARM_SP_REGNUM))
      {
          unsigned imm = insn & 0xff;
          unsigned rot = (insn & 0xf00) >> 7;
          int rd = bits (insn, 12, 15);
          imm = (imm >> rot) | (imm << (32 - rot));
          regs[rd] = pv_add_constant (regs[bits (insn, 16, 19)], -imm);
          continue;
      }
...
...
 else if ((insn & 0xfffff000) == 0xe24dd000)    /* sub sp, sp #n */
      {
            unsigned imm = insn & 0xff;
            unsigned rot = (insn & 0xf00) >> 7;
            imm = (imm >> rot) | (imm << (32 - rot));
            regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
      }
...
...
}

5.
gedit /root/project_board/lollipop51/myandroid/bootable/bootloader/uboot-imx/arch/arm/lib/cache-cp15.c
static void cache_disable(uint32_t cache_bit)
{
...
if (cache_bit == (CR_C | CR_M))
    {
        flush_dcache_all();
        /* issue begin */
//mark here
/*
        set_cr(reg & ~CR_C);
        flush_dcache_all();
*/
    }
...
}

6. Change to usb upload
Hardware Switch Boot Mode1 to Boot Mode0

7. open new terminal
openocd -f /opt/openocd/share/openocd/scripts/target/imx6d-1gb.cfg

8. open new terminal
~#/root/project_board/free_imx/myandroid/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gdb
(gdb)target remote localhost:3333
(gdb)monitor reset halt
(gdb)symbol-file /root/project_board/free_imx/out/matrix_io/uboot/u-boot  //must before load
(gdb)load /root/project_board/free_imx/out/matrix_io/uboot/u-boot
(gdb)break relocate_code
(gdb)continue
Breakpoint 1, relocate_code ()
    at /root/project_board/free_imx/myandroid/bootable/bootloader/uboot-imx/arch/arm/lib/relocate.S:25
        subs    r4, r0, r1        /* r0 <- relocation addr */

//////////relocate address uboot debug/////////
1.
//in u-boot start operation
Power key pressed
Normal Boot
Hit any key to stop autoboot:  0
=> bdinfo
arch_number = 0x00000F8C
boot_params = 0x10000100
DRAM bank   = 0x00000000
-> start    = 0x10000000
-> size     = 0x40000000
eth0name    = FEC
ethaddr     = (not set)
current eth = FEC
ip_addr     = <NULL>
baudrate    = 115200 bps
TLB addr    = 0x4FFF0000
relocaddr   = 0x4FF49000   ///////---> this value for add-symbol-file of arm-eabi-gdb
reloc off   = 0x3DF49000
irq_sp      = 0x4F546EE0
sp start    = 0x4F546ED0
FB base     = 0x00000000

2.
in u-boot start operation,  open new terminal type follows
~# openocd -f /opt/openocd/share/openocd/scripts/interface/ftdi/dp_busblaster.cfg -f /opt/openocd/share/openocd/scripts/target/imx6.cfg

3.
~#/root/project_board/free_imx/myandroid/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gdb
(gdb)target remote localhost:3333
(gdb)add-symbol-file /root/project_board/free_imx/out/matrix_io/uboot/u-boot 0x4FF49000
(gdb)monitor reg
(gdb)cont (then press ctrl+c)
(gdb)bt
//////////////will show follows
#0  0x12000000 in ?? ()
#1  0x4ff704c8 in serial_getc ()
    at /root/project_board/free_imx/myandroid/bootable/bootloader/uboot-imx/drivers/serial/serial.c:413
#2  0x00000000 in ?? ()

4.
4ff704c8 - 3DF49000(reloc off) = 120274C8
/*check  /root/project_board/free_imx/out/matrix_io/uboot/u-boot.map
            .text.serial_getc
                0x00000000120274b8       0x14 drivers/serial/built-in.o
                0x00000000120274b8                serial_getc
             
                .text.serial_tstc
                0x00000000120274cc       0x14 drivers/serial/built-in.o
                0x00000000120274cc                serial_tstc             

confirm 120274b8  < [120274C8] < 120274cc the address is correct
openocd uboot debug is ok~~*/

////////////kernel console debug
1.
//default config
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/configs/mx6dq_matrix_android_defconfig
//enableCONFIG_DEBUG_INFO=y
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y

note:
CONFIG_FTRACE & CONFIG_FUNCTION_TRACER will enable CONFIG_FRAME_POINTER
[config FRAME_POINTER] in ~/myandroid/kernel_imx/arch/arm/Kconfig.debug 

2.
gedit /root/project_board/free_imx/myandroid/device/fsl/matrix_io/init.matrix_io.rc
on init
    #start watchdogd   -->mark here

#service watchdogd /sbin/watchdogd 10 20 5   -->mark here
#    class core
#    seclabel u:r:watchdogd:s0

3. //linux kernel
gedit /root/project_board/free_imx/myandroid/kernel_imx/Makefile
KBUILD_CFLAGS    += -O2
to
KBUILD_CFLAGS    += -O1 -g

if set -O0 or compile error, refer to
http://fatalfeel.blogspot.tw/2013/09/kgdb-eclipse-debug-kernel-on-imx6.html

4. debug linux drivers. (select any directory which you want to debug)
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/Makefile
//first line add
KBUILD_CFLAGS    += -O0 -g

//rebuild

5. remove breakpoint and watchpoint reset action
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/kernel/hw_breakpoint.c
//in functon reset_ctrl_regs(void *unused)
//mark this section
/*
for (i = 0; i < raw_num_brps; ++i) {
    write_wb_reg(ARM_BASE_BCR + i, 0UL);
    write_wb_reg(ARM_BASE_BVR + i, 0UL);
}
for (i = 0; i < core_num_wrps; ++i) {
    write_wb_reg(ARM_BASE_WCR + i, 0UL);
    write_wb_reg(ARM_BASE_WVR + i, 0UL);
}
*/

//in function static u8 get_max_wp_len(void)
//mark this section
/*
write_wb_reg(ARM_BASE_WVR, 0);
write_wb_reg(ARM_BASE_WCR, ctrl_reg);
*/

6. remove low power clock
arm clock need always enable for jtag have 2 ways, select one.
(a.)way
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/mach-imx/pm-imx6.c
val |= 0x1 << BP_CLPCR_LPM;
val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
to
/*val |= 0x1 << BP_CLPCR_LPM;
val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;*/

(b.)way
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/configs/mx6dq_android_defconfig
CONFIG_CPU_IDLE=y
to
#CONFIG_CPU_IDLE=y

I select way (a.)

7.
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/kernel/entry-armv.S
//find .macro    svc_entry, stack_hole=0
sub        sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
//change to
subs    sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)

8. disable jtag alarm for Android 6.0
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/crypto/caam/secvio.c
//find
static int snvs_secvio_probe(struct platform_device *pdev)

#if defined(CONFIG_JTAG_DEBUG)
    wr_reg32(&svpriv->svregs->hp.secvio_intcfg, HP_SECVIO_INTEN_SRC4 | HP_SECVIO_INTEN_SRC0);
#else
    wr_reg32(&svpriv->svregs->hp.secvio_intcfg, HP_SECVIO_INTEN_SRC4 | HP_SECVIO_INTEN_SRC2 | HP_SECVIO_INTEN_SRC1 | HP_SECVIO_INTEN_SRC0);
#endif

9. fixed for some device node can not stop on breakpoint
gedit /mnt/projects/marsh_mnt/myandroid/kernel_imx/drivers/base/devtmpfs.c
int __init devtmpfs_init(void)
{
...
...
/*kthread_run on myandroid/kernel_imx/include/linux/kthread.h*/
#if defined(CONFIG_JTAG_DEBUG)
    thread = kthread_create(devtmpfsd, &err, "kdevtmpfs");

    if (!IS_ERR(thread))
    {
        thread->wake_cpu = 0;
        wake_up_process(thread);
    }
#else
    thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
#endif
...
...
    printk(KERN_INFO "devtmpfs: initialized\n");
    return 0;
}

10. pass compile -O0 for Android 6.0
gedit /root/project_board/free_imx/myandroid/kernel_imx/kernel/seccomp.c
static inline void seccomp_sync_threads(void)
{
...
...
#if defined(CONFIG_JTAG_DEBUG)
        smp_mb(); //pass compiletime_assert_atomic_type on -O0
        ACCESS_ONCE(thread->seccomp.filter) =  caller->seccomp.filter;
#else
        smp_store_release(&thread->seccomp.filter, caller->seccomp.filter);
#endif
...
...
}

11. Stop Android layer for speed up debugging(option item)
gedit /root/project_board/free_imx/myandroid/device/fsl/matrix/etc/init.rc
disable healthd zygote media surfaceflinger drm
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    #onrestart restart healthd
    #onrestart restart zygote
    #onrestart restart media
    #onrestart restart surfaceflinger
    #onrestart restart drm



...
#service surfaceflinger /system/bin/surfaceflinger
#    class main
#    user system
#    group graphics drmrpc
#    onrestart restart zygote

#service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
#    class main
#    socket zygote stream 660 root system
#    onrestart write /sys/android_power/request_state wake
#    onrestart write /sys/power/state on
#    onrestart restart media
#    onrestart restart netd

#service drm /system/bin/drmserver
#    class main
#    user drm
#    group drm system inet drmrpc

#service media /system/bin/mediaserver
#    class main
#    user media
#    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc
#    ioprio rt 4

#service bootanim /system/bin/bootanimation
#    class main
#    user graphics
#    group graphics
#    disabled
#    oneshot





on  property:sys.boot_completed=1
start config_eth0
remove other services after “start config_eth0”

12. kernel start operation at  [0.000000] Booting Linux on physical CPU 0x0
open new terminal type follows
~# /root/project_board/free_imx/myandroid/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gdb
(gdb)target remote localhost:3333
(gdb)symbol-file /root/project_board/free_imx/out/matrix_io/kernel/vmlinux
(gdb)cont
(then press ctrl+c)

//show follows
Program received signal SIGINT, Interrupt.
0x8025c548 in kernel_map_pages (page=0x822bef44, numpages=1, enable=1)
    at /root/project_board/free_imx/myandroid/kernel_imx/mm/debug-pagealloc.c:99
            unpoison_pages(page, numpages);

////////////Openocd eclipse GUI
////////////u-boot GUI debug
1.install eclipse kepler
http://www.eclipse.org/downloads/packages/release/Kepler/SR2
Eclipse Standard 4.3.2 -> linux 64bits
install eclipse-standard-kepler-SR2-linux-gtk-x86_64.tar.gz
extract to /opt/eclipse
chmod 755 -R /opt/eclipse

gedit /opt/eclipse.ini
-XX:PermSize=64m
-XX:MaxPermSize=256m
-Xms128m
-Xmx4096m

Here is full install step:
http://fatalfeel.blogspot.tw/2013/09/eclipse-setting-for-ubuntu-imx6-android.html

2.
Help -> install new software...
work with: http://gnuarmeclipse.sourceforge.net/updates
//check
GNU ARM C/C++ OpenOCD Debugging

3.
right click project
Debug As -> Debug Configurations -> GDB Hardware Debugging
double click to create new name
c/c++ application: /root/project_board/free_imx/out/matrix_io/uboot/u-boot
click bottom line Select other... -> GDB(DSF) Hardware Debugging Launcher
check [disable auto build]

4.
click Debugger tab
GDB Command: /root/project_board/free_imx/myandroid/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gdb
check [Use Remote Target]
Jtag device: GUN ARM OPENOCD
Host name or ip address:localhost
port number:3333

5.
click startup tab
uncheck the all items on startup page
add those lines under [Halt] Box
monitor reset halt
symbol-file /root/project_board/free_imx/out/matrix_io/uboot/u-boot //must before load
load /root/project_board/free_imx/out/matrix_io/uboot/u-boot

6. //Load code and boot-up
because add 2 events in our imx6d-1gb.cfg
$_TARGETNAME configure -event reset-assert
$_TARGETNAME configure -event reset-end

please compare mx6d1G_4x_mt41j128.cfg with imx6d-512mb-oocd-0.8.0.cfg
mx6d1G_4x_mt41j128.cfg at /root/project_board/free_imx/myandroid/bootable/bootloader/uboot-imx/board/freescale/imx/ddr
imx6d-512mb-oocd-0.8.0.cfg at http://www.voipac.com/downloads/imx/jtag

replace correct define on clock, ddr, cache, "set" address and "mww phys" write value in imx6d-512mb-oocd-0.8.0.cfg
save to /opt/openocd/share/openocd/scripts/target/imx6d-1gb.cfg

7. Change to usb upload
Hardware Switch Boot Mode1 to Boot Mode0

8. open new terminal
openocd -f /opt/openocd/share/openocd/scripts/target/imx6d-1gb.cfg

9.
click eclipse [Debug] button
//done

////////second debug, after u-boot relocate code address///////
1.
click startup tab
uncheck all the items on startup page
add this line under [Halt] Box
add-symbol-file /root/project_board/free_imx/out/matrix_io/uboot/u-boot 0x4FF04000
rember 0x4FF04000 is from u-boot start operation and input [bdinfo] will show you

2.
After u-boot relocate code address,  open new terminal type follows
~# openocd -f /opt/openocd/share/openocd/scripts/target/imx6d-1gb.cfg
or
~# openocd -f /opt/openocd/share/openocd/scripts/interface/ftdi/dp_busblaster.cfg -f /opt/openocd/share/openocd/scripts/target/imx6.cfg

3.
after into u-boot start operation click eclipse [Debug] button
//done

////////////Kernel GUI debug/////////
/////////////////////////////////////////
1.
right click project
Debug As -> Debug Configurations -> GDB Hardware Debugging
double click to create new name
C/C++ application: /root/project_board/free_imx/out/matrix_io/kernel/vmlinux
click bottom line Select other... -> GDB(DSF) Hardware Debugging Launcher
check [disable auto build]

2.
click startup tab
uncheck all items on startup page
two ways choice, I use way (a.)

(a.)//target remote localhost:3333 first then load symbol-file
add this line under [Halt] checkbox
symbol-file /root/project_board/free_imx/out/matrix_io/kernel/vmlinux

(b.) //load symbol-file first then target remote localhost:3333
check [Load symbols], Use project binary:

3.
After u-boot relocate code address, open new terminal type follows
~# openocd -f /opt/openocd/share/openocd/scripts/target/imx6d-1gb.cfg
or
~# openocd -f /opt/openocd/share/openocd/scripts/interface/ftdi/dp_busblaster.cfg -f /opt/openocd/share/openocd/scripts/target/imx6.cfg

4.
click eclipse debug
click debug continue

5.
in target console u-boot start operation
==> boot
then enter Starting kernel ...

6.
when Starting kernel operation at [0.000000] Booting Linux on physical CPU 0x0
click eclipse suspend button quickly

7.
set breakpoint
click continue
//done

///////////How debug module .ko
insmod /mytest/hellotest.ko
When cat /sys/module/hellotest/sections/.text = 0x00000000
Try one of these ways
1.
(a.)
gedit /root/project_board/free_imx/myandroid/kernel_imx/kernel/module.c
//in function module_sect_show
return sprintf(buf, "0x%pK\n", (void *)sattr->address);
//change to
return sprintf(buf, "0x%p\n", (void *)sattr->address);

(b.)
geidt ~/myandroid/device/fsl/matrix/etc/init.rc
write /proc/sys/kernel/kptr_restrict 2
//change to
write /proc/sys/kernel/kptr_restrict 0

I select (b.)

2.
root@matrix_io:/ # insmod /data/hellomod/hellotest.ko
[   76.104855] Hello, world
root@matrix_io:/ # cat /sys/module/hellotest/sections/.text
0x7f11c000  //-->get this addr

3.
in eclipse right click your project
Debug As -> Debug Configurations -> GDB Hardware Debugging
click [Startup tab]
uncheck the all items on startup page
add those lines under [Halt] box but do not check [Halt]
add-symbol-file /root/project_board/free_imx/out/matrix_io/uboot/u-boot 0x7f11c000
then click [Apply]

//////////////////////////////////////////////////////////////////////////////////////////////
///////////Hardware shared lib debugging
//////////////////////////////////////////////////////////////////////////////////////////////
1. Get target load address
cat /proc/*/maps | grep gralloc_viv.imx6.so
ad920000-ad924000 r-xp 00000000 103:02 722       /system/lib/hw/gralloc_viv.imx6.so

2. Get shared lib .text address
/mnt/projects/lollipop_mnt/myandroid/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-readelf -S /mnt/projects/lollipop_mnt/out/matrix_io/android/target/product/matrix_io/system/lib/hw/gralloc_viv.imx6.so
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 8] .text             PROGBITS        000013d8 0013d8 001988 00  AX  0   0  8

0xad920000 + 0x000013d8 = 0xad921d38

3. Set to arm-eabi-gdb
click Startup tab
uncheck the all items on startup page
add those lines under [Halt] box but do not check [Halt]
add-symbol-file /mnt/projects/lollipop_mnt/out/matrix_io/android/target/product/matrix_io/system/lib/hw/gralloc_viv.imx6.so 0xad9213d8
apply to debug

4. Set breakpoint in a function
/mnt/projects/lollipop_mnt/myandroid/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-readelf -s /mnt/projects/lollipop_mnt/out/matrix_io/android/target/product/matrix_io/system/lib/hw/gralloc_viv.imx6.so
28: 00001af1   456 FUNC    GLOBAL DEFAULT    8 _Z25gralloc_alloc_framebu

gralloc_alloc_frame = 0x00001af1 - 0x1 = 0x00001af0 (aligned 4 address in arm cortex)

set break point at target
0xad920000 + 0x00001af0 = 0xad921af0

//////////////////////////////////////////////////////////////////////////////////////////////
//Modify openocd on Ubuntu 16.04
//////////////////////////////////////////////////////////////////////////////////////////////
1.
gedit all configure*.* and Makefile*.*
change keyword 1.14 change to 1.15 for automake

2.
gedit ~/src/flash/nor/jtagspi.c
there are 2 lines
uint32_t status;
change to
uint32_t status = 0;

3.
sudo aclocal
sudo libtoolize --force
sudo automake --add-missing
sudo autoreconf

4.
./configure --prefix=/opt/openocd --enable-maintainer-mode --enable-ftdi
make && make install

//////////////////////////////////////////////////////////////////////////////////////////////
//Watchpoint patch
//////////////////////////////////////////////////////////////////////////////////////////////
1.
gedit /root/openocd-0.9.0/src/target/cortex_a.h
//berfore struct cortex_a_common
//add new
struct cortex_a_wrp
{
    int used;
    uint32_t value;
    uint32_t control;
    uint8_t WRPn;
};

//in struct cortex_a_common
//after struct cortex_a_brp *brp_list;
//add new
int wrp_num;
int wrp_num_available;
struct cortex_a_wrp* wrp_list;

2.
gedit /root/openocd-0.9.0/src/target/cortex_a.c
//after function cortex_a_remove_breakpoint
//add functions
static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
{
    int retval;
    int wrp_i = 0;
    uint32_t    control;
    uint8_t        access_mode;
    uint8_t        byte_addr_select = 0x0F;
    struct cortex_a_common*    cortex_a    = target_to_cortex_a(target);
    struct armv7a_common*        armv7a    = &cortex_a->armv7a_common;
    struct cortex_a_wrp*            wrp_list    = cortex_a->wrp_list;

    if (watchpoint->set)
    {
        LOG_WARNING("breakpoint already set");
        return ERROR_OK;
    }

    while (wrp_list[wrp_i].used && (wrp_i < cortex_a->wrp_num))
        wrp_i++;

    if (wrp_i >= cortex_a->wrp_num)
    {
        LOG_ERROR("ERROR Can not find free Watchpoint Register Pair");
        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
    }

    watchpoint->set = wrp_i + 1;

    if (watchpoint->length == 2)
        byte_addr_select = (3 << (watchpoint->address & 0x02));

    access_mode = watchpoint->rw+1;
    control = (byte_addr_select << 5) | (access_mode << 3) | (3 << 1) | 1;
    wrp_list[wrp_i].used = 1;
    wrp_list[wrp_i].value = (watchpoint->address & 0xFFFFFFFC);
    wrp_list[wrp_i].control = control;

    retval = cortex_a_dap_write_memap_register_u32(target,
                                                                                    armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].WRPn,
                                                                                    wrp_list[wrp_i].value);
    if (retval != ERROR_OK)
        return retval;

    retval = cortex_a_dap_write_memap_register_u32(target,
                                                                                    armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].WRPn,
                                                                                    wrp_list[wrp_i].control);

    if (retval != ERROR_OK)
        return retval;

    return ERROR_OK;
}

static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
{
    int retval;
    int wrp_i;
    struct cortex_a_common *cortex_a = target_to_cortex_a(target);
    struct armv7a_common *armv7a = &cortex_a->armv7a_common;
    struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;

    if (!watchpoint->set)
    {
        LOG_WARNING("watchpoint not set");
        return ERROR_OK;
    }

    wrp_i = watchpoint->set - 1;

    if ((wrp_i < 0) || (wrp_i >= cortex_a->wrp_num))
    {
        LOG_DEBUG("Invalid WRP number in watchpoint");
        return ERROR_OK;
    }

    LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i, wrp_list[wrp_i].control, wrp_list[wrp_i].value);

    wrp_list[wrp_i].used = 0;
    wrp_list[wrp_i].value = 0;
    wrp_list[wrp_i].control = 0;

    retval = cortex_a_dap_write_memap_register_u32(target,
                                                                                        armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].WRPn,
                                                                                        wrp_list[wrp_i].control);
    if (retval != ERROR_OK)
        return retval;

    retval = cortex_a_dap_write_memap_register_u32(target,
                                                                                        armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].WRPn,
                                                                                        wrp_list[wrp_i].value);
    if (retval != ERROR_OK)
        return retval;

    watchpoint->set = 0;

    return ERROR_OK;
}

static int cortex_a_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
{
     struct cortex_a_common* cortex_a = target_to_cortex_a(target);

     if (cortex_a->wrp_num_available < 1)
     {
         LOG_INFO("no hardware breakpoint available");
         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
     }

     //if (breakpoint->type == BKPT_HARD)
     cortex_a->wrp_num_available--;

     return cortex_a_set_watchpoint(target, watchpoint);
}

static int cortex_a_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
{
    struct cortex_a_common* cortex_a = target_to_cortex_a(target);

    if (watchpoint->set)
    {
        //if (breakpoint->type == BKPT_HARD)
        cortex_a_unset_watchpoint(target, watchpoint);

        cortex_a->wrp_num_available++;
    }

    return ERROR_OK;
}

3.
gedit /root/openocd-0.9.0/src/target/cortex_a.c
//in cortex_a_examine_first(struct target *target)
//after LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num);
//add
cortex_a->wrp_num = ((didr >> 28) & 0x0F) + 1;
cortex_a->wrp_num_available = cortex_a->wrp_num;
free(cortex_a->wrp_list);
cortex_a->wrp_list = calloc(cortex_a->wrp_num, sizeof(struct cortex_a_wrp));

for (i = 0; i < cortex_a->wrp_num; i++)
{
    cortex_a->wrp_list[i].used = 0;
    cortex_a->wrp_list[i].value = 0;
    cortex_a->wrp_list[i].control = 0;
    cortex_a->wrp_list[i].WRPn = i;
}
LOG_DEBUG("Configured %i hw watchpoints", cortex_a->wrp_num);

4.
gedit /root/openocd-0.9.0/src/target/cortex_a.c
//both struct target_type cortexa_target and struct target_type cortexr4_target
.add_watchpoint = NULL,
.remove_watchpoint=NULL,
//change to
.add_watchpoint = cortex_a_add_watchpoint,
.remove_watchpoint = cortex_a_remove_watchpoint,

5.
gedit /root/openocd-0.9.0/src/target/arm_dpm.c
//in arm_dpm_setup(struct arm_dpm *dpm)
target->type->add_watchpoint = dpm_add_watchpoint;
target->type->remove_watchpoint = dpm_remove_watchpoint;
//change to
if (!target->type->add_watchpoint)
{
    target->type->add_watchpoint = dpm_add_watchpoint;
    target->type->remove_watchpoint = dpm_remove_watchpoint;
}

//////////////////////////////////////////////////////////////////////////////////////////////
//Using watchpoint on eclipse
//////////////////////////////////////////////////////////////////////////////////////////////
in eclipse [Console] window select [GDB Hardware Debugging]  window
add watchpoint command:
monitor wp address sizeof(unit) r/w/a(read/write/access)
ex:
monitor wp 0x8144be4c 4 r

remove watchpoint command:
monitor rwp address
ex:
monitor rwp 0x8144be4c

or

open [Breakpoints] window
click [View Menu] -> [Add Watchpoint (C/C++)...]

Note:After trigger the watchpoint, you must remove it or debug can not continue.
https://picasaweb.google.com/106185541018774360364/IMx6#6245065388141165858

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Ref. site:
a. bus blaster and i.mx6 setting
http://imx6dev.blogspot.tw/2014/07/inexpensive-jtag-on-imx6-solo-u-boot.html
http://wiki.wandboard.org/index.php/JTAG-BusBlaster
b. openocd console config
http://www.edlangley.co.uk/blog/2014/06/rescuing-bricked-secure-mode-i.mx6
http://wiki.voipac.com/xwiki/bin/view/imx6+rex/jtag_oocd
http://www.imx6rex.com/software/how-to-run-ddr3-calibration-on-imx6
c. openocd eclipse setting
https://www.tincantools.com/wiki/BeagleBone_Black_Eclipse_and_GDB
http://thehackerworkshop.com/?tag=eclipse
d. arm clock enable
https://community.freescale.com/thread/376786

Demo:
1. https://www.youtube.com/watch?v=8K1qY3St06k
2. https://www.youtube.com/watch?v=2L1vr_LA8Nc 
3. https://picasaweb.google.com/106185541018774360364/IMx6#6241487014458388690
4. https://picasaweb.google.com/106185541018774360364/IMx6#6241103017491328690
5. https://picasaweb.google.com/106185541018774360364/IMx6#6240074819468163938
6. https://picasaweb.google.com/106185541018774360364/IMx6#6239524844608161106

My OpenOcd full patch:
http://www.mediafire.com/file/y5s3ku3s09xy6gb/openocd-0.10.0_v16.tar.gz
http://www.mediafire.com/file/d42me9vgcbse9bd/openocd-0.10.0_v15.tar.gz
http://www.mediafire.com/file/3rs2wtitv3hmvtf/openocd-0.10.0_v14.tar.gz
http://www.mediafire.com/file/mn6y7c8tz4nuhjg/openocd-0.10.0_v13.tar.gz
http://www.mediafire.com/file/ejzocu266juicrt/openocd-0.10.0_v12.tar.gz
http://www.mediafire.com/file/p5ogkicf8nhg14i/openocd-0.9.0_v16.tar.gz

Docx files:
http://www.mediafire.com/file/ueixkx0xqj63p56/openocdv18.docx
http://www.mediafire.com/file/t4cv7b1d2z0b53g/openocdv17.docx
http://www.mediafire.com/file/3b5tbabxjj5a0a6/openocdv16.docx

My modified source code of uboot and kernel. Search all key words JTAG_DEBUG in files:
http://www.mediafire.com/file/rddsei4hsdcw8ad/myandroid.tar.gz

openocd plugin for Eclipse Kepler SR2
https://github.com/gnu-mcu-eclipse/eclipse-plugins/releases/download/v2.12.1-201604190915/ilg.gnuarmeclipse.repository-2.12.1-201604190915.zip
 
Eclipse 64bits linux with ADT + CDT + Openocd plugins. Extract to /opt/eclipse
http://www.mediafire.com/file/7auvmwm2uw8avod/eclipse_adt_cdt_openocd.tar.gz

4 則留言:

  1. Excellent article. Do you have dual or quad version ? How do you do multicore debug with openocd ?

    回覆刪除
  2. dual and quad are the same code~~~on imx6 i try on dual is ok

    回覆刪除
  3. support cortex a53 of armv8
    http://www.mediafire.com/file/bdddt53fsb81t3l/openocd-0.10.0_v5.tar.gz

    回覆刪除
  4. openocd update to
    Revision: 828ee07657914212f81152a768a8ec43bb73db03
    Author: Paul Fertser
    Date: 2018/1/13 下午 09:22:10
    server: bind to IPv4 localhost by default
    and
    update libjaylink to 2.0

    回覆刪除