///
staticlongOK6410_LED_ioctl(
structfile*file,
unsignedintcmd,
unsignedlongarg);
staticssize_tOK6410_LED_write(
structfile*file,
constchar__user*buff,
size_tsize,
loff_t*loff);
staticssize_tOK6410_LED_read(
structfile*file,
char__user*buff,
size_tsize,
loff_t*loff);
///
/*这个结构是字符设备驱动的核心
*当应用程序操作设备文件所提供的open,read,write等函数,
*最终会调用到这个结构中的对应函数
*/
staticstructfile_operationsdev_fops={
.owner=THIS_MODULE,//这是一个宏,指向编译模块时手动创建的__this_module变量
.unlocked_ioctl=OK6410_LED_ioctl,
.read=OK6410_LED_read,
.write=OK6410_LED_write
};
//注册驱动所使用的相关信息
staticstructmiscdevicemisc={
.minor=MISC_DYNAMIC_MINOR,
.name=DEVICE_NAME,//驱动模块名称
.fops=&dev_fops,
};
//LED设备访问讯号量
structsemaphoreled_sem;
/****************************************************************************************************************
*函数名:staticint__initOK6410_LED_init(void)
*功能:LED模块初始化函数
*参数:无
*返回:0:成功;
*依赖:linux底层宏定义
*作者:异灵元()
*创建时间:2012/08/2717:28
*最后更改时间:2012/08/2717:28
*说明:初始化LED硬件,注册LED驱动
****************************************************************************************************************/
staticint__initOK6410_LED_init(void)
intret;
unsignedintreg;
//GPIOM0-3单端输出
reg=readl(S3C64XX_GPMCON);//获取GPIOM寄存器数据
reg&=(~0xffff);//消除之前设置
reg|=0x1111;//单端输出
writel(reg,S3C64XX_GPMCON);//配置IO模式
reg=readl(S3C64XX_GPMDAT);//读取输出寄存器之前数据
reg|=0xf;
writel(reg,S3C64XX_GPMDAT);//写入1,让所有的灯都熄灭
ret=misc_register(&misc);//注册驱动
if(ret<0)
printk(DEVICE_NAME"can'tinitializedLED!n");
returnret;
init_MUTEX(&led_sem);//注册讯号量
printk(DEVICE_NAME"initializedn");
return0;//返回成功
/****************************************************************************************************************
*函数名:staticlongOK6410_LED_ioctl(
structfile*file,
unsignedintcmd,
unsignedlongarg)
*功能:发送命令给LED驱动模块,无实际作用linux 驱动 makefile,直接返回0
*参数:无作用
*返回:0
*依赖:无
*作者:异灵元()
*创建时间:2012/08/2717:28
*最后更改时间:2012/08/2717:28
*说明:无
****************************************************************************************************************/
staticlongOK6410_LED_ioctl(
structfile*file,
unsignedintcmd,
unsignedlongarg)
return0;
/****************************************************************************************************************
*函数名:staticssize_tOK6410_LED_write(
structfile*file,
constchar__user*buff,
size_tsize,
loff_t*loff)
*功能:写数据到LED驱动模块,低电平灯亮
*参数:file:文件表针(无作用);buff:数据缓冲区表针;buff:数据数目;loff:无作用
*返回:0:成功;
*依赖:linux底层宏
*作者:异灵元()
*创建时间:2012/08/2717:43
*最后更改时间:2012/08/2717:43
*说明:点灯函数,低电平亮,0-3BIT有效;对应4个LED
****************************************************************************************************************/
staticssize_tOK6410_LED_write(
structfile*file,
constchar__user*buff,
size_tsize,
loff_t*loff)
unsignedintreg;
if(down_interruptible(&led_sem))//获取讯号量
return-ERESTARTSYS;
reg=readl(S3C64XX_GPMDAT);
reg&=(~0xf);
reg|=buff[0]&0xf;
writel(reg,S3C64XX_GPMDAT);
up(&led_sem);//释放讯号量
return0;
/****************************************************************************************************************
*函数名:staticssize_tOK6410_LED_read(
structfile*file,
char__user*buff,
size_tsize,
loff_t*loff)
*功能:读LED状态,低电平灯亮
*参数:file:文件表针(无作用);buff:数据缓冲区表针;buff:数据数目;loff:无作用
*返回:0:成功;
*依赖:linux底层宏
*作者:异灵元()
*创建时间:2012/08/2717:48
*最后更改时间:2012/08/2717:48
*说明:读取灯的状态,低电平灯亮,0-3bit有效;对应4个LED
****************************************************************************************************************/
staticssize_tOK6410_LED_read(
structfile*file,
char__user*buff,
size_tsize,
loff_t*loff)
unsignedintreg;
if(down_interruptible(&led_sem))//获取讯号量
return-ERESTARTSYS;
reg=readl(S3C64XX_GPMDAT);
buff[0]=reg|0xfffffff0;
up(&led_sem);//释放讯号量
return0;
/****************************************************************************************************************
*函数名:staticvoid__exitOK6410_LED_exit(void)
*功能:卸载LED驱动
*参数:无
*返回:无
*依赖:linux底层宏
*作者:异灵元()
*创建时间:2012/08/2717:50
*最后更改时间:2012/08/2717:50
*说明:卸载驱动
****************************************************************************************************************/
staticvoid__exitOK6410_LED_exit(void)
unsignedintreg;
//GPIOM0-3输入
reg=readl(S3C64XX_GPMCON);//获取GPIOM寄存器数据
reg&=(~0xffff);//消除之前设置
writel(reg,S3C64XX_GPMCON);//配置IO模式
misc_deregister(&misc);//卸载驱动
//动态加载驱动插口(必须)
module_init(OK6410_LED_init);
module_exit(OK6410_LED_exit);
//其它信息(非必需)
MODULE_AUTHOR("");//驱动程序作者
MODULE_DESCRIPTION("OK6410(S3C6410)LEDDriver");//一些描述信息
MODULE_LICENSE("GPL");//遵守的合同
此时会有警告,不管他。
在工程属性上将手动生成makefile选项除去
3.新建一个makefile文件更改makefile,编译驱动文件
ARCH=arm
CROSS_COMPILE=arm-linux-
obj-m:=led.o
KDIR:=/home/cfan/linux/linux-3.0.1
PWD:=$(shellpwd)
all:
$(MAKE)-C$(KDIR)M=$(PWD)modules
clean:
$(MAKE)-C$(KDIR)M=$(PWD)cleanled.o文件就是你的编译文件的名称,根据自己实际情况修开
保存后按ctrl+B编译工程。
完成后会发觉目录上面多了一个led.ko,这就是编译好的LED驱动模块。
4.加载驱动
在开发板后边加载驱动,没有NFS的童鞋将led.ko复制到开发板中,不管是SD卡还是U盘,有NFS的就好办了,在并口终端中CD到工程目录
执行insmodled.ko加载驱动,加载成功后会发觉LED灯都灭了,前面会添加这个驱动的测试程序
到这儿使用eclipse编撰驱动就完成了,菜鸟肯定会感觉太冗长linux 驱动 makefile,虽然一共就三步,只不过我写的比较详尽而已,之后每次构建工程可以直接复制工程或则导出之前的那种xml文件皆可,麻烦也之麻烦这一次红帽子linux,希望对你们有所帮助。
5.附加,解决OK6410驱动难以卸载问题。
在嵌入式驱动开发过程中须要频繁的加载卸载驱动,并且使用rmmod的时侯你会发觉,驱动难以卸载,如rmmodledlinux 删除文件,卸载的时侯不须要.ko,直接是模块名,我的弄错了。
这个可以看我的这篇文章:
解决后就可以卸载驱动了。
文章评论