第23章Linux设备驱动的移植之巧用同类设备驱动

23.2 巧用同类设备驱动

23.2.1 巧用 demo 板驱动

        对于推出的重要芯片,芯片厂商会同时提供一套 demo 板。这样的 demo 板不仅在硬件设计中被硬件工程师充分利用并进行参考,而且其提供的驱动程序在新设计的硬件系统中被参考。

        借用 demo 板驱动的方法主要是寻找共性中的差异,例如共性是芯片相同,差异则可能体现在所使用的 I/O 内存(片选)、中断和 DMA 资源不同,在这种情况下,修改 I/O 内存基地址、中断号以及 DMA 通道,demo 板的驱动就可以用在目标电路板上。而如果除了芯片相同以外,外围芯片与 CPU 连接所用的内存、中断和 DMA 资源都相同的话,则 demo 板驱动基本上不加任何修改可以搬到目标电路板上。

        如果 demo 板和目标电路板所用资源不同,而 demo 板对应设备被定义为 pltaform_device,且其资源并定义在 resource 结构体数组中,则直接修改 resource 结构体即可,如下所示:

static struct resource xxx _ resource[] = {
        [0] = {
                .start = XXX _ MEM _ START, /* 替换 I/O 内存基地址 */
                .end = XXX _ MEM _ START + XXX _ MEM _ SIZE,
                .flags = IORESOURCE _ MEM,
        },
        [1] = {
                 .start = XXX _ INT _ START, /* 换中断 */
                .end = XXX _ INT _ END,
                .flags = IORESOURCE _ IRQ,
        }

};

        同时,在编写新驱动时要牢记的设计理念是:将硬件和平台相关的信息(内存地址、中断号、DMA 通道、硬件设置等)放入 BSP 中,作为 platform 信息、SPI board 信息、I 2 C board 信息等,而不是直接放在驱动里面。

23.2.2 巧用类似芯片的驱动程序

        任何驱动工程师都没有必要在面对新设备驱动编写需求时一切从头开始,因为内核源代码 drivers 目录(音频设备的驱动在 sound 目录)中已经包含了大量现成的类似芯片驱动的源代码,是极好的参考模板,不需要“re-invent the wheel”。实际上,在内核源代码许多后期编写的驱动程序中,就直接参考了之前的驱动源码,所以同类设备的驱动往往呈现出非常相似的架构和数据结构定义。来看看 sound/oss/ au1550_ac97.c 文件最开始的一段注释:

/*
* au1550 _ ac97.c -- Sound driver for Alchemy Au1550 MIPS Internet Edge
* Processor.
*
* Copyright 2004 Embedded Edge, LLC
*  dan@embeddededge.com
*
* Mostly copied from the au1000.c driver and some from the PowerMac dbdma driver.
* We assume the processor can do memory coherent DMA.
...
*/

        这段注释很清楚地说明其绝大多数代码都来自 au1000.c 驱动,还有一些来自 PowerMac dbdma驱动。

        打开 sound/oss 目录下的 au1550_ac97.c(Alchemy Au1550 MIPS 处理器的音频驱动)、es1370.c
(Ensoniq ES1370/Asahi Kasei AK4531 声卡驱动)、es1371.c(reative Ensoniq ES1371 声卡驱动)、

cs46xx.c(Crystal SoundFusion CS46xx 声卡驱动),发现如下相似之处。

1、它们全都自定义了全局的 xxx_state 结构体实例用于封装音频设备的锁、信号量、缓冲区、ID 等信息,这几个结构体分别是:au1550_state、es1370_state、es1371_state、cs_state。

2、它们的核心函数都使用了完全相同的实现方法,au1550_ac97.c 的 au1550_read()和es1370.c 的 es1370_read()的处理流程是一致的。

可以看出,内核中看似神秘的、庞大的设备驱动源码也是互相学习、互相借鉴的结果。

23.2.3 借用芯片厂商的范例程序

        外围芯片上市之前,芯片厂商进行了严格的验证,在验证过程中,必然会编写代码去访问和控制这些芯片。很多时候,这些代码稍经整理就被芯片厂商随同 datasheet 一起在网站上作为参考代码发布。

        范例程序停留在无操作系统的层次上,只是最底层的硬件操作代码,这一部分代码对驱动工程师的意义如下。

  1、帮助工程师进一步理解芯片与 CPU 的接口原理、芯片的访问和控制方法。

  2、直接加以改进后搬到 Linux 设备驱动中。      

Linux 设备驱动的硬件操作方法会与无操作系统时的硬件操作方法有如下差异。

1、无操作系统的硬件访问方法中没有物理地址到虚拟地址的映射过程,搬到Linux 系统中时,要注意以静态映射或 ioremap()等方式映射到虚拟地址

2、硬件访问中夹杂着延时,在无操作系统的源码中,经常出现 xxx_delay()的 for 循环延迟,这些代码应该被内核中的 ndelay()或 udelay()替换。如果延迟时间达到数十 ms,应该使用 msleep()或 msleep_interruptible()等函数。

3、芯片范例程序只是对芯片的操作方法进行示范,并不会考虑真实应用场景中对 CPU 的资源占用以及代码的时间性能。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值