当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]Powerpc构架系统内核和内核模块调试

说明:

此文档的目标系统为freescale MPC8349E-mITX,对其他采用powerPC,MIPS,ARM的芯片的系统亦具有参考意义。 此文档中内核调试为了简化,采用目标系统中的UBOOT初始化目标板,并通过UBOOT或者BDI2000加载内核到目标板的RAM中。

1. BDI2000配置:

下面是MPC8349E-mITX的BDI2000配置文件,

; BDI-2000 CONfiguraTIon file for the MPC8349E-mITX

; Tip: If after a reset, the BDI-2000 fails to halt at 0x100,

; you may need to power-down the bOArd for a few seconds.

[INIT]

; we use UBOOT to initialize the board

[TARGET]

CPUTYPE 8349

JTAGCLOCK 1

;STARTUP RESET

STARTUP RUN

BREAKMODE HARD

STEPMODE HWBP

BOOTADDR 0x00000100

;If you‘re getting "Writing to workspace failed" errors during flash operations,

;then try uncommenting this line instead. This moves the FLASH window to

;high memory, leaving low memory available for DDR.

RCW 0xb060a000 0x04040000 ;Set the HRCW to boot the image at 0xFE000000

MMU XLAT ;0xc0000000

PTBASE 0xf0 ;

[HOST]

IP 192.168.7.90

FILE $u-boot.bin

LOAD MANUAL

PROMPT 8349E-mITX-GP>

DUMP itx-dump.bin

[Flash]

CHIPTYPE AM29BX16

CHIPSIZE 0x800000

BUSWIDTH 16

;WORKSPACE 0x1000

FORMAT BIN 0xfe000000

;flash_image.bin is an image file of an entire 8MB flash region.

;Flash this file at 0xfe0000000 to restore all of flash.

;ERASE 0xFE000000 0x10000 127 ; 127 sectors @ 64KB each

;ERASE 0xFE7F0000 0x2000 8 ; 8 sectors @ 8KB each

;FILE $flash_image.bin

;Use these lines if you just want to flash U-Boot

ERASE 0xfe000000 0x10000? 4; Erase 384KB, each sector is 64KB

FILE? mpc8349e/u-boot131-mitx-gp.bin

[REGS]

FILE $reg8349e.def

以上配置文件的【HOST】段的IP要改为主机IP,关键的字段MMU XLAT 和PTBASE 是POWERPC和MIPS经常需要设置的,关于PTBASE的具体设置,超出本文范围,详细情况请参考BDI2000的手册

2.内核修改和配置

为了能够调试内核,需要在内核中的Makefile中增加如下调试选项:

CFLAGS 增加C代码调试选项-g –ggdb

AFLAGS 增加汇编代码调试选项:-Wa,-L -gdwarf-2

去掉CFLAGS编译选项中-fomit-frAME-pointer

GCC的-fomit-frame-pointer选项是优化函数栈回溯(stack backtrace)的,我们调试的时候需要提供函数回溯能力,所以我们要去掉这个选项,当然,有的系统系统不受它的影响,或者说它不起作用,为了统一,我们统一去掉它。

相对个案来说,我是做如下改动的:

--- Makefile 2008-07-08 03:07:38.000000000 +0800

+++ Makefile.debug 2008-07-08 03:06:04.000000000 +0800

-CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)

+ifdef CONFIG_DEBUG_INFO

+

+ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) -g -ggdb

-CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs

+ CFLAGS := $(CPPFLAGS) -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs

-fno-strict-aliasing -fno-common

-AFLAGS := -D__ASSEMBLY__

+ AFLAGS := -D__ASSEMBLY__ -Wa,-L -gdwarf-2

+else

+ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)

+ CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs

+ -fno-strict-aliasing -fno-common

+ AFLAGS := -D__ASSEMBLY__

+

+endif

@@ -491,27 +500,33 @@

# Defaults vmlinux but it is usually overridden in the arch makefile

all: vmlinux

-ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE

-CFLAGS += -Os

-else

-CFLAGS += -O2

-endif

include $(srctree)/arch/$(ARCH)/Makefile

-ifdef CONFIG_FRAME_POINTER

-CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)

-else

-CFLAGS += -fomit-frame-pointer

-endif

ifdef CONFIG_UNWIND_INFO

CFLAGS += -fasynchronous-unwind-tables

endif

-ifdef CONFIG_DEBUG_INFO

-CFLAGS += -g

-endif

+#ifdef CONFIG_DEBUG_INFO

+CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)

+CFLAGS += -g -ggdb

+CFLAGS += -O

+#else

+

+# ifdef CONFIG_FRAME_POINTER

+ CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)

+# else

+ CFLAGS += -fomit-frame-pointer

+# endif

+

+# ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE

+ CFLAGS += -Os

+# else

+ CFLAGS += -O2

+# endif

+

+#endif

通过以上修改后,系统的的调试信息简单的通过CONFIG_DEBUG_INFO宏来控制了,那么CONFIG_DEBUG_INFO宏又是从哪里来的呢?它其实是从内核的配置文件.config里面来的。

一般内核通过make menuconfig做配置的时候,都有

Kernel hacking --->

[*] Kernel debugging

[*] Compile the kernel with debug info

[*] Force gcc to inline functions marked ‘inline‘ (2.6比较新的内核有这一项)[!--empirenews.page--]

[*] Include BDI-2000 user context switcher (有的系统直接提供了这个选项,它和BDI2000的PTBASE设置配合)

通过保存后,以上选项会生成如下配置选项:

CONFIG_DEBUG_KERNEL=y

CONFIG_DEBUG_INFO=y

CONFIG_FORCED_INLINING=y

CONFIG_BDI_SWITCH=y

值得关注的是PowerPC内核中CONFIG_BDI_SWITCH,它到底在内核中怎样起作用的?

我们看arch/powerpc/kernel/head_32.S的关键代码:

/* Load up the kernel Context */

2: bl load_up_mmu

#ifdef CONFIG_BDI_SWITCH

/* Add helper information for the Abatron bdiGDB debugger.

* We do this here because we know the mmu is disabled, and

* will be enabled for real in just a few instructions.

*/

lis r5, abatron_pteptrs@h

ori r5, r5, abatron_pteptrs@l

stw r5, 0xf0(r0)??? /* This much match your Abatron config */

lis r6, swapper_pg_dir@h

ori r6, r6, swapper_pg_dir@l

tophys(r5, r5)

stw r6, 0(r5)

#endif /* CONFIG_BDI_SWITCH */

/* Now turn on the MMU for real! */

它在MMU真正时能之前先增加了BDI2000帮助信息。在arch/powerpc/kernel/head_32.S的最后通过abatron_pteptrs保留了8个自己的空间给BDI2000用于保存2个页表指针,如下:

/* Room for two PTE pointers, usually the kernel and current user pointers

* to their respective root page table.

*/

abatron_pteptrs:

.space 8

3. 内核调试

通过以上的准备工作,就可以进行内核和模块的调试了,内核调试步骤如下:

说明:下面的步骤中

8349E-mITX-GP> 表示BDI2000的命令行窗口

[root@newhost misc-modules]# 表示开发主机

DDD> 或GDB> 表示是开发主机上的DDD的调试窗口中

root@mpc8349emitxgp:~# 表示目标系统中

1. 获取恰当的断点设置位置:

[shyi@newhost pro50_mpc8349_kernel]$ cat System.map |grep start_kernel

c03b05dc T start_kernel #得到start_kernel的虚拟地址

2.设置断点,加载内核,启动DDD的连接

8349E-mITX-GP>reset

8349E-mITX-GP>halt

8349E-mITX-GP>bi 0xc03b05dc (这个值是由System.map中的start_kernel的地址而来的)

8349E-mITX-GP>go

- TARGET: stopped #提示系统进入断点了

8349E-mITX-GP>info

Target CPU : MPC83xx (e300c1)

Target state : debug mode

Debug entry cause : instruction address breakpoint

Current PC : 0xc03b05dc

Current CR : 0x44044022

Current MSR : 0x00001032

Current LR : 0x00003438

8349E-mITX-GP>

# 这时串口可看打到打印信息如:

Uncompressing Kernel Image ... OK

Booting using the fdt at 0xc00000

Loading Device Tree to 007fc000, end 007fefff ... OK

图形系统中启动DDD

[root@newhost scull]# cd /opt/pro50/montavista/pro/devkit/ppc/83xx/target/root/examples/misc-Modules

[root@newhost misc-modules]# ddd --debugger ppc_83xx-gdb –gdb /home/shyi/workspace/pro50_mpc8349_kernel/vmlinux

(gdb)target remote 192.168.7.64:2001 (其中192.168.7.64:2001为BDI2000的IP和调试端口)

8349E-mITX-GP>ci

8349E-mITX-GP>break soft #改变为软断点方式

这时候可以在DDD>图形界面里面最右边点击鼠标右键来设置断点,如图:

 

 

(注意:系统有些地方不能停住,需要在合适的位置来设置断点)

(gdb)cont

这时候系统就会停止在断点设置的地方,接下来就可以进行内核断点调试了,如下图:

 

 

4.内核模块的调试

使用LDD3的jit.c模块进行调试的演示,DDD(或者说GDB)GDB的初始化脚本放置在~/.gdbinit:

其中.gdbinit的内容如下:

define lsmod

printf "AddressttModulen"

set $m=(struct list_head *)&modules

set $done=0

while ( !$done )

# list_head is 4-bytes into struct module

set $mp=(struct module *)((char *)$m->next - (char *)4)

printf "0x%08Xt%sn", $mp, $mp->name

if ($mp->list->next == &modules)

set $done=1

end

set $m=$m->next

end

end

define addmodulesymbols

set $myModule=(struct module*) $arg0

set $myAddr=$myModule->module_core

add-symbol-file $arg1 $myAddr

end

document addmodulesymbols

Adds the symbols for a module to the kernel.equires two parameters:

addmodulesymbols <0xAddress> <.ko-file>

end

(说明: 定义了lsmod和addmodulesymbols 2个宏,并且定义了addmodulesymbols的帮助文档)

内核模块调试前面的步骤和内核调试完全一致,先要在start_kernel的地方设置断点,然后让内核能进行调试,接下来:

# 按DDD的按钮继续内核的运行

内核起来之后→

root@mpc8349emitxgp:~# cd /root/examples/misc-modules[!--empirenews.page--]

root@mpc8349emitxgp:~/examples/scull# insmod ./jit.ko

然后在DDD下按→

(gdb) lsmod

Address Module

0xD106FB00 jit

0xD25EE500 ipv6

(gdb) addmodulesymbols 0xd106fb00 ./jit.ko

add symbol table from file "./jit.ko" at

.text_addr = 0xd106e000

(注意启动DDD的时候要在此调试模块的目录下,否则要指定jit.ko在主机上的绝对路径位置)

(gdb) b jit_currentime

(gdb)cont

在目标平台输出终端上→

root@mpc8349emitxgp:~/examples/misc-modules# cat /proc/currentime

此时执行停住了,接下来我就可以在DDD中跟踪驱动的执行了。如下图:

 

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭