首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

关于s3c2440+linux2.6.34.14KGDB的使用

关于s3c2440+linux2.6.34.14KGDB的使用

高版本的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要在配置内核的时候勾选上相关的选项。
继承事业,薪火相传
返回列表