介绍
架构
ADC 驱动遵循 Linux 的工业 I/O (IIO)子系统。IIO 为用户空间提供 ADC 接口。ADC 软件架构如下面的图所示。
ADC 软件架构包含以下部分:
IIO 驱动程序: ADC 驱动程序。
ADC: ADC 驱动程序。
Comparator: 比较器驱动程序,仅在 ADC 处于比较器辅助模式时使用。
IIO 定时器触发器:仅在 ADC 或比较器处于定时器触发模式时使用。
IIO 框架:IIO 子系统核心驱动程序。
IIO 用户(内核):供内核使用。
应用:用户空间使用。
libiio:Libiio 是一个用于访问 IIO 设备的开源库。它封装了对 /sys/bus/IIO/devices(配置 IIO)和 /dev/IIO/deviceX(读/写 IIO)的访问,并提供了易于测试的 IIO 命令行工具(iio_info / iio_readdev)和 iiod 服务器。有关 libiio 的源代码,请参阅 github libiio 。
Demo: 一个展示如何使用 ADC 的简单示例。
参考 kernel industrial v5.4 或 kernel industrial v6.6 获取有关 IIO 的更多细节。
实现
ADC 驱动在以下文件中实现。
文件 |
描述 |
---|---|
<linux>/drivers/rtkdrivers/adc/Kconfig |
ADC 驱动程序 Kconfig |
<linux>/drivers/rtkdrivers/adc/Makefile |
ADC 驱动程序 Makefile |
<linux>/drivers/rtkdrivers/adc/realtek-adc.c |
ADC 函数 |
<linux>/drivers/rtkdrivers/adc/realtek-adc.h |
ADC 相关的函数声明、宏定义、结构体定义以及引用的其他头文件。 |
<linux>/drivers/rtkdrivers/adc/realtek-comparator.c |
ADC 比较器函数。它在 ADC 处于比较器辅助模式时使用。 |
<linux>/drivers/rtkdrivers/adc/realtek-comparator.h |
比较器相关的函数声明、宏定义、结构体定义以及引用的其他头文件。 |
配置
设备树配置
ADC 设备树节点:
adc: adc@42012000 {
compatible = "realtek,ameba-adc";
#address-cells = <1>;
#size-cells = <1>;
#io-channel-cells = <1>;
reg = <0x42012000 0x100>,
<0x42012800 0x100>;
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc RTK_CKE_CTC>, <&rcc RTK_CKE_ADC>;
clock-names = "rtk_ctc_clk", "rtk_adc_clk";
rtk,adc-mode = <0>; // 0: Software-trigger mode, 1: Automatic mode, 2: Timer-trigger mode
rtk,adc-timer-period = <200000000>; // Useful only in timer-trigger mode. Unit: ns. Range: 100ms~2s
//rtk,adc-channels = <0>, <1>, <2>, <6>;
//rtk,adc-diff-channels = <4 5>;
nvmem-cells = <&adc_normal_cal>, <&adc_vbat_cal>;
nvmem-cell-names = "normal_cal", "vbat_cal";
status = "disabled";
comparator: comparator@0 {
compatible = "realtek,ameba-comparator";
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
rtk,cmp-ref0 = <10>;
rtk,cmp-ref1 = <30>;
};
};
ADC 的设备树配置在下表中列出。
属性 |
描述 |
默认值 |
可配置 |
---|---|---|---|
compatible |
ADC描述符 |
“realtek,ameba-adc” |
否 |
reg |
ADC的硬件地址和大小 |
<0x42012000 0x100> |
否 |
reg |
比较器的硬件地址和大小 |
<0x42012800 0x100> |
否 |
interrupts |
ADC的GIC编号 |
<GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH> |
否 |
interrupts |
比较强的GIC编号 |
<GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH> |
否 |
clocks |
ADC的时钟 |
<&rcc RTK_CKE_CTC> and <&rcc RTK_CKE_ADC> |
否 |
rtk,adc-mode |
ADC比较模式
|
0/1/2/3 |
|
rtk,adc-timer-period |
ADC定时器周期 只在比较器辅助模式时使用。 单位:纳秒。 范围: 100ms~2s |
||
nvmem-cells |
ADC的nvmem单元 |
||
nvmem-cell-names |
ADC的nvmem单元的名称 |
||
status |
是否启用该设备
|
||
rtk,cmp-ref0 |
比较器内部参考电压 0 |
0~31 |
|
rtk,cmp-ref1 |
比较器内部参考电压 1 |
0~31 |
备注
当选择 ADC 定时器触发模式时,必须进行以下配置。
rtk,adc-mode = <2>;
在
realtek-adc.c
中的参数 realtek_adc_cfg 中选择的定时器索引,其对应的定时器设备树节点状态必须设置为 okay。只有当
rtk,adc-mode = <3>
时,比较器子节点才会被填充。当选择比较器定时器触发模式时,必须进行以下配置。
rtk,adc-mode = <3>;
在
realtek-comparator.c
中的参数 realtek_comp_priv_info 中选择的定时器索引,其对应的定时器设备树节点状态必须设置为 okay。
编译配置
按顺序选择
:
APIs
官方文件: kernel API guide v5.4 或 kernel API guide v6.6 。
用户空间 API
Sysfs 接口
接口 |
介绍 |
---|---|
/sys/bus/iio/devices/iio:deviceX |
配置并启用 IIO 设备。 |
/sys/bus/iio/devices/triggerX |
配置并启用 IIO 触发器。 |
更多有关 API 的细节请参考 <linux>/Documentation/ABI/testing/sysfs-bus-iio
。
用户空间 ADC 的演示在 <test>/adc
。
ADC 示例
该演示是一个用于读取单个 ADC 样本数据的简单示例。
打开 ADC 单通道原始读取功能
sprintf(dev_name, "/sys/bus/iio/devices/iio:device0/in_voltage%d_raw", adc_ch); fd = open(dev_name, O_RDONLY);
单次读取 ADC 样本数据
read(fd, buffer, 4);
将读取的数据从字符转换为整型(int)
value = atoi(buffer);
该值是 ADC 单次读取的数据。
ADC 单次读取示例
获取单个原始样本数据
cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw
获取 ADC 偏置
cat /sys/bus/iio/devices/iio:device0/in_voltage_offset
获取 ADC 量程
cat /sys/bus/iio/devices/iio:device0/in_voltage_scale
获取 ADC 差分偏置
cat /sys/bus/iio/devices/iio:device0/in_voltage-voltage_offset
获取 ADC 差分量程
cat /sys/bus/iio/devices/iio:device0/in_voltage-voltage_scale
ADC 缓存读取示例
读取 ADC 缓冲区的步骤如下:
创建触发器
echo 0 > /sys/devices/iio_sysfs_trigger/add_trigger
备注
0 是我们需要分配给触发器的索引。
将触发器分配给设备
echo sysfstrig0 > /sys/bus/iio/devices/iio:device0/trigger/ current_trigger
备注
由于我们使用 0 作为索引,因此触发器将被命名为 sysfstrig0。
启用扫描元素:选择其数据值将被推入缓冲区的通道
echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage1_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage2_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage6_en
设置缓存大小
echo 100 > /sys/bus/iio/devices/iio:device0/buffer/length
启用缓存
echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable
启用触发器:开始采集
echo 1 > /sys/bus/iio/devices/trigger0/trigger_now
关闭缓存
echo 0 > /sys/bus/iio/devices/iio:device0/buffer/enable
字符设备
接口 |
介绍 |
---|---|
/dev/iio:deviceX |
访问配置的事件和数据。 |
内核空间 API
用途
接口 |
介绍 |
---|---|
iio_read_channel_raw |
从指定的通道读取。 |
iio_convert_raw_to_processed |
将原始值转换为处理后的值。 |
iio_read_channel_attribute |
从设备属性中读取值。 |
iio_read_channel_offset |
读取通道的偏置。 |
iio_read_channel_scale |
读取通道的缩放值。 |
iio_read_channel_processed |
从指定通道读取处理后的值。 |
iio_get_channel_type |
获取通道的类型。 |
配置文件系统
接口 |
介绍 |
---|---|
iio_sw_trigger_create |
创建新触发器类型。 |
iio_sw_trigger_destroy |
终止触发器类型。 |
iio_register_sw_trigger_type |
注册新触发器类型。 |
iio_unregister_sw_trigger_type |
注销触发器类型。 |
更多有关 API 的细节请参考:
<linux>/Documentation/ABI/testing/configfs-iio
<linux>/Documentation/iio/iio_configfs.rst
调试文件系统
接口 |
介绍 |
---|---|
iio_debugfs_read_reg |
读取寄存器 |
iio_debugfs_write_reg |
写寄存器 |
simple_open |
打开 |