完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
串口驱动的源文件一般是使用drivers/serial/8250.c文件,或该文件的稍作修改。这是因为大多的串口接口的操作寄存器都是符合相关的定义,都是基本一样的。那么在移植串口驱动时,一般是为该驱动添加我们的串口接口设备。一般来说,串口接口设备在board文件中添加或在板级目录下添加专属的serial文件。 设备的定义一般如下: struct plat_serial8250_port serial_std_platform_data[] = { { .membase = (void *) io_p2v(UART5_BASE), .mapbase = UART5_BASE, .irq = IRQ_UART_IIR5, .uartclk = MAIN_OSC_FREQ, .regshift = 2, .iotype = UPIO_MEM32, .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, }, { .membase = (void *) io_p2v(UART3_BASE), .mapbase = UART3_BASE, .irq = IRQ_UART_IIR3, .uartclk = MAIN_OSC_FREQ, .regshift = 2, .iotype = UPIO_MEM32, .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, }, { .membase = (void *) io_p2v(UART4_BASE), .mapbase = UART4_BASE, .irq = IRQ_UART_IIR4, .uartclk = MAIN_OSC_FREQ, .regshift = 2, .iotype = UPIO_MEM32, .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, } } struct platform_device serial_std_platform_device = { .name = "serial8250", .id = 0, .dev = { .platform_data = serial_std_platform_data, }, }; 这个platform_device对象的私有数据指成员向一个plat_serial8250_port类型的数组。在这里该数组描述了三个串口接口的基本信息。当8250驱动检测到这个platform_device对象后,就分析该对象的私有数据成员指向的那个plat_serial8250_port类型的数组。然后根据该数组的每个成员描述的信息生成一个串口对象设备。 实现了这个platform_device结构体后,把这个对象注册即可。但这个对象的name必须是serial8250。否则8250驱动检测不到这个样的设备。 如果注册顺利且工作正常,那么在驱动加载时会打印出串口接口探测信息: serial8250.0: ttyS0 at MMIO 0x40080000 (irq = 7) is a 16550A serial8250.0: ttyS1 at MMIO 0x40088000 (irq = 8) is a 16550A serial8250.0: ttyS2 at MMIO 0x40098000 (irq = 10) is a 16550A serial8250.0表示8250驱动检测到的第一个platform_device对象。如果检测到第二个platform对象,会打印成serial8250.1;如此类推。 0x40080000表示串口接口寄存器物理地址的基地址; irq描述串口接口所用的中断; 16550A表示该串口接口的类型。有可能这个类型的名字不是我们所预期的,但是只要该类型的TX/RX FIFO长度和我们实际串口接口的一样,就可以接受。 ttyS0/1/2表示串口设备的名字 如果注册成功,则在/dev/目录下生成: ttyS0,ttyS1,ttyS2的设备文件节点。同时在/sys/devices/platform/目录下,生成serial8250,serial8250.0目录。 这时即可对串口的各设备文件节点进行测试。 下面详细介绍plat_serial8250_port这个对象。我们看一段上面的代码: { .membase = (void *) io_p2v(UART5_BASE), .mapbase = UART5_BASE, .irq = IRQ_UART_IIR5, .uartclk = MAIN_OSC_FREQ, .regshift = 2, .iotype = UPIO_MEM32, .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, }, membase: 该成员描述的该串口接口寄存器虚拟地址的基地址。在初始化该成员时,需要自己把该串口接口寄存器的物理地址映射到虚拟地址空间。并且该映射工作需要在内核的板级初始化阶段完成。 mapbase: 该成员描述的该串口接口寄存器物理地址的基地址。其实只要初始化了mapbase成员,上面的membase成员就可以不必初始化了。因为8250驱动如果检测到只初始化了mapbase成员而membase为NULL,则自动把该串口接口寄存器的物理地址空间映射到虚拟地址空间。 irq: 该成员描述的是该串口接口使用的中断号。 uartclk: 该成员描述了该串口接口使用的时钟频率。 regshift: 该成员表示:在访问该串口接口的某个寄存器时,需把该寄存器的号左移多少位然后加基地址(不管是物理或虚拟地址)才能得能到这个寄存器的址址。 iotype: 该成员表示该串口接口寄存器的地址类型,可以取值以下的其中一个: UPIO_PORT 端口地址,8位 UPIO_HUB6 UPIO_MEM 8位的内存地址 UPIO_MEM32 32位的内存地址 UPIO_AU UPIO_TSI UPIO_DWAPB UPIO_RM9000 一般来说,如果该成员初始化为UPIO_MEM或UPIO_PORT,那么regshift成员应该为0;如果该成员初始化为UPIO_MEM32,那么regshift成员应该为2. flags: UPF_BOOT_AUTOCONF 表示自动探测串口类型,这个一般是需要的 UPF_SKIP_TEST 表示在探测串口类型时,是否测试地址的可访问性。这在调试阶段是需要的。 除了flags,上面的各个成员都必须严格设置正确才能保证串口接口被正确探测和初始化。 如果串口接口类型没有被探测出来,或者FIFO长度不对,这需要考虑寄存器的访问是否正确,这包括:基地址是否正确,regshift和iotype是否正确,时钟频率是否正确。 如果探测信息也没有,或者接口数量不对。那么请在mem menuconfig中,在 Device Drivers ---> Character devices ---> Serial drivers ---> (8) Maximum number of 8250/16550 serial ports (8) Number of 8250/16550 serial ports to register at runtime 这两项的数字等于在8250注册串口接口的总数。 宋工企鹅号:35--24-65--90-88 Tel/W~X:173--17--95--19--08 想学习的你和我联系预约就可以免费听课了。 |
|
相关推荐 |
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4684 浏览 0 评论
87058 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4190 浏览 2 评论
3258 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2249 浏览 0 评论
1233浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
891浏览 1评论
439浏览 1评论
1905浏览 0评论
2932浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-3-29 23:37 , Processed in 0.923131 second(s), Total 66, Slave 51 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 深圳华秋电子有限公司
电子发烧友 (电路图) 粤公网安备 44030402000349 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号