linux QSPI flash驱动学习

目录

一、介绍

1.1 mtd子系统结构

1.2 SPI子系统框架

二、各个模块(函数)调用依赖关系介绍


一、介绍

         linux内核版本:3.14-xilinx

         具体使用和查看的代码文件主要有如下几个:

         /drivers/mtd/Mtdchar.c    --MTD字符设备

         /drivers/mtd/Mtdblock.c   --MTD块设备

         /drivers/mtd/Mtdcore.c    --MTD原始设备

         /drivers/mtd/Devices/M25p80.c  --SPI Flash设备驱动

         /drivers/spi/Spi-zynq-qspi.c  --QSPI控制器驱动

         /drivers/spi/Spi.c          -- SPI总线核或者通用API

1.1 mtd子系统结构

         *设备节点层:MTD框架可以在/dev下创建字符设备节点(主设备号90)以及块设备节点(主设备号31), 用户通过访问此设备节点即可访问MTD字符设备或块设备。

         *MTD设备层: 基于MTD原始设备, Linux在这一层次定义出了MTD字符设备和块设备, 字符设备在mtdchar.c中实现, 块设备则是通过结构mtdblk_dev来描述,"/drivers/mtd/mtdchar.c"文件实现了MTD字符设备接口; "/drivers/mtd/mtdblock.c"文件实现了MTD块设备接口

         *MTD原始设备层: 由MTD原始设备的通用代码+特定的Flash数据组成。mtd_info、mtd_part、mtd_partition以及mtd_partitions等对象及其操作方法就属于这一层,对应的文件是"drivers/mtd/mtdcore.c"。类似于i2c驱动框架中的核心层。

         *硬件驱动层: 内核将常用的flash操作都已经在这个层次实现, 驱动开发只需要将相应的设备信息添加进去即可, 比如nor flash的芯片驱动位于"drivers/mtd/chips/", nand flash位于"drivers/mtd/nand/

         引用:Linux MTD子系统 _从模型分析到Flash驱动模板 - Abnor - 博客园

1.2 SPI子系统框架

         SPI子系统采用分层分离的思想,大体框架如下所示:

        https://img-blog.csdn.net/20170612235635541?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGluZ2Zlbmc1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

        其中,客户驱动对应于/drivers/mtd/Devices/M25p80.c

         SPI core对应于/drivers/spi/Spi.c

      控制器驱动对应于/drivers/spi/Spi-zynq-qspi.c

二、各个模块(函数)调用依赖关系介绍

         熟悉各个函数的调用关系,先按照mtd_read这一个操作以此往下查看。

         首先,在mtdchar.c中有mtdchar设备的初始化函数init_mtdchar()。其中就注册了mtd设备的操作函数mtd_fops。

        

        

         接下来进入mtdchar_read()函数,获取该函数的调用关系如下:

         mtdchar_read()     ---(mtdchar.c)

             mtd_read()      ---(mtdcore.c)

                 mtd->_read()    ---(mtdcore.c)

                      flash->mtd._read = m25p80_read_ext    --- (M25p80.c   m25p_probe() )

  

         m25p80_read_ext()   ---( M25p80.c)

               m25p80_read()  ---( M25p80.c)

                   spi_sync()    ---(Spi.c)

                      master->transfer()   ---( Spi.c)

        在spi_register_master()中有

        

        在注册spi master的时候,如果没有指定master->transfer(),则在spi_master_initialize_queue()中对master->transfer()以及对master-> transfer_one_message进行初始化。

        

        在函数spi_queued_transfer()中,我们发现spi数据是交给内核线程进行处理的,内核线程为master->pump_message,如下

        

        在上一步中的spi_master_initialize_queue(),对master->transfer()进行初始化后,接着调用了spi_init_queue()这个函数,在该函数中发现有对master->pump_message进行初始化。如下:

        

        接着,进入内核线程spi_pump_messages()继续。发现在该线程中,通过调用master->fn的几个函数最终完成数据发送。如下:

        

        到这里,spi总线的工作就完成了。那么master->fn这些函数哪里注册的,还有spi_register_master()是哪里调用的?

        最后,在Spi-zynq-qspi.c中的zynq_qspi_probe()中发现了这些函数的注册。如下:                       

        这样,函数的调用关系就到此为止了。至于数据是怎样进行传递的,就需要注意各个模块、设备以及驱动的结构体了,里面有用于数据传递的指针定义。

         总结:mtd设备读写是调用的Flash设备驱动(具体的芯片驱动,例如m25p80)的读写函数,一般在驱动初始化时将设备的读写函数注册到mtd设备,设备驱动使用SPI总线向外发送数据,而SPI总线在接收到读写请求时,通过一个内核线程对数据进行处理,在线程中会调用SPI master的读写函数, SPI master的读写操作函数在SPI控制器驱动中进行注册。

         注:在SPI收发数据时,为什么会使用到内核线程(kthread_worker与kthread_work)以及线程同步(completion),是由于SPI控制器在进行数据传输时使用的中断进行处理,例如发送完成、接收到数据时都会进入中断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值