赞
踩
写在前面
初次接触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函数开始的,看看它的定义:
- 00001025 static int __init spi_init(void)
- 00001026 {
- 00001027 int status;
- 00001028
- 00001029 buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
- 00001030 if (!buf) {
- 00001031 status = -ENOMEM;
- 00001032 goto err0;
- 00001033 }
- 00001034
- 00001035 status = bus_register(&spi_bus_type);
- 00001036 if (status < 0)
- 00001037 goto err1;
- 00001038
- 00001039 status = class_register(&spi_master_class);
- 00001040 if (status < 0)
- 00001041 goto err2;
- 00001042 return 0;
- 00001043
- 00001044 err2:
- 00001045 bus_unregister(&spi_bus_type);
- 00001046 err1:
- 00001047 kfree(buf);
- 00001048 buf = NULL;
- 00001049 err0:
- 00001050 return status;
- 00001051 }

1029行,分配spi buf内存,其中buf和SPI_BUFSIZ都在spi.c文件中定义:
- 00000945 #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
- 00000946
- 00000947 static u8 *buf;
1035行,注册spi总线,同样是在spi.c文件中:
- 00000145 struct bus_type spi_bus_type = {
- 00000146 .name = "spi",
- 00000147 .dev_attrs = spi_dev_attrs,
- 00000148 .match = spi_match_device,
- 00000149 .uevent = spi_uevent,
- 00000150 .suspend = spi_suspend,
- 00000151 .resume = spi_resume,
- 00000152 };
146行,总线的名字就叫spi。
148行,比较重要的,spi_match_device是spi总线上匹配设备和设备驱动的函数,同样是在spi.c文件中:
- 00000085 static int spi_match_device(struct device *dev, struct device_driver *drv)
- 00000086 {
- 00000087 const struct spi_device *spi = to_spi_device(dev);
- 00000088 const struct spi_driver *sdrv = to_spi_driver(drv);
- 00000089
- 00000090 /* Attempt an OF style match */
- 00000091 if (of_driver_match_device(dev, drv))
- 00000092 return 1;
- 00000093
- 00000094 if (sdrv->id_table)
- 00000095 return !!spi_match_id(sdrv->id_table, spi);
- 00000096
- 00000097 return strcmp(spi->modalias, drv->name) == 0;
- 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中:
- 00000069 struct spi_device {
- 00000070 struct device dev;
- 00000071 struct spi_master *master;
- 00000072 u32 max_speed_hz;
- 00000073 u8 chip_select;
- 00000074 u8
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。