嵌入式Linux設(shè)備驅(qū)動(dòng)開發(fā)之:按鍵驅(qū)動(dòng)程序?qū)嵗?/h1>
本文引用地址:http://butianyuan.cn/article/257107.htm下面是矩陣按鍵數(shù)組的定義,數(shù)組元素的信息(一個(gè)按鍵信息)按照0行0列,0行1列,…,3行2列,3行3列的順序逐行排列。
staticst_key_info_matrixkey_info_matrix[MAX_COLUMN][MAX_ROW]=
{
{{10,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPE11},/*0行0列*/
{11,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPG6},
{12,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPE13},
{16,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPG2}},
{{7,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPE11},/*1行0列*/
{8,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPG6},
{9,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPE13},
{15,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPG2}},
{{4,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPE11},/*2行0列*/
{5,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPG6},
{6,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPE13},
{14,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPG2}},
{{1,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPE11},/*3行0列*/
{2,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPG6},
{3,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPE13},
{13,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPG2}},
};
下面是與按鍵相關(guān)的端口的初始化函數(shù)。這些函數(shù)已經(jīng)在簡(jiǎn)單的GPIO字符設(shè)備驅(qū)動(dòng)程序里被使用過。此外,set_irq_type()函數(shù)用于設(shè)定中斷線的類型,在本實(shí)例中通過該函數(shù)將4個(gè)中斷線的類型配置為下降沿觸發(fā)式。
staticvoidinit_gpio(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);/*GPE11*/
s3c2410_gpio_setpin(S3C2410_GPE11,0);
s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);/*GPE13*/
s3c2410_gpio_setpin(S3C2410_GPE13,0);
s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);/*GPG2*/
s3c2410_gpio_setpin(S3C2410_GPG2,0);
s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);/*GPG6*/
s3c2410_gpio_setpin(S3C2410_GPG6,0);
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);/*GPF0*/
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);/*GPF2*/
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);/*GPG3*/
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);/*GPG11*/
set_irq_type(IRQ_EINT0,IRQT_FALLING);
set_irq_type(IRQ_EINT2,IRQT_FALLING);
set_irq_type(IRQ_EINT11,IRQT_FALLING);
set_irq_type(IRQ_EINT19,IRQT_FALLING);
}
下面講解按鍵驅(qū)動(dòng)的主要接口,以下為驅(qū)動(dòng)模塊的入口和卸載函數(shù)。
/*初始化并添加structcdev結(jié)構(gòu)到系統(tǒng)之中*/
staticvoidbutton_setup_cdev(structcdev*dev,
intminor,structfile_operations*fops)
{
interr;
intdevno=MKDEV(button_major,minor);
cdev_init(dev,fops);/*初始化結(jié)構(gòu)體structcdev*/
dev->owner=THIS_MODULE;
dev->ops=fops;/*關(guān)聯(lián)到設(shè)備的file_operations結(jié)構(gòu)*/
err=cdev_add(dev,devno,1);/*將structcdev結(jié)構(gòu)添加到系統(tǒng)之中*/
if(err)
{
printk(KERN_INFOError%daddingbutton%dn,err,minor);
}
}
……
/*驅(qū)動(dòng)初始化*/
staticintbutton_init(void)
{
intret;
/*將主設(shè)備號(hào)和次設(shè)備號(hào)定義到一個(gè)dev_t數(shù)據(jù)類型的結(jié)構(gòu)體之中*/
dev_tdev=MKDEV(button_major,0);
if(button_major)
{/*靜態(tài)注冊(cè)一個(gè)設(shè)備,設(shè)備號(hào)先前指定好,并設(shè)定設(shè)備名,用cat/proc/devices來查看*/
ret=register_chrdev_region(dev,1,BUTTONS_DEVICE_NAME);
}
else
{/*由系統(tǒng)動(dòng)態(tài)分配主設(shè)備號(hào)*/
ret=alloc_chrdev_region(dev,0,1,BUTTONS_DEVICE_NAME);
button_major=MAJOR(dev);/*獲得主設(shè)備號(hào)*/
}
if(ret0)
{
printk(KERN_WARNINGButton:unabletogetmajor%dn,button_major);
returnret;
}
/*初始化和添加結(jié)構(gòu)體structcdev到系統(tǒng)之中*/
button_setup_cdev(button_dev,0,button_fops);
printk(Buttondriverinitialized.n);
return0;
}
/*驅(qū)動(dòng)卸載*/
staticvoid__exitbutton_exit(void)
{
cdev_del(button_dev);/*刪除結(jié)構(gòu)體structcdev*/
/*卸載設(shè)備驅(qū)動(dòng)所占有的資源*/
unregister_chrdev_region(MKDEV(button_major,0),1);
printk(Buttondriveruninstalledn);
}
module_init(button_init);/*初始化設(shè)備驅(qū)動(dòng)程序的入口*/
module_exit(button_exit);/*卸載設(shè)備驅(qū)動(dòng)程序的入口*/
MODULE_AUTHOR(David);
MODULE_LICENSE(DualBSD/GPL);
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)
linux相關(guān)文章:linux教程
蜂鳴器相關(guān)文章:蜂鳴器原理
下面是矩陣按鍵數(shù)組的定義,數(shù)組元素的信息(一個(gè)按鍵信息)按照0行0列,0行1列,…,3行2列,3行3列的順序逐行排列。
staticst_key_info_matrixkey_info_matrix[MAX_COLUMN][MAX_ROW]=
{
{{10,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPE11},/*0行0列*/
{11,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPG6},
{12,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPE13},
{16,IRQ_EINT0,S3C2410_GPF0,S3C2410_GPG2}},
{{7,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPE11},/*1行0列*/
{8,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPG6},
{9,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPE13},
{15,IRQ_EINT2,S3C2410_GPF2,S3C2410_GPG2}},
{{4,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPE11},/*2行0列*/
{5,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPG6},
{6,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPE13},
{14,IRQ_EINT11,S3C2410_GPG3,S3C2410_GPG2}},
{{1,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPE11},/*3行0列*/
{2,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPG6},
{3,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPE13},
{13,IRQ_EINT19,S3C2410_GPG11,S3C2410_GPG2}},
};
下面是與按鍵相關(guān)的端口的初始化函數(shù)。這些函數(shù)已經(jīng)在簡(jiǎn)單的GPIO字符設(shè)備驅(qū)動(dòng)程序里被使用過。此外,set_irq_type()函數(shù)用于設(shè)定中斷線的類型,在本實(shí)例中通過該函數(shù)將4個(gè)中斷線的類型配置為下降沿觸發(fā)式。
staticvoidinit_gpio(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);/*GPE11*/
s3c2410_gpio_setpin(S3C2410_GPE11,0);
s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);/*GPE13*/
s3c2410_gpio_setpin(S3C2410_GPE13,0);
s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);/*GPG2*/
s3c2410_gpio_setpin(S3C2410_GPG2,0);
s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);/*GPG6*/
s3c2410_gpio_setpin(S3C2410_GPG6,0);
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);/*GPF0*/
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);/*GPF2*/
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);/*GPG3*/
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);/*GPG11*/
set_irq_type(IRQ_EINT0,IRQT_FALLING);
set_irq_type(IRQ_EINT2,IRQT_FALLING);
set_irq_type(IRQ_EINT11,IRQT_FALLING);
set_irq_type(IRQ_EINT19,IRQT_FALLING);
}
下面講解按鍵驅(qū)動(dòng)的主要接口,以下為驅(qū)動(dòng)模塊的入口和卸載函數(shù)。
/*初始化并添加structcdev結(jié)構(gòu)到系統(tǒng)之中*/
staticvoidbutton_setup_cdev(structcdev*dev,
intminor,structfile_operations*fops)
{
interr;
intdevno=MKDEV(button_major,minor);
cdev_init(dev,fops);/*初始化結(jié)構(gòu)體structcdev*/
dev->owner=THIS_MODULE;
dev->ops=fops;/*關(guān)聯(lián)到設(shè)備的file_operations結(jié)構(gòu)*/
err=cdev_add(dev,devno,1);/*將structcdev結(jié)構(gòu)添加到系統(tǒng)之中*/
if(err)
{
printk(KERN_INFOError%daddingbutton%dn,err,minor);
}
}
……
/*驅(qū)動(dòng)初始化*/
staticintbutton_init(void)
{
intret;
/*將主設(shè)備號(hào)和次設(shè)備號(hào)定義到一個(gè)dev_t數(shù)據(jù)類型的結(jié)構(gòu)體之中*/
dev_tdev=MKDEV(button_major,0);
if(button_major)
{/*靜態(tài)注冊(cè)一個(gè)設(shè)備,設(shè)備號(hào)先前指定好,并設(shè)定設(shè)備名,用cat/proc/devices來查看*/
ret=register_chrdev_region(dev,1,BUTTONS_DEVICE_NAME);
}
else
{/*由系統(tǒng)動(dòng)態(tài)分配主設(shè)備號(hào)*/
ret=alloc_chrdev_region(dev,0,1,BUTTONS_DEVICE_NAME);
button_major=MAJOR(dev);/*獲得主設(shè)備號(hào)*/
}
if(ret0)
{
printk(KERN_WARNINGButton:unabletogetmajor%dn,button_major);
returnret;
}
/*初始化和添加結(jié)構(gòu)體structcdev到系統(tǒng)之中*/
button_setup_cdev(button_dev,0,button_fops);
printk(Buttondriverinitialized.n);
return0;
}
/*驅(qū)動(dòng)卸載*/
staticvoid__exitbutton_exit(void)
{
cdev_del(button_dev);/*刪除結(jié)構(gòu)體structcdev*/
/*卸載設(shè)備驅(qū)動(dòng)所占有的資源*/
unregister_chrdev_region(MKDEV(button_major,0),1);
printk(Buttondriveruninstalledn);
}
module_init(button_init);/*初始化設(shè)備驅(qū)動(dòng)程序的入口*/
module_exit(button_exit);/*卸載設(shè)備驅(qū)動(dòng)程序的入口*/
MODULE_AUTHOR(David);
MODULE_LICENSE(DualBSD/GPL);
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)linux相關(guān)文章:linux教程
蜂鳴器相關(guān)文章:蜂鳴器原理
評(píng)論