作者:刘广富,
华清远见
嵌入式学院讲师。
本文不具体分析linux内核中SPI总线的架构,只针对这种架构阐述如何进行SPI设备驱动的编写。
简而言之,SPI驱动的编写分为两个部分:
第一、spi_device的构建和注册
第二、spi_driver的构建和注册
1.spi_device的构建并注册
首先在板文件中添加spi_board_info,例如:
static struct spi_board_info s3c_spi_devs[] __initdata = {
{
.modalias = "m25p10a",
.mode = SPI_MODE_0,
.max_speed_hz = 1000000,
.bus_num = 0,
.chip_select = 0,
.controller_data = &smdk_spi0_csi[SMDK_MMCSPI_CS],
},
};
并在板文件的init函数中调用spi_register_board_info(s3c_spi_devs,ARRAY_SIZE(s3c_spi_devs));
这个函数会把spi_board_info注册到链表board_list上。spi_device封装了一个spi_master结构体,事实上spi_master的注册会在spi_register_board_info之后,spi_master注册的过程中会调用scan_boardinfo扫描board_list,找到挂接在它上面的spi设备,然后创建并注册spi_device。
2. spi_driver的构建与注册,分为三部曲:
(1)构建spi_driver
static struct spi_driver m25p80_driver = {
. driver = {
.name ="m25p80",
.bus =&spi_bus_type,
.owner = THIS_MODULE,
},
.probe = m25p_probe,
.remove =__devexit_p(m25p_remove),
};
(2)spid_river的注册
spi_register_driver(&m25p80_driver);当匹配了spi_device以后调用probe
(3)实现probe操作:
spi_transfer(里面集成了数据buf空间地址等信息)
spi_message(是spi_transfer的**)的构建;spi_message_init(初始化spi_message)、spi_message_add_tail(将新的spi_transfer添加到spi_message队列尾部)
spi_sync函数的调用(调用spi_master发送spi_message)
例如:
struct spi_transfer st={
.tx_buf = buf,
.len = len,
。。。。。。。。。
};//填充spi_transfer 的tx_buf、rx_buf和len就可以
struct spi_message meg;//定义message
spi_init_message(&meg);//初始化meg
spi_message_add_tail(&st,&meg);
//将st放在message队列尾部
Spi_sync(spi_device,&meg);
//将message与spi_device关联,发送meg
这样就基本完成了SPI设备的驱动编写,读写具体操作要根据芯片的时序来确定,具体如何利用SPI传数据那么就要看自己程序的逻辑。
本文不具体分析linux内核中SPI总线的架构,只针对这种架构阐述如何进行SPI设备驱动的编写。
简而言之,SPI驱动的编写分为两个部分:
第一、spi_device的构建和注册
第二、spi_driver的构建和注册
1.spi_device的构建并注册
首先在板文件中添加spi_board_info,例如:
static struct spi_board_info s3c_spi_devs[] __initdata = {
{
.modalias = "m25p10a",
.mode = SPI_MODE_0,
.max_speed_hz = 1000000,
.bus_num = 0,
.chip_select = 0,
.controller_data = &smdk_spi0_csi[SMDK_MMCSPI_CS],
},
};
并在板文件的init函数中调用spi_register_board_info(s3c_spi_devs,ARRAY_SIZE(s3c_spi_devs));
这个函数会把spi_board_info注册到链表board_list上。spi_device封装了一个spi_master结构体,事实上spi_master的注册会在spi_register_board_info之后,spi_master注册的过程中会调用scan_boardinfo扫描board_list,找到挂接在它上面的spi设备,然后创建并注册spi_device。
2. spi_driver的构建与注册,分为三部曲:
(1)构建spi_driver
static struct spi_driver m25p80_driver = {
. driver = {
.name ="m25p80",
.bus =&spi_bus_type,
.owner = THIS_MODULE,
},
.probe = m25p_probe,
.remove =__devexit_p(m25p_remove),
};
(2)spid_river的注册
spi_register_driver(&m25p80_driver);当匹配了spi_device以后调用probe
(3)实现probe操作:
spi_transfer(里面集成了数据buf空间地址等信息)
spi_message(是spi_transfer的**)的构建;spi_message_init(初始化spi_message)、spi_message_add_tail(将新的spi_transfer添加到spi_message队列尾部)
spi_sync函数的调用(调用spi_master发送spi_message)
例如:
struct spi_transfer st={
.tx_buf = buf,
.len = len,
。。。。。。。。。
};//填充spi_transfer 的tx_buf、rx_buf和len就可以
struct spi_message meg;//定义message
spi_init_message(&meg);//初始化meg
spi_message_add_tail(&st,&meg);
//将st放在message队列尾部
Spi_sync(spi_device,&meg);
//将message与spi_device关联,发送meg
这样就基本完成了SPI设备的驱动编写,读写具体操作要根据芯片的时序来确定,具体如何利用SPI传数据那么就要看自己程序的逻辑。