驅動篇 乙個簡單的led驅動

2021-10-25 11:24:10 字數 4389 閱讀 1829

1.構造裝置結構體

struct light_dev ;
cdev結構體

struct cdev ;
2.設定裝置資訊

struct light_dev *light_devp;//設定裝置結構體變數

int light_major = light_major;//設定主裝置號

3.設定並填充file_operations結構體

int light_open(struct inode *inode, struct file *filp)

int light_release(struct inode *inode, struct file *filp)

/* 讀寫裝置 : 可以不需要 */

ssize_t light_read(struct file *filp, char __user *buf, size_t count,

loff_t *f_pos)

/*__user不能直接進行拷貝等,要使用例如copy_from_user,copy_to_user等函式。

預設是核心空間,因為這是驅動,是在核心空間執行的。直接拷貝不了,因為乙個是在使用者空間

乙個是在核心空間*/

/*為了增強程式的可移植性,便有了size_t

在32位系統上 定義為 unsigned int 也就是說在32位系統上是32位無符號整形。

在64位系統上定義為 unsigned long 也就是說在64位系統上是64位無符號整形。

而ssize_t這個資料型別用來表示可以被執行讀寫操作的資料塊的大小.它和size_t類似,

但必需是signed.意即:它表示的是signed size_t型別的。

##可能失敗返回< 0的函式時,則使用ssize_t;

*//*

個人小總結:

size_t 為 unsigned long/int 型別

ssize_t 為 long/int 型別

總而言之 ssize_t = signed size_t

loff_t 為 long long 型別

unsigned long copy_from_user(void *to, const void *from, unsigned long n);

to:目標位址(核心空間)

from:源位址(使用者空間)

n:將要拷貝資料的位元組數

返回:成功返回0,失敗返回沒有拷貝成功的資料位元組數

get_user巨集

int get_user(data, ptr);

data:可以是位元組、半字、字、雙字型別的核心變數

ptr:使用者空間記憶體指標

返回:成功返回0,失敗返回非0

核心空間-->使用者空間

copy_to_user函式

unsigned long copy_to_user(void *to, const void *from, unsigned long n)

to:目標位址(使用者空間)

from:源位址(核心空間)

n:將要拷貝資料的位元組數

返回:成功返回0,失敗返回沒有拷貝成功的資料位元組數

put_user巨集:

int put_user(data, prt)

data:可以是位元組、半字、字、雙字型別的核心變數

ptr:使用者空間記憶體指標

返回:成功返回0, 失敗返回非0

*/ssize_t light_write(struct file *filp, const char __user *buf, size_t count,

loff_t *f_pos)

/* ioctl 函式 */

int light_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,

unsigned long arg)

return 0;

}struct file_operations light_fops = ;

4.設定module_init和module_exit

/* 設定字元裝置 cdev 結構體 */

static void light_setup_cdev(struct light_dev *dev, int index)

/*說明: 獲取裝置在裝置表中的位置。

major 主裝置號

minor 次裝置號

mkdev(ma,mi) 就是先將主裝置號左移20位,然後與次裝置號相加得到裝置號。

靜態記憶體定義初始化:

struct cdev my_cdev;

cdev_init(&my_cdev, &fops);

my_cdev.owner = this_module;

動態記憶體定義初始化:

struct cdev *my_cdev = cdev_alloc();

my_cdev->ops = &fops;

my_cdev->owner = this_module;

簡單地說,裝置驅動程式通過呼叫cdev_add把它所管理的裝置物件的指標嵌入到

乙個型別為struct probe的節點之中,然後再把該節點加入到cdev_map所實現的雜湊鍊錶中。

對系統而言,當裝置驅動程式成功呼叫了cdev_add之後,就意味著乙個字元裝置物件已經

加入到了系統,在需要的時候,系統就可以找到它。對使用者態的程式而言,cdev_add呼叫

之後,就已經可以通過檔案系統的介面呼叫到我們的驅動程式。當乙個字元裝置驅動不再

需要的時候(比如模組解除安裝),就可以用 cdev_del() 函式來釋放 cdev 占用的記憶體。

*/int light_init(void)

if (result < 0)

return result;

/* 分配裝置結構體的記憶體 */

light_devp = kmalloc(sizeof(struct light_dev), gfp_kernel);

if (!light_devp)

memset(light_devp, 0, sizeof(struct light_dev));

light_setup_cdev(light_devp, 0);

light_gpio_init();

return 0;

fail_malloc:

unregister_chrdev_region(dev, light_devp);

return result;}/*

register_chrdev_region(dev_t first,unsigned int count,char *name)

first :要分配的裝置編號範圍的初始值, 這組連續裝置號的起始裝置號, 相當於register_chrdev()中主裝置號

count:連續編號範圍. 是這組裝置號的大小(也是次裝置號的個數)

name:編號相關聯的裝置名稱. (/proc/devices); 本組裝置的驅動名稱

alloc_chrdev_region函式,來讓核心自動給我們分配裝置號

(1)register_chrdev_region是在事先知道要使用的主、次裝置號時使用的;要先檢視

cat /proc/devices去檢視沒有使用的。

(2)更簡便、更智慧型的方法是讓核心給我們自動分配乙個主裝置號,使用alloc_chrdev_region

就可以自動分配了。

(3)自動分配的裝置號,我們必須去知道他的主次裝置號,否則後面沒法去mknod建立

他對應的裝置檔案。

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

1:這個函式的第乙個引數,是輸出型引數,獲得乙個分配到的裝置號。可以用major巨集和

minor巨集,將主裝置號和次裝置號,提取列印出來,看是自動分配的是多少,方便我們在

mknod建立裝置檔案時用到主裝置號和次裝置號。 mknod /dev/*** c 主裝置號 次裝置號

2:第二個引數:次裝置號的基準,從第幾個次裝置號開始分配。

3:第三個引數:次裝置號的個數。

4:第四個引數:驅動的名字。

5:返回值:小於0,則錯誤,自動分配裝置號錯誤。否則分配得到的裝置號就被第乙個引數帶出來。

*/void light_cleanup(void)

module_init(light_init);

module_exit(light_cleanup);

總結:1.構造裝置結構體 2.設定裝置資訊 3.設定並填充file_operations結構體 4.設定module_init和module_exit

乙個簡單的LED驅動 不基於驅動框架

驅動 include include include include include include include static int led major 1 static struct class led mark class null static struct device led mar...

乙個LED驅動的編寫

include include include include include include include include include include include define gpm4con 0x110002e0 volatile unsigned long baseaddr 0 位址...

基於arm的乙個簡單的led驅動

在學寫驅動的時候一定不要盲目的跟從,要有自己的方法。要記住一點,學習驅動要學習驅動的模板,每個驅動程式其結構基本上都是一樣的。只要大家掌握了驅動的結構以後在寫驅動的時候就相對來說要簡單一些。只要大家學會寫驅動過後後頭來看其實驅動都是大同小異的。在這裡我給大家介紹乙個簡單的led驅動的寫法,defin...