Buffers

工業I/O核心提供了一種基於觸發源的連續資料捕獲方式。 可以從/dev/iio:deviceX字元裝置節點一次讀取多個數據通道,從而降低CPU負載。

IIO緩衝區sysfs介面

IIO緩衝區在/sys/bus/iio/devices/iio:deviceX/buffer/*下有一個關聯的屬性目錄。 以下是一些現有屬性

  • length,可以由緩衝區儲存的資料樣本總數(容量)。

  • enable,啟用緩衝區捕獲。

IIO緩衝區設定

與放置在緩衝區中的通道讀取相關的元資訊稱為掃描元素。 配置掃描元素的重要位透過/sys/bus/iio/devices/iio:deviceX/scan_elements/目錄暴露給使用者空間應用程式。 此目錄包含以下形式的屬性

  • enable,用於啟用通道。 當且僅當其屬性非時,觸發捕獲將包含此通道的資料樣本。

  • index,通道的scan_index。

  • type,描述緩衝區中掃描元素的資料儲存,因此也描述了從使用者空間讀取它的形式。 格式為[be|le]:[s|u]bits/storagebits[Xrepeat][>>shift] 。

    • bele,指定大端或小端。

    • su,指定有符號(2的補碼)或無符號。

    • bits,是有效資料位的數量。

    • storagebits,是在緩衝區中佔用的位數(填充後)。

    • repeat,指定bits/storagebits重複的次數。 當repeat元素為0或1時,則省略repeat值。

    • shift,如果指定,是在遮蔽掉未使用的位之前需要應用的位移。

例如,一個3軸加速度計的驅動程式,其12位解析度的資料儲存在兩個8位暫存器中,如下所示

  7   6   5   4   3   2   1   0
+---+---+---+---+---+---+---+---+
|D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
+---+---+---+---+---+---+---+---+

  7   6   5   4   3   2   1   0
+---+---+---+---+---+---+---+---+
|D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
+---+---+---+---+---+---+---+---+

對於每個軸,將具有以下掃描元素型別

$ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
le:s12/16>>4

使用者空間應用程式會將從緩衝區讀取的資料樣本解釋為兩位元組小端有符號資料,在遮蔽掉12個有效資料位之前需要右移4位。

為了實現緩衝區支援,驅動程式應在iio_chan_spec定義中初始化以下欄位

struct iio_chan_spec {
/* other members */
        int scan_index
        struct {
                char sign;
                u8 realbits;
                u8 storagebits;
                u8 shift;
                u8 repeat;
                enum iio_endian endianness;
               } scan_type;
       };

實現上述加速度計的驅動程式將具有以下通道定義

struct iio_chan_spec accel_channels[] = {
        {
                .type = IIO_ACCEL,
                .modified = 1,
                .channel2 = IIO_MOD_X,
                /* other stuff here */
                .scan_index = 0,
                .scan_type = {
                        .sign = 's',
                        .realbits = 12,
                        .storagebits = 16,
                        .shift = 4,
                        .endianness = IIO_LE,
                },
        }
        /* similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1)
         * and Z (with channel2 = IIO_MOD_Z, scan_index = 2) axis
         */
 }

在此, scan_index 定義了啟用通道在緩衝區中放置的順序。 具有較低 scan_index 的通道將放置在具有較高索引的通道之前。 每個通道都需要具有唯一的 scan_index

scan_index 設定為-1可用於指示特定通道不支援緩衝捕獲。 在這種情況下,不會在scan_elements目錄中為通道建立任何條目。

更多細節

int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, void *data, int64_t timestamp)

將資料和時間戳推送到緩衝區

引數

struct iio_dev *indio_dev

裝置的iio_dev結構。

void *data

樣本資料

int64_t timestamp

樣本資料的時間戳

描述

將資料推送到IIO裝置的緩衝區。 如果為裝置啟用了時間戳,則該函式會將提供的時間戳儲存為樣本資料緩衝區中的最後一個元素,然後再將其推送到裝置緩衝區。 樣本資料緩衝區需要足夠大,以容納額外的時間戳(通常緩衝區應為indio->scan_bytes位元組大)。

成功時返回0,否則返回負錯誤程式碼。

bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, const unsigned long *mask)

驗證是否只選擇了一個通道

引數

struct iio_dev *indio_dev

iio裝置

const unsigned long *mask

要檢查的掃描掩碼

描述

如果掃描掩碼中只設置了一位,則返回true,否則返回false。 它可以用於一次只能啟用一個通道進行取樣的裝置。

int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)

推送到註冊的緩衝區。

引數

struct iio_dev *indio_dev

裝置的iio_dev結構。

const void *data

完整掃描。

int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev, const void *data, size_t data_sz, int64_t timestamp)

推送到註冊的緩衝區,沒有對齊或空間要求。

引數

struct iio_dev *indio_dev

裝置的iio_dev結構。

const void *data

不包括時間戳的通道資料。

size_t data_sz

資料大小。

int64_t timestamp

樣本資料的時間戳。

描述

這個特殊的iio_push_to_buffers_with_timestamp()變體不需要時間戳的空間,也不需要資料的8位元組對齊。 但是,它確實需要在第一次呼叫時進行分配,並在所有呼叫時進行額外複製,因此如果可能,應避免使用。

struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)

獲取緩衝區的引用

引數

struct iio_buffer *buffer

要獲取引用的緩衝區,可以為NULL

描述

返回傳遞給該函式的緩衝區的指標。

void iio_buffer_put(struct iio_buffer *buffer)

釋放緩衝區的引用

引數

struct iio_buffer *buffer

要釋放引用的緩衝區,可以為NULL

int iio_device_attach_buffer(struct iio_dev *indio_dev, struct iio_buffer *buffer)

將緩衝區附加到IIO裝置

引數

struct iio_dev *indio_dev

應將緩衝區附加到的裝置

struct iio_buffer *buffer

要附加到裝置的緩衝區

描述

如果成功,則返回0,如果出錯,則返回負數。

此函式將緩衝區附加到IIO裝置。 緩衝區保持附加到裝置,直到裝置被釋放。 由於歷史原因,第一個附加的緩衝區也將分配給“indio_dev->buffer”。 此處分配的陣列將透過iio_device_detach_buffers()呼叫釋放,該呼叫由iio_device_free()處理。