当前位置:   article > 正文

Linux设备驱动剖析之SPI(一)_linux spi驱动

linux spi驱动

写在前面

初次接触SPI是因为几年前玩单片机的时候,由于普通的51单片机没有SPI控制器,所以只好用IO口去模拟。最近一次接触SPI是大三时参加的校内选拔赛,当时需要用2440去控制nrf24L01,从而实现数据的无线传输。nrf24L01是一种典型的SPI接口的2.4GHz无线收发器,当时搞了很久,由于时间比较紧,而且当时根本不熟悉Linux的SPI子系统,最后虽然采用IO口模拟SPI的方式勉强实现了,但是这根本就不符合Linux驱动的编程规范,或者说是在破坏Linux、污染kernel。

根据我个人所知道的,Linux SPI一直是处于被“忽略”的角色,市场上大部分板子在板级文件里都没有关于SPI的相关代码,而大部分讲驱动的书籍也没有专门的一章来讲述关于Linux SPI方面的内容,与IIC相比,SPI就是一个不被重视的“家伙”,为什么?我也不知道。为了帮SPI抱打不平,我决定基于Linux-2.6.36,说说Linux中SPI子系统。

先给出Linux SPI子系统的体系结构图:

SPI子系统体系结构

下面开始分析SPI子系统。

Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的,看看它的定义:

  1. 00001025 static int __init spi_init(void)
  2. 00001026 {
  3. 00001027 int status;
  4. 00001028
  5. 00001029 buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
  6. 00001030 if (!buf) {
  7. 00001031 status = -ENOMEM;
  8. 00001032 goto err0;
  9. 00001033 }
  10. 00001034
  11. 00001035 status = bus_register(&spi_bus_type);
  12. 00001036 if (status < 0)
  13. 00001037 goto err1;
  14. 00001038
  15. 00001039 status = class_register(&spi_master_class);
  16. 00001040 if (status < 0)
  17. 00001041 goto err2;
  18. 00001042 return 0;
  19. 00001043
  20. 00001044 err2:
  21. 00001045 bus_unregister(&spi_bus_type);
  22. 00001046 err1:
  23. 00001047 kfree(buf);
  24. 00001048 buf = NULL;
  25. 00001049 err0:
  26. 00001050 return status;
  27. 00001051 }

1029行,分配spi buf内存,其中buf和SPI_BUFSIZ都在spi.c文件中定义:

  1. 00000945 #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
  2. 00000946
  3. 00000947 static u8 *buf;

1035行,注册spi总线,同样是在spi.c文件中:

  1. 00000145 struct bus_type spi_bus_type = {
  2. 00000146 .name = "spi",
  3. 00000147 .dev_attrs = spi_dev_attrs,
  4. 00000148 .match = spi_match_device,
  5. 00000149 .uevent = spi_uevent,
  6. 00000150 .suspend = spi_suspend,
  7. 00000151 .resume = spi_resume,
  8. 00000152 };

146行,总线的名字就叫spi。

148行,比较重要的,spi_match_device是spi总线上匹配设备和设备驱动的函数,同样是在spi.c文件中:

  1. 00000085 static int spi_match_device(struct device *dev, struct device_driver *drv)
  2. 00000086 {
  3. 00000087 const struct spi_device *spi = to_spi_device(dev);
  4. 00000088 const struct spi_driver *sdrv = to_spi_driver(drv);
  5. 00000089
  6. 00000090 /* Attempt an OF style match */
  7. 00000091 if (of_driver_match_device(dev, drv))
  8. 00000092 return 1;
  9. 00000093
  10. 00000094 if (sdrv->id_table)
  11. 00000095 return !!spi_match_id(sdrv->id_table, spi);
  12. 00000096
  13. 00000097 return strcmp(spi->modalias, drv->name) == 0;
  14. 00000098 }

写过驱动的都应该知道platform总线有struct platform_device和struct platform_driver,到了SPI总线,当然也有对应的struct spi_device和struct spi_driver,如87、88行所示。87行,关于struct spi_device的定义是在include/linux/spi/spi.h中:

  1. 00000069 struct spi_device {
  2. 00000070 struct device dev;
  3. 00000071 struct spi_master *master;
  4. 00000072 u32 max_speed_hz;
  5. 00000073 u8 chip_select;
  6. 00000074 u8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/712398
推荐阅读
相关标签
  

闽ICP备14008679号