当前位置: 首页 > news >正文

《嵌入式驱动(二):驱动编写基本概念》

《嵌入式驱动(二):驱动编写基本概念》

版本号

uboot 2016.03        kernel 4.1.15        busybox 

一、基本概念:

        1. 驱动分类


                1)字符设备驱动:按照单个字符扫描设备信息
                2)块设备驱动:按照块(512字节)扫描设备信息,用于存储设备
                3)网络设备驱动:需要网络协议栈支持TCP/IP、CAN

        2. 驱动编译


                1) 静态编译

                将驱动代码加入到zImage的内核中
                        在合适的内核目录下编写驱动代码 hello.c(/drive/char/)
                        修改Kconfig,新增配置项
                        make menuconfig 选中该配置项
                        对应配置项的CONFIG_XXX 会加入.config文件中‘
                        在驱动代码对应的Makefile中加入编译规则 obj-$(CONFIG_XXX ) += hello.o


                2)动态编译

                将驱动代码以模块的方式编译,动态加入内核或者从内核中去除
                        编写hello.c
                        修改Kconfig,新增配置项
                        通过make menuconfig 选择 M,以模式形式编译
                        对应配置项的CONFIG_XXX 会加入.config文件中 CONFIG_XXX =m
                        在Makefie中 obj-$(CONFIG_XXX ),以模块编译
                        make modules 内核会编译所有模块生成一个.ko驱动文件
                        将驱动文件动态加载到执行的内核中,从内核中去除该驱动模块


二、重点


1. uboot如何编译的?uboot的功能?

        1)解压uboot压缩包,并进入uboot源码目录

tar -zxvf uboot.tar.gz
cd uboot

        2)uboot图形界面是基于ncurses库编写的,所以需要先安装该库

sudo apt-get install libncurses5-dev

        3)编译uboot源码

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean    //清楚原来编译内容,包括.config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig    //用默认配置生成.config,y表示加入编译
make V=0  ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16    //编译
ARCH:指定目标硬件架构
CROSS_COMPILE:设置交叉编译工具链
V=0:控制编译输出的详细程度,0表示启动静默/精简输出模式,1表示完整的编译命令,便于调
试。


2. 内核如何编译?如何裁剪?

         编译:

                1) 先利用apt-get工具集下载安装lzop工具(必须保证apt-get源配置,请参考《apt-get源设置》,而且Ubuntu可以上公网,请参考《双网卡网络配置》) 

sudo apt-get install lzop

安装成功,后续可通过该工具生成zImage文件

                2) 将《驱动资料包\源码\内核》内核文件拷贝到Ubuntu系统中,并对文件进行解压缩。

tar -zxvf linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek.tar.gz

                  3)编译内核

cd linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean    //清除旧源
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig    //生成新的.config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig    //微调
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16    //编译
distclean:表示清除之前的编译内容
imx_alientek_emmc_defconfig:将该配置作为内核的.config配置
menuconfig:通过图形界面配置.config
all -j16:通过16核编译代码
ARCH=arm:编译arm32位平台
CROSS_COMPILE=arm-linux-gnueabihf-:设置编译工具链

结果文件主要有2个:
        内核镜像文件:arch/arm/boot/zImage
        设备树文件:arch/arm/boot/dts/imx6ull-alientek-emmc.dtb文件

        裁剪:通过make menuconfig进行微调


3. 根文件系统如何制作?如何自启动?涉及哪些脚本?

        1)将源码拷贝到Ubuntu主机下。(我们可以从busybox官网下载源码,也可以直接使用我下载好的源码,文件在《驱动资料包\工具\busybox》目录下)        

        2)解压文件

tar -vxjf busybox-1.29.0.tar.bz2

        3)修改busybox顶层的Makefile

cd busybox-1.29.0/
vim Makefile

        4) 修改文件中的内容

修改
CROSS_COMPILE ?=
为
CROSS_COMPILE ?= arm-linux-gnueabihf-

修改
ARCH ?= $(SUBARCH)
为
ARCH ?= arm

        5) 配置busybox

make defconfig          //使用默认配置
make menuconfig         //打开图形化配置

        6)通过图形界面配置busybox工具

                配置路径如下:

Location:
-> Settings
-> Build static binary (no shared libs)

Location:
-> Settings
-> vi-style line editing commands

Location:
-> Linux Module Utilities
-> Simplified modutils

Location:
-> Linux System Utilities
-> mdev (16 kb) //确保下面的全部选中,默认都是选中的

           7) 创建一个用来存放生成根文件系统的目录,并编译busybox

mkdir /home/linux/nfs/rootfs                                        //创建存放
根文件系统的目录
make                                                                //编译
make install CONFIG_PREFIX=/home/linux/nfs/rootfs                   //安装
ls -l /home/linux/nfs/rootfs                                        //查看根文
件系统是否创建成功

        8)此时的文件系统还缺少了一些运行的库文件,需要将工具链中的libc库拷贝过去

cd /home/linux/nfs/rootfs
mkdir lib
cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/libc/lib/*so* /home/linux/nfs/rootfs/lib/ -d
cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/libc/lib/*.a /home/linux/nfs/rootfs/lib/ -d

        9)将符号链接库删除,并拷贝真实的库文件

rm /home/linux/nfs/rootfs/lib/ld-linux-armhf.so.3
cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/libc/lib/ld-linux-armhf.so.3 /home/linux/nfs/rootfs/lib

        10)将工具链下的lib库拷贝过去

cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/lib/*so* /home/linux/nfs/rootfs/lib/ -d
cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/lib/*.a /home/linux/nfs/rootfs/lib/ -d

        11)将工具链的usr/lib库拷贝过去

mkdir /home/linux/nfs/rootfs/usr/lib -p
cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/libc/usr/lib/*so* /home/linux/nfs/rootfs/usr/lib -d
cp ~/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-
gnueabihf/libc/usr/lib/*.a /home/linux/nfs/rootfs/usr/lib -d

        12)进入根目录文件系统查看这两个目录的大小

cd /home/linux/nfs/rootfs
du ./lib ./usr/lib -sh

与上图所示大小一样即为正确。

        13) 创建其余文件夹

mkdir dev
mkdir proc
mkdir mnt
mkdir sys
mkdir tmp
mkdir root
mkdir lib/modules

        14) 我们还需要完善下根我们系统中的配置文件,这些配置文件可以进一步完善Linux系统中的功能

                1. 创建/etc/init.d/rcS文件,并将文件修改为如下内容,该文件是一个shell脚本,Linux内核启动后需要启动的一些服务都可以通过该脚本进行配置

mkdir ~/nfs/rootfs/etc/init.d -p
touch ~/nfs/rootfs/etc/init.d/rcS
vim ~/nfs/rootfs/etc/init.d/rcS

        修改文件内容如下:

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

                2. 修改文件权限

chmod 0777 ~/nfs/rootfs/etc/init.d/rcS

                3. 创建/etc/fstab文件,并将文件修改为如下内容,在rcS脚本中执行mount -a,挂载所有文件系统,就会找到fstab文件,并进行文件挂载。

touch ~/nfs/rootfs/etc/fstab
vim ~/nfs/rootfs/etc/fstab

修改内容如下:

#
proc            /proc           proc    defaults    0       0
tmpfs           /tmp            tmpfs   defaults    0       0
sysfs           /sys            sysfs   defaults    0       0

                4. 创建/etc/inittab文件,该文件指定启动后一些代码的运行方式。

touch ~/nfs/rootfs/etc/inittab
vim ~/nfs/rootfs/etc/inittab

修改文件内容如下:

#etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

以上内容的格式为:

<id>:<runlevels>:<action>:<process>
<id>:每个指令的标识符,不能重复。对于busybox而言<id>用来指定启动进程的控制tty,一般
我们将串口或者LCD屏幕设置为控制tty。
<runlevels>:对busybox来说此项说明完成没用
<action>:动作,用于指定<process>可能使用到的动作。如下图所示
<process>:具体的动作,如程序、脚本、命令等。

action动作可配置为如下参数:

        15) 接下来就可以通过nfs挂载测试了。

根文件系统(rootfs)构建工具的实体信息:

busybox:用于生成轻量级、最基本的根文件系统(特点是缺少库、缺少软件);

buildrootyocto:可选择安装某些库、某些软件(用来扩展根文件系统的功能)。

用一张图来表示这个过程

开机自启动:代码写在/etc/init.d/rcS或者/etc/profile

4.总结


5. 内核驱动静态编译和动态编译的区别?

静态编译
将驱动代码直接编译进内核映像(如zImage),成为内核的一部分。驱动随内核启动自动加载,无法单独卸载或更新。适用于核心功能或必须常驻的驱动。

        优点:无需手动加载,性能略高;

        缺点:需重新编译内核才能更新驱动。

        动态编译
将驱动编译为独立模块(.ko文件),可动态加载或卸载。适用于非必需或需频繁调试的驱动。

        优点:灵活性高,便于调试;

        缺点:需手动管理模块依赖。

关键差异

        集成方式:静态编译直接嵌入内核,动态编译生成独立模块。

        维护性:动态编译支持热插拔,静态编译需全内核更新。

        使用场景:核心驱动用静态,可选功能或调试阶段用动态。

http://www.hskmm.com/?act=detail&tid=18073

相关文章:

  • 一站式电竞平台解决方案:数据、直播、源码,助力业务飞速启航 - 数据服务
  • nfs故障排查
  • 数字信封
  • 程序员的内容创作利器:深度解析小红书爆款笔记生成提示词
  • Unigine整合Myra UI Library全纪录(2):渲染
  • 元人文AI:为价值创新构筑“舞台”、订立“契约”、预演“未来”
  • 设计一个关于python的if 语句的练习题
  • 基于CSMA/CA协议的V2X通信MATLAB仿真
  • 【招聘专场】想斩获高含金量名企Offer?京东、微芯研究院等企业 软件测试开发岗,虚位以待!
  • 练习题:成绩评定系统
  • Day22方法重写
  • python调试方法:验证安装路径与路径配置
  • CentOS将软件源修改为国内源
  • 【C++进阶】C++11 的新特性 | lambda | 包装器 - 实践
  • orcad放置器件时器件不在预览框中心
  • 易路一站式智能招聘,开启人才管理新纪元
  • kingbase数据库SHELL端迁移工具访问及使用
  • 数据质量定胜负:Apple 如何破解双语大模型性能鸿沟
  • 从零开始:VirtualBox 虚拟机安装与 CentOS 7 部署 + 双网卡网络配置指南
  • 微信个人号api|搭建高效微信机器人系统
  • 【光照】[物理模型]中的[BRDF]是什么?
  • [fakeadmin]-(session伪造flask框架)-CTF
  • 《Linux Robust锁》
  • Manim实现气泡特效
  • 完整教程:决策树(Decision Tree)
  • C# Inno Setup
  • CF2139虚拟游记
  • 新方向 - MKT
  • 翻斗幼儿园历险记-CTF-WP
  • .net8+winform+Antdui 制作 LOL 小助手