開發板: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,不是共享型別,所以,...