您的位置:首页 > 运维架构 > Linux

(一)驱动开发之环境搭建

2017-09-24 04:45 281 查看
Linux驱动开发环境搭建

 1,ubuntu中配置编译环境

  设置交叉工具链:

   tar -xvf gcc-4.6.4.tar.xz -C  ~/Linux_4412/toolchain

  设置环境变量:

   vim  ~/.bashrc  最后面添加

    export PATH=$PATH:/home/george/Linux_4412/toolchain/gcc-4.6.4/bin

  更新脚本:

   source ~/.bashrc
   arm-none-linux-gnueabi-gcc -v

    Using built-in specs.

    COLLECT_GCC=arm-none-linux-gnueabi-gcc

    COLLECT_LTO_WRAPPER=/home/george/Linux_4412/toolchain/gcc-4.6.4/bin/

    ../libexec/gcc/arm-arm1176jzfssf-linux-gnueabi/4.6.4/lto-wrapper
 2,运行开发

  a,通过tftp去启动内核

   1,将uImage和dtb文件放入到ubuntu中/tftpboot

   2,在开发板中设置uboot参数,使其能够去加载内核

    set ipaddr 192.168.7.22

    set serverip 192.168.7.21

    set bootcmd tftp 0x41000000 uImage \; tftp 0x42000000 exynos4412-fs4412.dtb \; bootm 0x41000000 - 0x42000000

    save

  

  b,通过nfs去挂载rootfs

   1,需要一个跟文件系统目录--rootfs.tar.xz,需要解压到ubuntu

    sudo tar -xvf rootfs.tar.xz  -C /opt/4412/

   

   2, 配置nfs服务器(需要安装),让/opt/4412/rootfs可以被挂载

    sudo vim /etc/exports

      /opt/4412/rootfs                *(subtree_check,rw,no_root_squash,async)

    

    sudo service nfs-kernel-server restart  //重启nfs服务器

   

    测试:

     sudo mount -t nfs localhost:/opt/4412/rootfs   /mnt

   3,在开发中去指定内核要挂载/opt/4412/rootfs--切换到开发操作

    set bootargs console=ttySAC2,115200 init=/linuxrc root=/dev/nfs rw nfsroot=192.168.7.21:/opt/4412/rootfs ip=192.168.7.22

    save
    解释:

     bootargs 是uboot传递给内核到启动参数,是一个字符串
      console=xxx: 告诉内核启动时候到调试信息是从哪个设备输出

      init=xxx:  告诉内核linux到第一个用户进程是什么

      root=xxx : 告诉内核根文件系统在哪里

       root=/dev/nfs 表示根文件系统在网路远端

       nfsroot=ip:path

      ip=xxx :告诉内核开机的时候内核的ip地址是多少(静态分配ip)
      

    

 

 3,可以开始去编写代码--开发驱动

  a, 编译内核

    tar -xvf linux-3.14.tar.xz

    步骤:

    1,设置交叉工具链--uImage也运行arm开发板

     vim  Makefile

      ARCH = arm

      CROSS_COMPILE = arm-none-linux-gnueabi-

    2, 选择一个soc ,可以支持很多到soc,所以必须挑出针对我们到平台到代码

     make exynos_defconfig

      //  cp -raf  arch/arm/configs/exynos_defconfig   .config

    

    3,make menuconfig 内核裁剪,产生一个图像界面

      System Type  --->

       (2) S3C UART to use for low-level messages

    4,make uImage  : 编译内核
     //如果编译报错:缺mkimage

      sudo cp -raf mkimage  /usr/bin/

      sudo chmod 777 /usr/bin/

      重新在make uImage
    5,编译设备树文件--描述设备信息--最终要编译成dtb

     以一个默认到dts为参考,变成我们自己想要的dts
     arch/arm/boot/dts$ cp exynos4412-origen.dts exynos4412-fs4412.dts

     arch/arm/boot/dts$ vim Makefile

      70行        exynos4412-fs4412.dtb \
     回到内核源码顶层目录:

     george@ubuntu:~/Linux_4412/kernel/linux-3.14$ make dtbs

        DTC     arch/arm/boot/dts/exynos4210-origen.dtb

        DTC     arch/arm/boot/dts/exynos4210-smdkv310.dtb

        DTC     arch/arm/boot/dts/exynos4210-trats.dtb

        DTC     arch/arm/boot/dts/exynos4210-universal_c210.dtb

        DTC     arch/arm/boot/dts/exynos4412-odroidx.dtb

        DTC     arch/arm/boot/dts/exynos4412-origen.dtb

        DTC     arch/arm/boot/dts/exynos4412-fs4412.dtb

        DTC     arch/arm/boot/dts/exynos4412-smdk4412.dtb

        DTC     arch/arm/boot/dts/exynos4412-tiny4412.dtb

        DTC     arch/arm/boot/dts/exynos4412-trats2.dtb

        DTC     arch/arm/boot/dts/exynos5250-arndale.dtb

        DTC     arch/arm/boot/dts/exynos5250-smdk5250.dtb

        DTC     arch/arm/boot/dts/exynos5250-snow.dtb

        DTC     arch/arm/boot/dts/exynos5420-arndale-octa.dtb

        DTC     arch/arm/boot/dts/exynos5420-smdk5420.dtb

        DTC     arch/arm/boot/dts/exynos5440-sd5v1.dtb

        DTC     arch/arm/boot/dts/exynos5440-ssdk5440.dtb
   使用uImag和dtb文件

    cp -raf arch/arm/boot/uImage  /tftpboot

    cp -raf arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot

  ==============================================

  移植dm9000

   实际是设备树文件修改

    vim   arch/arm/boot/dts/exynos4412-fs4412.dts

   添加如下内容:

    srom-cs1@5000000 {

      compatible = "simple-bus";

      #address-cells = <1>;

      #size-cells = <1>;

      reg = <0x5000000 0x1000000>;

      ranges;
      ethernet@5000000 {

        compatible = "davicom,dm9000";

        reg = <0x5000000 0x2 0x5000004 0x2>;

        interrupt-parent = <&gpx0>;

        interrupts = <6 4>;

        davicom,no-eeprom;

        mac-address = [00 0a 2d a6 55 a2];

      };

    };
    保存退出后,需要再次编译dts文件

     make dtbs
   配置内核:

    make menuconfig

    [*] Networking support   --->

       Networking options   --->

        <*> Packet socket

        <*> Unix domain sockets

        [*] TCP/IP networking

        [*]    IP: kernel level autoconfiguration

         [*]     IP: BOOTP support
    Device Drivers   --->

     [*] Network device support   --->

      [*]    Ethernet driver support (NEW)   --->

       <*>    DM9000 support

    File systems   --->

      [*] Network File Systems (NEW)   --->

        <*>    NFS client support

        [*]  NFS client support for NFS version 2

        [*]      NFS client support for NFS version 3

        [*]        NFS client support for the NFSv3 ACL protocol extension

        [*]    Root file system on NFS

    退出到时候要保存:

     再次编译内核:

      make  uImage -j2
    cp -raf arch/arm/boot/uImage  /tftpboot

    cp -raf arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot
    在开发板中到uboot设置中,添加一个参数 clk_ignore_unused  

    set bootargs  clk_ignore_unused console=ttySAC2,115200 init=/linuxrc root=/dev/nfs rw nfsroot=192.168.7.21:/opt/4412/rootfs ip=192.168.7.22

    重新启动开发板

  b, 编写驱动代码

   1,用什么工具去写---source insight(看代码的工具)

     环境搭建\烧录镜像和工具\si_linux3.14-ori.tgz

     解压到内核源码的顶层目录:
     tar  -xvf   si_linux3.14-ori.tgz

   2,怎么写

    在souceinsght去写

    

    驱动代码需要有四个部分

     1,头文件

      #include <linux/init.h>

      #include <linux/module.h>

     2,驱动模块装载和卸载函数入口到声明

      module_init(hello_drv_init);

      module_exit(hello_drv_exit);

     3,实现模块装载和卸载函数入口

      static int __init hello_drv_init(void)

      {
       return 0;

      }
      static void __exit hello_drv_exit(void)

      {

      }

     4,GPL声明

      MODULE_LICENSE("GPL");

  c,编译驱动代码--Makefile(被读取两次: make  2,内核源码中Makefile)

   ROOTFS_DIR = /opt/4412/rootfs
   ifeq ($(KERNELRELEASE), )

   #内核源码到路径,不同环境会不一样,内核源码一定要先编译

   KERNEL_DIR = /home/george/Linux_4412/kernel/linux-3.14

   CUR_DIR = $(shell pwd)
   all :

     make -C  $(KERNEL_DIR) M=$(CUR_DIR) modules
   clean :

     make -C  $(KERNEL_DIR) M=$(CUR_DIR) clean
   install:

     cp -raf *.ko   $(ROOTFS_DIR)/drv_module

   else

   #用于指定到底编译哪个代码--hello.c

   obj-m += hello.o

   endif

  d,加载ko

   [root@farsight drv_module]# insmod hello.ko

    [ 2789.700000] -------hello_drv_init-------------
   [root@farsight drv_module]# lsmod

    hello 805 0 - Live 0xbf000000 (O)

   [root@farsight drv_module]# rmmod hello

    rmmod: can't change directory to '/lib/modules': No such file or directory

   [root@farsight drv_module]# mkdir /lib/modules
   [root@farsight drv_module]# rmmod hello

    rmmod: can't change directory to '3.14.0': No such file or directory

   [root@farsight drv_module]# mkidr /lib/modules/3.14.0
   [root@farsight drv_module]# rmmod hello

    [ 2903.230000] -------hello_drv_exit-------------

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息