程式碼:#include<linux/module.h>#include<linux/kernel.h>#include<asm/io.h>#include<linux/miscdevice.h>#include<linux/fs.h>#include<asm/uaccess.h>//流水燈程式碼#define GPM4CON 0x110002e0#define GPM4DAT 0x110002e4static unsigned long*ledcon=NULL;static unsigned long*leddat=NULL;//自定義write檔案操作(不自定義的話,核心有預設的一套檔案操作函式)static ssize_t test_write(struct file*filp,const char __user*buff,size_t count,loff_t*offset){int value=0;int ret=0;ret=copy_from_user(&value,buff,4);//底層驅動只定義基本操作動作,不定義功能if(value==1){*leddat|=0x0f;*leddat&=0xfe;}if(value==2){*leddat|=0x0f;*leddat&=0xfd;}if(value==3){*leddat|=0x0f;*leddat&=0xfb;}if(value==4){*leddat|=0x0f;*leddat&=0xf7;}return 0;}//檔案操作結構體初始化static struct file_operations g_tfops={.owner=THIS_MODULE,.write=test_write,};//雜裝置資訊結構體初始化static struct miscdevice g_tmisc={.minor=MISC_DYNAMIC_MINOR,.name="test_led",.fops=&g_tfops,};//驅動入口函式雜裝置初始化static int __init test_misc_init(void){//IO地址空間對映到核心的虛擬地址空間ledcon=ioremap(GPM4CON,4);leddat=ioremap(GPM4DAT,4);//初始化led*ledcon&=0xffff0000;*ledcon|=0x00001111;*leddat|=0x0f;//雜設備註冊函式misc_register(&g_tmisc);return 0;}//驅動出口函式static void __exit test_misc_exit(void){//釋放地址對映iounmap(ledcon);iounmap(leddat);}//指定模組的出入口函式module_init(test_misc_init);module_exit(test_misc_exit);MODULE_LICENSE("GPL");擴充套件資料:include用法:#include命令預處理命令的一種,預處理命令可以將別的原始碼內容插入到所指定的位置;可以標識出只有在特定條件下才會被編譯的某一段程式程式碼;可以定義類似識別符號功能的宏,在編譯時,預處理器會用別的文字取代該宏。插入標頭檔案的內容#include命令告訴預處理器將指定標頭檔案的內容插入到預處理器命令的相應位置。有兩種方式可以指定插入標頭檔案:1、#include<檔名>2、#include"檔名"如果需要包含標準庫標頭檔案或者實現版本所提供的標頭檔案,應該使用第一種格式。如下例所示:#include<math.h>//一些數學函式的原型,以及相關的型別和宏如果需要包含針對程式所開發的原始檔,則應該使用第二種格式。採用#include命令所插入的檔案,通常副檔名是
.h
myProject_dbg.h
myProject.h
程式碼:#include<linux/module.h>#include<linux/kernel.h>#include<asm/io.h>#include<linux/miscdevice.h>#include<linux/fs.h>#include<asm/uaccess.h>//流水燈程式碼#define GPM4CON 0x110002e0#define GPM4DAT 0x110002e4static unsigned long*ledcon=NULL;static unsigned long*leddat=NULL;//自定義write檔案操作(不自定義的話,核心有預設的一套檔案操作函式)static ssize_t test_write(struct file*filp,const char __user*buff,size_t count,loff_t*offset){int value=0;int ret=0;ret=copy_from_user(&value,buff,4);//底層驅動只定義基本操作動作,不定義功能if(value==1){*leddat|=0x0f;*leddat&=0xfe;}if(value==2){*leddat|=0x0f;*leddat&=0xfd;}if(value==3){*leddat|=0x0f;*leddat&=0xfb;}if(value==4){*leddat|=0x0f;*leddat&=0xf7;}return 0;}//檔案操作結構體初始化static struct file_operations g_tfops={.owner=THIS_MODULE,.write=test_write,};//雜裝置資訊結構體初始化static struct miscdevice g_tmisc={.minor=MISC_DYNAMIC_MINOR,.name="test_led",.fops=&g_tfops,};//驅動入口函式雜裝置初始化static int __init test_misc_init(void){//IO地址空間對映到核心的虛擬地址空間ledcon=ioremap(GPM4CON,4);leddat=ioremap(GPM4DAT,4);//初始化led*ledcon&=0xffff0000;*ledcon|=0x00001111;*leddat|=0x0f;//雜設備註冊函式misc_register(&g_tmisc);return 0;}//驅動出口函式static void __exit test_misc_exit(void){//釋放地址對映iounmap(ledcon);iounmap(leddat);}//指定模組的出入口函式module_init(test_misc_init);module_exit(test_misc_exit);MODULE_LICENSE("GPL");擴充套件資料:include用法:#include命令預處理命令的一種,預處理命令可以將別的原始碼內容插入到所指定的位置;可以標識出只有在特定條件下才會被編譯的某一段程式程式碼;可以定義類似識別符號功能的宏,在編譯時,預處理器會用別的文字取代該宏。插入標頭檔案的內容#include命令告訴預處理器將指定標頭檔案的內容插入到預處理器命令的相應位置。有兩種方式可以指定插入標頭檔案:1、#include<檔名>2、#include"檔名"如果需要包含標準庫標頭檔案或者實現版本所提供的標頭檔案,應該使用第一種格式。如下例所示:#include<math.h>//一些數學函式的原型,以及相關的型別和宏如果需要包含針對程式所開發的原始檔,則應該使用第二種格式。採用#include命令所插入的檔案,通常副檔名是
.h
,檔案包括函式原型、宏定義和型別定義。只要使用#include命令,這些定義就可被任何原始檔使用。如下例所示:#include"myproject.h"//用在當前專案中的函式原型、型別定義和宏你可以在#include命令中使用宏。如果使用宏,該宏的取代結果必須確保生成正確的#include命令。例1展示了這樣的#include命令。【例1】在#include命令中的宏#ifdef _DEBUG_#define MY_HEADER"myProject_dbg.h"#else#define MY_HEADER"myProject.h"#endif#include MY_HEADER當上述程式程式碼進入預處理時,如果_DEBUG_宏已被定義,那麼預處理器會插入myProject_dbg.h
的內容;如果還沒定義,則插入myProject.h
的內容。