当前位置: 首页 > news >正文

内核spi驱动流程图

在这里插入图片描述

1. module_init 与 module_exit 这两个是在模块加载和卸载时需要使用

流程1: module_init -> spi_register_driver

2. 驱动开发填充两个结构体 XXX_device xxx_driver(spi_driver)

3. 定义一个spi_driver,里面包含了device_driver 基类

1)在spi_register_driver时,匹配会去执行probe函数
2)id_table 和driver结构体中,填充和device匹配的名称

struct spi_driver {const struct spi_device_id *id_table;int                     (*probe)(struct spi_device *spi);int                     (*remove)(struct spi_device *spi);void                    (*shutdown)(struct spi_device *spi);struct device_driver    driver;
};
流程2spi_register_driver(spi_driver) -> __spi_register_driver(spi_driver) -> driver_register(device_driver) ->  bus_add_driver(device_driver) -> driver_attach(device_driver) -> __driver_attach(在driver注册的总线bus_type上找设备(spi_device))  -> really_probe -> probe(回调到spi_driver)

设备树解析
设备树中的设备(device)是用来描述硬件资源的存在
被内核解析,生成一个 struct device_node;
再由 platform 总线(或其他总线)创建 platform_device/ spi_device等对象;
匹配上驱动的 platform_driver 后调用驱动中的 probe() 函数;

4. 定义一个XXX_device

1) spi_driver 中的probe函数执行
2) 创建cdev设备,这个是给用户层的接口,供用户进行系统调用
3) 创建类class_create
4) 根据定义的XXX_device创建设备

流程3probe(回调到spi_driver) -> cdev_add (创建cdev设备,设备中包含ops调用接口) -> class_create(创建类) -> device_create(创建 /dev 节点,并连接到类 以及cdev设备接口)
struct xxx_dev
{dev_t devid;                                                    /* 设备号 */                                 struct cdev cdev;                                               /* cdev */struct class *class;                                    /* 类 */struct device *device;                                  /* 设备 */struct device_node *nd;                                 /* 设备节点 */int major;                                                              /* 主设备号 */int pdwn_gpio;int cs_gpio;                                                    /* cs所使用的GPIO编号 */int reset_gpio;                                                 /* reset所使用的GPIO编号 */int drdy_gpio;                                                  /* drdy所使用的GPIO编号 */unsigned char channels[8];                              /* 采样通道,最多8个 */unsigned char channel_num;                              /* 采样通道数量 */int delay_us;                                                   /* 采样间隔时间 */void *private_data;                                             /* 私有数据 */
};

匹配结构体流程如下:

在这里插入图片描述


升入剖析下结构体的定义:(ads1256 spi 设备)

平台驱动结构体

static struct spi_driver ads1256_driver = { .probe = ads1256_probe,.remove = ads1256_remove,.driver = { .owner = THIS_MODULE,.name = "ads1256",                                                                                   .of_match_table = ads1256_of_match,},  .id_table = ads1256_id,
};

为什么是上面定义(总线设备驱动模型)

  1. spi_driver 承载着总线驱动的功能,当总线驱动注册时,找到匹配的总线设备后,需要执行我们的回调函数probe函数。
  2. 当卸载时,我们需要remove相应总线下的子设备。
  3. 其他的是需要与总线设备匹配的总线驱动名称。

平台设备结构体

struct spi_device {struct device           dev;struct spi_master       *master;u32                     max_speed_hz;u8                      chip_select;u8                      bits_per_word;u16                     mode;int                     irq;void                    *controller_state;void                    *controller_data;char                    modalias[SPI_NAME_SIZE];int                     cs_gpio;        /* chip select gpio *//* the statistics */struct spi_statistics   statistics;
};
  1. 平台设备也作为一个设备存在dev,也是作为一个设备注册。
  2. 平台设备作为主设备时的一些参数
  3. 其他就是spi设备的一些具体参数,中断号、模式 、速度等。

spi平台设备下具体设备

struct ads1256_dev
{dev_t devid;                                                    /* 设备号 */struct cdev cdev;                                               /* cdev */struct class *class;                                    /* 类 */struct device *device;                                  /* 设备 */struct device_node *nd;                                 /* 设备节点 */int major;                                                              /* 主设备号 */int pdwn_gpio;int cs_gpio;                                                    /* cs所使用的GPIO编号 */int reset_gpio;                                                 /* reset所使用的GPIO编号 */int drdy_gpio;                                                  /* drdy所使用的GPIO编号 */unsigned char channels[8];                              /* 采样通道,最多8个 */unsigned char channel_num;                              /* 采样通道数量 */int delay_us;                                                   /* 采样间隔时间 */void *private_data;                                             /* 私有数据 */
};
  1. 作为一个设备注册device
  2. 所属类class
  3. 字符设备cdev
  4. 以及具体设备的一些数据参数

相关文章:

  • 特征工程四-2:使用GridSearchCV 进行超参数网格搜索(Hyperparameter Tuning)的用途
  • HarmonyOS NEXT 诗词元服务项目开发上架全流程实战(一、项目介绍及实现效果)
  • [OS_9] C 标准库和实现 | musl libc | offset
  • 打印及判断回文数组、打印N阶数组、蛇形矩阵
  • 高炉项目中DeviceNET到Ethernet的转换奥秘
  • 基于STM32、HAL库的DS2401P安全验证及加密芯片驱动程序设计
  • mysql community 8.0.23升级到8.0.42再到8.4.5
  • 风力发电领域canopen转Profinet网关的应用
  • terraform local-exec与remote-exec详解
  • [OS] POSIX C库介绍
  • Java后端接口调用拦截处理:注解与拦截器的实现
  • 【线性规划】对偶问题的实际意义与重要性质 学习笔记
  • 大数据应用开发与实战(1)
  • 模板--进阶
  • 民办生从零学C的第十二天:指针(1)
  • 辛格迪客户案例 | 华道生物细胞治疗生产及追溯项目(CGTS)
  • Qt内置图标速查表
  • 编译原理:由浅入深从语法树到文法类型
  • TMI投稿指南(三):共同作者
  • Unity-粒子系统:萤火虫粒子特效效果及参数
  • 节前A股持续震荡,“五一”假期持股还是持币过节胜率更高?
  • 朝鲜证实出兵俄罗斯协助收复库尔斯克
  • 准“90后”山西壶关县委常委、副县长高雅亭赴北京密云挂职
  • 与包乐史驾帆航行|航海、钓鱼和写书:一个记者的再就业之路
  • 何以中国|福建武夷山:千年茶道的文旅“破圈”与新生
  • 舞剧《百合花》7月绽放,王安忆:这是送给母亲的一份礼物