eclipse开发驱动例程.docx
《eclipse开发驱动例程.docx》由会员分享,可在线阅读,更多相关《eclipse开发驱动例程.docx(30页珍藏版)》请在冰点文库上搜索。
eclipse开发驱动例程
使用eclipse集成开发环境开发第一个嵌入式Linux驱动(zz)
转自:
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++常规---->CodeAnalysis---->路径和符号
点击下方ExportSettings,将设置导出为xml文件.我的道出到桌面上面了,这个大家随意
点击确定应用退出即可。
到你刚才保存的位置处打开那个.xml文件,用文本编辑器打开即可,我的在桌面上面,右键单击,使用文本编辑器打开
现在我们还需要将autoconf.h中的宏定义加入到Eclipse中,执行如下步骤
打开内核的这个目录include/generated/这个按个人实际情况而定,我的是cd/home/cfan/linux/linux-3.0.1/include/generated/,另外打开一个终端cd到这个目录
在刚刚这个终端中执行
[cpp]viewplaincopy
catautoconf.h|grepdefine|awk'{print""$2""$3""}'>symbol.xml
此时打开这个目录/home/cfan/linux/linux-3.0.1/include/generated,会多了一个文件
将symbol.xml这个文件用文本编辑器打开
此时文本编辑器里面打开了两个xml文件了,将之前导出eclipse的那个xml文件打开,需要添加一行代码,在这两行代码之间(如果有两个,是下面的那个)
[html]viewplaincopy
添加
[html]viewplaincopy
__KERNEL__1
如下图
添加后
再将刚刚那个symbol.xml文件里面的所有代码复制到
[html]viewplaincopy
__KERNEL__1
这行的下一行,如下图
在上面的一个
[html]viewplaincopy
添加
[cpp]viewplaincopy
/home/cfan/linux/linux-3.0.1/include
/home/cfan/linux/linux-3.0.1/arch/arm/include
/home/cfan/linux/linux-3.0.1/arch/arm/plat-samsung/include
/home/cfan/linux/linux-3.0.1/arch/arm/mach-s3c64xx/include
这里面的路径要看自己实际的内核路径进行修改,也可以在工程属性中一个一个的添加,就是添加一个linux有关的路径而已。
保存退出即可。
再打开eclipse的刚刚那个导出的位置,现在将导出的文件导入即可
点击完成即可,如果导入出问题了,仔细对照我的教程。
应用,退出即可,导入后会多了几个路径,内核目录里面的头文件路径
然后新建一个.c文件
代码是之前写的
[cpp]viewplaincopy
/****************************************************************************************************************
*文件名称:
led_drive.c
*简介:
OK6410LED驱动
*作者:
异灵元(cp1300@)
*创建时间:
2012/08/2717:
28
*修改时间:
2012/08/27
*说明:
OK6410开发板(S3C6410)LED(GPIO)驱动
****************************************************************************************************************/
//系统头文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//--------------------------//
#include
#include
#include
//--------------------------//
#include
#include
#include
///////////////////////////////////////////////
//驱动模块名称
#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@)
*创建时间:
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"initialized\n");
return0;//返回成功
}
/****************************************************************************************************************
*函数名:
staticlongOK6410_LED_ioctl(
structfile*file,
unsignedintcmd,
unsignedlongarg)
*功能:
发送命令给LED驱动模块,无实际作用,直接返回0
*参数:
无作用
*返回:
0
*依赖:
无
*作者:
异灵元(cp1300@)
*创建时间:
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:
成功;<0:
失败
*依赖:
linux底层宏
*作者:
异灵元(cp1300@)
*创建时间:
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:
成功;<0:
失败
*依赖:
linux底层宏
*作者:
异灵元(cp1300@)
*创建时间:
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底层宏
*作者:
异灵元(cp1300@)
*创建时间:
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("cp1300@");//驱动程序作者
MODULE_DESCRIPTION("OK6410(S3C6410)LEDDriver");//一些描述信息
MODULE_LICENSE("GPL");//遵循的协议
此时会有警告,不管他。
在工程属性中将自动生成makefile选项去掉
3.新建一个makefile文件修改makefile,编译驱动文件
[cpp]viewplaincopy
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)clean
led.o文件就是你的编译文件的名称,按照自己实际情况修开
保存后按ctrl+B编译工程。
完成后会发现目录里面多了一个led.ko,这就是编译好的LED驱动模块。
4.加载驱动
在开发板上面加载驱动,没有NFS的童鞋将led.ko复制到开发板中,不管是SD卡还是U盘,有NFS的就好办了,在串口终端中CD到工程目录
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.
8.
9.
10.int main(void)
11.{
12. int fd;
13. int retval;
14. unsigned char led;
15.
16. //LED测试
17. printf("LED test...\n");
18. fd = open("/dev/OK6410_LE