设备驱动之SPI
本文非专业讲SPI,只是讲网上看到的资料略微总结,并加上自己的想法,附资料links。
devs.c :各个platform_device 的定义,比如I2C、USB、SPI等等。应该是内核加载时,读取该配置文件,然后注册进系统。目录在/arch/arm/plat-samsung/devs.c
比如:
/* SPI */ #ifdef CONFIG_PLAT_S3C24XX static struct resource s3c_spi0_resource[] = { //下面s3c_device_spi0对象的资源 [0] = DEFINE_RES_MEM(S3C24XX_PA_SPI, SZ_32), [1] = DEFINE_RES_IRQ(IRQ_SPI0), }; struct platform_device s3c_device_spi0 = { // 声明s3c_device_spi0 platform设备 .name = "s3c2410-spi", //会与驱动匹配,比较两个名字是一样的 .id = 0, //相当于次设备号 .num_resources = ARRAY_SIZE(s3c_spi0_resource), .resource = s3c_spi0_resource, .dev = { .dma_mask = &samsung_device_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), } };
spi_master 本质上是个device,看做总线。spi总线以spi_master体现,可以当做一样
奇怪 SPI_MASTER: comment "SPI Master Controller Drivers"
struct spi_master { struct device dev; //说明spi_master本质上是device的封装,总线本身就是一个设备 struct list_head list; s16 bus_num; u16 num_chipselect; u16 dma_alignment; /* spi_device.mode flags understood by this controller driver */ u16 mode_bits; /* other constraints relevant to this driver */ u16 flags; #define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ #define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */ #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ /* lock and mutex for SPI bus locking */ spinlock_t bus_lock_spinlock; struct mutex bus_lock_mutex; /* flag indicating that the SPI bus is locked for exclusive use */ bool bus_lock_flag; int (*setup)(struct spi_device *spi); int (*transfer)(struct spi_device *spi, struct spi_message *mesg); /* called on release() to free memory provided by spi_master */ void (*cleanup)(struct spi_device *spi); bool queued; struct kthread_worker kworker; struct task_struct *kworker_task; struct kthread_work pump_messages; spinlock_t queue_lock; struct list_head queue; struct spi_message *cur_msg; bool busy; bool running; bool rt; int (*prepare_transfer_hardware)(struct spi_master *master); int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); int (*unprepare_transfer_hardware)(struct spi_master *master); };
struct boardinfo { struct list_head list; struct spi_board_info board_info; };
SPI分三层:
SPI核心层:/drivers/spi/spi.c
postcore_initcall(spi_init);--->内核调用spi_init()---->status = bus_register(&spi_bus_type);spi总线对象注册到platform_bus上。
SPI控制器驱动层:/drivers/spi/spi-s3c24xx.c
module_platform_driver(s3c24xx_spi_driver);--->s3c24xx_spi_driver->probe()初始化控制器各项--->spi_alloc_master()分配一个spi_master(spc.c中fun)--->
-->spi_bitbang_start()中---->调用spi_register_master()(spc.c中fun)注册spi_master主控制器到platform_bus上,--->device_add(&master->dev);(spc.c中fun)//register the device, then userspace will see it.
SPI设备驱动层: /drivers/spi/spidev.c
module_init(spidev_init);--->spidev_init(void)--->spi_register_driver(&spidev_spi_driver);(spi.c中fun) //注册设备驱动
1、spi_device代表一个外围spi设备,由master controller driver注册完成后扫描BSP中注册设备产生的设备链表并向spi_bus注册产生。
2、 spi_driver代表一个SPI protocol drivers,即外设驱动。
3、spi_master代表一个主机控制器,此处即S3C2440中的SPI控制器,它是抽象出来的?
4、spi_transfer代表一个读写缓冲对,包含接收缓冲区及发送缓冲区,其实,spi_transfer的发送是通过构建spi_message实现,通过将spi_transfer中的链表transfer_list链接到spi_message中的transfers,再以spi_message形势向底层发送数据。
5、spi_message代表spi消息,由多个spi_ transfer段组成:
6、s3c24xx_spi代表具体的s3c2440中的spi控制器,包含了控制器的信息,如中断,寄存器等信息,定义于/drivers/spi/spi_s3c24xx.c(因为该结构与具体的硬件有关,属于linux里面的非通用代码)
7、struct spi_bitbang是具体的负责信息传输的数据结构,它维护一个workqueue_struct,每收到一个消息,都会向其中添加一个work_struct,由内核守护进程在将来的某个时间调用该work_struct中的function进行消息发送。
related links:
2、解构技能,找出实现80%效果的那20%
3、不要一心二用
4、练习练习再练习!然后获得即时反馈
5、坚持,不要在低谷期放弃