原文地址:http://fpcfjf.blog.163.com/blog/static/55469793201291582350752/
谈到驱动的基本数据结构,通过以前的平台驱动学习可以猜测出,SPI也得有以下几种数据结构:
Spi_master,spi_driver,spi_device,bus_type,class,spi_board_info,spi_message,spi_transfer这几个主要的数据结构,其它的还有几个,但都是在这几个基础上进行再次封包的。这几个数据结构,可能后面几个大家还是猜不出来,前几个应该可以想象得出来是干什么的。
Spi_master是用来描述主机控制驱动器的驱动的,spi_driver是用来描述外设驱动的,spi_device是用来描述外部设备的,bus_type,class自动略过,如果不明白可以去看平台设备的解释,一样的。这回主要讲这几个数据结构。
1. struct spi_master {
2. struct device dev;/总线编号,从0开始/
3. s16 bus_num;/支持的片选的数量,从设备的片选号不能大于这个数量/
4. u16 num_chipselect;
5. u16 dma_alignment;/改变spi_device的特性如:传输模式,字长,时钟频率/
6. int (setup)(struct spi_device *spi);/添加消息到队列的方法,这个函数不可睡眠,他的任务是安排发生的传送并且调用注册的回调函数complete()/
7. int (*transfer)(struct spi_device *spi,struct spi_message *mesg);
8. void (*cleanup)(struct spi_device *spi);
9. };
10. struct spi_driver {
11. int (*probe)(struct spi_device *spi);
12. int (*remove)(struct spi_device *spi);
13. void (*shutdown)(struct spi_device *spi);
14. int (*suspend)(struct spi_device *spi, pm_message_t mesg);
15. int (*resume)(struct spi_device *spi);
16. struct device_driver driver;
};
1. struct spi_device {
2. struct device dev;
3. struct spi_master *master; //对应的控制器指针u32
4. max_speed_hz; //spi通信的时钟u8
5. chip_select; //片选,用于区分同一总线上的不同设备
6. u8 mode;
7. #define SPI_CPHA 0x01 / clock phase /
8. #define SPI_CPOL 0x02 / clock polarity /
9. #define SPI_MODE_0 (0|0) / (original MicroWire) /#define SPI_MODE_1 (0|SPI_CPHA)
10. #define SPI_MODE_2 (SPI_CPOL|0)
11. #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)#define SPI_CS_HIGH 0x04 / chipselect active high? /
12. #define SPI_LSB_FIRST 0x08 / per-word bits-on-wire /
13. #define SPI_3WIRE 0x10 / SI/SO signals shared /
14. #define SPI_LOOP 0x20 / loopback mode /
15. u8 bits_per_word; //每个字长的比特数
16. int irq; //使用的中断
17. void *controller_state;
18. void *controller_data;
19. char modalias[32]; //名字
};
1. struct bus_type spi_bus_type = {
2. .name = “spi”,
3. .dev_attrs = spi_dev_attrs,
4. .match = spi_match_device,
5. .uevent = spi_uevent,
6. .suspend = spi_suspend,
7. .resume = spi_resume,
8. };
9. static struct class spi_master_class = {
10. .name = “spi_master”,
11. .owner = THIS_MODULE,
12. .dev_release = spi_master_release,
};
看到他们是不是有些熟悉的感觉,对,和platform_driver,platform_device,特别是spi_driver和platform_driver,有极高的相似度。
struct platform_driver {
int (*probe)(struct platform_device );
int (remove)(struct platform_device );
void (shutdown)(struct platform_device );
int (suspend)(struct platform_device , pm_message_t state);
int (resume)(struct platform_device );
struct device_driver driver;
struct platform_device_id *id_table;
};
这两个结构都有probe,suspend,resume,remove等函数指针。他们三者间的关系如下:
其实在LINUX的驱动编写中,大量的基本数据结构和大量的函数指针,以及不断变化的宏,是读写代码的感到困难的一个很主要的方面,原理一讲就通,可真正看起代码来,却是麻烦的紧,所以不能着急,要慢慢的来看,时间长了,就熟悉了。
某个明星说的:先混个脸熟。