文章摘要: 本文主要描述了基于串口驱动程序框架下,新建虚拟串口设备,不涉及硬件内容。
内核版本: Linux-3.8.13


注册串口驱动

// 串口驱动结构
static struct uart_driver serial_driver = {
.owner       = THIS_MODULE,
.driver_name = DRIVER_NAME,      // 驱动程序名称
.dev_name    = DEV_NAME,         // 设备文件称 ttyVn
.nr          = 20,                // 驱动程序支持串口的最大数量
//.cons      = &serial_console,  // 关连控制台
};

// 声明端口列表:端口列表应该放在设备私有数据中,
// 这里为了简单说明,采用了全局变量,
// 实际应用中不建议这么干
// 否则当多个驱动多个设备时,会出现严重问题。
static uart_port port[4];

// 注册串口驱动
ret = uart_register_driver(&serial_driver);

// 添加多个端口,port->line来表示端口号,端口号不能重复,  
// 几个相同设备共用一个驱动时,这里需注意调整;
for(i = 0; i < 4; i++)
{              
    port.line     = i;                  // 端口号
    port.ops      = serial_port_ops;    // 端口操作回调列表(后面详细说明)  
    
    port.type     = PORT_EFMUART;       // 端口类型
    port.iotype   = UPIO_MEM32;         // 32bit寄存器
    port.fifosize = 128;                // 发送FIFO深度        
    port.flags    = UPF_BOOT_AUTOCONF;  // 标志
    
    // 添加端口(正常情况下返回0)
    ret = uart_add_one_port(&serial_driver, &port[i]); 
}
    

此步操作后,将可以在设备目录下看到生成的4个串口设备。


移除设备

// 删除端口
for(i = 0; i < 4; i++)
{
    uart_remove_one_port(&serial_driver, &port[i]);     
} 

// 注销串口驱动
uart_unregister_driver(&serial_driver);

端口操作回调函数说明:

static struct uart_ops serial_port_ops = {
    .tx_empty     = is_tx_empty,        // 测试发送FOFI是否空
    .set_mctrl    = serial_set_mctrl,   // 硬件握手用
    .get_mctrl    = serial_get_mctrl,   // 硬件握手用
    .stop_tx      = serial_stop_tx,     // 函数调用
    .start_tx     = serial_start_tx,    // write时调用
    .stop_rx      = serial_stop_rx,     // 
    .enable_ms    = serial_enable_ms,    
    .break_ctl    = serial_break_ctl,     
    .startup      = serial_startup,     // open时调用
    .shutdown     = serial_shutdown,    // close时调用
    .set_termios  = serial_set_termios, // 设置参数,open时第2步调用
    .type         = serial_type,
    .release_port = serial_release_port,// 移除端口时调用
    .request_port = serial_request_port,
    .config_port  = serial_config_port, // 超级重要
    .verify_port  = serial_verify_port,
};
/*
 * 非常重要,添加端口后,自动调用的第一个回调函数
 * 如果不这里设置的值,则串口不会正常工作
 */
static void serial_config_port(struct uart_port *port, int type)
{   
    port->type = PORT_EFMUART;
}