最佳入門教程!嵌入式必會的Linux驅(qū)動開發(fā)之IIO子系統(tǒng)
Linux 驅(qū)動開發(fā) / IIO子系統(tǒng)入門1
1. 什么是 IIO 子系統(tǒng)?
1.1 IIO 概述
1.2 IIO 相關(guān)的組件
2. IIO 功能特性
3. IIO 相關(guān)配置
3.1 配置內(nèi)核
3.2 配置設(shè)備樹
3.2.1 IIO providers
3.2.2 IIO consumers
4. IIO API
4.1 用戶空間 API
4.1.1 4種接口
4.1.2 操作實(shí)例
5. 更多值得學(xué)習(xí)的知識點(diǎn)
6. 相關(guān)參考
-
整理一些 IIO 子系統(tǒng)的入門知識。
1. 什么是 IIO 子系統(tǒng)?
1.1 IIO 概述
ADC / DAC
加速度計(jì)
磁力計(jì)
陀螺儀
壓力傳感器
濕度傳感器
溫度傳感器
...
1.2 IIO 相關(guān)的組件
char device, sysfs, configfs, debugfs。
include/linux/iio/consumer.h
IIO 子系統(tǒng)的核心實(shí)現(xiàn)。
2. IIO 的功能特性
-
Linux-4.14/drivers/staging/iio/Documentation/overview.txt
-
類似于 hwmon 子系統(tǒng),它們都可以通過 sysfs 以輪循的方式訪問設(shè)備;
-
類似于 input 子系統(tǒng),iio 子系統(tǒng)也可以向應(yīng)用層上報(bào)事件(hardware triggered events),例如閾值檢測事件,自由落體檢測事件、更復(fù)雜的動作檢測事件;
-
目前 event 的格式為:event code + 時間戳;
3. IIO 相關(guān)配置
3.1 配置內(nèi)核
$ make menuconfig
Device Drivers --->
<*> Industrial I/O support --->
[*] Enable buffer support within IIO
< > IIO callback buffer used for push in-kernel interfaces
<*> Industrial I/O HW buffering
<*> Industrial I/O buffering based on kfifo
< > Enable IIO configuration via configfs
[*] Enable triggered sampling support
(2) Maximum number of consumers per trigger
< > Enable software triggers support
Accelerometers --->
Analog to digital converters --->
Amplifiers --->
Chemical Sensors --->
Hid Sensor IIO Common ----
SSP Sensor Common --->
Digital to analog converters --->
IIO dummy driver --->
Frequency Synthesizers DDS/PLL --->
Digital gyroscope sensors --->
Health Sensors --->
Humidity sensors --->
Inertial measurement units --->
Light sensors --->
Magnetometer sensors --->
Inclinometer sensors ----
Triggers - standalone --->
Digital potentiometers --->
Pressure sensors --->
Lightning sensors --->
Proximity sensors --->
Temperature sensors --->
3.2 配置設(shè)備樹
-
Linux-4.14/Documentation/devicetree/bindings/iio/iio-bindings.txt
3.2.1 IIO providers
-
IIO channels 源在設(shè)備樹中用 IIO providers 來指定;
-
io-channel-cells,0 表示只有 1 路 IIO output,1 表示有多路 IIO output;
-
io-channel-ranges: 一個 empty 屬性(即不用賦值),會在 driver/iio/inkern.c/iio_channel_get() 中被引用,它表明繼承了當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)可以引用當(dāng)前節(jié)點(diǎn)的 IIO channel;
adc: voltage-sensor@ 35 {
compatible = "maxim,max1139";
reg = < 0x35>;
#io-channel-cells = <1>;
};
adc@ 35 {
compatible = "some-vendor,some-adc";
reg = < 0x35>;
adc1: iio-device@ 0 {
#io-channel-cells = <1>;
/* other properties */
};
adc2: iio-device@ 1 {
#io-channel-cells = <1>;
/* other properties */
};
};
3.2.2 IIO consumers
-
IIO consumer 節(jié)點(diǎn)的形式是
<phandle iio_specifier>
; -
它的作用是連接 IIO provider 的 input 端到 IIO consumer 的 output 端;
-
其中,phandle 是 IIO provider 的句柄,specifier 用于選擇第幾路 channel;
-
類似 gpio specifier, IIO specifier 是有 1 個或者多個 cells 的數(shù)組,用于確定 IIO device的 output 端,即 1 個 cell 對應(yīng)一個 IIO channel output;
-
IIO specifier 數(shù)組的長度由 IIO provider 節(jié)點(diǎn)的 #io-channel-cells 屬性決定;
-
io-channels: <phandle iio_specifier> 列表, 一個 <phandle iio_specifier> 代表該設(shè)備連接著的一路 IIO input。如果 IIO provider 的 io-channel-cells=0 (即只有1路 IIO output), 則省略 iio_specifier。
-
io-channel-names: IIO input 的名稱列表,順序要和 io-channels 屬性保持一致,Consumers drivers 會將該名稱和 iio_specifier 指定的 IIO input match 到一起。
some_consumer {
io-channels = <&adc 1>, <&ref 0>;
io-channel-names = "vcc", "vdd";
};
4. IIO API
4.1 用戶空間 API
-
IIO user space interface -
How to use the IIO user space interface
4.1.1 4種接口
-
/sys/bus/iio/devices/iio:deviceX;
-
可用于配置 /dev/iio:deviceX 接口的 events / data
-
可用于輪循的方式低速地直接讀/寫 IIO 設(shè)備;
-
Documentation/ABI/testing/sysfs-bus-iio;
-
/dev/iio:deviceX,該接口在 IIO 子系統(tǒng)里是可選非必要的;
-
標(biāo)準(zhǔn)的文件 IO API: open(), read(), write(), close().
-
用于讀取 events 和 data;
-
用于配置額外的 IIO 特性,例如:軟件 triggers 或者 hrtimer triggers;
-
詳細(xì)說明:
-
Documentation/ABI/testing/configfs-iio; -
Documentation/iio/iio_configfs.txt;
-
一些調(diào)試功能,例如 direct_reg_access 節(jié)點(diǎn)可用于讀寫寄存器;
4.1.2 操作實(shí)例
1) 直接讀 ADC
確定 sysfs 節(jié)點(diǎn)(方式1,不依賴工具)
$ grep -H "" /sys/bus/iio/devices /*/name | grep adc
/sys/bus/iio/devices/iio:device0/name:48003000.adc:adc@0
/sys/bus/iio/devices/iio:device1/name:48003000.adc:adc@1
$ cd /sys/bus/iio/devices/iio:device0/
$ cat in_voltage6_raw # Convert ADC1 channel 0 (analog-to-digital): get raw value
40603
$ cat in_voltage_scale # Read scale
0.044250488
$ cat in_voltage_offset # Read offset
0
$ awk "BEGIN{printf (\"%d\n\", (40603 + 0) * 0.044250488)}"
1796
確定 sysfs 節(jié)點(diǎn)(方式2)
$ lsiio | grep dac
Device 003: 40017000.dac:dac@ 1
Device 004: 40017000.dac:dac@ 2
$ cd /sys/bus/iio/devices/iio:device3/
$ cat out_voltage1_scale # Read scale
0.708007812
$ awk "BEGIN{printf (\"%d\n\", 2000 / 0.708007812)}" # 假設(shè)要輸出 2000 mV
2824
$ echo 2824 > out_voltage1_raw # Write raw value to DAC1
$ echo 0 > out_voltage1_powerdown # Enable DAC1 (out of power-down mode)
5. 更多值得學(xué)習(xí)的知識點(diǎn)
-
以 timer triggers 和 buffers 的方式讀 ADC 或者寫 DAC; -
IIO 內(nèi)核空間 API; -
編寫 IIO device driver -
編寫 IIO consumer driver -
...
6. 相關(guān)參考
-
IIO Overview -
Linux Industrial I/O Subsystem -
《Linux Device Drivers Development》
本文授權(quán)轉(zhuǎn)載自公眾號“嵌入式Hacker”,作者吳偉東Jack
-END-
推薦閱讀
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!