linux裝置驅動(一) 字元裝置之led驅動

2021-06-11 13:36:07 字數 4384 閱讀 1728

我的板子上有4個led,對應的gpio口是gpb5,gpb6,gpb8,gpb10

io對映用的是靜態對映的方式,靜態對映的內容再arch/arm/mach-s3c2410/mach-smdk2410.c中,如果每記錯就是這個路徑

linux核心對著個soc支援還是很好的,硬體資源都已標頭檔案的方式寫在原始碼中了,但由於目錄紛繁複雜,建議使用vim+ctag瀏覽**

回頭用空把我對靜態對映的理解也寫下來,現在就先預設對映都已經做好。

還是用了mach/gpio-fns.h中的s3c2410_gpio_cfgpin等配置gpio的函式,比較好用,很省心

先把**貼上來再說

1. 標頭檔案部分,沒什麼好說的,用什麼就include進來

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define led_major249

#define device_name     "myled"

2.一些巨集定義

關於s3c2410_gpb(x)這個巨集,這個巨集定義再mach/gpio-nrs.h中,定義如下

#define s3c2410_gpb(_nr)    (s3c2410_gpio_b_start + (_nr))

在這個之前有個列舉的結構

enum s3c_gpio_number ;

這裡定義了一組start

再往上看

#define s3c2410_gpio_next(__gpio) \

((__gpio##_start) + (__gpio##_nr) + config_s3c_gpio_space + 0)

在#define中,標準定義了#和##兩種操作。#用來把引數轉換成字串,##則用來連線兩個前後兩個引數,把它們變成乙個字串。
s3c2410_gpio_b_start = s3c2410_gpio_next(s3c2410_gpio_a)
這句話就可一翻譯成
s3c2410_gpio_b_start=s3c2410_gpio_a_start + s3c2410_gpio_a_nr + config_s3c_gpio_space
s3c2410_gpio_a_nr定義為#define s3c2410_gpio_a_nr   (32)
config_s3c_gpio_space 定義為 #define config_s3c_gpio_space 0
那麼最終
s3c2410_gpio_a_start=0
s3c2410_gpio_b_start=32
以此類推,這個32實際上就是對應每個gpio口的位址空間,也就是說
gpb0=32,gpb1=33 ...
這些都是偏移量,那基位址在**呢?這就要看s3c2410_gpio_cfgpin函式中的操作了
這個追下去簡直是個無底洞,有興趣的可以試試,這裡就不往下追了,繼續看**,關於gpb0~10的定義就清楚了

//*************************繼續************************************

#define gpb0(s3c2410_gpb(0))

#define gpb5(s3c2410_gpb(5))

#define gpb6(s3c2410_gpb(6))

#define gpb8(s3c2410_gpb(8))

#define gpb10(s3c2410_gpb(10))

//************************這裡定義乙個陣列,儲存每個led對應的gpio口,便於後面呼叫

static unsigned int led_index[5]=;

static int led_major=led_major;

static int led_minor;

//定義led裝置結構體,重點是要包含cdev,這個結構體相當於驅動程式掛接再核心驅動框架的介面,其他的引數都是根據自己需要定義的,比如led_status

struct led_dev

;struct led_dev *led_devp;

//led的開啟函式,驅動模組載入後,mknod相應的節點,open /dev/led就呼叫到了這個函式

//這裡做了幾件事情,首先是根據inode節點獲得裝置號,然後從裝置號中分離出次裝置號

//因為由4個led,他們用同樣的驅動程式,也就是共用4個裝置號,但如果想單獨操作每個led的話,就要根據led0~led3來區別對待

//這個區別的方法就是用次裝置號,這個次裝置號一方面再mknod時指定,最重要的要再後面的模組init模組中建立相應的裝置結構

//這個後面會看到

//得到了次裝置號,就配置對應的gpio口為輸出模式

static int s3c2440_led_open(struct inode *inode,struct file *filp)

//release函式,這裡沒做什麼事

static int s3c2440_led_release(struct inode *inode,struct file *filp)

//ioclt函式,這是乙個很有用的函式,後面對led的操作的應用程式就是呼叫的這個函式操作led的

//通過傳遞的cmd引數,對led進行操作

static int s3c2440_led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)

return 0;

}//函式掛接

static struct file_operations s3c2440_led_ops=

;//設定cdev,這是對字元裝置的通用做法

static void led_setup_cdev(struct led_dev* dev,int index)

}//init模組,模組載入的時候會呼叫這個函式。前面說過,如果要支援多個裝置,也就是多個裝置號,那麼要申請多個裝置號,同時申請多個對應的裝置結構

static int __init s3c2440_led_init(void)

//申請了5個次裝置號,對應要申請5個裝置結構體

memset(led_devp,0,5*sizeof(struct led_dev));

led_setup_cdev(&led_devp[0],0);

led_setup_cdev(&led_devp[1],1);

led_setup_cdev(&led_devp[2],2);

led_setup_cdev(&led_devp[3],3);

led_setup_cdev(&led_devp[4],4);

printk(kern_notice "init module, result=%d\n",result);

return result;

}//解除安裝函式

static void __exit s3c2440_led_exit(void)

module_author("weicz");

module_license("dual bsd/gpl");

module_init(s3c2440_led_init);

module_exit(s3c2440_led_exit);

至此驅動部分**就完成了

下面是乙個測試程式用來測試這段驅動程式,很簡單就不說什麼了

關於編譯,編譯模組制定的選項比較多,每次寫很麻煩,我寫成乙個makefile,,只要在同一目錄下make一下就好

makefilene內容

obj-m :=led.o

kernel_dir := /home/huniu/sources/kernel/linux-2.6.35

pwd :=$(shell pwd)

all:

make -c $(kernel_dir) subdirs=$(pwd) modules

clean:

rm *.o *.ko *.mod.c

.phony:clean

這裡的kernel_dir根據自己的原始碼路徑修改

那個應用程式的編譯比較簡單

如果檔案系統沒有移植glibc庫的話,要靜態編譯才能使用stdio.h的函式,也就是編譯選項中加入-static選項

led的驅動就寫到這裡,後面寫按鍵驅動

Linux裝置驅動之《字元裝置驅動》

linux裝置中最大的特點就是裝置操作猶如檔案操作一般,在應用層看來,硬體裝置只是乙個裝置檔案。應用程式可以像操作檔案一樣對硬體裝置進行操作,如open close read write 等。下面是乙個字元裝置驅動程式的簡單實現test.c 模組分析 1.初始化裝置驅動的結構體 struct fil...

Linux裝置驅動之字元裝置驅動

一 linux裝置的分類 linux系統將裝置分成三種基本型別,每個模組通常實現為其中某一類 字元模組 塊模組或網路模組。這三種型別有 字元裝置 字元裝置是個能夠像位元組流 類似檔案 一樣被訪問的裝置,由字元裝置驅動程式來實現這種特性。字元裝置可以通過檔案系統節點來訪問,比如 dev tty1等。這...

Linux裝置驅動程式學習(1) 字元裝置驅動程式

linux裝置驅動程式學習 1 字元裝置驅動程式 一 分配裝置號 1 對字元裝置的訪問是通過檔案系統內的裝置名稱進行的 dev ttys0 在核心中,include dev t 用來儲存裝置編號 包括主裝置號和次裝置號。由dev t獲得主次裝置號 major dev t dev minor dev ...