一、树莓派等芯片带操作系统的启动过程
1.X86、Intel、windows等设备的启动过程
启动过程:电源- > BIOS -> windows内核 -> C,D盘的启动 -> 程序的启动(例如QQ的启动)
2.嵌入式产品(树莓派、mini2440、mini6410、nanopi、海思、RK(瑞芯微) )的启动过程
启动过程:电源 -> BootLoader (引导操作系统启动) -> linux内核 -> 文件系统(根据功能性来组织文件夹,带访问权限)-> 实实在在的嵌入式产品的启动(例如KTV点歌机)
3.安卓操作系统的启动过程
启动过程:电源 -> fastBoot/Bootloader/ -> linux内核 -> 文件系统 -> 虚拟机 -> HOME应用程序 -> 点击某图标打开某app
4.C51、STM32(裸机,不带操作系统)的开发流程
不带操作系统的裸机开发是C语言直接操控底层寄存器实现相关业务。
业务流程型的裸机代码:
例如:遥控灯:while(1)
垃圾桶:WemosD1 LOOP(函数)
智能车:stm32
5.文件系统补充
上图都是文件,它是根据功能来放的,比如说dev放的是设备相关,lib放的是各种动态库和静态库,proc放的是内核的数据信息,home是用户登录的工作界面,opt是跟内核底层有关的,sbin通常是可执行文件或指令,bin也是指令和可执行文件,boot是启动要加载的配置等等。
二、树莓派linux源码分析
linux内核认知:
linux内核大约由1.3w个C文件组成,1100w行代码左右
linux是开源的,免费的,linux开源社区由其工作者和爱好者共同进行维护
linux是一个开源的,支持多架构多平台代码
可移植性非常高
但是linux内核编译出来一般就是几M,一般是4M左右
因为是支持多平台多架构,所以在编译之前是需要进行配置的,配置成适合的目标平台来用
三、树莓派内核源码下载
首先使用命令uname -r查看树莓派版本,然后选择相应的版本,下载到共享文件夹,以便拷贝到linux。
顺便下载交叉编译工具链,之前文章写过了,这里就省略了。
四、树莓派Linux源码配置
为什么要进行源码配置呢?
这是因为驱动代码的编写需要驱动代码的编译,而驱动代码的编译需要一个提前编译好的内核,编译内核必须配置。
一般我们购买了芯片,厂家都会配linux内核源码,比如说我们买了树莓派,厂家就会向我们提供树莓派linux内核源码。
linux源码中有很多工程:
树莓派1的工程是bcmrpi_defconfig;
树莓派2跟3的工程是bcm2709_defconfig;
4.1 方式一
使用厂家提供的config进行配置(即 cp 厂家.config .config)
查找厂家的config指令:find -name *_defconfig
解压完后到解压的文件目录查找。
然后在终端执行以下指令
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
代码解释
ARCH=arm(指定当前要编译的是arm架构)
CROSS_COMPILE=arm-linux-gnueabihf- (指定编译器是树莓派,即交叉工具链,arm交叉工具链的安装以及相关环境变量的设置在前面的博文有记录)
KERNEL=kernel7 (指明kernel类型,树莓派1设置为kernel,树莓派2,3设置为kernel7)
make bcm2709_defconfig(make为配置命令)
这个命令的作用就是获取bcm2709_defconfig的配置到config中来
除了以上的方式,我们也可以用最传统的方式:cp arch/arm/configs/bcm2709_defconfig .config 然后去使用这个.config
4.2 方式二
通过make menuconfig 一项项的来配置,通常都是基于厂家的config来进行配置
在此之前,我们要先来安装一下等下要用到的库
sudo apt-get install bc
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g:i386
sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5
4.2.1 对内核菜单进行配置
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make menuconfig
之后会出现以下界面
选项讲解:
General setup —>(通用选项)
[ * ] Enable loadable module support —> 内核模块选项
[ * ]Enable the block layer —> 块设备逻辑层选项(大文件支持、分区、I/O调度)
System Type —>(平台选项)
Bus support —> 总线选项
Kernel Features —>内核特征
Boot options —> 引导选项
CPU Power Management —> CPU电源管理选项
Floating point emulation —> 浮点运算
Userspace binary formats —> 用户程序格式
Power management options —> 电源管理选项
[*] Networking support —> 网络协议选项
Device Drivers —> 设备驱动
Firmware Drivers ---- 驱动固件选项
File systems —> 文件系统选项
Kernel hacking —> 内核调试选项
Security options —> 安全模块选项
选择要配置的文件,例如
指令解释:使用空格可以切换[ ]里面的模式
[*]:编译进内核(*代表Y,编译进内核,zImage包含了驱动)
[M]:编译成模块(以模块的方式生成驱动文件xxx.ko,系统启动后,通过命令inmosd xxx.ko来加载驱动)
[ ]:表示不需要的部分
空格可切换修改。
修改完毕后,保存退出
五、树莓派linux内核源码的编译
5.1编译指令
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
make -j4:指定用多少电脑资源进行编译(j4是四核的意思,这个要每个人根据自己的电脑的配置以及虚拟机的设置的核数来决定)
zImage:生成内核镜像
modules:要生成驱动模块
dtbs:生成配置文件
编译的时间会比较久(看电脑配置),编译过程中如果跑了几分钟没有报错,那基本就是正确的。
编译成功后会生成VMlinux,如下图
vmlinux是未压缩的linux,zImage(目标镜像)是压缩好的linux,在/arch/arm/boot底下。
5.2把zImage打包成树莓派可用的xxx.img文件
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
5.3然后插入树莓派SD卡的U盘,把U盘映射到虚拟机
输入dmesg查看内核信息
如果出现以上图中的sdb1 和 sdb2 那么说明U盘已经成功的映射到虚拟机上了。
5.4创建新目录并挂载U盘
在根目录底下创建文件夹,这里创建了data1和data2两个文件夹。
输入2个命令
sudo mount /dev/sdb1 data1 挂载U盘的sdb1文件分区到当前路径下的data1文件夹 一个fat分区,是boot相关的内容,kernel的img
sudo mount /dev/sdb2 data2 挂载U盘的sdb2文件分区到当前路径下的data2文件夹 一个是ext4分区,也就是系统的根目录分区。
这样两文件夹就有内容了。
5.5安装modules
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=[ext4] modules_install
操作ext4分区需要root权限
[ext4]为第二分区(sdb2)虚拟机上挂载的地址(data2的位置),需要根据自己的地址更改
我的指令为
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/my/data2 modules_install
在linux-rpi-4.14.y目录底下输入我的指令。
安装后hdmi接口、usb、wifi、io口等等的设备才能使用。
5.6安装更新 kernel.img 文件,注意镜像名字是kernel7.img
首先我们先把原本的镜像进行备份,以防新的镜像损坏导致树莓派无法启动
接着把新编译生成的镜像拷贝到data1即boot分区底下,起名为kernel7.img
我们来查看文件大小
指令:
du xxx 这样是以kb为单位查看文件的大小
du xxx -h 在文件的后加上-h后,是以M为单位查看文件的大小
查看文件在拷贝过程中是否有损坏
在文件拷贝的过程中有一个md5的值,如果拷贝过程中文件没有损坏的话,md5的值是不变的,如果拷贝失败或者是文件损坏的话,这个值就会改变
5.7拷贝配置相关文件
cp arch/arm/boot/dts/.*dtb* [fat]/
cp arch/arm/boot/dts/overlays/.*dtb* [fat]/overlays/
cp arch/arm/boot/dts/overlays/README [fat]/overlays/
[fat]为第一分区(sdb1)虚拟机上挂载的地址(data1的位置),需要根据自己的地址更改
我的拷贝代码
cp arch/arm/boot/dts/.*dtb* /home/my/data1
cp arch/arm/boot/dts/overlays/.*dtb* /home/my/data1/overlays/
cp arch/arm/boot/dts/overlays/README /home/my/data1/overlays/
这样就完成了,然后断开与虚拟机的连接,把cmdline.txt更改成以下内容,用串口查看是否刷机成功。
dwc_otg.lpm_enable=0 console=tty1 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
最后启动树莓派
用串口或者远程登录树莓派后,用指令uname -r查看内核版本,发现内核信息已经是发生改变了
更换内核前
更换内核后:
发现尾缀不一样了,也就是内核更换成功。
学习笔记,仅供参考。