TQ2440在linux下的LED驅動程式

2021-06-16 07:33:36 字數 2692 閱讀 8592

學習驅動程式不久,看ldd3大概有4章吧,最開始寫了個hello world驅動,後來是個面向記憶體的字元裝置驅動,後者讓我清楚了量子和量子集的使用,但是沒有個真正的,肉眼看得見的裝置真是有點不爽,查了些資料,參考了下其他書,打算自己寫個led的linux驅動,學了字元裝置驅動的話寫這個其實挺簡單的。

帶系統的驅動跟裸機的驅動可不一樣啊,裸機的驅動像微控制器那種,你只要把埠設0或者設1就可以控制那些裝置,多簡單,與帶作業系統的驅動程式不同。第一,微控制器驅動控制的位址是實體地址,而帶作業系統的驅動控制的是虛擬位址,這個在linux上可以很方便的用ioremap函式把物理位址對映為虛擬位址,這個函式在宣告;第二,帶作業系統的驅動,是在核心空間工作的,你要提供api給使用者,使用者用這些介面來寫他們的應用程式,他們不會關心底層是怎麼執行的,好比餐廳裡的,作業系統的驅動是廚師,應用程式是顧客,這樣說可能明白很多。

看下圖,是linux的應用程式呼叫的基本框架,上部黃色的是使用者空間,下部藍色的是核心空間。從上往下,程式設計師在最上層寫程式,操作一些檔案,這些檔案可以是普通的檔案,也可能是裝置檔案等等,這些操作例如open、read、write、ioctl等,這些操作,到了c庫這一層,c庫會產生乙個swi val中斷或者說異常,這個異常就會使應用程式從使用者空間進入到核心空間,下面一層叫system all inte***ce,系統呼叫介面,這一層會呼叫下面的虛擬檔案系統vfs(virtual file system)的sys_open、sys_write這些函式,這些函式就會根據不同的檔案不同的屬性,裝置檔案中還會根據裝置號,來尋找特定的驅動程式,這些驅動程式就是我們要寫的,裡面帶led_open、led_write這些函式。

這些虛擬檔案系統函式sys_open等是怎麼找到我們的驅動程式裡的led_open等的呢?其實在虛擬檔案系統中有我們的很多種類的檔案,普通檔案、目錄檔案、裝置檔案等,就裝置檔案中的字元裝置舉例,它會建立乙個字元裝置的陣列,這些陣列以主裝置號為下標,貌似從0到255,這些陣列裡面裝的是一些file_operations結構指標,這些file_operations是在驅動程式裡面定義的,而file_operations結構裡面就包含了我們的驅動的操作函式led_open、led_write等,陣列成員不同,file_operations結構就不同,驅動程式就不同,操作的裝置就不同......大概是這樣

上面是為了幫助大家理清思路,大牛無視就行了,

下面正題了,簡單的在linux下的led驅動程式。

開發平台:

ubuntu10.04

測試平台:

tq2440,作業系統為linux,核心版本linux-2.6.30.4

#include #include #include #include #include #include #include #define gpbout  (1<

int major = 0;

struct cdev* leds_cdev;

volatile unsigned long *gpbcon = null;

volatile unsigned long *gpbdat = null;

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

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

switch (cmd)

return 0;

}struct file_operations leds_fops =

;static int __init leds_init(void)

static void __exit leds_exit(void)

module_init(leds_init);

module_exit(leds_exit);

module_license("gpl");

module_author("不做超哥已多年");

module_description("leds");

測試程式:

//leds_test.c

#include #include #include #include #include #define on 0

#define off 1

int main(int argc, char* argv)

int fd;

fd = open("/dev/leds", o_rdwr);

if (fd < 0)

led_no = strtoul(argv[1], 0, 0); //將字串轉換成無符號長整型數

if (!strcmp(argv[2], "on"))

ioctl(fd, on, led_no);

else if (!strcmp(argv[2], "off"))

ioctl(fd, off, led_no);

else

exit(0);

return 0;

}

編譯驅動模組,在arm板上載入,交叉編譯測試程式,在板子上執行成功

命令是./leds_test led_no on/off 如 ./led_test 1 on就是點亮led1燈

點亮四個燈後效果:

看到可以控制燈亮滅了,你是否想起了當初玩微控制器時點led燈時的興奮呢......哈哈哈哈,好興奮啊

tq2440 的dma裸機驅動

dma是一種提高cpu效率的工具。如果讓cpu去負責搬運資料,效率是十分低下的,因為在這個過程中,cpu就只能做這麼一件事。因此dma就應運而生。只要告訴dma,要搬運的資料源位址,以及要搬運到 去的位址,何種方式,使能它,dma就會獲取匯流排控制權,自動地搬運資料,從而解放cpu,提高效率。tq2...

TQ2440 軟中斷的基本使用

在c源程式中用軟中斷時可以使用 格式 swi 軟中斷號 函式名 形參 來宣告乙個軟中斷函式 例如 swi 0x01 led void 這樣就宣告了乙個具有中斷號為0x01的軟中斷函式。注 在arm處理器中,一般將軟中斷號放在發生軟中斷的那條指令的低24位。下面是處理軟中斷的彙編 在彙編 前面需要加i...

TQ2440的mount掛載NFS過程中出現的問題

本次錯誤大多數來自於粗心。燒寫好了整個系統後。基於minicom平台,開始啟動tq2440 這裡用的都是出廠時帶的uboot kernel logo root 進行網路配置 etc net.conf檔案設定id。ipaddr netmask gateway mac xx.xx.xx.xx.xx.xx...