• SPI protocol驱动编写实例


    内核版本:3.9.5

    Linux中SPI驱动有俩个部分组成:controller驱动,直接和底层硬件打交道,protocol驱动,针对特定的设备,也是我们要做的.

    这里只考虑SPI protocol驱动

    在主线内核中有一个通用的字符型驱动范例spidev.本文不讨论spidev,而是探讨如何编写一个自定义SPI设备驱动.

    为何要编写一个自定义驱动:

    • 可以掌控性能;
    • 无需给内核打补丁.SPI框架完整支持在可加载内核模块中进行驱动设置.这也就允许我们在内核源码树外进行编写代码;

    Kernel Configuration

    关掉SPIDEV选项以支持自定义的驱动

    Device Drivers-->

    SPI support-->

    *** SPI Protocol Masters ***

    <> User mode SPIdevice driver support

    为使linuxSPI系统识别你的驱动,需要做两步准备.

    1. 在特定的SPI总线(一个master就是一条总线)上注册SPI slave设备.可以是内核初始化的时候亦或是在你的驱动代码中动态的进行.设备名称在这步中必须指定;

    2. 注册SPI protocol驱动.使用的名字必须和步骤1中的一致,这样kernel就可以将它们链接在一起了;

    两个步骤可以以任意次序进行,但是得知道当他们完成之后,SPI框架就可以响应你驱动中的probe()调用了.你将得到一个spi_device用来和SPI系统进行交互了.一旦你的probe函数调用成功,你就可以开始使用SPI总线了.

    静态注册SPI设备涵盖在spidev中了.

    动态主册SPI设备的步骤如下:

    1. 得到管理总线的spi_master控制器指针(句柄);

    2. 为总线分配spi_device结构;

    3. 验证没有其他的设备已经在这条总线bus.cs上注册过了;

    4. 使用设备特定的值(speed,datasize,etc)来填充spi_device;

    5. 将新的spi_device添加到总线;

    有个范例代码:

     1 static int __init add_spike_device_to_bus(void)
     2 {
     3     struct spi_master *spi_master;
     4     struct spi_device *spi_device;
     5     struct device *pdev;
     6     char buff[64];
     7     int status = 0;
     8 
     9     spi_master = spi_busnum_to_master(SPI_BUS);
    10     if (!spi_master) {
    11         printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL
    ",
    12             SPI_BUS);
    13         printk(KERN_ALERT "Missing modprobe omap2_mcspi?
    ");
    14         return -1;
    15     }
    16 
    17     spi_device = spi_alloc_device(spi_master);
    18     if (!spi_device) {
    19         put_device(&spi_master->dev);
    20         printk(KERN_ALERT "spi_alloc_device() failed
    ");
    21         return -1;
    22     }
    23 
    24     /* specify a chip select line */
    25     spi_device->chip_select = SPI_BUS_CS1;
    26 
    27     /* Check whether this SPI bus.cs is already claimed */
    28     snprintf(buff, sizeof(buff), "%s.%u", 
    29             dev_name(&spi_device->master->dev),
    30             spi_device->chip_select);
    31 
    32     pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);
    33      if (pdev) {
    34         /* We are not going to use this spi_device, so free it */ 
    35         spi_dev_put(spi_device);
    36 
    37         /* 
    38          * There is already a device configured for this bus.cs combination.
    39          * It's okay if it's us. This happens if we previously loaded then 
    40                  * unloaded our driver. 
    41                  * If it is not us, we complain and fail.
    42          */
    43         if (pdev->driver && pdev->driver->name && 
    44                 strcmp(this_driver_name, pdev->driver->name)) {
    45             printk(KERN_ALERT 
    46                 "Driver [%s] already registered for %s
    ",
    47                 pdev->driver->name, buff);
    48             status = -1;
    49         } 
    50     } else {
    51         spi_device->max_speed_hz = SPI_BUS_SPEED;
    52         spi_device->mode = SPI_MODE_0;
    53         spi_device->bits_per_word = 8;
    54         spi_device->irq = -1;
    55         spi_device->controller_state = NULL;
    56         spi_device->controller_data = NULL;
    57         strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE);
    58         status = spi_add_device(spi_device);
    59 
    60         if (status < 0) {    
    61             spi_dev_put(spi_device);
    62             printk(KERN_ALERT "spi_add_device() failed: %d
    ", 
    63                 status);        
    64         }                
    65     }
    66 
    67     put_device(&spi_master->dev);
    68 
    69     return status;
    70 }

    稍微有点复杂,这是个完整的样板.你完全可以只更改spi_device中指定域来服务你自己的驱动.

    注册spi_driver,首先要用驱动名字还有些回调函数来初始化他.至少你得提供一个probe()函数,让他能够找到他的另一半spi_device.

    范例:

    1 static struct spi_driver spike_driver = {
    2     .driver = {
    3         .name =this_driver_name,
    4         .owner =THIS_MODULE,
    5     },
    6     .probe =spike_probe,
    7     .remove =spike_remove,
    8 };

    具体的也可参考linux/spi/spi.h文件

    接着就可一在某个地方调用spi_register_driver()进行注册了.

    1 spi_register_driver(&spike_driver); 

    本文转自:http://blog.csdn.net/wuhzossibility/article/details/7831652

  • 相关阅读:
    继承ServletContextListener可以完成的事情
    redis-win7
    jquery-attr与prop
    web表单disable问题
    html-select
    wordpress安装五步法
    CSS布局整理
    photoshop制作古风画
    CSS布局——三栏布局
    sublime text3配置插件
  • 原文地址:https://www.cnblogs.com/jason-lu/p/3164477.html
Copyright © 2020-2023  润新知