第2课第1节_SPI驱动框架

         SPI裸板程序,我们分为了下图所示的三部分:

         类似的,linux SPI驱动程序也可分为三个部分。疑问的是SPI_master驱动程序不止一个?那I2C驱动也有多个吗?区别在哪里?

SPI控制器驱动,各个平台都会根据SPI总线在自己平台芯片上的定义来实现自己的SPI控制器驱动。SPI控制器驱动主要是对SPI总线本身的一个控制,如SPI总线的上下电时序,时钟,SPI中断,DMA以及最主要也最重要的SPI通信等资源的控制。SPI控制器在整个SPI系统中作为一个master存在,可以看作是系统中SPI总线的一个管理者,同时,它提供接口出来为各个SPI外设服务。
      LINUX SPI核心层,在linux的核心层代码中主要定义了SPI主控制器spi_masterSPI驱动spi_driverSPI设备spi_deviceSPI通信相关的spi_transfer,spi_message等数据结构,这些数据结构是构成整个SPI系统的最基本的元素,同时,在SPI的核心层中又定义了这些基本元素之间的关系。SPI核心层对SPI系统提供了最基础的搭建方法,如向系统注册一个控制器master,向控制器上添加一个新的spi设备,spi设备和控制器的电源管理,spi设备与驱动关联条件等。
     SPI设备,spi设备指的是通过spi总线与主芯片进行通信的设备,如数据电视芯片ISDBT,通常是指具有特定功能的电子芯片。spi设备在系统中以一个spi_device的数据结构存在。

 

 

 

         linux SPI驱动程序框架如下图所示:

 

         对于bus_num的理解:假设2440上有spi控制器0和1,那单板上的OLED挂载到哪一个spi控制器里面,是需要指定的,因此单板信息里要通过bus_num来指定OLED是挂载到哪个spi控制器上了。

 

 

 

枚举过程

drivers/spi/spi.c:

    spi_register_board_info

        /* 对于每一个spi_master,调用spi_match_master_to_boardinfo */

        list_for_each_entry(master, &spi_master_list, list)

            spi_match_master_to_boardinfo

            /* board_info里含有bus_num, 如果某个spi_master的bus_num跟它一样

             * 则创建一个新的spi_device

             */

                    if (master->bus_num == bi->busnum)

                        spi_new_device

                            spi_alloc_device

                            /* 记录bi信息, 比如片选,MODE,MAX HZ */   

                            spi_add_device /* 根据名字找到spi_driver, 调用它的probe函数 */

                                spi_setup(spi);

                                device_add  /* 把设备添加到总线上面,然后会绑定到一个spi_driver */(疑问:有多个SPI设备时怎么办,在这个函数里并没有发现循环语句?是多添加几个spi_board_info?

 

 

 

 

驱动程序如何去调用master驱动里面的函数来收发数据:

数据收发过程

    设备驱动中spi_write

        spi_message_init(&m);

        初始化一个spi_message  /* 一个不可打断的SPI传输过程: cs=0,传数据,cs=1 */

                               /* 一个spi_message由多个spi_transfer组成 */

        spi_message_add_tail(&t, &m);  /* spi_transfe是SPI上传输的单方向1个或多个字节 */

        spi_sync(spi, &m);  /* 启动传输并等待完成 */

 

spi_driver如何调用spi_controller:

    spi_sync

        __spi_sync(spi, message, 0);

            spi_async_locked

                __spi_async

                    master->transfer(spi, message);

            wait_for_completion

猜你喜欢

转载自blog.csdn.net/hahaha_2017/article/details/81262572
今日推荐