驅動之路四 adc驅動(input裝置)

2021-06-19 05:58:23 字數 4119 閱讀 2405

開發板:smdk6410

開發環境:linux

突然想起一點,寫這些驅動,核心需要配成支援搶占才行。

前面的部落格已經將其它的基本知識都解釋了,這裡也就不過多的闡述了,咱就直接寫**吧

這次寫的是adc驅動,將其做為輸入裝置進行使用,

先寫標頭檔案,s3c_adc.h

#ifndef __adc_h

#define __adc_h

#include #include #include struct adc_info ;

#define s3c_pa_adc 0x7e00b000

#define s3c_sz_adc sz_4k

#define adccon 0x000

#define adctsc 0x004

#define adcdly 0x008

#define adcdat0 0x00c

#define adcdat1 0x010

#define adcupdn 0x014

#define adcclrint 0x018

#define adcclrintpndnup 0x020

#define s3c_irq_adc_s irq_adc

#define s3c_irq_adc_e irq_adc

#endif

標頭檔案主要即使裝置資訊結構體和相關的巨集定義,

現在寫裝置檔案,

#include #include #include #include #include "s3c_adc.h"

void b_release(struct device *dev)

//資源也是兩類,mem一類,irq一類

struct resource b_res = ,

[1] =

};struct platform_device dev =

};static __init int module_test_init(void)

static __exit void module_test_exit(void)

module_init(module_test_init);

module_exit(module_test_exit);

module_license("gpl");

module_author("musesea");

module_version("1.0");

module_description("test for module");

看過前幾篇驅動的應該都直到,套路比較固定,只要將其中的很少的東西修改以下就行,就不詳細說每一步的功能了,

下面寫驅動檔案,這才是大頭,

#include #include #include #include #include #include #include #include #include #include #include #include "s3c_adc.h"

void start_adc(struct adc_info *a)

//這個函式執行在中斷上下文,函式體內可不能含有可睡眠的函式

void do_timer(unsigned long data)

int get_adc(struct adc_info *a)

irqreturn_t do_adc(int no, void *data)

void s3c_adc_exit(struct adc_info *a)

void s3c_adc_init(struct adc_info *a)

int b_probe(struct platform_device *pdev)

//申請裝置結構體

adc->dev = input_allocate_device();

if(!adc->dev)

adc->dev->name = pdev->name;

adc->dev->uniq = "20131113";

adc->dev->phys = "/dev/eventx";

adc->dev->id.bustype = bus_host;

adc->dev->id.vendor = 110;

adc->dev->id.product = 120;

adc->dev->id.version = 119;

//4.設定該裝置要支援的事件型別

set_bit(ev_syn, adc->dev->evbit);

set_bit(ev_abs, adc->dev->evbit);

//使該裝置支援絕對的x事件

//寫絕對事件時不要使用set_bit,使用核心給出的下列函式

input_set_abs_params(adc->dev, abs_x, 0, 4095, 0, 0);

//5.註冊input裝置

ret = input_register_device(adc->dev);

if(ret)

goto input_register_device_error;

//將adc儲存到pdev中

platform_set_drvdata(pdev, adc);

//6.開啟clock;注意在初始化adc之前一定要寫開啟時鐘;只要使用時鐘的裝置,在初始化之前都要先開啟時鐘

adc->clk = clk_get(null, "adc");

clk_enable(adc->clk);

//7.初始化adc

//sprintf(adc->name, "adc");

adc->user = 0;

adc->irq = irq_res->start;

adc->handle = do_adc;

//涉及時鐘的硬體在初始化之前一定要確認時鐘開啟

s3c_adc_init(adc);

//8.申請中斷(adc)

ret = request_irq(adc->irq, adc->handle, 0, pdev->name, adc);

if(ret)

//9.建立乙個adc->timer_list,定時時間為0.5s,處理函式為do_adc->timer

setup_timer(&adc->timer, do_timer, (unsigned long)adc);

mod_timer(&adc->timer, jiffies + hz / 2);//這裡不要用0.5*hz,核心是不支援浮點數的,也可以寫成(hz>>1)

return 0;

free_irq(adc->irq, adc);

request_irq_error:

input_unregister_device(adc->dev);

input_register_device_error:

input_free_device(adc->dev);

input_allocate_device_error:

iounmap(adc->v);

remap_error:

kfree(adc);

return ret;

}int b_remove(struct platform_device *pdev)

struct platform_driver drv = ,

.probe = b_probe,

.remove = b_remove,

};static __init int module_test_init(void)

static __exit void module_test_exit(void)

module_init(module_test_init);

module_exit(module_test_exit);

module_license("gpl");

module_author("musesea");

module_version("1.0");

module_description("test for module");

應該注意的地方在**中做了標註了,至此又乙個驅動搞完了。

還是那句話,大家若是發現有什麼問題,一定要告訴我,大家一起學習了。

Linux驅動修煉之道 ADC驅動

對於s3c2440 來說,實現a d 轉換比較簡單,主要應用的是adc 控制暫存器adccon 和adc 轉換資料暫存器adcdat0 暫存器adcdat0 的低10 位用於儲存a d 轉換後的資料。暫存器adccon 的第15 位用於標識a d 轉換是否結束。第14 位用於使能是否進行預分頻,而第...

Linux驅動修煉之道 ADC驅動

對於s3c2440 來說,實現a d 轉換比較簡單,主要應用的是adc 控制暫存器adccon 和adc 轉換資料暫存器adcdat0 暫存器adcdat0 的低10 位用於儲存a d 轉換後的資料。暫存器adccon 的第15 位用於標識a d 轉換是否結束。第14 位用於使能是否進行預分頻,而第...

ARM Linux驅動 ADC驅動(中斷方式)

硬體平台 fl2440 核心版本 2.6.28 主機平台 ubuntu 11.04 核心版本 2.6.39 這個驅動寫了好久,因為原來的linux核心編譯的時候將觸控螢幕驅動編譯進核心了,而觸控螢幕驅動裡的adc中斷在註冊的時候型別選擇的是 irqf sample random,不是共享型別,所以,...