led驱动.docx
《led驱动.docx》由会员分享,可在线阅读,更多相关《led驱动.docx(10页珍藏版)》请在冰点文库上搜索。
led驱动
第一个驱动程序:
点灯
编写驱动函数
1)定义file_operation结构体,填充(用户定义什么接口,结构体对应有什么成员)
2)在内核中注册设备
早期的办法:
register_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops)
3)驱动的入口函数
intfirst_drv_init(void){
上面定义的注册设备驱动程序的方法
return0;
}
内核如何区分入口函数
4)修饰入口函数
module_init(first_drv_init);
示例代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
staticintfirst_drv_open(structinode*inode,structfile*file)
{
printk("first_drv_open!
\n");
return0;
}
staticssize_tfirst_drv_write(structfile*file,constchar__user*buf,size_tcount,loff_t*ppos)
{
printk("first_drv_write!
\n");
return0;
}
staticstructfile_operationsfirst_drv_fops={
.owner=THIS_MODULE,/*这是一个宏,推向编译模块时自动创建__this_module*/
.open=first_drv_open,
.write=first_drv_write,
};
/*入口函数,注册驱动徎序,早期的办法*/
intfirst_drv_init(void)
{
/*major设备的主设备号,name是驱动程序的名称,fops默认的是file_operations结构*/
//如果主设备号为0,系统会自动分配
register_chrdev(111,"first_drv",&first_drv_fops);
return0;
}
/*出口函数,卸载驱动*/
voidfirst_drv_exit()
{
/*major和name必须和注册时的值一致*/
unregister_chrdev(111,"first_drv");
}
/*修饰入口函数*/
module_init(first_drv_init);
/*修饰出口函数*/
module_exit(first_drv_exit);
5)编译makefile文件
示例代码如下:
KERN_DIR=/mnt/sda3/FriendlyARM/mini6410/linux/linux-2.6.38
all:
make-C$(KERN_DIR)M=`pwd`modules
clean:
make-C$(KERN_DIR)M=`pwd`modulesclean
rm-rfmodules.order
obj-m +=first_drv.o
6)测试驱动模块
查看系统设备号cat/proc/devices
上传模块到开发板
在开发板上先进入/tmp目录,然后输入rz。
先择文件后上传
装载到系统中
insmodfirst_drv.ko
查看
方法一:
lsmod|grepword_count
[root@FriendlyARM/tmp]#lsmod|grepfirst_drv
first_drv11560-Live0xbf006000(P)
方法二:
cat/proc/devices
[root@FriendlyARM/tmp]#cat/proc/devices
Characterdevices:
...
108ppp
111first_drv
...
编写测试程序
示例代码如下:
#include
#include
#include
#include
//测试
intmain(intargc,char**argv){
intfd;
intval=1;
fd=open("dev/xxx",O_RDWR);
if(fd<0){
printf("cannotopen!
\n");
}
write(fd,&val,4);
return0;
}
运行程序查看结果如下:
[root@FriendlyARM/tmp]#./Firstdrvtest
-/bin/sh:
./Firstdrvtest:
Permissiondenied
[root@FriendlyARM/tmp]#chmodu+xFirstdrvtest
[root@FriendlyARM/tmp]#./Firstdrvtest
cannotopen!
创设备:
[root@FriendlyARM/tmp]#mknod/dev/xxxc1110
[root@FriendlyARM/tmp]#./Firstdrvtest
first_drv_open!
first_drv_write!
自动创建设备文件
示例代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
staticstructclass*firstdrv_class;
staticstructdevice *firstdrv_class_dev;
staticintfirst_drv_open(structinode*inode,structfile*file)
{
printk("first_drv_open!
\n");
return0;
}
staticssize_tfirst_drv_write(structfile*file,constchar__user*buf,size_tcount,loff_t*ppos)
{
printk("first_drv_write!
\n");
return0;
}
staticstructfile_operationsfirst_drv_fops={
.owner=THIS_MODULE,/*这是一个宏,推向编译模块时自动创建__this_module*/
.open=first_drv_open,
.write=first_drv_write,
};
/*入口函数,注册驱动徎序,早期的办法*/
intmajor;
intfirst_drv_init(void)
{
/*major设备的主设备号,name是驱动程序的名称,fops默认的是file_operations结构*/
//设备号写0由系统自动分配
major=register_chrdev(0,"first_drv",&first_drv_fops);
firstdrv_class=class_create(THIS_MODULE,"firstdrv");
//创建设备节点
firstdrv_class_dev=device_create(firstdrv_class,firstdrv_class_dev,MKDEV(major,0),NULL,"firstdrv-%s","firstdrv");
return0;
}
/*出口函数,卸载驱动*/
voidfirst_drv_exit()
{
/*major和name必须和注册时的值一致*/
unregister_chrdev(major,"first_drv");
//删除设备节点
//class_device_unregister(firstdrv_class_dev);
device_destroy(major,firstdrv_class_dev);
class_destroy(firstdrv_class);
}
/*修饰入口函数*/
module_init(first_drv_init);
/*修饰出口函数*/
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
重新装载,显示如下内容
[root@FriendlyARM/tmp]#insmodfirst_drv.ko
first_drv:
Unknownsymbol__class_create(err0)
first_drv:
Unknownsymbolclass_destroy(err0)
first_drv:
Unknownsymboldevice_create(err0)
first_drv:
Unknownsymboldevice_destroy(err0)
insmod:
can'tinsert'first_drv.ko':
unknownsymbolinmoduleorinvalidparameter
在代码中添加
MODULE_LICENSE("GPL");
重新加载,查看已生成设备节点
[root@FriendlyARM/tmp]#ls/dev/firstdrv-firstdrv
/dev/firstdrv-firstdrv
完善点灯程序
看原理图
GPK4-7
查看芯片手册
GPKCON00x7F008800R/WPortKConfigurationRegister00x22222222
GPKDAT0x7F008808R/WPortKDataRegisterUndefined
GPK4[19:
16] 0000=Input 0001=Output
0010=HostI/FDATA[4]0011=HSITXREADY
0100=Reserved 0101=DATA_CF[4]
0110=Reserved 0111=Reserved
0010
编写代码:
单板的物理地址
驱动中操作的是虚拟地址(ioremap映射)
配置引角:
GPKCON0
设置(高低电平):
GPKDAT
示例代码如上:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
staticstructclass*firstdrv_class;
staticstructdevice *firstdrv_class_dev;
volatileunsignedlong*gpkcon=NULL;
volatileunsignedlong*gpkdat=NULL;
staticintfirst_drv_open(structinode*inode,structfile*file)
{
printk("first_drv_open!
\n");
/*配置GPK4-7为输出*/
/*清零*/
*gpkcon&=~(0xFFFF);
*gpkcon|=0x11110000;
printk("gpkcon:
%u",gpkcon);
return0;
}
staticssize_tfirst_drv_write(structfile*file,constchar__user*buf,size_tcount,loff_t*ppos)
{
intval;
copy_from_user(&val,buf,count);
if(val==1){
//点灯
*gpkdat&=~((1<<4)|(1<<5)|(1<<6)|(1<<7));
printk("ongpkdat:
%u",gpkdat);
}else{
//灭灯
*gpkdat|=(1<<4)|(1<<5)|(1<<6)|(1<<7);
printk("offgpkdat:
%u",gpkdat);
}
printk("first_drv_write!
\n");
return0;
}
staticstructfile_operationsfirst_drv_fops={
.owner=THIS_MODULE,/*这是一个宏,推向编译模块时自动创建__this_module*/
.open=first_drv_open,
.write=first_drv_write,
};
/*入口函数,注册驱动徎序,早期的办法*/
intmajor;
intfirst_drv_init(void)
{
/*major设备的主设备号,name是驱动程序的名称,fops默认的是file_operations结构*/
//设备号写0由系统自动分配
major=register_chrdev(0,"first_drv",&first_drv_fops);
firstdrv_class=class_create(THIS_MODULE,"firstdrv");
//创建设备节点
firstdrv_class_dev=device_create(firstdrv_class,firstdrv_class_dev,MKDEV(major,0),NULL,"firstdrv-%s","firstdrv");
/*映射虚拟地址*/
gpkcon=(volatileunsignedlong*)ioremap(0x7F008800,32);
gpkdat=(volatileunsignedlong*)ioremap(0x7F008808,32);
printk("initmethodofgpkcon:
%u,gpkdata:
%u",gpkcon,gpkdat);
return0;
}
/*出口函数,卸载驱动*/
voidfirst_drv_exit()
{
/*major和name必须和注册时的值一致*/
unregister_chrdev(major,"first_drv");
//删除设备节点
//class_device_unregister(firstdrv_class_dev);
device_destroy(major,firstdrv_class_dev);
class_destroy(firstdrv_class);
/*取消映射*/
iounmap(gpkcon);
iounmap(gpkdat);
}
/*修饰入口函数*/
module_init(first_drv_init);
/*修饰出口函数*/
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
重新编译,下载到开发板
装载驱动,检查是否安装成功
编写测试程序:
示例代码如下:
#include
#include
#include
#include
/**
*firstdrvteston点灯
*firstdrvtestoff灭灯
**/
intmain(intargc,char**argv){
intfd;
intval=1;
fd=open("/dev/firstdrv-firstdrv",O_RDWR);
if(fd<0){
printf("cannotopen!
\n");
}
if(argc!
=2){
printf("Usage:
\n");
printf("%s",argv[0]);
}
if(strcmp(argv[1],"on")==0){
val=1;
}else{
val=0;
}
write(fd,&val,4);
return0;
}