Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103739
  • 博文数量: 32
  • 博客积分: 230
  • 博客等级: 二等列兵
  • 技术积分: 183
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-19 11:30
文章分类
文章存档

2014年(18)

2013年(8)

2012年(6)

我的朋友

分类: LINUX

2013-02-25 16:59:06

    高版本的linux2.6内核中已经把kgdb集成到内核中了,但若想在s3c2440平台上使用kgdb还需对内核做一些修改。

下面我们就来分析一下如何修改内核使kgdb可用。

    在drivers/serial/kgdboc.c文件中有一行代码module_init(init_kgdboc),所以在内核启动的时候会调用init_kgdboc

函数,函数调用关系为init_kgdboc->configure_kgdboc->tty_find_polling_driver,函数tty_find_polling_driver主要

做的工作是根据命令行参数kgdboc在已经注册的tty设备中选择对应的设备,这里假设我们用串口2作为kgdb所使用

的串口,则设置u-boot引导参数bootargs时有这么一句kgdboc=ttySAC2 kgdbwait,这样就选则串口2作为kgdb的

通信串口了。但是tty_find_polling_driver函数存在一个问题,if (strncmp(name, p->name, len) != 0)这句应该改为

if (strncmp(name, p->driver_name, len) != 0)因为串口2的p->name是s3c2410-uart,p->driver_name才是ttySAC。

我们继续朝下,tty_find_polling_driver中找到tty设备后调用设备的poll_init函数(p->ops->poll_init)。

    那串口2的poll_init的函数是在哪定义的呢?在文件drivers/serial/samsung.c中有这么一句

module_init(s3c24xx_serial_modinit);这样s3c24xx_serial_modinit将在初始化的时候被调用,调用关系如下:

s3c24xx_serial_modinit->uart_register_driver,在函数uart_register_driver中有这么一句tty_set_operations(normal, &uart_ops);

到这里我们就知道串口2的poll_init函数在uart_ops中被初始化即为uart_poll_init:

static const struct tty_operations uart_ops = {
......

#ifdef CONFIG_CONSOLE_POLL
 .poll_init = uart_poll_init,
 .poll_get_char = uart_poll_get_char,
 .poll_put_char = uart_poll_put_char,
#endif
};

我们注意到这里在配置内核的时候要定义CONFIG_CONSOLE_POLL宏。所以串口2的poll_init即为uart_poll_init函数,这个函数主要做一些验

证工作,这里有一个关键的地方if (!(port->ops->poll_get_char && port->ops->poll_put_char))检测串口的poll_get_char和poll_put_char

有没有定义,在2.6.34.14内核中这两个函数没有定义我们要在文件drivers/serial/samsung.c中添加,代码如下:

static void s3c24xx_serial_get_char(struct uart_port *port)
{
 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
 unsigned long ufstat, utrstat;
 while(1){
  if (ufcon & S3C2410_UFCON_FIFOMODE) {
   ufstat = rd_regl(port, S3C2410_UFSTAT);
   if(ufstat & 0x3f)
    return rd_regl(port, S3C2410_URXH);
  }
  else{
   utrstat = rd_regl(port, S3C2410_UTRSTAT);
   if(utrstat & 0x01)
    return rd_regl(port, S3C2410_URXH);
  }
  barrier();
 }
}
static int
s3c24xx_serial_txrdy(struct uart_port *port, unsigned int ufcon)
{
        struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
        unsigned long ufstat, utrstat;

        if (ufcon & S3C2410_UFCON_FIFOMODE) {
                /* fifo mode - check amount of data in fifo registers... */

                ufstat = rd_regl(port, S3C2410_UFSTAT);
                return (ufstat & info->tx_fifofull) ? 0 : 1;
        }

        /* in non-fifo mode, we go and use the tx buffer empty */

        utrstat = rd_regl(port, S3C2410_UTRSTAT);
        return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
}

static void s3c24xx_serial_put_char(struct uart_port *port,unsigned char ch)
{
 unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
 while (!s3c24xx_serial_txrdy(port, ufcon))
  barrier();
 wr_regb(port, S3C2410_UTXH, ch);
}

static struct uart_ops s3c24xx_serial_ops = {
 .poll_put_char  = s3c24xx_serial_put_char,
 .poll_get_char  = s3c24xx_serial_get_char,
};

添加这些代码后kgdb就可以正确的初始化了,现在回到init_kgdboc函数,最终会把串口2的tty_driver赋值给kgdb_tty_driver,

以后kgdb就可以通过kgdb_tty_driver接送和发送串口2的数据了。

    最后多说一句要用在想使用kgdb要在配置内核的时候勾选上相关的选项。

阅读(2201) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~