需要了解Linux下SPI从设备驱动的编写

 S     PI      (Serial Peripheral In     te      rface) 是一个同步的四线制串行线,用于连接微控制器和     传感器      、存储器及外围设备。三条     信号线      持有     时钟      信号(SCLK,经常在10MHz左右)和并行数据线带有“主出,从进(MOSI)”或是“主进,从出(     MI      SO)”信号。数据交换的时候有四种时钟模式,模式0和模式3是最经常使用的。每个时钟周期将会传递数据进和出。如果没有数据传递的话,时钟将不会循环。

    需要了解Linux下SPI从设备驱动的编写_设计制作_嵌入式技术  

SPI驱动分为两类:

控制器驱动:它们通常内嵌于片上系统处理器,通常既支持主设备,又支持从设备。这些驱动涉及硬件     寄存器   ,可能使用     DMA   。或它们使用GPIO引脚成为PIO bitbange     rs   。这部分通常会由特定的开发板提供商提供,不用自己写。

协议驱动:它们通过控制器驱动,以SPI连接的方式在主从设备之间传递信息。这部分涉及具体的SPI从设备,通常需要自己编写。

那么特定的目标板如何让     Linux   操控SPI设备?下面以AT91SAM9260系列     CAN   设备驱动为例,Linux内核版本为2.6.19。本文不涉及控制器驱动分析。

board_info提供足够的信息使得系统正常工作而不需要芯片驱动加载

[cpp] view pl     ai   n copy

在arch/     arm   /mach-at91rm9200/board-at91sam9260.c中有如下代码:

#include

#include

…….

sta     ti   c struct spi_board_info ek_spi_devices[] = {

/* spi can ,add by mrz */

#if defined(CONFIG_CAN_MCP2515)

{

.modalias = "mcp2515",

.chip_select = 0,

//      .controller_data = AT91_PIN_PB3,

.irq = AT91_PIN_PC6, //AT91SAM9260_ID_IRQ0,

.platform_data = &mcp251x_data,

.max_speed_hz = 10 * 1000 * 1000,

.bus_num = 1,

.mode = 0,

}

#endif

};.

………

sta  TI c void __init ek_board_init(void)

{

……

/* SPI */

at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));

}

这样在Linux初始化时候就可以加载SPI CAN驱动。

下面来看MCP2515 CAN驱动的结构,协议驱动有点类似平台设备驱动,本文只列出框架,不涉及具体实现代码,在/driver/CAN/MCP2515.c中:

[c-sharp] view plain copy

sta  TI c struct spi_driver mcp251x_driver = {

.driver = {

.name   = mcp2515,

.bus    = &spi_bus_type,

.owner  = THIS_MODULE,

},

.probe  = mcp251x_probe,

.remove = __devexit_p(mcp251x_remove),

#ifdef CONFIG_PM

.suspend    = mcp251x_suspend,

.resume = mcp251x_resume,

#endif

};

驱动将自动试图绑定驱动到任何board_info给定别名为" mcp2515"的SPI设备。

sta  TI c int __devinit mcp251x_probe(struct spi_device *spi)

{

struct mcp251x *chip;

int ret = 0;

dev_dbg(&spi->dev, "%s: start/n",  __FUNC  TI ON__);

chip = kmalloc(sizeof(struct mcp251x), GFP_KERNEL);

if (!chip) {

ret = -ENOMEM;

goto error_alloc;

}

dev_set_drvdata(&spi->dev, chip);

chip->txbin = chip->txbout = 0;

chip->rxbin = chip->rxbout = 0;

chip->count = 0;

chip->spi = spi;

init_MUTEX(&chip->lock);

init_MUTEX(&chip->txblock);

init_MUTEX(&chip->rxblock);

init_waitqueue_head(&chip->wq);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))

INIT_WORK(&chip->irq_work, mcp251x_irq_handler);

#else

INIT_WORK(&chip->irq_work, mcp251x_irq_handler, spi);

#endif

chip->spi_transfer_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);

if (!chip->spi_transfer_buf) {

ret = -ENOMEM;

goto error_buf;

}

ret = request_irq(spi->irq, mcp251x_irq, SA_SAMPLE_RANDOM, DRIVER_NAME, spi);

if (ret < 0) {

dev_err(&spi->dev, "request irq %d failed (ret = %d)/n", spi->irq, ret);

goto error_irq;

}

cdev_init(&chip->cdev, &mcp251x_fops);

chip->cdev.owner = THIS_MODULE;

ret = cdev_add(&chip->cdev, MKDEV(MAJOR(can_devt), can_minor), 1);

if (ret < 0) {

dev_err(&spi->dev, "register char device failed (ret = %d)/n", ret);

goto error_register;

}

chip->class_dev = class_device_create(can_class, NULL,

MKDEV(MAJOR(can_devt), can_minor),

&spi->dev, "can%d", can_minor);

if (IS_ERR(chip->class_dev)) {

dev_err(&spi->dev, "cannot create CAN class device/n");

ret = PTR_ERR(chip->class_dev);

goto error_class_reg;

}

dev_info(&spi->dev, "device register at dev(%d:%d)/n",

MAJOR(can_devt), can_minor);

mcp251x_hw_init(spi);

mcp251x_set_bit_rate(spi, 125000); /* A reasonable default */

mcp251x_hw_sleep(spi);

can_minor++;

return 0;

error_class_reg:

cdev_del(&chip->cdev);

error_register:

free_irq(spi->irq, spi);

error_irq:

kfree(chip->spi_transfer_buf);

error_buf:

kfree(chip);

error_alloc:

return ret;

}

一旦进入probe(),驱动使用"struct spi_message"向SPI设备要求I/O。当remove()返回时,驱动保证将不会提交任何这种信息。
一个spi_message是协议操作序列,以一个原子序列执行。SPI驱动控制包括:
(1)当双向读写开始,是根据spi_transfer要求序列是怎样安排的。
(2)随意设定传递后的短延时,使用spi_transfer.delay_usecs设定。
(3)在一次传递和任何延时之后,无论片选是否活跃,使用spi_transfer.cs_change标志,    暗示下条信息是否进入这个同样的设备,使用原子组中最后一次传输上的spi_transfer.cs_change标志位,可能节省芯片选择取消操作的成本。



84
199
0
74

相关资讯

  1. 1、国家二级运动员出身,改行当演员凭《特种兵》走红,今没戏可拍!2068
  2. 2、《暴风眼》:戴着镣铐跳舞的典范作品2001
  3. 3、吴克群对《为你写诗》信心非常高,可惜8天票房才1200万!1316
  4. 4、新流量搅动三月艺人格局,作品、角色和CP营业为演员热度加冕1292
  5. 5、《我们的法兰西岁月》:青春励志理想飞扬4627
  6. 6、《白日焰火》票房大卖王学兵痴恋桂纶镁超虐心2727
  7. 7、曾出演《琅琊榜》,结婚30年无儿无女,如今花60万克隆两只狗1192
  8. 8、揭秘好莱坞3D的中国特供:没真假只有好坏3125
  9. 9、《独孤皇后》8月开播叫板《扶摇》:乔恩杨幂谁担“后宫之主”2794
  10. 10、《西游》2日腾讯首映周星驰现场授“降魔”经2565
全部评论(0)
我也有话说
0
收藏
点赞
顶部