多语言展示
当前在线:582今日阅读:19今日分享:20

eclipse arm Linux驱动开发环境搭建

eclipse开发一个最简单的驱动程序  arm Linux驱动开发环境搭建。
工具/原料
1

eclipse

2

arm-linux-gcc

方法/步骤
1

建立驱动工程,设置eclipse 打开eclipse如下图

2

建议将工程目录选择在NFS共享的那个目录,这样方便从开发板加载驱动或者执行程序,新建一个C项目,空项目

3

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

4

设置完成后点击完成。

5

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

6

点击下方ExportSettings,将设置导出为xml文件.

7

点击确定 应用 退出即可。到开那个.xml文件,用文本编辑器打开即可,

8

现在我们还需要将autoconf.h中的宏定义加入到Eclipse中,执行如下步骤打开内核的这个目录 include/generated/  ,我的是 cd /home/cfan/linux/linux-3.0.1/include/generated/ ,另外打开一个终端 cd到这个目录

9

在刚刚这个终端中执行[cpp] view plaincopycat autoconf.h |grep define |awk '{print '' $2 '' $3 ''}' > symbo

10

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

11

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

12

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

13

添加后

14

再将刚刚那个symbol.xml文件里面的所有代码复制到[html] view plaincopy__KERNEL__1  这行的下一行,如下图

15

在上面的一个[html] view plaincopy          添加[cpp] view plaincopy/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有关的路径而已。

16

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

17

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

18

然后新建一个.c文件

19

代码是之前写的[cpp] view plaincopy/****************************************************************************************************************  * 文件名称 :   led_drive.c   //系统头文件  #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       ///////////////////////////////////////////////  //驱动模块名称  #define DEVICE_NAME 'OK6410_LED'    //函数声明  ///////////////////////////////////////////////  static long OK6410_LED_ioctl(          struct file *file,          unsigned int cmd,          unsigned long arg);  static ssize_t OK6410_LED_write(          struct file *file,          const char __user *buff,          size_t size,          loff_t *loff);  static ssize_t OK6410_LED_read(          struct file *file,          char __user *buff,          size_t size,          loff_t *loff);  ///////////////////////////////////////////////////      /*  这个结构是字符设备驱动的核心 *   当应用程序操作设备文件所提供的open,read,write等函数, *   最终会调用到这个结构中的对应函数 */  static struct file_operations dev_fops = {          .owner              = THIS_MODULE,      //这是一个宏,指向编译模块时自动创建的__this_module变量          .unlocked_ioctl     = OK6410_LED_ioctl,          .read               = OK6410_LED_read,          .write              = OK6410_LED_write  };    //注册驱动所使用的相关信息  static struct miscdevice misc = {          .minor = MISC_DYNAMIC_MINOR,          .name = DEVICE_NAME,                        //驱动模块名称          .fops = &dev_fops,  };    //LED设备访问信号量  struct semaphore led_sem;      /**************************************************************************************************************** *函数名        :   static int  __init OK6410_LED_init(void) *功能       : LED模块初始化函数 *参数       : 无 *返回       : 0:成功;<0:失败 *依赖       :     linux底层宏定义 *作者       : 异灵元(cp1300@139.com) *创建时间   :   2012/08/27 17:28 *最后修改时间:    2012/08/27 17:28 *说明     :   初始化LED硬件,注册LED驱动 ****************************************************************************************************************/  static int  __init OK6410_LED_init(void)  {      int ret;      unsigned int reg;        //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't initialized LED!\n');          return ret;      }      init_MUTEX(&led_sem);           //注册信号量      printk(DEVICE_NAME ' initialized\n');      return 0;                           //返回成功  }      /**************************************************************************************************************** *函数名        :   static long OK6410_LED_ioctl(                         struct file *file,                         unsigned int cmd,                         unsigned long arg) *功能       : 发送命令给LED驱动模块,无实际作用,直接返回0 *参数       : 无作用 *返回       : 0 *依赖       :     无 *作者       : 异灵元(cp1300@139.com) *创建时间   :   2012/08/27 17:28 *最后修改时间:    2012/08/27 17:28 *说明     :   无 ****************************************************************************************************************/  static long OK6410_LED_ioctl(          struct file *file,          unsigned int cmd,          unsigned long arg)  {      return 0;  }      /**************************************************************************************************************** *函数名        :   static ssize_t OK6410_LED_write(                         struct file *file,                         const char __user *buff,                         size_t size,                         loff_t *loff) *功能       : 写数据到LED驱动模块,低电平灯亮 *参数       : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用 *返回       : 0:成功;<0:失败 *依赖       :     linux底层宏 *作者       : 异灵元(cp1300@139.com) *创建时间   :   2012/08/27 17:43 *最后修改时间:    2012/08/27 17:43 *说明     :   点灯函数,低电平亮,0-3BIT有效;对应4个LED ****************************************************************************************************************/  static ssize_t OK6410_LED_write(          struct file *file,          const char __user *buff,          size_t size,          loff_t *loff)  {      unsigned int reg;        if(down_interruptible(&led_sem))    //获取信号量          return -ERESTARTSYS;      reg = readl(S3C64XX_GPMDAT);      reg &= (~0xf);      reg |= buff[0] & 0xf;      writel(reg,S3C64XX_GPMDAT);      up(&led_sem);                           //释放信号量        return 0;  }      /**************************************************************************************************************** *函数名        :   static ssize_t OK6410_LED_read(                         struct file *file,                         char __user *buff,                         size_t size,                         loff_t *loff) *功能       : 读LED状态,低电平灯亮 *参数       : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用 *返回       : 0:成功;<0:失败 *依赖       :     linux底层宏 *作者       : 异灵元(cp1300@139.com) *创建时间   :   2012/08/27 17:48 *最后修改时间:    2012/08/27 17:48 *说明     :   读取灯的状态,低电平灯亮,0-3bit有效;对应4个LED ****************************************************************************************************************/  static ssize_t OK6410_LED_read(          struct file *file,          char __user *buff,          size_t size,          loff_t *loff)  {      unsigned int reg;        if(down_interruptible(&led_sem))    //获取信号量          return -ERESTARTSYS;      reg = readl(S3C64XX_GPMDAT);      buff[0] = reg | 0xfffffff0;      up(&led_sem);                           //释放信号量        return 0;  }        /**************************************************************************************************************** *函数名        :   static void __exit OK6410_LED_exit(void) *功能       : 卸载LED驱动 *参数       : 无 *返回       : 无 *依赖       :     linux底层宏 *作者       : 异灵元(cp1300@139.com) *创建时间   :   2012/08/27 17:50 *最后修改时间:    2012/08/27 17:50 *说明     :   卸载驱动 ****************************************************************************************************************/  static void __exit OK6410_LED_exit(void)  {      unsigned int reg;        //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@139.com');                        //驱动程序作者  MODULE_DESCRIPTION('OK6410(S3C6410) LED Driver');   //一些描述信息  MODULE_LICENSE('GPL');  //遵循的协议  此时会有警告,不管他。

20

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

21

3.新建一个makefile文件修改makefile,编译驱动文件[cpp] view plaincopyARCH=arm  CROSS_COMPILE=arm-linux-  obj-m := led.o  KDIR :=/home/cfan/linux/linux-3.0.1   PWD :=$(shell pwd)  all:      $(MAKE) -C $(KDIR) M=$(PWD) modules  clean:      $(MAKE) -C $(KDIR) M=$(PWD) clean  led.o文件就是你的编译文件的名称,按照自己实际情况修开

22

保存后按 ctrl+B编译工程。完成后会发现目录里面多了一个led.ko,这就是编译好的LED驱动模块。在开发板上面加载驱动,没有NFS的将led.ko复制到开发板中,不管是SD卡还是U盘,有NFS的就好办了,在串口终端中CD到工程目录

23

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

24

到这里使用eclipse编写驱动就完成了,其实一共就三步,只不过我写的比较详细而已,以后每次建立工程可以直接复制工程或者导入之前的那个xml文件皆可,。 在嵌入式驱动开发过程中需要频繁的加载卸载驱动,但是使用rmmod的时候你会发现,驱动无法卸载,如 rmmod led,卸载的时候不需要.ko,直接是模块名。

推荐信息