Linux下驅動開發
1.簡介
驅動,是指驅動計算機里軟件的程序。驅動程序全稱設備驅動程序,是添加到操作系統中的特殊程序,其中包含有關硬件設備的信息。驅動程序是操作系統與硬件連接的橋梁。
設備驅動最通俗的解釋就是“驅使硬件設備行動”。驅動與底層硬件直接打交道,按照硬件設備的具體工作方式,讀寫設備的寄存器,完成設備的輪詢、中斷處理、DMA通信,進行物理內存向虛擬內存的映射等,最終讓通信設備能收發數據,讓顯示設備能顯示文字和畫面,讓存儲設備能記錄文件和數據。
2.驅動分類
Linux驅動分類:
字符設備、塊設備、網絡設備。
網絡設備: 有線網卡、無線網卡、其它與網絡相關的設備。
塊設備: U盤、SD卡、硬盤、光盤等。
字符設備: 除了塊設備和網絡設備,其它都歸結于字符設備。
字符設備中分類: 雜項設備、輸入設備(鍵盤、鼠標、觸摸屏)、幀緩沖(顯示類設備)、RTC設備、串口設備等。
3.雜項設備
驅動程序是應用層和硬件層的連接橋梁,應用層只管完成應用邏輯開發和界面設計,驅動層則處理硬件配置,實現應用層相關接口函數。
雜項設備:字符設備類的一種,是除了上述輸入設備、幀緩沖設備、RTC設備后的其它設備,例LED設備,由于不好歸結于上述分類,則可將LED設備按雜項設備類進行注冊。雜項設備主設備號為10。
在生成的設備節點中,主設備號用來區分設備類。如字符設備中雜項設備主設備號為10,幀緩沖設備主設備號為29;次設備號用來區分這個類中的具體硬件。
4.驅動注冊框架
4.1開發平臺
開發平臺:Ubuntu18.04
編譯器:arm-linux-gcc
硬件平臺:tiny4412基于Cortex-A9 4核1.5GHZ
開發板內核:Linux3.5
4.2 驅動模板
#include
#include
/*驅動初始化*/
static int __init wbyq_hello_module_init(void)
{
printk("驅動入口,驅動注冊成功n");
return 0;
}
/*驅動釋放*/
static void __exit wbyq_hello_module_cleanup(void)
{
printk("驅動出口,驅動注銷成功n");
}
module_init(wbyq_hello_module_init);//驅動入口函數
module_exit(wbyq_hello_module_cleanup);//驅動出口函數
MODULE_LICENSE("GPL");//驅動注冊協議
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 hello Driver");
4.3 驅動編譯
KER_ADD=/home/wbyq/src_pack/linux-3.5 #linux3.5內核的Makefile位置
all:
make -C $(KER_ADD) M=`pwd` modules #通過調用linux3.5內核的Makefile文件進行編譯
cp ./*.ko /home/wbyq/src_pack/rootfs/code #將驅動文件拷貝到code目錄下
make -C $(KER_ADD) M=`pwd` modules clean #清空文件
obj-m +=hello_drv.o #添加依賴文件
4.4 驅動安裝
[root@wbyq code]# insmod hello_drv.ko #安裝驅動
[ 4684.795000] 驅動入口,驅動注冊成功
[root@wbyq code]# modinfo hello_drv.ko #查看驅動詳細信息
modinfo: can't open '/lib/modules/3.5.0-FriendlyARM/modules.dep': No such file or directory
[root@wbyq code]# mkdir /lib/modules/3.5.0-FriendlyARM/ -p
[root@wbyq code]# touch /lib/modules/3.5.0-FriendlyARM/modules.dep
[root@wbyq code]# lsmod #查看動態安裝的驅動
hello_drv 612 0 - Live 0xbf000000 (O)
[root@wbyq code]# rmmod hello_drv.ko #注銷驅動
[ 5610.635000] 驅動出口,驅動注銷成功
5 編寫蜂鳴器驅動
5.1 硬件接口
??蜂鳴接口:BP1 – GPD0_0 高電平驅動。
?? GPD0_CON:0x1140 0000+0x00A0 --配置寄存器
5.2 蜂鳴器驅動層
?? 1.調用驅動注冊和注銷函數,在驅動入口函數中實現BEEP硬件接口配置。在驅動出口函數中完成硬件資源釋放。
?? 2.通調用雜項設備驅動框架完成雜項設備注冊,注冊成功后在/dev生成beep的設備節點。完成應用層相關接口函數編寫。
#include
#include
#include
#include
#include
/*驅動初始化*/
unsigned int *GPDO_CON;
unsigned int *GPDO_DAT;
int beep_open(struct inode *inode, struct file *file)/*對應應用層open函數*/
{
printk("open函數調用成功n");
return 0;
}
int beep_release(struct inode *inode, struct file *file) /*對應應用層close*/
{
printk("releasse函數調用成功n");
*GPDO_DAT&=~(1<<0);
return 0;
}
ssize_t beep_read(struct file *file, char __user * data, size_t size, loff_t *offset)/*對應應用層read*/
{
int *p=(int *)data;
*p=123;
printk("read函數調用成功n");
return 4;
}
ssize_t beep_write(struct file *file, const char __user *data, size_t size, loff_t *offset)/*對應應用層write*/
{
char buff[20];
memcpy(buff,data,size);
buff[size]='';
printk("buff=%sn",buff);
if(strcmp(buff,"beep_on")==0)//開蜂鳴器
{
*GPDO_DAT|=1<<0;
}
else if(strcmp(buff,"beep_off")==0)//關蜂鳴器
{
*GPDO_DAT&=~(1<<0);
}
return size;//返回寫入成功的字節數
}
/*文件操作集合結構體*/
static struct file_operations beep_fops=
{
.owner = THIS_MODULE,/*當前模塊*/
.open = beep_open,
.release = beep_release,
.read =beep_read,
.write =beep_write
};
/*雜項設備結構體*/
static struct miscdevice tiny4412_beep = {
.minor = MISC_DYNAMIC_MINOR,//次設備號,255表示由系統自動分配
.name = "beep", /*在/dev生成的設備節點名字*/
.fops = &beep_fops,
};
static int __init wbyq_beep_init(void)
{
printk("驅動入口,驅動注冊成功n");
/*蜂鳴器配置*/
GPDO_CON=ioremap(0x114000A0, 4);//將GPDO_CON物理地址轉換虛擬地址
GPDO_DAT=ioremap(0x114000A4, 4);//將GPDO_DAT物理地址轉換虛擬地址
/*蜂鳴器*/
*GPDO_CON&=0xfffffff0;//清除當前GPD0_0的配置
*GPDO_CON|=0x00000001;//設置為輸出模式
/*注冊雜項設備:在/dev下生成設備節點,實現應用層接口函數*/
misc_register(&tiny4412_beep);
return 0;
}
/*驅動釋放*/
static void __exit wbyq_beep_cleanup(void)
{
printk("驅動出口,驅動注銷成功n");
/*注銷雜項設備*/
misc_deregister(&tiny4412_beep);
iounmap(GPDO_CON);
iounmap(GPDO_DAT);
}
module_init(wbyq_beep_init);//驅動入口函數
module_exit(wbyq_beep_cleanup);//驅動出口函數
MODULE_LICENSE("GPL");//驅動注冊協議
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 beep Driver");
?? 雜項設備主設備為10,次設備可填值為0~254;當次設備號填255時表示有系統分配。
5.3 蜂鳴器應用層
?? Linux下一切皆文件,操作設備就和操作文件一樣。只需要open打開設備、讀寫設備、操作完成關閉設備即可。
#include
#include
#include
#include
#include
#include
int main()
{
/*1.打開設備*/
int fd=open("/dev/beep",2);
if(fd<0)
{
printf("/dev/beep 設備打開失敗n");
return 0;
}
int data=0;
int size;
/*讀寫文件*/
size=read(fd,&data,4);
printf("size=%d,data=%dn",size,data);
while(1)
{
write(fd,"beep_on",strlen("beep_on"));//開蜂鳴器
sleep(1);
write(fd,"beep_off",strlen("beep_off"));//關蜂鳴器
sleep(1);
}
close(fd);//關閉文件
}
? 在Linux內核中,設備節點的訪問是通過主設備+次設備號的組合來完成的,占32位,主設備號是20 ~ 31位。次設備號是0 ~ 19位。
-
內核
+關注
關注
3文章
1372瀏覽量
40289 -
Linux
+關注
關注
87文章
11304瀏覽量
209483 -
驅動開發
+關注
關注
0文章
130瀏覽量
12077
發布評論請先 登錄
相關推薦
評論