国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > VELT-0.1.5开发:使用kgdb调试Linux内核

VELT-0.1.5开发:使用kgdb调试Linux内核

来源:程序员人生   发布时间:2015-03-16 10:25:09 阅读次数:4613次

VELT的全称是Visual EmbedLinuxTools,它是1个与visual gdb类似的visual studio插件,用以辅助完成Linux开发。利用这个插件,将可以在visual studioIDE中进行Linux利用程序的开发(包括编译和调试),也能够进行ubootlinux内核的编译,并根据编译时的毛病信息正肯定位到源码。目前的版本是0.1.4,仅支持vs2013。此插件可以在CSDN下载频道下载(http://download.csdn.net/detail/lights_joy/8429771),安装进程参见《vs2013+velt-0.1.4进行嵌入式开发:插件安装》。下面是它的基本功能:

  1. 支持x86 Linux,海思hi3516/hi3520MinGW这几个平台,提供这几个平台的项目模板。

  2. 完成UBOOT的编译,并根据编译的毛病信息自动定位到相应的文件位置。

  3. 完成LINUX内核的编译,并根据编译的毛病信息自动定位到相应的文件位置。

  4. VS下完成Linux内核的配置。

  5. 不使用Makefile进行Linux利用程序的编译。

  6. 使用Makefile进行Linux利用程序的开发。

  7. 使用SSH连接目标机器并用gdb进行利用程序的调试。

  8. 使用Telnet连接目标机器并用gdb进行利用程序的调试。

  9. VS中集成Linux终端(Poderosa),支持SSH/Telnet/Com,在打开终端时自动将VS的变量导出为bash里的变量,如ProjectDir等。


接下来尝试通过串口调试Linux内核。

hi3520的内核为实验对象。


1.1  打开内核的调试开关


首先打开内核的调试开关:


加上内核的调试信息:


打开kgdb



1.2  引导参数配置


UBOOT下配置传递给内核的参数:

Kernel command line: mem=127m console=ttyAMA0,115200ip=192.168.110.10:::255.255.255.0::eth0: root=mtd:work02 init=/sbin/initmtdparts=hi_sfc:256K(uboot01),64K(env01),64K(sysinfo01),3712k(configs01),8M(boot01),20M(work01),256K(uboot02),64K(env02),64K(sysinfo02),3712k(configs02),8M(boot02),20M(work02)kgdboc=ttyAMA0,115200 kgdbwait

这里最重要的是kgdbockgdbwait两个参数,前1个参数指明要使用的串口参数,后1个参数让kgdb在内核启动的时候进行等待。

加载内核:

kgdb: Registered I/O driver kgdboc.

kgdb: Waiting for connection from remote gdb...

然后系统开始等待。



1.3  MinGW gdb连接内核


直接用MinGW gdb打开编译内核时生成的vmlinux文件,

然后用

target remote COM1

连接串口,很遗憾,超时!

 


1.3  修改内核代码


检查了1下内核的代码,在等待连接时内核停在了下面的位置:

static int gdbstub_read_wait(void) { int ret = dbg_io_ops->read_char(); while (ret == NO_POLL_CHAR) ret = dbg_io_ops->read_char(); return ret; }

它将不停地查询串口上是不是有数据,刚开始时怀疑是串口参数配置不正确致使读取不到数据,但跟踪进去后发现这里的read_char可以正确地调用串口驱动(amba-pl011.c)中的查询函数:

static int pl010_get_poll_char(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status, ena_status; status = readw(uap->port.membase + UART01x_FR); ena_status = readw(uap->port.membase + UART011_CR); if (status & UART01x_FR_RXFE) return NO_POLL_CHAR; return readw(uap->port.membase + UART01x_DR); }

只不过在读取UART01x_FR寄存器时总是返回无数据的结果。

进1步的检查发现这个时候串口的接收使能是关闭的,而发送使能则是打开的!因此串口固然只能发送数据不能接收了!

不太想追究为何会这样,直接在shutdown函数中打开接收使能:

static void pl011_shutdown(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; /* * disable all interrupts */ spin_lock_irq(&uap->port.lock); uap->im = 0; writew(uap->im, uap->port.membase + UART011_IMSC); writew(0xffff, uap->port.membase + UART011_ICR); spin_unlock_irq(&uap->port.lock); pl011_dma_shutdown(uap); /* * Free the interrupt */ free_irq(uap->port.irq, uap); /* * disable the port */ uap->autorts = false; writew(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, uap->port.membase + UART011_CR); /* * disable break condition and fifos */ pl011_shutdown_channel(uap, uap->lcrh_rx); if (uap->lcrh_rx != uap->lcrh_tx) pl011_shutdown_channel(uap, uap->lcrh_tx); /* * Shut down the clock producer */ clk_disable(uap->clk); if (uap->port.dev->platform_data) { struct amba_pl011_data *plat; plat = uap->port.dev->platform_data; if (plat->exit) plat->exit(); } }

修改了这1行:

writew(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, uap->port.membase + UART011_CR);

原来的代码是这样的:

writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);

直接给上加上使能标记!


再履行gdbtarget remote COM1命令,可以正常连接了!!

 


1.5  kdb


HI3520的内核中已带了kdb的支持:



当选上最下面的那个选项时将启用kdb,这样我们就能够在目标机器上履行1些简单的调试命令了,也不需要依赖于主机上的gdb

但由于我们希望通过gdb结合源码进行调试,因此不选择kdb,仅仅用kgdb










??
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生