现在的位置: 首页 > 综合 > 正文

Linux-2.6 16c550 串口驱动移植

2018年03月18日 ⁄ 综合 ⁄ 共 2487字 ⁄ 字号 评论关闭

本文中将要说道的是Linux驱动移植中最为初级最为简单的一种,就是通用性很强的UART设备驱动的移植,当然这还不能完全满足博主我这可怜的智商。

我所移植的这个驱动不是别的就是可以使用已有驱动8250.c来驱动的16c550, 千万别笑话我,谁叫这是第一次呢。

其实说到底我也没干什么,就是配置了一些参数而已,剩下的就都交给platform和8250了。

下面就是重要的结构体的配置具体情况:

static struct plat_serial8250_port sc16550_data[] = {
.mapbase
= sc16550_UART_BASE,
//flags使用IOREMAP,8250驱动会自动映射mapbase

.irq = sc16550_UART_IRQ,
.uartclk
= sc16550_UART_BAUD * 16,
.iotype
= UPIO_MEM,
.flags
= UPF_BOOT_AUTOCONF | 
                          UPF_SKIP_TEST | UPF_IOREMAP,
        .regshift       = 0,
};

static struct platform_device sc16550_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = { .platform_data = sc16550_data, },
};

这个platform_device对象的私有数据指成员向一个plat_serial8250_port类型的数组。在这里该数组描述了一个串口接口的基本信息。当8250驱动检测到这个platform_device对象后,就分析该对象的私有数据成员指向的那个plat_serial8250_port类型的数组。然后根据该数组的每个成员描述的信息生成一个串口对象设备。

实现了这个platform_device结构体后,把这个对象注册即可。但这个对象的name必须是serial8250。否则8250驱动检测不到这个样的设备。

下面详细介绍plat_serial8250_port这个对象。我们看一段代码:

  1. {
  2.             .membase = (void *) io_p2v(UART5_BASE),
  3.             .mapbase = UART5_BASE,
  4.             .irq = IRQ_UART_IIR5,
  5.             .uartclk = MAIN_OSC_FREQ,
  6.             .regshift = 2,
  7.             .iotype = UPIO_MEM32,
  8.             .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_IOREMAP,
  9. },

    membase: 
        
该成员描述的该串口接口寄存器虚拟地址的基地址。在初始化该成员时,需要自己把该串口接口寄存器的物理地址映射到虚拟地址空间。并且该映射工作需要在内核的板级初始化阶段完成。
    mapbase:
        
该成员描述的该串口接口寄存器物理地址的基地址。其实只要初始化了mapbase成员,上面的membase成员就可以不必初始化了。因为8250驱动如果检测到只初始化了mapbase成员而membaseNULL,flags使用IOREMAP,8250驱动会自动映射mapbase,即自动把该串口接口寄存器的物理地址空间映射到虚拟地址空间。
    irq:
        
该成员描述的是该串口接口使用的中断号。
    uartclk:
        
该成员描述了该串口接口使用的时钟频率。
    regshift:
        
该成员表示:在访问该串口接口的某个寄存器时,需把该寄存器的号左移多少位然后加基地址(不管是物理或虚拟地址)才能得能到
        
这个寄存器的址址。
    iotype:
        
该成员表示该串口接口寄存器的地址类型,可以取值以下的其中一个:

  1.         UPIO_PORT 端口地址,8位
  2.         UPIO_HUB6 
  3.         UPIO_MEM 8位的内存地址 
  4.         UPIO_MEM32 32位的内存地址 
  5.         UPIO_AU 
  6.         UPIO_TSI 
  7.         UPIO_DWAPB 
  8.         UPIO_RM9000

        一般来说,如果该成员初始化为UPIO_MEMUPIO_PORT,那么regshift成员应该为0;如果该成员初始化为UPIO_MEM32,那么regshift成员应该为2. 
    flags:
        UPF_BOOT_AUTOCONF   
表示自动探测串口类型,这个一般是需要的
        UPF_SKIP_TEST       
表示在探测串口类型时,是否测试地址的可访问性。这在调试阶段是需要的。

        

    
除了flags,上面的各个成员都必须严格设置正确才能保证串口接口被正确探测和初始化。
    
如果串口接口类型没有被探测出来,或者FIFO长度不对,这需要考虑寄存器的访问是否正确,这包括:基地址是否正确,regshiftiotype是否正确,时钟频率是否正确。
    
如果探测信息也没有,或者接口数量不对。那么请在mem menuconfig中,在

  1. Device Drivers ---> 
  2.         Character devices ---> 
  3.             Serial drivers --->
  4.                    (8) Maximum number of 8250/16550
    serial ports 
  5.                               (8) Number of 8250/16550
    serial ports to register at runtime

    这两项的数字等于在8250注册串口接口的总数。

抱歉!评论已关闭.