lINUX驱动之IIO设备数据结构

一、IIO子系统各数据结构说明

IIO子系统大概包含几个主要的部分
对于连续数据采集相关功能,主要由iio buffer实现;
连续数据采集的触发机制,主要由iio trigger实现;
IIO device的事件触发机制,主要由iio event实现;
提供单次原始数据的采集功能,主要通过syfs属性文件实现。
iio子系统中,主要包括如下几个数据结构:

struct iio_dev,描述一个iio device
struct iio_event_interface,描述iio device的事件触发模块的数据结构;
struct iio_buffer,描述iio device连续数据采集功能相关的数据结构;
struct iio_trigger,描述iio device的trigger机制相关的数据结构
struct iio_chan_spec,描述iio device的一个通道的属性信息;
struct iio_info,描述iio device各通道的原始数据读取接口、event使能与event参数读写相关接口、trigger有效性检测接口、设备树节点解析等接口;
struct iio_buffer_setup_ops,描述iio buffer使能与否的接口(建立iio buffer与iio tigger的关联,从而保证iio trigger触发后,可将数据刷新到对应的iio buffer中);
struct iio_chan_spec_ext_info,描述一个channel扩展属性相关的信息,包括属性名称、读写接口等
struct iio_trigger_ops,表示iio trigger的操作接口,包括设置trigger的状态(使能与否)、重新使能trigger、设备有效性判断等接口;
struct iio_buffer_access_funcs,描述iio buffer的access接口,包括数据写入到iio buffer的缓存、缓存数据是否有效、从缓存中读取数据等等接口。

二、数据结构

struct iio_dev
</include/linux/iio/iio.h>
/*DIRECT_MODE表示不对采集数据进行缓存,可直接读取单次的数据(可通过访问sysfs下的属性文件方式,读取数据);
 *INDIO_BUFFER_XXX表示支持对iio device采集数据进行缓存的模式,可理解为采集连续的数据(这些数据则需要通过
 *访问字符设备文件进行读取);
 *NDIO_EVENT_TRIGGRED则主要表示事件触发功能,如针对温度传感器可监控当前温度是否超过温度告警上限或下限,
 *当出现温度告警后则向SOC发送中断信号,若支持这类功能则增加INDIO_EVENT_TRIGGRED模式的支持即可。*/
#define INDIO_DIRECT_MODE       0x01 
#define INDIO_BUFFER_TRIGGERED      0x02
#define INDIO_BUFFER_SOFTWARE       0x04
#define INDIO_BUFFER_HARDWARE       0x08//设备具有硬件缓冲区
#define INDIO_EVENT_TRIGGERED       0x10
#define INDIO_HARDWARE_TRIGGERED    0x20
</include/linux/iio/iio.h>
struct iio_dev {
    int             id;
    struct module           *driver_module;
    int             modes;//表示设备支持的不同模式
    int             currentmode;//设备实际使用的模式
    struct device           dev;//IIO设备绑定的设备
    struct iio_event_interface  *event_interface;//事件相关的数据结构
    struct iio_buffer       *buffer;//该iio device对应的iio buffer
    struct list_head        buffer_list;
    //表示单次采集数据的长度,该值主要根据当前active channel的个数、每一个通道采集数据的长度计算而得
    int             scan_bytes;
    struct mutex            mlock;
    const unsigned long     *available_scan_masks;//表示当前iio device可使用的channel的掩码
    unsigned            masklength;
    const unsigned long     *active_scan_mask;//已启用通道的位掩码
    bool                scan_timestamp;// 对于通过buffer采集的数据是否需要时间戳
    unsigned            scan_index_timestamp;
    struct iio_trigger      *trig;//当前设备的触发器
    bool                trig_readonly;
    struct iio_poll_func        *pollfunc;//为buffer的中断处理函数的接口信息
    struct iio_poll_func        *pollfunc_event;//为event的中断处理函数的接口信息,基本不用
    struct iio_chan_spec const  *channels;//所有channel相关的参数信息
    int             num_channels;//指定通道数量
    struct list_head        channel_attr_list;//包含了IIO子系统为所有channel创建的动态属性
    struct attribute_group      chan_attr_group;
    const char          *name;//设备名称
    const struct iio_info       *info;//来自驱动程序的回调和常量信息
    clockid_t           clock_id;
    struct mutex            info_exist_lock;
    //启用/禁用缓冲区之前和之后调用的一组回调函数
    const struct iio_buffer_setup_ops   *setup_ops;//建立buffer与trigger的关联
    struct cdev         chrdev;//IIO内核创建的相关字符设备
#define IIO_MAX_GROUPS 6
    const struct attribute_group    *groups[IIO_MAX_GROUPS + 1];
    int             groupcounter;
    unsigned long           flags;
#if defined(CONFIG_DEBUG_FS)
    struct dentry           *debugfs_dentry;
    unsigned            cached_reg_addr;
#endif
};
struct iio_event_interface
struct iio_event_interface {
    /*当应用程序读取触发事件信息时,若当前无数据可读,则将当前进程加入到该等待队列,
     *待调用iio_push_event将触发事件信息加入kfifo后,则wakeup该队列中的进程*/
    wait_queue_head_t   wait;
    DECLARE_KFIFO(det_events, struct iio_event_data, 16);//定义kfifo,存储所有触发的事件信息,供应用程序获取
    /*将even子模块动态定义的event attribute均添加至该链表中(属性名称格式为
    *{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_{ev_type}_{ev_dir}_{ev_info})*/
    struct list_head    dev_attr_list;
    //标记该event是否已使能,(即应用程序是否通过ioctl调用创建一个匿名fd,若使能则置位IIO_BUSY_BIT_POS)
    unsigned long       flags; 
    struct attribute_group  group;
    struct mutex        read_lock;
};

三、IIO_buffer与struct iio_buffer_setup_ops

对struct iio_buffer_access_funcs则是该iio_buffer对应的缓存空间的访问访问,目前使用kfifo缓存数据,则其访问方法为iio_store_to_kfifo、iio_read_first_n_kfifo等,主要是将数据存储至kfifo或从kfifo中取出缓存数据等

struct iio_trigger与struct iio_trigger_ops
这两个数据结构主要实现iio 的trigger机制
</include/linux/iio/trigger.h>
struct iio_trigger {
    const struct iio_trigger_ops    *ops;
    struct module           *owner;
    int             id;
    const char          *name;
    struct device           dev;
    struct list_head        list;
    struct list_head        alloc_list;
    atomic_t            use_count;
    /*主要用于创建虚拟的irq chip,在trigger内部,当多个trigger consumer注册时,
    *则trigger内部会为其分配一个虚拟的irq,并根据trigger consumer提供给pollfunc,
    *为该irq注册中断处理函数,这样当该trigger触发后,则会遍历所有该trigger上已注
    *册的虚拟irq,调用其中断处理函数从而执行trigger consumer提供的处理函数*/
    struct irq_chip         subirq_chip;
    int             subirq_base;
    struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER];
    unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)];
    
    struct mutex            pool_lock;
    bool                attached_own_device;
};
struct iio_trigger_ops {
    int (*set_trigger_state)(struct iio_trigger *trig, bool state);//设置trigger的状态(使能与否)
    int (*try_reenable)(struct iio_trigger *trig);//重新使能
    //如实现的trigger只允许父device相同的iio device绑定,则可以实现该接口进行限制操作
    int (*validate_device)(struct iio_trigger *trig,
                   struct iio_dev *indio_dev);
};

四、struct iio_chan_spec

</include/linux/iio/iio.h>
    
struct iio_chan_spec {
    enum iio_chan_type  type;//指出通道产生的测量类型,包括IIO_TEMP、IIO_VOLTAGE等
    int         channel;//当indexed设置为1时,指定通道索引
    int         channel2;//当.modfied设置为1时,指定通道修饰符
    unsigned long       address;
    int         scan_index;//表示采集数据的index及数据的类型等(这两个变量主要由buffer使用)
    struct {//负责确定如何将通道的值存储到缓冲区中的元素
        char    sign;//n表示数据的符号,并匹配模式中的[s | u]
        u8  realbits;
        u8  storagebits;
        u8  shift;
        u8  repeat;
        enum iio_endian endianness; //排序
    } scan_type;
    long            info_mask_separate;//将属性标记为专属于此通道
    long            info_mask_separate_available;
    long            info_mask_shared_by_type;//将该属性标记为由相同类型的所有通道共享
    long            info_mask_shared_by_type_available;
    long            info_mask_shared_by_dir;//将该属性标记为由相同方向的所有通道共享
    long            info_mask_shared_by_dir_available;
    long            info_mask_shared_by_all;//将该属性标记为所有类型的所有通道共享
    long            info_mask_shared_by_all_available;
    const struct iio_event_spec *event_spec; //定义event相关的信息
    unsigned int        num_event_specs;
    const struct iio_chan_spec_ext_info *ext_info;
    const char      *extend_name;
    const char      *datasheet_name;
    unsigned        modified:1;
    unsigned        indexed:1;//指出通道属性名称是否具有索引
    unsigned        output:1;
    unsigned        differential:1;
}; 

五、struct iio_info

该数据结构主要定义了通过syfs读写channel属性的接口,其中read_raw、write_raw可用于读取通道的raw数据等;而write_event_value则主要用于event事件触发的阈值参数的设置与读取等、而read_event_config、write_event_config则可以用于实现event的使能与否;而event_attrs、attrs则主要用于设备驱动自定义的属性参数(包括event属性参数以及iio device相关的属性参数)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值