kernel调试串口的设置

1,内核调试打印用串口2,共4个串口,id 为0,  1,  2, 3

 

2,init.rc   cmdline= init=/init console=ttyS2,115200

 

3,各个串口的定义

Devices.c (arch/arm/mach-pxa/generic)

static struct resource pxa_resource_ffuart[] = {
 {
  .start = 0x40100000,
  .end = 0x40100023,
  .flags = IORESOURCE_MEM,
 }, {
  .start = IRQ_FFUART,
  .end = IRQ_FFUART,
  .flags = IORESOURCE_IRQ,
 }
};

struct platform_device pxa_device_ffuart= {
 .name  = "pxa2xx-uart",
 .id  = 0,
 .resource = pxa_resource_ffuart,
 .num_resources = ARRAY_SIZE(pxa_resource_ffuart),
};

void __init pxa_set_ffuart_info(struct pxa_uart_mach_info *info)
{
 pxa_register_device(&pxa_device_ffuart, info);
}

static struct resource pxa_resource_btuart[] = {
 {
  .start = 0x40200000,
  .end = 0x40200023,
  .flags = IORESOURCE_MEM,
 }, {
  .start = IRQ_BTUART,
  .end = IRQ_BTUART,
  .flags = IORESOURCE_IRQ,
 }
};

struct platform_device pxa_device_btuart = {
 .name  = "pxa2xx-uart",
 .id  = 1,
 .resource = pxa_resource_btuart,
 .num_resources = ARRAY_SIZE(pxa_resource_btuart),
};

void __init pxa_set_btuart_info(struct pxa_uart_mach_info *info)
{
 pxa_register_device(&pxa_device_btuart, info);
}

static struct resource pxa_resource_stuart[] = {
 {
  .start = 0x40700000,
  .end = 0x40700023,
  .flags = IORESOURCE_MEM,
 }, {
  .start = IRQ_STUART,
  .end = IRQ_STUART,
  .flags = IORESOURCE_IRQ,
 }
};

struct platform_device pxa_device_stuart = {
 .name  = "pxa2xx-uart",
 .id  = 2,
 .resource = pxa_resource_stuart,
 .num_resources = ARRAY_SIZE(pxa_resource_stuart),
};

void __init pxa_set_stuart_info(struct pxa_uart_mach_info *info)
{
 pxa_register_device(&pxa_device_stuart, info);
}

static struct resource pxa_resource_hwuart[] = {
 {
  .start = 0x41600000,
  .end = 0x4160002F,
  .flags = IORESOURCE_MEM,
 }, {
  .start = IRQ_HWUART,
  .end = IRQ_HWUART,
  .flags = IORESOURCE_IRQ,
 }
};

struct platform_device pxa_device_hwuart = {
 .name  = "pxa2xx-uart",
 .id  = 3,
 .resource = pxa_resource_hwuart,
 .num_resources = ARRAY_SIZE(pxa_resource_hwuart),
};

void __init pxa_set_hwuart_info(struct pxa_uart_mach_info *info)
{
 pxa_register_device(&pxa_device_hwuart, info);
}

4,串口平台驱动数据结构的定义

Pxa.c (drivers/serial)

static struct platform_driver serial_pxa_driver = {
        .probe          = serial_pxa_probe,
        .remove         = serial_pxa_remove,

 .suspend = serial_pxa_suspend,
 .resume  = serial_pxa_resume,
 .driver  = {
         .name = "pxa2xx-uart",
  .owner = THIS_MODULE,
 },
};

int __init serial_pxa_init(void)
{
 int ret;

 ret = uart_register_driver(&serial_pxa_reg);
 if (ret != 0)
  goto out;

 ret = platform_driver_register(&serial_pxa_driver);
 if (ret != 0) {
  uart_unregister_driver(&serial_pxa_reg);
  goto out;
 }
 return ret;

out:
 return ret;
}

 

5,

devices 的 .name  = "pxa2xx-uart",

driver的name   .driver  = {
         .name = "pxa2xx-uart",
  .owner = THIS_MODULE,
 },
都是pxa2xx-uart,注册时mach,就调用probe

 

6,串口驱动数据结构的定义


static struct console serial_pxa_console = {
 .name  = "ttyS",
 .write  = serial_pxa_console_write,
 .device  = uart_console_device,
 .setup  = serial_pxa_console_setup,
 .flags  = CON_PRINTBUFFER,
 .index  = -1,
 .data  = &serial_pxa_reg,
};

控制台=  .name  = "ttyS", + 串口的ID

也就是ttys0, 或者 ttys1  ,  ttys2  所以在命令行console =ttys2 这个ttys是console的名字name  = "ttyS",,不是串口设备的名字dev_name ,console的名字name 可以和串口设备的名字dev_name不一样,这里两者相同是巧合。

static struct uart_driver serial_pxa_reg = {
 .owner  = THIS_MODULE,
 .driver_name = "PXA serial",
 .dev_name = "ttyS",
 .major  = TTY_MAJOR,
 .minor  = 64,
 .nr  = 4,
 .cons  = PXA_CONSOLE,
};

7,

串口的名字为 .dev_name+id

 .dev_name = "ttyS",

所以各个串口的名字分别为ttys0   ttys1   ttys2     ttys3 

本板为ttys2为调试串口所以console=ttyS2



serial_pxa_init

uart_register_driver(&serial_pxa_reg);

platform_driver_register(&serial_pxa_driver);

 

 

int uart_register_driver(struct uart_driver *drv)
{
 struct tty_driver *normal = NULL;
 int i, retval;

 BUG_ON(drv->state);

 /*
  * Maybe we should be using a slab cache for this, especially if
  * we have a large number of ports to handle.
  */
 drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
 retval = -ENOMEM;
 if (!drv->state)
  goto out;

 normal  = alloc_tty_driver(drv->nr);
 if (!normal)
  goto out;

 drv->tty_driver = normal;

 normal->owner  = drv->owner;
 normal->driver_name = drv->driver_name;
 normal->name  = drv->dev_name;
 normal->major  = drv->major;
 normal->minor_start = drv->minor;
 normal->type  = TTY_DRIVER_TYPE_SERIAL;
 normal->subtype  = SERIAL_TYPE_NORMAL;
 normal->init_termios = tty_std_termios;
 normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
 normal->flags  = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 normal->driver_state    = drv;
 tty_set_operations(normal, &uart_ops);

 /*
  * Initialise the UART state(s).
  */
 for (i = 0; i < drv->nr; i++) {
  struct uart_state *state = drv->state + i;

  state->close_delay     = 500; /* .5 seconds */
  state->closing_wait    = 30000; /* 30 seconds */
  mutex_init(&state->mutex);

  tty_port_init(&state->info.port);
  init_waitqueue_head(&state->info.delta_msr_wait);
  tasklet_init(&state->info.tlet, uart_tasklet_action,
        (unsigned long)state);
 }

 retval = tty_register_driver(normal);
 out:
 if (retval < 0) {
  put_tty_driver(normal);
  kfree(drv->state);
 }
 return retval;
}

 

 

 启动是根据命令行cmdline console =ttys2 讲consle指向串口2

printk调用serial_pxa_console_write,最终往串口2写字符

下面是printk调用过程

asmlinkage int printk(const char *fmt, ...)
{
 va_list args;
 int r;

 va_start(args, fmt);
 r = vprintk(fmt, args);
 va_end(args);

 return r;
}

 

asmlinkage int vprintk(const char *fmt, va_list args)

{

.........

 emit_log_char(*p);

  release_console_sem();
............

}

 

void release_console_sem(void)
{
..............  

  call_console_drivers(_con_start, _log_end);
  .........

}

 

static void call_console_drivers(unsigned start, unsigned end)
{.............

    _call_console_drivers(start_print, cur_index, msg_level);
............

}

 

 

static void _call_console_drivers(unsigned start,
    unsigned end, int msg_log_level)
{...........
    __call_console_drivers(start, end);
  }
 

 

static void __call_console_drivers(unsigned start, unsigned end)
{
 struct console *con;

 for (con = console_drivers; con; con = con->next) {
  if ((con->flags & CON_ENABLED) && con->write &&
    (cpu_online(smp_processor_id()) ||
    (con->flags & CON_ANYTIME)))
   con->write(con, &LOG_BUF(start), end - start);
 }
}

最终调用serial_pxa_console_write

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值