日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 嵌入式微處理器
[導讀]由于需要對ADC進行驅動設計,因此學習了一下Linux驅動的IIO子系統(tǒng)。本文翻譯自《Linux Device Drivers Development 》--John Madieu

直接來源:嵌入式客棧

出處:https://www.cnblogs.com/yongleili717/p/10744252.html

作者三石li

由于需要對ADC進行驅動設計,因此學習了一下Linux驅動的IIO子系統(tǒng)。本文翻譯自《Linux Device Drivers Development 》--John Madieu

IIO Framework

工業(yè)I/O(IIO)是專用于模數轉換器(ADC)和數模轉換器(DAC)的內核子系統(tǒng)。隨著越來越多的具有不同代碼實現的傳感器(具有模擬到數字或數字到模擬,功能的測量設備)分散在內核源上,收集它們變得必要。這就是IIO框架以通用的方式所做的事情。自2009年以來,Jonathan Cameron和Linux-IIO社區(qū)一直在開發(fā)它。

加速度計,陀螺儀,電流/電壓測量芯片,光傳感器,壓力傳感器等都屬于IIO系列器件。

IIO模型基于設備和通道架構:

  • 設備代表芯片本身。它是層次結構的頂級。
  • 通道代表設備的單個采集線。設備可以具有一個或多個通道。例如,加速度計是具有 ?三個通道的裝置,每個通道對應一個軸(X,Y和Z)。

IIO芯片是物理和硬件傳感器/轉換器。它作為字符設備(當支持觸發(fā)緩沖時)暴露給用戶空間,以及包含一組文件的sysfs目錄條目,其中一些文件代表通道。單個通道用單個sysfs文件條目表示。

下面是從用戶空間與IIO驅動程序交互的兩種方式:

  • /sys/bus/iio/iio:deviceX/:表示傳感器及其通道
  • /dev/iio:deviceX: 表示導出設備事件和數據緩沖區(qū)的字符設備

IIO框架架構和布局

上圖顯示了如何在內核和用戶空間之間組織IIO框架。驅動程序使用IIO核心公開的一組工具和API來管理硬件并向IIO核心報告處理。然后,IIO子系統(tǒng)通過sysfs接口和字符設備將整個底層機制抽象到用戶空間,用戶可以在其上執(zhí)行系統(tǒng)調用。

IIO API分布在多個頭文件中,如下所示:

#include?????/*?mandatory?*/
#include???/*?mandatory?since?sysfs?is?used?*/
#include??/*?For?advanced?users,?to?manage?iio?events?*/
#include??/*?mandatory?to?use?triggered?buffers?*/
#include?/*?Only?if?you?implement?trigger?in?your?driver?(rarely?used)*/

在以下文章中,我們將描述和處理IIO框架的每個概念,例如

  • 遍歷其數據結構(設備,通道等)
  • 觸發(fā)緩沖支持和連續(xù)捕獲,以及其sysfs接口
  • 探索現有的IIO觸發(fā)器
  • 以單次模式或連續(xù)模式捕獲數據
  • 列出可用于幫助開發(fā)人員測試其設備的可用工具

IIO數據結構

IIO設備在內核中表示為struct iio_dev結構體的一個實例,并由struct iio_info結構體描述。所有重要的IIO結構都在include/linux/iio/iio.h中定義。

iio_dev結構

該結構代表IIO設備,描述設備和驅動程序。它告訴我們:

  • 設備上有多少個通道?

  • 設備可以在哪些模式下運行:單次,觸發(fā)緩沖?

  • 這個驅動程序可以使用哪些hooks鉤子?

struct?iio_dev?{
???[...]
???int?modes;
???int?currentmode;
???struct?device?dev;
???struct?iio_buffer?*buffer;
???int?scan_bytes;
???const?unsigned?long?*available_scan_masks;
???const?unsigned?long?*active_scan_mask;
???bool?scan_timestamp;
???struct?iio_trigger?*trig;
???struct?iio_poll_func?*pollfunc;
???struct?iio_chan_spec?const?*channels;
???int?num_channels;
???const?char?*name;
???const?struct?iio_info?*info;
???const?struct?iio_buffer_setup_ops?*setup_ops;
???struct?cdev?chrdev;

};

完整的結構在IIO頭文件中定義。我們將不感興趣的字段在此處刪除。

  • modes: 這表示設備支持的不同模式。支持的模式有:

    • INDIO_DIRECT_MODE表示設備提供的sysfs接口。
    • INDIO_BUFFER_TRIGGERED表示設備支持硬件觸發(fā)器。使用iio_triggered_buffer_setup()函數設置觸發(fā)緩沖區(qū)時,此模式會自動添加到設備中.
    • INDIO_BUFFER_HARDWARE表示設備具有硬件緩沖區(qū)。
    • INDIO_ALL_BUFFER_MODES是上述兩者的聯(lián)合。
  • currentmode: 這表示設備實際使用的模式。

  • dev: 這表示IIO設備所依賴的struct設備(根據Linux設備型號)。

  • buffer: 這是您的數據緩沖區(qū),在使用觸發(fā)緩沖區(qū)模式時會推送到用戶空間。使用iio_triggered_buffer_setup函數啟用觸發(fā)緩沖區(qū)支持時,它會自動分配并與您的設備關聯(lián)。

  • scan_bytes: 這是捕獲并饋送到緩沖區(qū)的字節(jié)數。當從用戶空間使用觸發(fā)緩沖區(qū)時,緩沖區(qū)應至少為indio-> scan_bytes字節(jié)大。

  • available_scan_masks: 這是允許的位掩碼的可選數組。使用觸發(fā)緩沖器時,可以啟用通道捕獲并將其饋入IIO緩沖區(qū)。如果您不想允許某些通道啟用,則應僅使用允許的通道填充此數組。以下是為加速度計(帶有X,Y和Z通道)提供掃描掩碼的示例:

/*
?*?Bitmasks?0x7?(0b111)?and?0?(0b000)?are?allowed.
?*?It?means?one?can?enable?none?or?all?of?them.
?*?one?can't?for?example?enable?only?channel?X?and?Y
?*/


static?const?unsigned?long?my_scan_masks[]?=?{0x7,?0};
indio_dev->available_scan_masks?=?my_scan_masks;
  • active_scan_mask: 這是啟用通道的位掩碼。只有來自這些通道的數據能被推入緩沖區(qū)。例如,對于8通道ADC轉換器,如果只啟用第一個(0),第三個(2)和最后一個(7)通道,則位掩碼將為0b10000101(0x85)。active_scan_mask將設置為0x85。然后,驅動程序可以使用for_each_set_bit宏遍歷每個設置位,根據通道獲取數據,并填充緩沖區(qū)。

  • scan_timestamp: 這告訴我們是否將捕獲時間戳推入緩沖區(qū)。如果為true,則將時間戳作為緩沖區(qū)的最后一個元素。時間戳大8字節(jié)(64位)。

  • trig: 這是當前設備觸發(fā)器(支持緩沖模式時)。

  • pollfunc:這是在接收的觸發(fā)器上運行的函數。

  • channels: 這表示通道規(guī)范結構,用于描述設備具有的每個通道。

  • num_channels: 這表示通道中指定的通道數。

  • name: 這表示設備名稱。

  • info: 來自驅動程序的回調和持續(xù)信息。

  • setup_ops: 啟用/禁用緩沖區(qū)之前和之后調用的回調函數集。這個結構在include / linux / iio / iio.h中定義,如下所示:

struct?iio_buffer_setup_ops?{
????int?(*?preenable)?(struct?iio_dev?*);
????int?(*?postenable)?(struct?iio_dev?*);
????int?(*?predisable)?(struct?iio_dev?*);
????int?(*?postdisable)?(struct?iio_dev?*);
????bool?(*?validate_scan_mask)?(struct?iio_dev?*indio_dev,
?????????????????????????????????const?unsigned?long?*scan_mask);
};
  • setup_ops: 如果未指定,則IIO內核使用drivers / iio / buffer / industrialio-triggered-buffer.c中定義的缺省iio_triggered_buffer_setup_ops。

  • chrdev: 這是由IIO核心創(chuàng)建的關聯(lián)字符設備。

用于為IIO設備分配內存的函數是iio_device_alloc():

struct?iio_dev?*?iio_device_alloc(int?sizeof_priv)?
///struct?iio_dev?*devm_iio_device_alloc(struct?device?*dev,?int?sizeof_priv)
/*?Resource-managed?iio_device_alloc()*/
/*Managed?iio_device_alloc.?iio_dev?allocated?with?this?function?is?automatically?freed?on?driver?detach.
If?an?iio_dev?allocated?with?this?function?needs?to?be?freed?separately,?devm_iio_device_free()?must?be?used.?*/

dev是為其分配iio_dev的設備,sizeof_priv是用于為任何私有結構分配的內存空間。這樣,傳遞每個設備(私有)數據結構非常簡單。如果分配失敗,該函數返回NULL:

struct?iio_dev?*indio_dev;
struct?my_private_data?*data;
indio_dev?=?iio_device_alloc(sizeof(*data));
if?(!indio_dev)
??????????return?-ENOMEM;
/*data?is?given?the?address?of?reserved?momory?for?private?data?*/
data?=?iio_priv(indio_dev);

在分配IIO設備存儲器之后,下一步是填充不同的字段。完成后,必須使用iio_device_register函數向IIO子系統(tǒng)注冊設備:

int?iio_device_register(struct?iio_dev?*indio_dev)
???????//devm_iio_device_register(dev,?indio_dev)
/*?Resource-managed?iio_device_register()?*/

在執(zhí)行此功能后,設備將準備好接受來自用戶空間的請求。反向操作(通常在釋放函數中完成)是iio_device_unregister():

void?iio_device_unregister(struct?iio_dev?*indio_dev)
//?void?devm_iio_device_unregister(struct?device?*?dev,?struct?iio_dev?*?indio_dev)

一旦取消注冊,iio_device_alloc分配的內存可以用iio_device_free釋放:

void?iio_device_free(struct?iio_dev?*iio_dev)
//?void?devm_iio_device_free(struct?device?*?dev,?struct?iio_dev?*?iio_dev)

給定IIO設備作為參數,可以通過以下方式檢索私有數據:

?struct?my_private_data?*the_data?=?iio_priv(indio_dev);

iio_info結構體

struct iio_info結構用于聲明IIO內核使用的鉤子,以讀取/寫入通道/屬性值:

struct?iio_info?{
???????????struct?module?*driver_module;
????????????const?struct?attribute_group?*attrs;
????????????int?(*read_raw)(struct?iio_dev?*indio_dev,
???????????????struct?iio_chan_spec?const?*chan,
???????????????int?*val,?int?*val2,?long?mask);

????????????int?(*write_raw)(struct?iio_dev?*indio_dev,

????????????????struct?iio_chan_spec?const?*chan,

????????????????int?val,?int?val2,?long?mask);
?????????????[...]

};
  • driver_module: 這是用于確保chrdev正確擁有的模塊結構,通常設置為THIS_MODULE。

  • attrs: 這表示設備屬性。

  • read_raw: 這是用戶讀取設備sysfs文件屬性時的回調運行。mask參數是一個位掩碼,它允許我們知道請求了哪種類型的值。channel參數讓我們知道相關的通道。它可以是采樣頻率,用于將原始值轉換為可用值的比例,或原始值本身。

  • write_raw: 這是用于將值寫入設備的回調。例如,可以使用它來設置采樣頻率。

以下代碼顯示了如何設置struct iio_info結構:

static?const?struct?iio_info?iio_dummy_info?=?{
????.driver_module?=?THIS_MODULE,
????.read_raw?=?&iio_dummy_read_raw,
????.write_raw?=?&iio_dummy_write_raw,
[...]

/*
?*?Provide?device?type?specific?interface?functions?and
?* constant data. 提供設備類型特定的接口功能和常量數據。
?*/

indio_dev->info?=?&iio_dummy_info;

IIO channels

通道代表單條采集線。例如加速度計具有3個通道(X,Y,Z),因為每個軸代表單個采集線。struct iio_chan_spec是表示和描述內核中單個通道的結構:

?struct?iio_chan_spec?{
????????enum?iio_chan_type?type;
????????int?channel;
????????int?channel2;
????????unsigned?long?address;
????????int?scan_index;
????????struct?{
????????????charsign;
????????????u8?realbits;
????????????u8?storagebits;
????????????u8?shift;
????????????u8?repeat;
????????????enum?iio_endian?endianness;
????????}?scan_type;
????????long?info_mask_separate;
????????long?info_mask_shared_by_type;
????????long?info_mask_shared_by_dir;
????????long?info_mask_shared_by_all;
????????const?struct?iio_event_spec?*event_spec;
????????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;

????};

各個參數意義:

  • type: 這指定了通道的測量類型。在電壓測量的情況下,它應該是IIO_VOLTAGE。對于光傳感器,它是IIO_LIGHT。對于加速度計,使用IIO_ACCEL。所有可用類型都在include / uapi / linux / iio / types.h中定義,如enum iio_chan_type。要為給定轉換器編寫驅動程序,請查看該文件以查看每個通道所屬的類型。

  • channel: 這指定.indexed設置為1時的通道索引。

  • channel2: 這指定.modified設置為1時的通道修飾。

  • modified: 這指定是否將修飾符應用于此通道屬性名稱。在這種情況下,修飾符設置在.channel2中。(例如,IIO_MOD_X,IIO_MOD_Y,IIO_MOD_Z是關于xyz軸的軸向傳感器的修改器)。可用修飾符列表在內核IIO頭中定義為枚舉iio_modifier。修飾符只會破壞sysfs中的通道屬性名稱,而不是值。

  • indexed: 這指定通道屬性名稱是否具有索引。如果是,則在.channel字段中指定索引。

  • scan_index and scan_type: 當使用緩沖區(qū)觸發(fā)器時,這些字段用于標識緩沖區(qū)中的元素。scan_index設置緩沖區(qū)內捕獲的通道的位置。具有較低scan_index的通道將放置在具有較高索引的通道之前。將.scan_index設置為-1將阻止通道進行緩沖捕獲(scan_elements目錄中沒有條目)。

暴露給用戶空間的通道sysfs屬性以位掩碼的形式指定。根據共享信息,可以將屬性設置為以下掩碼之一:

  • info_mask_separate 將屬性標記為特定于此通

  • info_mask_shared_by_type 將該屬性標記為由相同類型的所有通道共享。導出的信息由相同類型的所有通道共享。

  • info_mask_shared_by_dir 將屬性標記為由同一方向的所有通道共享。導出的信息由同一方向的所有通道共享。

  • info_mask_shared_by_all 將屬性標記為所有通道共享,無論其類型或方向如何。導出的信息由所有渠道共享。用于枚舉這些屬性的位掩碼都在include / linux / iio / iio.h中定義:

enum?iio_chan_info_enum?{
????IIO_CHAN_INFO_RAW?=?0,
????IIO_CHAN_INFO_PROCESSED,
????IIO_CHAN_INFO_SCALE,
????IIO_CHAN_INFO_OFFSET,
????IIO_CHAN_INFO_CALIBSCALE,
????[...]
????IIO_CHAN_INFO_SAMP_FREQ,
????IIO_CHAN_INFO_FREQUENCY,
????IIO_CHAN_INFO_PHASE,
????IIO_CHAN_INFO_HARDWAREGAIN,
????IIO_CHAN_INFO_HYSTERESIS,
????[...]
};

字節(jié)序字段應為以下之一:

enum?iio_endian?{
??????IIO_CPU,
??????IIO_BE,
??????IIO_LE,
};

通道屬性命名約定

屬性的名稱由IIO核心自動生成,具有以下模式:{direction} _ {type} _ {index} _ {modifier} _ {info_mask}:

  • direction方向對應于屬性方向,根據drivers / iio / industrialio-core.c中的struct iio_direction結構:
static?const?char?*?const?iio_direction[]?=?{
???[0]?=?"in",
???[1]?=?"out",?
};?
  • type對應于通道類型,根據char數組const iio_chan_type_name_spec:
static?const?char?*?const?iio_chan_type_name_spec[]?=?{
???[IIO_VOLTAGE]?=?"voltage",
???[IIO_CURRENT]?=?"current",
???[IIO_POWER]?=?"power",
???[IIO_ACCEL]?=?"accel",
???[...]
???[IIO_UVINDEX]?=?"uvindex",
???[IIO_ELECTRICALCONDUCTIVITY]?=?"electricalconductivity",
???[IIO_COUNT]?=?"count",
???[IIO_INDEX]?=?"index",
???[IIO_GRAVITY]??=?"gravity",
};
  • lindex 索引模式取決于是否設置了通道.indexed字段。如果設置,索引將從.channel字段中獲取,以替換{index}模式。
  • modifier 模式取決于通道所設置的.modified字段。如果設置,修飾符將從.channel2字段中獲取,{modifier}模式將根據char數組struct iio_modifier_names結構替換:
static?const?char?*?const?iio_modifier_names[]?=?{
???[IIO_MOD_X]?=?"x",
???[IIO_MOD_Y]?=?"y",
???[IIO_MOD_Z]?=?"z",
???[IIO_MOD_X_AND_Y]?=?"x&y",
???[IIO_MOD_X_AND_Z]?=?"x&z",
???[IIO_MOD_Y_AND_Z]?=?"y&z",
???[...]
???[IIO_MOD_CO2]?=?"co2",
???[IIO_MOD_VOC]?=?"voc",
};

l info_mask取決于char數組iio_chan_info_postfix中的通道信息掩碼,私有或共享索引值:

/*?relies?on?pairs?of?these?shared?then?separate依賴于這些共享的對,然后分離*/
static?const?char?*?const?iio_chan_info_postfix[]?=?{
???[IIO_CHAN_INFO_RAW]?=?"raw",
???[IIO_CHAN_INFO_PROCESSED]?=?"input",
???[IIO_CHAN_INFO_SCALE]?=?"scale",
???[IIO_CHAN_INFO_CALIBBIAS]?=?"calibbias",
???[...]
???[IIO_CHAN_INFO_SAMP_FREQ]?=?"sampling_frequency",
???[IIO_CHAN_INFO_FREQUENCY]?=?"frequency",
???[...]
};

通道區(qū)分

當每種通道類型有多個數據通道時,您可能會遇到麻煩。困境將是:如何識別它們。有兩種解決方案:索引和修飾符。

使用索引:給定具有一個通道線的ADC器件,不需要索引。通道定義如下:

static?const?struct?iio_chan_spec?adc_channels[]?=?{
????????????????{
????????????????????????.type?=?IIO_VOLTAGE,
????????????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),

???????????????},
}

由前面描述的通道產生的屬性名稱將是in_voltage_raw。

/sys/bus/iio/iio:deviceX/in_voltage_raw

現在讓我們看一下有4個甚至8個通道的轉換器。我們如何識別它們?解決方案是使用索引。將.indexed字段設置為1將使用.channel值替換{index}模式來替換通道屬性名稱:

??static?const?struct?iio_chan_spec?adc_channels[]?=?{
????????{
????????????????.type?=?IIO_VOLTAGE,
????????????????.indexed?=?1,
????????????????.channel?=?0,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),

????????},

????????{
????????????????.type?=?IIO_VOLTAGE,
????????????????.indexed?=?1,
????????????????.channel?=?1,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),
????????},
????????{
????????????????.type?=?IIO_VOLTAGE,
????????????????.indexed?=?1,
????????????????.channel?=?2,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),
????????},
????????{
????????????????.type?=?IIO_VOLTAGE,
????????????????.indexed?=?1,
????????????????.channel?=?3,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),
????????},
}

生成的通道屬性為:

/sys/bus/iio/iio:deviceX/in_voltage0_raw
/sys/bus/iio/iio:deviceX/in_voltage1_raw
/sys/bus/iio/iio:deviceX/in_voltage2_raw
/sys/bus/iio/iio:deviceX/in_voltage3_raw

使用修飾符:給定一個帶有兩個通道的光傳感器 - 一個用于紅外光,一個用于紅外和可見光,沒有索引或修改器,屬性名稱將為in_intensity_raw。在這里使用索引可能容易出錯,因為使用in_intensity0_ir_raw和in_intensity1_ir_raw是沒有意義的。使用修飾符將有助于提供有意義的屬性名稱。通道的定義如下:

static?const?struct?iio_chan_spec?mylight_channels[]?=?{

????????{
????????????????.type?=?IIO_INTENSITY,
????????????????.modified?=?1,
????????????????.channel2?=?IIO_MOD_LIGHT_IR,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),
????????????????.info_mask_shared?=?BIT(IIO_CHAN_INFO_SAMP_FREQ),
????????},
????????{
????????????????.type?=?IIO_INTENSITY,
????????????????.modified?=?1,
????????????????.channel2?=?IIO_MOD_LIGHT_BOTH,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),
????????????????.info_mask_shared?=?BIT(IIO_CHAN_INFO_SAMP_FREQ),
????????},
????????{
????????????????.type?=?IIO_LIGHT,
????????????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_PROCESSED),
????????????????.info_mask_shared?=BIT(IIO_CHAN_INFO_SAMP_FREQ),

????????},
???????}

屬性結果:

l?/sys/bus/iio/iio:deviceX/in_intensity_ir_raw?用于測量IR強度的通道
l?/sys/bus/iio/iio:deviceX/in_intensity_both_raw用于測量紅外和可見光的通道
l?/sys/bus/iio/iio:deviceX/in_illuminance_input用于處理后的數據
l?/sys/bus/iio/iio:deviceX/sampling_frequency?用于采樣頻率,由所有人共享

這也適用于加速度計,我們將在案例研究中進一步了解?,F在,讓我們總結一下我們到目前為止在虛擬IIO驅動程序中討論過的內容。

總結

讓我們總結一下迄今為止我們在一個簡單的虛擬驅動器中看到的內容,它將暴露出四個電壓通道。我們將忽略read()或write()函數:

#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?


#define?FAKE_VOLTAGE_CHANNEL(num)??????????????????\
???{???????????????????????????????????????????????\
?????????.type?=?IIO_VOLTAGE,??????????????????????\
?????????.indexed?=?1,?????????????????????????????\
?????????.channel?=?(num),?????????????????????????\
?????????.address?=?(num),?????????????????????????\
?????????.info_mask_separate?=?BIT(IIO_CHAN_INFO_RAW),???\
?????????.info_mask_shared_by_type?=BIT(IIO_CHAN_INFO_SCALE)?\

???}

struct?my_private_data?{
????int?foo;
????int?bar;
????struct?mutex?lock;
};

static?int?fake_read_raw(struct?iio_dev?*indio_dev,
???????????????????struct?iio_chan_spec?const?*channel,?int?*val,
???????????????????int?*val2,?long?mask)

{
????return?0;
}

static?int?fake_write_raw(struct?iio_dev?*indio_dev,
???????????????????struct?iio_chan_spec?const?*chan,
???????????????????int?val,?int?val2,?long?mask)

{
????return?0;
}

static?const?struct?iio_chan_spec?fake_channels[]?=?{
???FAKE_VOLTAGE_CHANNEL(0),
???FAKE_VOLTAGE_CHANNEL(1),?
???FAKE_VOLTAGE_CHANNEL(2),
???FAKE_VOLTAGE_CHANNEL(3),

};

static?const?struct?of_device_id?iio_dummy_ids[]?=?{
????{?.compatible?=?"packt,iio-dummy-random",?},
????{?/*?sentinel?*/?}
};

static?const?struct?iio_info?fake_iio_info?=?{
???.read_raw?=?fake_read_raw,
???.write_raw????????=?fake_write_raw,
???.driver_module?=?THIS_MODULE,
};

static?int?my_pdrv_probe?(struct?platform_device?*pdev)
{
????struct?iio_dev?*indio_dev;
????struct?my_private_data?*data;
???indio_dev?=?devm_iio_device_alloc(&pdev->dev,?sizeof(*data));

???if?(!indio_dev)?{
?????????dev_err(&pdev->dev,?"iio?allocation?failed!\n");
?????????return?-ENOMEM;
???}

???data?=?iio_priv(indio_dev);
???mutex_init(&data->lock);
???indio_dev->dev.parent?=?&pdev->dev;
???indio_dev->info?=?&fake_iio_info;
???indio_dev->name?=?KBUILD_MODNAME;
???indio_dev->modes?=?INDIO_DIRECT_MODE;
???indio_dev->channels?=?fake_channels;
???indio_dev->num_channels?=?ARRAY_SIZE(fake_channels);
???indio_dev->available_scan_masks?=?0xF;
????iio_device_register(indio_dev);
????platform_set_drvdata(pdev,?indio_dev);
????return?0;
}
static?void?my_pdrv_remove(struct?platform_device?*pdev)
{
????struct?iio_dev?*indio_dev?=?platform_get_drvdata(pdev);
????iio_device_unregister(indio_dev);
}
static?struct?platform_driver?mypdrv?=?{
????.probe??????=?my_pdrv_probe,
????.remove?????=?my_pdrv_remove,
????.driver?????=?{
????????.name?????=?"iio-dummy-random",
????????.of_match_table?=?of_match_ptr(iio_dummy_ids),??
????????.owner????=?THIS_MODULE,
????},
};
module_platform_driver(mypdrv);
MODULE_AUTHOR("John?Madieu?");
MODULE_LICENSE("GPL");

加載上述模塊后, 我們將有以下輸出, 顯示我們的設備確實對應于我們已注冊的平臺設備:

??~#?ls?-l?/sys/bus/iio/devices/
lrwxrwxrwx?1?root?root?0?Jul?31?20:26?iio:device0?->?../../../devices/platform/iio-dummy-random.0/iio:device0
lrwxrwxrwx?1?root?root?0?Jul?31?20:23?iio_sysfs_trigger?->?../../../devices/iio_sysfs_trigger

下面的列表顯示了此設備的通道及其名稱, 這些通道與我們在驅動程序中描述的內容完全對應:

?~#?ls?/sys/bus/iio/devices/iio\:device0/
dev?in_voltage2_raw?name?uevent
in_voltage0_raw?in_voltage3_raw?power
in_voltage1_raw?in_voltage_scale?subsystem
~#?cat?/sys/bus/iio/devices/iio:device0/name
iio_dummy_random

END

來源:嵌入式客棧

版權歸原作者所有,如有侵權,請聯(lián)系刪除。

推薦閱讀

飛機上一般是什么操作系統(tǒng)?

高速CAN、容錯CAN、LIN總線有什么區(qū)別?

大佬終于把鴻蒙OS講明白了,收藏了!

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關注更多精彩內容

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉