前言

  • 以野火i.M 6U为例

1. 开发环境搭建

驱动运行条件

  • 设备驱动是具有独立功能的程序,它可以被单独编译,但不能独立运行, 在运行时它被链接到内核作为内核的一部分在内核空间运行。
  • 因此想要我们写的内核模块在某个版本的内核上运行, 那么就必须在该内核版本上编译它,如果我们编译的内核与我们运行的内核具备不相同的特性,设备驱动则可能无法运行。

驱动简要编译步骤

  • 首先我们需要知道内核版本,并准备好该版本的内核源码,使用交叉编译工具编译内核源码。
  • 其次,依赖编译的内核源码编译我们的驱动模块以及设备树文件。
  • 最终将驱动模块和设备树拷贝到开发板上运行。

1.1 环境准备

1.1.1 安装工具

在编译源码前需要准备好交叉编译环境,安装必要的依赖和工具,如:

  • gcc-arm-linux-gnueabihf 交叉编译器
  • bison 语法分析器
  • flex 词法分析器
  • libssl-dev OpenSSL 通用库
  • lzop LZO压缩库的压缩软件

参考命令:

  • sudo apt install make gcc-arm-linux-gnueabihf gcc bison flex libssl-dev dpkg-dev lzop

1.1.2 编译内核

编译好内核,有以下两个用途:

  • 制作系统镜像,烧录至开发板
  • 保留一份在开发环境的系统中,用于辅助驱动开发
1.1.2.1 获取内核源码

若内核已经烧写至开发板上,则可以通过命令 uname -a 查看内核版本。

*

知道内核版本后可在其官网上下载其内核源码,如并章节以版本为 Linux npi 4.1.9.71-imx-r1 为例,可在gitee或github上下载(野火官方提供

  • 命令:git clone https://gitee.com/Embedfire/ebf-buster-linux.git
1.1.2.2 编译内核

编译内核的步骤过程根据不同官方提供的脚步和Makefile不一样而不同。以下为野火的i.M 6U编译linux内核例程。

单独新建一个工作目录,将其内核源码放在该目录下,切换到内核源码目录,找到 make_deb.sh 脚本,修改里面的配置参数,如内核编译位置等等。修改好配置参数后,只需要执行脚本即可编译内核。(其它内核可以参考该脚本,也可以自己手写一个编译脚本

deb_distro=bionic
DISTRO=stable
build_opts="-j 6"
build_opts="${build_opts} O=build_image/build"
build_opts="${build_opts} ARCH=arm"
build_opts="${build_opts} KBUILD_DEBARCH=${DEBARCH}"
build_opts="${build_opts} LOCALVERSION=-imx-r1" build_opts="${build_opts} KDEB_CHANGELOG_DIST=${deb_distro}"
build_opts="${build_opts} KDEB_PKGVERSION=1${DISTRO}"
build_opts="${build_opts} CROSS_COMPILE=arm-linux-gnueabihf-"
build_opts="${build_opts} KDEB_SOURCENAME=linux-upstream" make ${build_opts} npi_v7_defconfig
make ${build_opts}
make ${build_opts} bindeb-pkg
  • O=build_image/build:指定编译好的内核放置的位置。
  • ARCH=arm:目标是 ARM 体系结构内核。
  • KBUILD_DEBARCH=${DEBARCH}:对于deb-pkg目标,允许覆盖deb-pkg部署的常规启发式。
  • LOCALVERSION=-imx-r1:使用内核配置选项 "LOCALVERSION" 为常规内核版本附加一个唯一的后缀。
  • KDEB_CHANGELOG_DIST=${deb_distro}
  • KDEB_PKGVERSION=1${DISTRO}:版本信息。
  • CROSS_COMPILE=arm-linux-gnueabihf-:指定交叉编译器。
  • KDEB_SOURCENAME=linux-upstream:KDEB_SOURCENAME make变量仅控制已打包的源tarball的名称,并不影响bind -pkg和deb-pkg输出的.deb包名称。
  • make ${build_opts} npi_v7_defconfig:生成配置文件。
  • make ${build_opts} bindeb-pkg:编译文件进行打包。

1.2 内核驱动模块编译和加载

hello 例程可以去 李柱明的gitee clone: demo_code_for_mystudy/linux/driverTest/helloModule

1.2.1 hello 例程分析

这只是一个模块例程,不含驱动部分

必须内容可分为以下几点:

  • 入口函数
  • 出口函数
  • 协议

hello_module.c

/** @file hello_module.c
* @brief 简要说明
* @details 详细说明
* @author lzm
* @date 2021-02-21 18:08:07
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
*
**********************************************************
* @LOG 修改日志:
**********************************************************
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
// 入口函数:安装驱动时调用的函数
static int __init hello_init(void)
{
printk(KERN_EMERG "[ KERN_EMERG ] Hello Module Init\n");
printk( "[ default ] Hello Module Init\n");
return 0;
}
// 出口函数:卸载驱动时调用的函数
static void __exit hello_exit(void)
{
printk("[ default ] Hello Module Exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
//MODULE_LICENSE("GPL2");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");

1.2.2 和内核源码一起编译

1.2.3 加载内核驱动模块

编译好得到的内核驱动模块 xx.ko 可以通过多种方式拷贝到 ARM 板上,如NFS网络文件系统、SCP命令得到。

挂载方法可以参考李柱明博客园NFS篇章

1.3 设备树编译和加载

设备树是在 Linux3.x 才引入的,用于描述一个硬件平台的板级细节。

本系列笔记的驱动例程如无特殊说明,都是依赖于设备树的

下面简略演示设备树的编译和加载,具体原理由具体篇章说明。

1.3.1 设备树编译

1.3.1.1 使用内核中的dtc根据编译

编译后的内核会自动生成 dtc 工具。其路径是:内核/scripts/dtc/dtc

编译命令:内核构建目录/scripts/dtc/dtc -I dts -O dtb -o xxx.dtbo xxx.dts

  • 意为编译 dts 为 dtb
1.3.1.2 在内核源码中编译(推荐)

编译内核时都会自动编译设备树,此时,只需要把设备树源文件放到规定位置即可,设备树源文件、编译生成的设备树文件及我们所用到的设备树文件都会存放在 内核源码/arch/arm/boot/dts 里面。但是,编译内核耗时长,所以,推荐只编译设备树,方法如下:

  • 两条命令都在内核源码顶层路径下执行(其实就是利用顶层Makefile):

    • 如果在内核源码中执行了 make distclean ,则必须执行第一条命令来生成默认的配置文件。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
1.3.1.3 加载设备树

替换设备树的方法:

  • 第一种:设备树是编译到内核中的,所以,重新编译内核,重新制作镜像即可。(麻烦,不推荐)
  • 第二种:将编译好的设备树或设备树插件替换到开发板里面的。(推荐)
  • 第三种:将编译好的设备树放到开发板中,**/boot/dtbs/xxx/,修改boot启动参数。(推荐)

查看是否加载成功:

  • 进入 /proc/device-tree 目录下查看已加载的设备节点,看看有没有改动。

1.4 设备树插件的编译和加载

Linux4.4 以后引入了动态设备树,设备树插件被动态的加载到系统中,供内核识别。

设备树插件一般用于只修改添加部分硬件信息。如只添加 RGB 灯的硬件信息,就只需要编译 RGB 灯的 .dts 文件为 .dtbo 即可。

编译设备树插件的时候,无需重新编译整个设备树插件,只需要编译修改的部分即可。

1.4.1 单独使用dtc工具编译

设备树和设备树插件都是使用 DTC 编译工具编译。

设备树编译后得到的是 .dtb 文件;

而设备树插件编译后得到的是 .dtbo 文件。

使用野火提供的一键式编译工具:

  • 地址:git clone https://gitee.com/Embedfire/ebf-linux-dtoverlays.git
  • 要编译的设备树插件源文件放在 ebf-linux-dtoverlays/overlays/ebf 目录下, 然后回到编译工具的根目录 ebf-linux-dtoverlays/ 执行“make”即可。
  • 生成的.dtbo位于 ~/ebf-linux-dtoverlays/output 目录下。
  • 需要注意的是,如果你在执行“make”后出现报错,可以尝试先卸载device-tree-compiler(卸载命令为:“sudo apt-get autoremove device-tree-compiler”), 重新安装,然后在“ebf-linux-dtoverlays/basic/fixdep文件的权限, 修改权限命令为:“chmod 777 scripts/basic/fixdep”。

1.4.2 内核dtc工具编译设备树插件

编译设备树插件和编译设备树类似,这里使用内核中的dtc工具编译编译设备树插件。

编译命令:内核构建目录/scripts/dtc/dtc -I dts -O dtb -o xxx.dtbo xxx.dts

  • 意为编译 dts 为 dtbo

1.4.3 加载设备树插件

先拷贝设备树插件文件到开发板上。

1.4.3.1 使用 echo 命令加载

先在 /sys/kernel/config/device-tree/overlays/下创建一个新目录,名字自定义。

然后将 dtbo 固件 echopath 属性文件中或将 dtbo 的内容 catdtbo 属性文件中。

echo xxx.dtbo >/sys/kernel/config/device-tree/overlays/xxx/path
# 或
cat xxx.dtbo >/sys/kernel/config/device-tree/overlays/xxx/dtbo

删除设备插件:rmdir /sys/kernel/config/device-tree/overlays/xxx

1.4.3.2 uboot 加载

不同的板子可能不支持。

修改环境变量文件即可,进入/boot目录下 修改 vim uEnv.txt

参考:

【linux】驱动-1-环境准备的更多相关文章

  1. s3c6410 Linux 驱动开发环境搭建

    s3c6410 Linux 驱动开发环境搭建 -- 既然你是做Linux开发的,你还用虚拟机? 非常多人都在win下做开发,于是SD_writer.exe之类的烧写工具"大行其道" ...

  2. Linux下搭建Android NDK , Linux 驱动开发环境

    Eclispe Luna(4.4):http://www.eclipse.org/downloads/ CDT :http://www.eclipse.org/cdt/downloads.php AD ...

  3. Linux设备驱动开发环境的搭建(转)

    经过两周的摸索,终于对Linux设备驱动开发有了个初步的认识,下面对Linux设备驱动开发环境的搭建做个小结,以方便自己以后查询,同时也能给同道的初学者一点帮助. 刚接触Linux设备驱动时,初学者往 ...

  4. Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRjYXN0Y3Bw/font/5a6L5L2T/font ...

  5. Unix/Linux环境C编程入门教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. 2.选择默认虚拟机 3.选择稍后安装操作系统 4.选择linux  opensuse 5. 选择默认虚拟机名称 6.设置处理器为双核. 7.内存设置为2 ...

  6. 嵌入式Linux驱动开发日记

    嵌入式Linux驱动开发日记 主机硬件环境 开发机:虚拟机Ubuntu12.04 内存: 1G 硬盘:80GB 目标板硬件环境 CPU: SP5V210 (开发板:QT210) SDRAM: 512M ...

  7. 【转】linux驱动开发的经典书籍

    原文网址:http://www.cnblogs.com/xmphoenix/archive/2012/03/27/2420044.html Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书 ...

  8. linux驱动系列之makefile

    在linux环境下做嵌入式无论是编写应用程序还是驱动程序等等,都需要用make来进行程序的编译,就需要学会自己编写Makefile.Makefile主要的作用有3点:1.决定编译哪些文件 2.怎样编译 ...

  9. linux驱动面试题2

    1.什么是GPIO? general purpose input/output GPIO是相对于芯片本身而言的,如某个管脚是芯片的GPIO脚,则该脚可作为输入或输出高或低电平使用,当然某个脚具有复用的 ...

  10. 树莓派linux驱动学习之hello world

    最近想学习一下linux驱动,看了一些书和教学视频,大概了解了一下,不过要想深入,肯定需要实践.手上有几块linux的板子,最终选择了树莓派作为我的实验平台,资料比较丰富,接口也比较简单. 程序员的入 ...

随机推荐

  1. springboot使用RestTemplate+httpclient连接池发送http消息

    简介 RestTemplate是spring支持的一个请求http rest服务的模板对象,性质上有点像jdbcTemplate RestTemplate底层还是使用的httpclient(org.a ...

  2. CN_Week2_Neuron_code

    CN_Week1_Neuron_code on Coursera Abstract for week2: -- 1. Technique for recording from the brain. - ...

  3. ts 修改readonly参数

    readonly name = "xxx"; updateValueAndValidity(): void { // this.name = 'a'; (this as { nam ...

  4. echarts手机端,数据多时可以滚动

    <div id="container" style="height: 400px"></div> <script type=&qu ...

  5. 03.Jupyter Notebook高级-魔法命令

    %run %run C:\Users\User\Desktop\hello.py hello world %timeit %timeit L = [i for i in range(1000)] 29 ...

  6. 鸿蒙开源第三方组件——进度轮ProgressWheel

    目录:1.前言2.背景3.组件功能展示4.Sample解析5.Library解析6.作者系列文章合集 前言 基于安卓平台的进度轮组件ProgressWheel(https://github.com/A ...

  7. 从跳频技术聊CDMA/WIFI之母海蒂·拉玛传奇的一生

    导语:本篇的内容都是 文末的参考文章摘要而来的,本人根据自己的癖好,以及对 海蒂·拉玛 人生的感慨整理成本文. "WiFi"之母的海蒂·拉玛在中国的知名度,比起克劳德·香农应该也不 ...

  8. Spring注解@PropertySource加载配置文件和SpringBoot注解@Value、@ConfigurationProperties进行属性映射

    SpringBoot的配置文件 位置:resources目录下 配置文件的作用: (1).SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用a ...

  9. 第46天学习打卡(四大函数式接口 Stream流式计算 ForkJoin 异步回调 JMM Volatile)

    小结与扩展 池的最大的大小如何去设置! 了解:IO密集型,CPU密集型:(调优)  //1.CPU密集型 几核就是几个线程 可以保持效率最高 //2.IO密集型判断你的程序中十分耗IO的线程,只要大于 ...

  10. 基于docker搭建DNSmasq

    一.概述 DNSmasq是一个小巧且方便地用于配置DNS和DHCP的工具,适用于小型网络,它提供了DNS功能和可选择的DHCP功能.它服务那些只在本地适用的域名,这些域名是不会在全球的DNS服务器中出 ...