linux裝置驅動分三種,包括字元裝置驅動、塊裝置驅動和網路裝置驅動
其中本文講的字元裝置(如lcd、觸控螢幕等)只能按位元組流先後順序訪問裝置記憶體,不能隨機訪問
字元裝置的基本框架比較簡單
載入驅動時,呼叫入口函式
解除安裝驅動時,呼叫出口函式
應用程式開啟驅動裝置時,呼叫open函式
應用程式讀寫驅動裝置時,呼叫read、write函式
……open、read、write等函式是在linux核心中的統一介面,使用open開啟裝置會返回乙個檔案識別符號,通過檔案識別符號使用read、write等函式會呼叫到裝置自己的read、write函式,從而操作到硬體,這些裝置自己的函式都被存放在乙個檔案結構體中
編寫字元裝置驅動的基本流程:
1、定義、設定檔案結構體
2、編寫入口函式,註冊結構體
3、編寫出口函式,銷毀結構體
4、在裝置開啟時,初始化裝置硬體
5、編寫read、write等功能函式
6、包含一些標頭檔案(參考其他驅動程式即可)
如:入口函式
static int __init ledsinit(void)
出口函式
static void __exit led***it(void)
入口、出口函式需要修飾:
module_init(ledsinit);
module_exit(led***it);
結構體定義
static struct file_operations g_tledsfops =
;
open、read、write函式宣告如下
static int ledsopen(struct inode *ino, struct file *filep);
static ssize_t ledswrite(struct file *fd, const char __user *buf, size_t cnt, loff_t * lof);
ssize_t ledsread(struct file *file, char __user *buf, size_t size, loff_t * ppos);
註冊結構體所用函式原型
int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
可以人為建立裝置,分配主裝置號,然後在major中輸入相應值,但一般來說都會使用linux核心所自帶的mdev機制,自動分配裝置號,建立裝置,具體操作如下:
定義class、class_device指標變數
static struct class *g_ptledsclass;
static struct class_device *g_ptledsclassdevice;
建立class和class_device所用函式原型
extern struct class *class_create(struct module *owner, const char *name);
extern struct class_device *class_device_create(struct class *cls,
struct class_device *parent,
dev_t devt,
struct device *device,
const char *fmt, ...)
__attribute__((format(printf,5,6)));
銷毀class和class_device所用函式原型
extern void class_unregister(struct class *);
extern void class_device_destroy(struct class *cls, dev_t devt);
使用mdev機制需要包含gpl協議
module_license("gpl");
附上乙個關於led的驅動程式和測試用的應用程式,**僅起示例作用
驅動程式
#include #include #include #include #include #include #include #include #include #include #include #include #include static volatile unsigned long *g_dwgpfcon,*g_dwgpfdat;
static struct class *g_ptledsclass;
static struct class_device *g_ptledsclassdevice;
static int ledopen(struct inode *ino, struct file *filep)
static ssize_t ledwrite(struct file *fd, const char __user *buf, size_t cnt, loff_t * lof)
if(!strcmp(argc[1],"on"))
else if(!strcmp(argc[1],"off"))
else
if(!strcmp(argc[2],"1"))
else if(!strcmp(argc[2],"2"))
else if(!strcmp(argc[2],"3"))
else if(!strcmp(argc[2],"all"))
else
ifd = open("/dev/leds",o_rdwr);
if(ifd < 0)
ierror = write(ifd,&ival,sizeof(ival));
return 0;
}
驅動程式之 1 字元裝置 3
基本排程關係 在應用程式中呼叫poll poll呼叫sys poll sys poll呼叫do sys poll do sys poll呼叫do poll do poll呼叫do pollfd do pollfd呼叫我們的驅動程式實現的my irq drv poll,my irq drv poll呼...
驅動程式之 1 字元裝置 7
阻塞操作 是指在執行裝置操作時若不能獲得資源則掛起程序,直到滿足可操作的條件後再進行操作。被掛起的程序進入休眠狀態,被從排程器的執行佇列移走,直到等待的條件被滿足。非阻塞操作 程序在不能進行裝置操作時並不掛起,它或者放棄,或者不停地查詢,直至可以進行操作為止。驅動程式中 如果是以非阻塞方式開啟檔案,...
驅動程式之 1 字元裝置 8
按下按鍵時,由於按鍵抖動,會產生幾個高低脈衝,而cpu處理太快,這幾次高低脈衝被當作有效訊號處理,處理辦法 使用定時器,檢測到第一次按下後,啟動定時器,延遲一段時間 一般取10ms 再檢測一次,如果這時候檢測到按鍵按下,則確定有按鍵按下 驅動程式中執行流程 按鍵中斷觸發後,記錄鍵值,修改定時值,10...