Linux主机驱动与外设驱动分离思想
truct spi_master *master); void spi_unregister_master(struct spi_master *master); 在Linux中,用代码清单12.13的spi_driver结构体来描述一个SPI外设驱动,可以认为是spi_master的client驱动. 代码清单12.13 spi_driver结构体 1 struct spi_driver { 2 int (*probe)(struct spi_device *spi); 3 int (*remove)(struct spi_device *spi); 4 void (*shutdown)(struct spi_device *spi); 5 int (*suspend)(struct spi_device *spi, pm_message_t mesg); 6 int (*resume)(struct spi_device *spi); 7 struct device_driver driver; 8 }; 可以看出,spi_driver结构体和platform_driver结构体有极大的相似性,都有probe()、remove()、suspend()、resume()这样的接口.是的,这几乎是一切client驱动的习惯模板. 在SPI外设驱动中,当透过SPI总线进行数据传输的时候,使用了一套与CPU无关的统一的接口.这套接口的第1个关键数据结构就是spi_transfer,它用于描述SPI传输,如代码清单12.14. 代码清单12.14 spi_transfer结构体 1 struct spi_transfer { 2 const void *tx_buf; 3 void *rx_buf; 4 unsigned len; 5 6 dma_addr_t tx_dma; 7 dma_addr_t rx_dma; 8 9 unsigned cs_change:1; 10 u8 bits_per_word; 11 u16 delay_usecs; 12 u32 speed_hz; 13 14 struct list_head transfer_list; 15 }; 而一次完整的SPI传输流程可能不只包含1次spi_transfer,它可能包含1个或多个spi_transfer,这些spi_transfer最终通过spi_message组织在一起,其定义如代码清单12.15. 代码清单12.15 spi_message结构体 1 struct spi_message { 2 struct list_head transfers; 3 4 struct spi_device *spi; 5 6 unsigned is_dma_mapped:1; 7 8 /* 完成被一个callback报告 */ 9 void (*complete)(void *context); 10 void *context; 11 unsigned actual_length; 12 int status; 13 14 struct list_head queue; 15 void *state; 16 }; 通过spi_message_init()可以初始化spi_message,而将spi_transfer添加到spi_message队列的方法则是: void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m); 发起一次spi_message的传输有同步和异步两种方式,使用同步API时,会阻塞等待这个消息被处理完.同步操作时使用的API是: int spi_sync(struct spi_device *spi, struct spi_message *message); 使用异步API时,不会阻塞等待这个消息被处理完,但是可以在spi_message的complete字段挂接一个回调函数,当消息被处理完成后,该函数会被调用.异步操作时使用的API是: int spi_async(struct spi_device *spi, struct spi_message *message); 代码清单12.16是非常典型的初始化spi_transfer、spi_message并进行SPI数据传输的例子,同时它们也是SPI核心层的2个通用API,在SPI外设驱动中可以直接调用它们进行写和读操作. 代码清单12.16 SPI传输实例spi_write()、spi_read() API 1 static inline int 2 spi_write(struct spi_device *spi, const u8 *buf, size_t len) 3 { 4 struct spi_transfer t = { 5 .tx_buf = buf, 6 .len = len, 7 }; 8 struct spi_message m; 9 10 spi_message_init(&m); 11 spi_message_add_tail(&t, &m); 12 return spi_sync(spi, &m); 13 } 14 15 static inline int 16 spi_read(struct spi_device *spi, u8 *buf, size_t len) 17 { 18 struct spi_transfer t = { 19 .rx_buf = buf, 20 .len = len, 21 }; 22 struct spi_message m; 23 24 spi_message_init(&m); 25 spi_message_add_tail(&t, &m); 26 return spi_sync(spi, &am |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |