Linux内核驱动(前言、工程环境搭建及linux系统移植)(7.3)
一、前言
驱动开发难点:1、c语言基础 2、工程环境搭建(脚本、makefile、apt-get软件下载工具、网络配置) 3、编程思想(多年优化后的源代码可能难理解,一些编程框架理解起来困难) 4、数据结构(内核链表高集成度不熟悉) 5、硬件操作、通信调试方法(逻辑分析仪使用、芯片手册阅读、内存泄漏调试、栈崩溃调试)
学习方法:学而不思则罔,思而不学则殆。未知的东西先去听老师的课、自己找资料大体了解,之后思考其中不懂的点,借助ai讲解掌握。
推荐资料:
驱动学习目标:1、如何将Linux系统移植到开发板 2、Linux驱动开发,将不同外设操作加到Linux系统 进阶1、源代码阅读 2、工程管理思想 3、软件编程框架思想。
未来安排:头两天把linux系统移植到imx6ull开发板上。后面依次学习:1、字符设备驱动框架 2、设备树 3、资源竞争与保护、I/O模型 4、platform架构 5、I2C子系统 6、SPI子系统
二、linux系统移植
1、为什么移植Linux系统?
1、开源(源码公开,网络下载) 2、免费 3、linux系统可剪裁(可加入删除源代码) 4、linux系统采用C语言编写(直接操作硬件,运行速度快)
补充:不同与Linux笨重的特点(笨重意味着功能强大),有一些轻量级的操作系统,称为微内核操作系统(只能完成多任务、多资源竞争的处理):常见:FreeRTOS 、RT-Thread 、UCOS
2、Linux系统组成
1、Linux系统内核五大子模块:内存管理 、多任务(时间片轮转调度算法:为任务确定一个时间,到达后来一个中断,然后处理另一个任务) 、多任务间通信(进程间通信) 、文件系统管理(一切皆是文件,所有硬件设备都可以以文件形式显示在操作系统) 、网络功能(协议栈、tcp/ip、蓝牙、zigbee)
2、内核外面:shell:保护内核(避免用户直接与内核交互)、命令解释器(ls、cd等命令) 库函数:对系统调用的封装(系统调用指内核函数接口)。
3、linux系统移植到imx6ull
1、设备移植的三种量级:字符设备:按照字符扫描设备信息(比如串口、键盘、鼠标等一般设备) 、块设备:按块(512)字节扫描设备信息(如存储设备) 、网络设备:需要协议栈配合工作的设备。 我们主要写字符设备,网络设备直接用别人写好的。
2、一些基本概念:
1、计算机基本组成:cpu(运算器、控制器)、存储器(内存、外存)、输入设备、输出设备。
2、内存:掉电丢失、造价贵、读写速度块。 外存:相反
内存与cpu交互,只有代码运行起来才会加载代码数据到内存。 外存存储一些文件。
3、只要与linux内核相关的都是GNU组织写的,imx6ull处理器的东西是NXP写的,imx6ull-min开发板上的外设等一些东西是正点原子写的。
imx6ull核心板:其上存储器有, 512M的DDR3L(内存)、 8G的EMMC(外存)、 32G的TF/SD卡(外存)。所以我们的目标是将目标文件烧写到硬件平台的EMMC或者SD上面。
4、内存是DDR3 L 512mb 、外存是 EMMC 8gb。
其他常见组合:内存SRAM +外存FLASH SDRAM+NandFlash/EMMC DDR+EMMC
cpu里面还有cache(Dcache 64k、Icache 64k、L2cache):数据缓存、指令缓存、栈区申请 SRAM(128k):外面的DDR未初始化时,先用这个进行一些简单代码的运行、 rom(97k)放启动代码和外设简单初始化的一些代码,不可修改。
3、imx6ull启动方式:
1、usb启动:需外部软件通过usb烧录代码 初次烧录系统
2、sd卡启动:把启动代码放sd卡,通过读取sd卡启动 烧录灵活,可移动,多用于开发验证
3、EMMC启动:启动代码在EMMC,读取启动 固化系统,EMMC可以看成固定在板子上的sd卡
4、NandFlash:在其上,读取启动。 固化系统,相较于EMMC便宜一些,市场批量生产
4、linux启动流程:1、设置启动方式 2、上电 3、运行imx6ullcpu内核里面rom启动代码(利用内部128k ram运行,实现简单初始化) 4、根据启动方式寻找对应内核引导文件(uboot) 5、uboot对内核要使用的外设初始化(DDR、EMMC、网卡、让系统进入C语言环境) 6、运行内核代码zImage,并将设备树.dbt文件硬件资源信息传递给内核,启动内核(5大功能启动),指定内核启动后要运行的第一个进程 7、内核进程启动所有预先设定的要启动的进程(就包括文件系统挂载进程) 8、内核找到要挂载的文件系统rootfs路径,并挂载系统到rootfs中,形成与用户交互的文件系统 9、文件系统启动shell来完成与用户的交互
*bootloader加载引导在sd卡或者其他启动方式对应启动代码的编译运行,因为内部内核只能控制简单初始化。可以把bootloader看作一个软件、代码等,即uboot.bin,完成硬件初始化、引导内核启动、给内核传参(比如各种需要的文件在哪)。
*zImage是linux内核代码经过编译压缩生成的内核镜像文件(5大子系统功能)
*.dbt设备树文件,包含硬件设备资源信息。开始板子设备资源都写在内核,后面就独立出来,就叫设备树。
*文件系统rootfs:对文件、设备管理,创建统一的文件系统VFS,方便与用户交互。
5、文件烧录:
1、需要烧录的文件:uboot内核启动引导文件 、zImage内核镜像文件 、.dbt设备树文件 、.rootfs文件系统
2、烧录地点:sd卡 32gb、 或 EMMC 8gb
3、烧录工具:sd卡:windows:mfgtools ubantu:imx6mksdboot.sh
EMMC:mfgtools imx6mkemmcboot.sh
4.模式一:烧写到SD卡
1.windows烧写
1. 安装mfgtool工具:
在 《驱动资料包\工具\mfgtool》目录下找到mfgtool.zip,并对文件进行解压缩后即可使用。注意:
1、 不要使用windows自带的解压工具,因为文件名比较长,所以会解压失败,推荐使用winrar或者7z工具解压。
2、此文件夹必须解压在没有中文路径的目录下,否则无法执行。
2. 烧录的文件内容:
烧录的内容是正点原子出厂的系统镜像,我们无需修改替换,如果想要修改替换,请注意修改文件的文件名与出厂时对应的文件名一致即可。
3. 操作步骤:
1. 启动mfgtool工具(启动前先关闭虚拟机,防止开发板OTG识别到虚拟机中,应该让其识别在windows系统中)
2. 操作开发板
1. 插上12v的电源线为开发板供电
2. 使用type-c连接线连接底板的USB_OTG接口与PC机(关闭虚拟机,让开发板OTG接口识别到windows系统中)
3. 将开发板拨码开关设置为USB启动方式(01000000)
4. 先去掉SD卡,防止软件识别错误
5. 开发板上电后,即可看到windows中的软件识别到开发板OTG接口
6. 插入SD卡
7. 软件mfgtool工具中的start开始烧录
8. 等待5分钟左右即可烧录完成
9. 修改为SD卡启动即可启动开发板Linux系统
2.Ubuntu烧写
1. 烧录工具
烧录工具使用广商提供的烧写脚本即可, imx6mksdboot.sh负责将系统烧写到SD卡上, imx6mkemmcboot.sh负责将系统烧写到emmc上,需要注意emmc的烧写必须在开发板Linux系统启动后执行脚本才能完成烧写。
2. 烧录文件介绍
boot:存放要烧写的uboot、 zImage、设备树文件
filesystem:存放要烧写的文件系统的压缩包
modules:存放要烧写的内核模块文件
注意:
如果想要烧写自己制作的系统,即可通过文件名替换成自己的文件即可,注意名字与出厂时保持一致
3. 配置步骤:
1. 将sd卡插入读卡器并连接到Ubuntu中。
2. 通过命令查看sd卡是否连接成功,并被成功识别为/dev/sdb
3. 将《驱动资料包\工具\mfgtool\Profiles\Linux\OS Firmware》目录下的files文件夹拷贝到Ubuntu系统中。注意:解压mfgtool工具时应该用winrar或者7z工具解压,否则会因为文件名过长而解压失败。
4. 进入files对应的目录执行脚本:
看到如上图效果即表示烧写完成。
5. 修改为SD卡启动即可启动开发板Linux系统
5.模式二:烧写到EMMC
1.windows烧写
1. 安装mfgtool工具:
在 《驱动资料包\工具\mfgtool》目录下找到mfgtool.zip,并对文件进行解压缩后即可使用。注意:
不要使用windows自带的解压工具,因为文件名比较长,所以会解压失败,推荐使用winrar或者7z工具解压。
此文件夹必须解压在没有中文路径的目录下,否则无法执行。
2. 烧录的文件内容:
烧录的内容是正点原子出厂的系统镜像,我们无需修改替换,如果想要修改替换,请注意修改文件的文件名与出厂时对应的文件名一致即可。
3. 操作步骤:
1. 启动mfgtool工具(启动前先关闭虚拟机,防止开发板OTG识别到虚拟机中,应该让其识别在windows系统中)
2. 操作开发板
1. 插上12v的电源线为开发板供电
2. 使用type-c连接线连接底板的USB_OTG接口与PC机(关闭虚拟机,让开发板OTG接口识别到windows系统中)
3. 将开发板拨码开关设置为USB启动方式(01000000)
4. 先去掉SD卡,防止软件识别错误
5. 开发板上电后,即可看到windows中的软件识别到开发板OTG接口
6. 软件mfgtool工具中的start开始烧录
7. 等待5分钟左右即可烧录完成
8. 修改为SD卡启动即可启动开发板Linux系统
2.Ubuntu烧写
请先完成《模式一:烧写到SD卡》中的Ubuntu烧写章节,因为EMMC烧写需要在开发板Linux系统启动后的界面通过脚本烧录。还需要完成《环境搭建》中的nfs服务器配置及minicom配置。
1. 将sd卡烧录为出厂系统,并选择SD卡启动。
2. 使用minicom连接开发板,并显示开发板终端交互界面。
3. 测试与主机是否网络连通
4. 将开发板的/mnt目录挂载到Ubuntu主机的共享目录下,形成共享文件夹(此操作是在minicom中操作开发板)
5. 将《驱动资料包\工具\mfgtool\Profiles\Linux\OS Firmware》目录下的files文件夹拷贝到Ubuntu系统的/home/linux/nfs/rootfs目录下。
6. 为imx6mkemmcboot.sh文件加上执行权限
7. 在开发板中执行烧录脚本(此操作是在minicom中操作开发板)
8. 修改为SD卡启动即可启动开发板Linux系统
三、环境搭建
1.双网卡网络配置
1.概念:
在嵌入式开发中, Ubuntu需要一个网卡与开发板连接,用来实现基于网络的tftp(文件传输)及nfs(目录共享)服务功能。如果Ubuntu想使用apt-get工具访问软件源下载软件,或想访问百度时就会非常不方便,此时我们可以通过设置双网卡来实现既能上网又能与开发板通信的效果。
2.虚拟机网络模式:
1.桥接模式:
桥接模式的组网方式如下:
Ubuntu虚拟机通过桥接模式以192.168.1.100作为IP地址来操作网卡, Windows系统则通过192.168.1.200作为IP地址操作网卡,两个IP地址均是存在的,所以Ubuntu可以作为独立的IP地址来进行网络操作。
该模式主要功能及局限性为:
作为服务器时必须选择桥接模式,因为服务器必须有真实IP地址,这样才能在网络中被找到。
Ubuntu与Windows作为独立的IP地址来上网, Ubuntu网络是否正常与Windows是没有关系的,两者网络连接状态是独立的。
如果在校园网等需要拨号上网的场景下,这种模式可能导致Ubuntu无法上外网,因为拨号上网通常一个账号只能获得一个IP地址,同时为Ubuntu和Windows分配地址。
2.NAT模式:
NAT模式的组网方式如下:
Ubuntu虚拟机通过NAT模式工作时, Windows会认为Ubuntu系统是工作在其上的一款软件,因此会为Ubuntu系统虚拟一个不存在的网卡,即192.168.XX.XX(此IP地址可以通过软件配置),如果Windows是能够正常上网的,那么Ubuntu一定也是能够上网的。
该模式的主要功能及局限性为:
上网方式简单, Windows有网的情况下, Ubuntu想要上网,配置为NAT模式是最简单快的。
NAT模式因为Ubuntu地址是虚拟IP地址,所以不能作为服务器IP地址,在网络中也是无法被找到的。
如果只是想Ubuntu上网,而不需要作为服务器被网络终端访问,推荐配置为NAT模式。
3.双网卡组网方式:
Ubuntu双网卡配置主要是为了能够让Ubuntu在能够与开发板通过有线网卡连接的情况下,还能够通过无线网卡实现上公网的目的,因为我们开发板需要tftp和nfs服务器,所以要求Ubuntu作为服务器工作在桥接模式,同时我们开发时经常需要下载软件,还要求Ubuntu能够上公网访问软件源,需要工作在NAT模式。
组网方式如下:
网络适配器1: NAT模式,负责Ubuntu上公网的功能。
网络适配器2:桥接模式,负责与开发板网络连接,作为开发板的tftp和nfs服务器。
4.配置步骤:
1. 添加双网卡:
我们需要两个网络适配器来实现与开发板连接和与公网连接的功能。
1. 添加一个新的网络适配器
2. 配置双网卡:
将网络适配器1设置为NAT模式,将网络适配器2设置为桥接模式。1.将网络适配器配置为NAT模式。2.将网络适配器3配置为桥接模式(可能名字不一定为"网络适配3")。
注意:
上图配置中,第一个网络适配器应该设置为NAT模式,第二个网络适配器(也就是新添加的网络适配器)应该设置为桥接模式,不要搞反了
3. 配置桥接网卡的具体信息:
桥接模式的网络适配器必须桥接到有线网卡,开发板通过网线与电脑有线网卡连接,通过桥接模式到Ubuntu虚拟机中,实现网络通信。
1.将桥接模式的网卡桥接到有线网卡上
4. 配置NAT网卡的具体信息:
NAT网卡的IP地址网段一般都是虚拟的,为了方便管理,我们统一配置为192.168.78.0这个网段,后续命令方便统一设置。
1.将NAT模式的网卡网段设置为192.168.78.0网段
5. 配置Ubuntu网络配置文件
我们需要将Ubuntu中的两个网卡设置为正确的IP地址。
1. 使用ifconfig查看两个网卡的名字, ens33和ens36(每个电脑可能不一样)
2. 打开网络配置文件
3. 配置ens33为自动获取IP地址, ens36为静态IP地址(192.168.1.100)
注意:
第二个网卡的名字每台电脑可能不一样,此处为ens36,应该对应ifconfig查看到的网卡2的名字
对应字符不能写错,否则虚拟机无法识别
4. 重启Ubuntu,让网络配置生效
5. 查看网卡信息
注意:
ens33网卡应该获得192.168.78.0网段内的一个IP地址
ens36网卡应该被设置为192.168.1.100这个IP地址
6. 查看路由
上图中:
default网段,该网段指如果目的不是后续的网段,将通过default实现数据路由,想访问百度,会通过default实现路由,但ens36不能上公网,所以default路由配置错误!
192.168.1.0网段,通过ens36网卡(IP: 192.168.1.100)实现数据路由,正确! 192.168.78.0网段,通过ens33网卡(IP: 192.168.78.137)实现数据路由,正确!
通过route命令删除default路由,更新配置, 192.168.78.2为虚拟机自动设置的ens33网卡的路由(ens33所在网段192.168.78.0,网关一般被虚拟机配置为192.168.78.2)
5. 测试:
1. 测试Ubuntu与百度是否连通
2. 测试Ubuntu与开发板是否连通(开发板地址一般设置为: 192.168.1.50)
6.常见错误:
如果上述配置均成功,还网络无法正常工作,请咨询老师解答。
1. 不能与百度ping通:
1. 需要检查路由是否配置正确
2. 需要检查DNS域名问题
2. 不能与开发板ping通:
1. 关闭windows防火墙
2. 最好配置windows端的有线网卡IP地址设为192.168.1.200
2.apt-get源设置
1.概念:
Ubuntu中想要下载软件的时候,手动到官网搜索的方式非常麻烦,所以提供了apt-get工具集,它有两个优点:
1. 分析软件的依赖关系,下载软件时,自动为用户下载该软件依赖的所有软件。
2. 通过配置源的方式,无需手动搜索,只需要简单输入软件名,即可自动在软件源中查找,下载,安装。
2.配置步骤:
请先完成《双网卡网络配置》,否则无法上网下载软件。
1. 将apt-get源配置为aliyun源
注意:一定不要选择revert(重置),否则配置无法生效
2. 更新软件源:
sudo apt-get autoclean //清除旧源
sudo apt-get update //更新新源
sudo apt-get install -f //重建软件源依赖关系
3. 安装和卸载软件
sudo apt-get install softwarename //安装softwarename软件
sudo apt-get remove softwarename //卸载softwarename软件
3.测试:
1. 可以下载vsftpd软件来测试apt-get工具集是否配置正确
2. 查看软件是否安装成功
3.minicom配置
1.概念:
在嵌入式开发中,开发板的工作状态查看和对开发板指令的控制都通过串口来实现,我们需要一个工具来与开发板实现信息的交互,常用的软件有putty、 SecureCRT、 minicom等,我们采用Ubuntu中常用的minicom软件。
2.配置步骤:
请先完成《双网卡网络配置》及《apt-get源设置》章节,否则无法安装minicom软件。
1. 使用apt-get工具集安装minicom
可以通过命令查看minicom是否安装成功:
2. 连接开发板串口线连接到虚拟机中
3. 首次使用时需要配置minicom(后续则无需再次配置)
退出后进入minicom界面
启动开发板后即可看到打印信息的
3.测试
1. 后续使用minicom,可以直接通过如下命令进入
sudo minicom
2. 退出minicom
ctrl + a
q 选
择yes, 即可退出
4.tftp服务器配置
1.概念:
tftp是基于TCP/IP网络协议的一个应用层协议,主要用来实现简单文本的传输,在嵌入式开发中,一般用于开发板和电脑间文件的传输。比如:开发板需要内核镜像文件,就可以使用tftp从服务器下载,并在开发板中运行。
2.配置步骤:
请先完成《双网卡网络配置》及《apt-get源设置》章节,否则无法安装tftp软件。
1. 使用apt-get工具集安装tftpd-hpa服务器软件和tftp客户端软件:
2. 打开服务器端的tftpd-hpa配置文件:
3. 修改配置文件内容如下:
tftp必须要进行服务器端的配置,我们应该指定允许客户端下载哪个目录下的文件,如果不设置客户端随意下载服务器文件,岂不是会产生信息安全问题。
注意:
TFTP_DIRECTORY:是指服务器端的tftp管理目录,服务区允许客户端下载文件的目录路径,也是客户端上传文件到服务器的目录路径
4. 创建对应的tftp管理目录路径
5. 重启tftp服务器
3.测试:
可以通过tftp客户端来访问服务器完成简单文件的上传和下载:
1. 上传功能测试:
1. 在任意目录下创建一个文件写入内容
echo "hello tftp" > a.txt
2. 上传当前目录下的a.txt到tftp服务器管理目录下
tftp 192.168.1.100 //使用tftp连接192.168.1.100服务器
put a.txt //将当前目录的a.txt文件上传到tftp服务
器端的tftp管理目录下
quit //退出tftp软件
3. 查看tftp管理目录下是否存在a.txt文件,文件内容是否与上传内容一致
管理目录中的文件与上传文件一致,上传功能成功。
2. 下载功能测试:
1. 在tftp管理目录下创建b.txt,并写入文件内容
2. 在任意目录下使用tftp软件下载b.txt文件
3. 查看当前目录下的b.txt文件内容是否与tftp管理目录中的内容一致
5.nfs服务器配置
1.概念:
nfs是基于网络的一种分布式文件系统协议,允许主机利用网络来实现目录的挂载。在嵌入式开发中,我们通常将开发板的文件系统挂载到Ubuntu的指定目录下,形成共享文件,这样我们在Ubuntu下编写软件,编译软件,将可执行程序放到共享目录下,开发板即可拿到代码,并执行代码。有了nfs,我们就不需要手动拷贝代码到开发板中,提高了开发效率。
2.配置步骤:
请先完成《双网卡网络配置》及《apt-get源设置》章节,否则无法安装nfs软件。
1. 安装nfs软件
2. 配置nfs配置文件
设置nfs的配置文件,指定服务器端允许客户端挂载的目录,及对客户端IP地址的筛选。
修改配置文件为如下形式:
/home/linux/nfs/rootfs 表示允许客户端挂载的服务器目录路径
* 表示允许所有客户端挂载
rw 表示允许客户端读写
sync 表示客户端读写后, 服务器同步写入磁盘
no_subtree_check 表示无需检测子目录权限
3. 创建共享目录并修改文件权限
4. 修改nfs的版本信息
5. 重启虚拟机
6. 重启nfs服务:
3.测试:
1. 先通过命令查看nfs允许的挂载目录
2. 测试将/mnt目录挂载到nfs服务器端的/home/linux/nfs/rootfs下
挂载成功,将/mnt目录挂载到192.168.1.100的/home/linux/nfs/rootfs文件夹下,形成共享文件夹
3. 创建文件测试是否实现共享功能
测试成功,此时在/mnt目录下的操作/home/linux/nfs/rootfs目录下也会实现响应操作
4. 卸载目录
6、交叉编译工具链,之前已经下载过了。