7.3.5. 设计说明

7.3.5.1. 源码说明

源代码位于:drivers/iio/adc/zx_adc.c

7.3.5.2. 模块架构

IIO

工业I/O,是Linux内核中专用于处理模数转换器(ADC)和数模转换器(DAC)的子系统,最初创建于2009年,提供了统一的框架来访问和控制各种类型的传感器,并且为用户态提供了标准的接口。

目前IIO支持的设备类型包括:ADC/DAC、加速度计、磁力计、陀螺仪、电流/电压测量芯片、压力传感器、温度传感器、湿度传感器、光传感器、压力传感器等。

整个IIO软件框架可抽象为下图:

../../../_images/sw_system.png

图 7.28 Linux IIO子系统架构图

  • IIO设备会提供字符设备(支持触发缓冲区)和Sysfs节点作为用户态的访问接口;

  • 一般情况下,每个通道对应一个sysfs节点文件;

  • 用户空间的设备文件名举例:
    • /sys/bus/iio/iio:deviceX/

    • /dev/iio:deviceX

7.3.5.3. 关键流程设计

7.3.5.3.1. 初始化流程

GPAI 模块完全遵循platform_driver的通用初始化流程,申请regs资源、clk、reset,还需要注册一个iio设备,使用iio子系统提供的注册接口iio_device_register():

#define iio_device_register(indio_dev) \
    __iio_device_register((indio_dev), THIS_MODULE)

参数indio_dev是一个struct iio_dev类型的指针,其中关键信息有:设备名称、通道数目、一组iio的操作集(struct iio_info)、通道配置信息等。在iio_info中,我们暂时只实现了一个read接口:

static const struct iio_info aic_gpai_iio_info = {
    .read_raw = aic_gpai_read_raw,
};

7.3.5.3.2. 中断处理流程

GPAI支持使用中断方式来读取数据,这样避免软件去做等待处理。

../../../_images/gpai_irq_flow.png

图 7.29 GPAI 非周期模式的数据采集流程

  • 对于非周期模式:当用户层触发read_raw()接口,就会启动一次硬件去读数据

  • 当硬件准备好数据,会产生一个中断

  • 在中断处理函数中,用INT Flag来区分是哪个通道有数据,逐个通道扫描将数据读出,会缓存到一个全局变量中

  • 对于周期模式:GPAI控制器会自动按给定周期产生一次数据中断

注意

周期模式时,当周期值太小,比如 < 10ms,会增加系统的调度负担。

备注

TODO:目前,当产生高电平、低电平告警的时候,只是驱动中打印警告信息,暂未做其他处理。

7.3.5.4. 数据结构设计

7.3.5.4.1. aic_gpai_data

记录各个通道的数据信息:

struct aic_gpai_data {
    int             num_bits;
    const struct iio_chan_spec  *channels;
    int             num_channels;
    u32             fifo_depth[AIC_GPAI_MAX_CH];
};

7.3.5.4.2. aic_gpai_ch

记录各个通道的配置信息:

struct aic_gpai_ch {
    u32 id;
    bool available;
    enum aic_gpai_mode mode;
    u16 latest_data;
    u16 fifo_thd;
    u32 smp_period;

    bool hla_enable; // high-level alarm
    u16 hla_thd;
    u16 hla_rm_thd;
    bool lla_enable; // low-level alarm
    u16 lla_thd;
    u16 lla_rm_thd;

    struct completion complete;
};

7.3.5.4.3. aic_gpai_dev

管理GPAI控制器的设备资源:

struct aic_gpai_dev {
    struct platform_device      *pdev;
    void __iomem            *regs;
    struct clk          *clk;
    struct reset_control        *rst;
    u32             irq;
    u32             pclk_rate;

    struct aic_gpai_ch      chan[AIC_GPAI_MAX_CH];
    const struct aic_gpai_data  *data;
};

7.3.5.5. 接口设计

7.3.5.5.1. aic_gpai_read_raw

函数原型

static int aic_gpai_read_raw(struct iio_dev *iodev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)

功能说明

读取一个ADC通道的当前数据

参数定义

iodev - 指向一个iio设备
chan - 当前ADC通道的配置信息
val - 用于保存读取到的数据
val2 - 用于保存读取到的数据,用于和val做数据组合,部分mask类型需要
mask - 数据类型

返回值

0,成功; < 0,失败

注意事项