900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 使用eclipse集成开发环境开发第一个嵌入式Linux驱动

使用eclipse集成开发环境开发第一个嵌入式Linux驱动

时间:2018-06-25 11:05:53

相关推荐

使用eclipse集成开发环境开发第一个嵌入式Linux驱动

1.准备工作

首先得安装好gcc工具链,以及开发环境,可以看看我的前面的几步。

还得编译好内核,一般开发板都带了,现在我还不知道配置内核,只能按照开发板默认的去编译,编译前需要先编译uboot,建议像我一样的新手先学会驱动编写,慢慢的去学习 内核的配置裁剪,我觉得到时候这个肯定是非常简单的过程,只不过没有找到门道而已,等我会了一定和大家分享,如果有会的可以教我一下,在下感激不尽。

我的嵌入式内核编译的路径为:/home/cfan/linux/linux-3.0.1/ ,这个待会会用到的。

今天我就教大家使用eclipse开发一个最简单的驱动程序,LED驱动,其实使用eclipse编译这种简单的驱动可能显得有点麻烦,如果是大工程我想集成开发环境的优势就会体现出来了,还有就是eclipse的编辑器界面比较友好,跟RVDS4.0一样。

2.建立驱动工程,设置eclipse

打开eclipse

可以在桌面上面建立一个指向eclipse的快捷键,或者到eclipse的目录执行 ./eclipse 即可启动,我设置了eclipse的全局变量,因此只需要在终端中输入eclipse即可启动,如下图

建议将工程目录选择在NFS共享的那个目录,这样方便从开发板加载驱动或者执行程序,我的就选择在nfs6410这个共享目录里面。

新建一个C项目,空项目

一直下一步,直到下图位置,填好自己的arm-linux-gcc的路径。

设置完成后点击完成。

到这一步新建工程完成了,此时还有重要的一部要做,先别急着添加.c文件。在工程上面右键,属性,到 C/C++常规---->Code Analysis---->路径和符号

点击下方ExportSettings,将设置导出为xml文件.我的道出到桌面上面了,这个大家随意

点击确定 应用 退出即可。

到你刚才保存的位置处打开那个.xml文件,用文本编辑器打开即可,我的在桌面上面,右键单击,使用文本编辑器打开

现在我们还需要将autoconf.h中的宏定义加入到Eclipse中,执行如下步骤

打开内核的这个目录 include/generated/ 这个按个人实际情况而定,我的是 cd /home/cfan/linux/linux-3.0.1/include/generated/ ,另外打开一个终端 cd到这个目录

在刚刚这个终端中执行

[cpp]view plaincopycatautoconf.h|grepdefine|awk'{print"<macro><name>"$2"</name><value>"$3"</value></macro>"}'>symbol.xml

此时打开这个目录/home/cfan/linux/linux-3.0.1/include/generated,会多了一个文件

将 symbol.xml这个文件用文本编辑器打开

此时文本编辑器里面打开了两个xml文件了,将之前导出eclipse的那个xml文件打开,需要添加一行代码,在这两行代码之间(如果有两个,是下面的那个)

[html]view plaincopy<languagename="C源文件"> </language> 添加[html]view plaincopy<macro><name>__KERNEL__</name><value>1</value></macro>

如下图

添加后

再将刚刚那个symbol.xml文件里面的所有代码复制到

[html]view plaincopy<macro><name>__KERNEL__</name><value>1</value></macro> 这行的下一行,如下图

在上面的一个

[html]view plaincopy<languagename="C源文件"> </language>

添加

[cpp]view plaincopy<includepath>/home/cfan/linux/linux-3.0.1/include</includepath> <includepath>/home/cfan/linux/linux-3.0.1/arch/arm/include</includepath> <includepath>/home/cfan/linux/linux-3.0.1/arch/arm/plat-samsung/include</includepath> <includepath>/home/cfan/linux/linux-3.0.1/arch/arm/mach-s3c64xx/include</includepath> 这里面的路径要看自己实际的内核路径进行修改,也可以在工程属性中一个一个的添加,就是添加一个linux有关的路径而已。

保存退出即可。

再打开eclipse的刚刚那个导出的位置,现在将导出的文件导入即可

点击完成即可,如果导入出问题了,仔细对照我的教程。应用,退出即可,导入后会多了几个路径,内核目录里面的头文件路径

然后新建一个.c文件

代码是之前写的

[cpp]view plaincopy/**************************************************************************************************************** *文件名称:led_drive.c *简介:OK6410LED驱动 *作者:异灵元(cp1300@) *创建时间:/08/2717:28 *修改时间:/08/27 *说明:OK6410开发板(S3C6410)LED(GPIO)驱动 ****************************************************************************************************************/ //系统头文件 #include<linux/miscdevice.h> #include<linux/delay.h> #include<asm/irq.h> #include<mach/hardware.h> #include<linux/kernel.h> #include<linux/module.h> #include<linux/init.h> #include<linux/mm.h> #include<linux/fs.h> #include<linux/types.h> #include<linux/delay.h> #include<linux/moduleparam.h> #include<linux/slab.h> #include<linux/errno.h> #include<linux/ioctl.h> #include<linux/cdev.h> #include<linux/string.h> #include<linux/list.h> #include<linux/pci.h> #include<asm/uaccess.h> #include<asm/atomic.h> #include<asm/unistd.h> //--------------------------// #include<mach/map.h> #include<mach/regs-clock.h> #include<mach/regs-gpio.h> //--------------------------// #include<plat/gpio-cfg.h> #include<mach/gpio-bank-e.h> #include<mach/gpio-bank-m.h> /// //驱动模块名称 #defineDEVICE_NAME"OK6410_LED" //函数声明 /// 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:成功;<0:失败 *依赖:linux底层宏定义 *作者:异灵元(cp1300@) *创建时间:/08/2717:28 *最后修改时间:/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"initialized\n"); return0;//返回成功 } /**************************************************************************************************************** *函数名:staticlongOK6410_LED_ioctl( structfile*file, unsignedintcmd, unsignedlongarg) *功能:发送命令给LED驱动模块,无实际作用,直接返回0 *参数:无作用 *返回:0 *依赖:无 *作者:异灵元(cp1300@) *创建时间:/08/2717:28 *最后修改时间:/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:成功;<0:失败 *依赖:linux底层宏 *作者:异灵元(cp1300@) *创建时间:/08/2717:43 *最后修改时间:/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:成功;<0:失败 *依赖:linux底层宏 *作者:异灵元(cp1300@) *创建时间:/08/2717:48 *最后修改时间:/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底层宏 *作者:异灵元(cp1300@) *创建时间:/08/2717:50 *最后修改时间:/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("cp1300@");//驱动程序作者 MODULE_DESCRIPTION("OK6410(S3C6410)LEDDriver");//一些描述信息 MODULE_LICENSE("GPL");//遵循的协议

此时会有警告,不管他。

在工程属性中将自动生成makefile选项去掉

3.新建一个makefile文件修改makefile,编译驱动文件

[cpp]view plaincopyARCH=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)clean led.o文件就是你的编译文件的名称,按照自己实际情况修开

保存后按 ctrl+B编译工程。

完成后会发现目录里面多了一个led.ko,这就是编译好的LED驱动模块。

4.加载驱动

在开发板上面加载驱动,没有NFS的童鞋将led.ko复制到开发板中,不管是SD卡还是U盘,有NFS的就好办了,在串口终端中CD到工程目录

执行 insmod led.ko 加载驱动,加载成功后会发现LED灯都灭了,后面会添加这个驱动的测试程序

到这里使用eclipse编写驱动就完成了,新手肯定会觉得太繁琐,其实一共就三步,只不过我写的比较详细而已,以后每次建立工程可以直接复制工程或者导入之前的那个xml文件皆可,麻烦也之麻烦这一次,希望对大家有所帮助。

5.附加,解决OK6410驱动无法卸载问题。

在嵌入式驱动开发过程中需要频繁的加载卸载驱动,但是使用rmmod的时候你会发现,驱动无法卸载,如 rmmod led,卸载的时候不需要.ko,直接是模块名,我的写错了。

这个可以看我的这篇文章:/cp1300/article/details/7994014

解决后就可以卸载驱动了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。