linux内核驱动:IIO子系统总结

前言

本笔记基于linux5.10.xx内核,dht11温湿度传感器总结对IIO驱动子系统的使用,基于运行linux内核的arm系列处理器soc;

一、概念

IIO为industrial I/O的简称,为一些传感器的数据采集提供了一套方便的软件框架,作为内核驱动子系统可以和温度、湿度、压力、加速度等传感器的驱动相结合,为相应数据获取提供方便的访问方式;

二、系统拓扑结构

在这里插入图片描述

通过将传感器抽象为iio设备后,最终会将其注册为一个字符设备;
芯片和传感器之间的接口可以是多种形式,如i2c、spi、adc、本例中的dht11单总线等;
通过iio可以将传感器的物理数据建立一个数据模型,iio将其定义通道,如dht11可以采集温度和湿度则定义了温度和湿度通道,其它传感器同理;

三、IIO子系统文件

industrialio-core.c

iio子系统的核心层;
iio总线的注册接口;
提供iio_dev结构的分配、、成员初始化、注册接口;
提供iio对应的字符设备的file_operation接口;
提供iio设备属性操作接口;

industrialio-event.c

提供iio设备event事件方式获取数据的接口;
主要操作的是struct iio_dev_opaque结构的event_interface成员和其子成员;

industrialio-buffer.c

提供iio设备数据buffer的功能接口;
对struct iio_buffer结构的操作封装;
iio设备可以选择不使用buffer功能,具体考虑应用场景;

buffer/kfifo_buf.c

提供struct iio_buffer结构的分配结构;
提供struct iio_buffer结构的access成员操作函数集;
将struct iio_buffer作为struct iio_kfifo结构的成员进行操作;

buffer/industrialio-buffer-cb.c

对struct iio_cb_buffer结构的操作封装;

inkern.c

对struct iio_channel结构的操作封装;

industrialio-sw-trigger.c
industrialio-triggered-event.c
buffer/industrialio-triggered-buffer.c

trigger相关模式需要的驱动iio子系统的文件,具体的驱动也要实现相关机制;

四、主要数据结构

struct iio_dev_opaque

定义于include/linux/iio/iio-opaque.h
通过此结构的定义来定义iio_dev;
成员iio_event_interface封装用户层阻塞访问设备时的等待队列头;
buffer_list定义数据buffer的列表;

struct iio_dev_opaque {
	struct iio_dev			indio_dev;
	struct iio_event_interface	*event_interface;
	struct list_head		buffer_list;
	struct list_head		channel_attr_list;
	struct attribute_group		chan_attr_group;
#if defined(CONFIG_DEBUG_FS)
	struct dentry			*debugfs_dentry;
	unsigned			cached_reg_addr;
	char				read_buf[20];
	unsigned int			read_buf_len;
#endif
};

struct iio_dev

定义于include/linux/iio/iio.h
对iio设备的数据表示;

struct iio_dev {
    //iio设备的id号,在设备节点中体现为/dev/iio:device+id号,如1则为/dev/iio:device1
	int				id;  
	struct module			*driver_module;
	//iio设备的操作模式,目前一共有6种,如INDIO_DIRECT_MODE为直接模式
	int				modes;
	int				currentmode;
	struct device			dev;
    //当操作模式使用buffer机制时,此成员需要分配
	struct iio_buffer		*buffer;
	int				scan_bytes;
	struct mutex			mlock;
	const unsigned long		*available_scan_masks;
	unsigned			masklength;
	const unsigned long		*active_scan_mask;
	bool				scan_timestamp;
	unsigned			scan_index_timestamp;
	//使用触发机制时需要分配此成员
	struct iio_trigger		*trig;
	bool				trig_readonly;
	struct iio_poll_func		*pollfunc;
	struct iio_poll_func		*pollfunc_event;
    //iio设备针某个器件所定义的通道
	struct iio_chan_spec const	*channels;
	//通道个数如dth11温湿度会定义两个通道
	int				num_channels;
	const char			*name;
	const char			*label;
	//此结构定义对器件原始数据操作的函数
	const struct iio_info		*info;
	clockid_t			clock_id;
	struct mutex			info_exist_lock;
	const struct iio_buffer_setup_ops	*setup_ops;
	//通过此成员将iio设备定义为标准字符设备
	struct cdev			chrdev;
#define IIO_MAX_GROUPS 6
	const struct attribute_group	*groups[IIO_MAX_GROUPS + 1];
	int				groupcounter;
	unsigned long			flags;
	void				*priv;
};

struct iio_info

定义于include/linux/iio/iio.h
定义操作通道原始数据的接口;
定义操作通道事件的接口;

struct iio_chan_spec

定义于include/linux/iio/iio.h
对器件通道类型定义;
如定义dht11温湿度传感器的温度和湿度通道;
成员enum iio_chan_type定义了iio支持的一些通道类型可以满足大多数场景;

struct iio_buffer

include/linux/iio/buffer_impl.h;
数据buffer的结构定义;

struct iio_trigger

定义于include/linux/iio/trigger.h;
使用trigger方式时,分配iio_dev的此类型成员;

struct file_operations iio_buffer_fileops

定义于industrialio-core.c;
以iio_dev的成员struct cdev chrdev注册为字符设备时,绑定的操作集;

五、驱动使用iio子系统的步骤

DHT11温湿度传感器直接模式

1、定义设备驱动

这里定义为平台设备驱动,并定义兼容属性表用于probe函数执行
static const struct of_device_id dht11_dt_ids[] = {
{ .compatible = “dht11”, },
{ }
};
static struct platform_driver dht11_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = dht11_dt_ids,
},
.probe = dht11_probe,
};

2、自定义设备结构体

不同的传感器按传感器实际特性定义
struct dht11 {
struct device *dev;
struct gpio_desc gpiod;
int irq;
struct completion completion;
/
The iio sysfs interface doesn’t prevent concurrent reads: /
struct mutex lock;
s64 timestamp;
int temperature;
int humidity;
/
num_edges: -1 means “no transmission in progress” */
int num_edges;
struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
};

3、定义通道

static const struct iio_chan_spec dht11_chan_spec[] = {
{ .type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), },
{ .type = IIO_HUMIDITYRELATIVE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }
};

4、定义iio_info结构

static const struct iio_info dht11_iio_info = {
.read_raw = dht11_read_raw,
};

5、驱动的初始化

平台设备和驱动match之后,dht11_probe函数中做一些初始化将以上结构进行赋值,最后调用devm_iio_device_register,以此完成驱动的工作,剩余的工作交给了iio子系统的核心层去处理;

6、应用层获取传感器数据

方法一:通过open 、read、poll函数操作/dev/iio:device0等设备节点号获取传感器数据
方法二: 通过/sys/bus/iio/devices/*****/温度属性文件或者湿度属性文件获取数据;

其它类型传感器

同理;
可能会使用buffer、event、trigger相关模式;

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值