文章目录
回顾:
- 学习交叉编译的时候了解到树莓派的操作系统也是需要经过交叉编译后再放到树莓派上,否则无法安装gcc编译器。而平台的运行需要至少两样东西:bootloader(启动引导代码)以及操作系统核心。本文章主要分析树莓派的启动过程以及对树莓派的Linux操作系统内核进行编译,得到时候树莓派的操作系统。
将linux内核代码和编译工具tools上传到ubuntu
- 根据树莓派的版本【执行
uname -r
可以查到】,在https://github.com/raspberrypi/,下载linux工程,要对应当前树莓派的版本
- 下载tools工具下载交叉编译工具并配置环境变量
参考文章:树莓派——交叉编译下的【交叉编译工具链的安装】
树莓派等芯片带操作系统的启动过程
不带操作系统的:
- C51,STM32(裸机)》》》》》》C直接操控底层寄存器实现相关业务。 业务流程型的裸机代码
- 遥控灯: while(1)
- 垃圾桶:WemosD1 LOOP循环
- 恩智浦智能车: stm32
带操作系统的:
-
X86,Intel windows
- 启动过程: 电源 -》 BIOS -》windows内核-》C,D盘-》 程序启动(QQ)
-
嵌入式产品: 树莓派,mini2440, mini6410,nanopi,海思,RK(瑞芯微)
- 启动过程: 电源-》BootLoader(引导操作系统启动)-》Linux内核-》文件系统(根据功能性来组织文件夹,带访问权限)-》KTV点歌机
- 文件系统在根目录下,dev放设备,lib放库,proc内核相关信息,home是用户登录的工作界面,sbin可执行文件或指令,bin可执行文件或指令,boot启动时候的相关数据
- 交叉编译的原因:只有存在linux系统才能编译文件,但是启动前还没有bootloader、linux内核、以及文件系统,所以需要使用交叉编译让bootloader、linux内核等可以为树莓派所使用
-
安卓:
- 启动过程: 电源-》 fastBoot/Bootloader/-》linux内核-》文件系统-》虚拟机(跑java代码)-》HOME应用程序-》点某图标打开某APP
BootLoader的工作流程:
- 一阶段: 让CPU 跟内存,FLASH, 串口,IIC,IIS, 数据段,打交道,驱动这些设备(汇编和C结合)
- 二阶段: 引导Linux内核启动 (纯C)
树莓派Linux源码目录树分析
可以查看Linux操作系统基础文章下的【Linux 系统目录】
树莓派Linux源码配置
Linux源码特点:
- Linux是开源,免费,LInux开源社区工作者共同维护,爱好
- Linux是一个开源的,支持多架构多平台代码,可移植性非常高
- Linux内核代码非常多,但是Linux内核编译出来一般就几M
- 因为支持多平台(arm、mips、powerpc、x86等),多架构,所以编译之前要配置,配置成适合的目标平台来用
为什么要对Linux内核进行配置?
- 因为从事驱动代码的编写时,驱动代码的编译需要一个提前编译好的内核,而编译内核就必须配置,将有用的文件编译出来,内核配置的最终目标会生成 .config文件,该文件指导Makefile去把有用东西组织成内核【适用于某个平台的内核】
如何对Linux内核进行配置?
- 第一种方式:
- 厂家给相应平台的linux内核源码,比如说买了树莓派,给树莓派linux内核源码
- cp 厂家.config .config
- 第一章将树莓派4.14版本的linux内核源码已经放到ubuntu中,在unbuntu的树莓派源文件夹中执行如下命令找到配置文件
find . -name *_defconfig
- 查找到./arch/arm/configs/bcm2709_defconfig【树莓派3使用的配置文件】
- 参考下面案例的方式一进行配置
- 第二种方式:
- make menuconfig 一项项配置,通常是基于厂家的config来配置
- 参考下面案例的方式二进行配置
- 第三种方式:
- 完全自己来
注意:
linux源码中有很多工程:
- 树莓派1的工程是bcmrpi_defconfig;
- 树莓派2、3的工程是bcm2709_defconfig。
配置树莓派的Linux内核
参考博文:
前期工作:
- 完成相应版本树莓派Linux内核源码上传到ubuntu
- 完成交叉编译工具链的永久配置
方式一:
在源码目录下将厂家的config文件拷贝到本地
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
- 指定ARM架构为arm
- CROSS_COMPILE指定编译器为arm-linux-gnueabihf
- KERNEL=kernel7是树莓派的固定配置,是核心指令
- 厂家的config文件的名称
方式二: 如果没什么改的就不用执行这一步
- 执行
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make menuconfig
则是在本地config文件上进行配置 - 可能需要安装:nurses libraries,执行
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g:i386
sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5
- nurses是个界面,提供可视化配置
- 自定义配置,一般只修改Device Drivers,修改设备驱动
驱动两种加载方式:
- 编译进内核 , zImage包含了驱动
- M 模块方式生成驱动文件xxx.ko 系统启动后,通过命令inmosd xxx.ko 加载
树莓派Linux内核编译
编译:
-
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
- j4指定用多少电脑资源进行编译
- zImage生成内核镜像
- modules要生成驱动模块
- dtbs生成配置文件
-
编译成功后,通过ls指令看到源码树目录多了vmlinux【没有压缩】,失败则无此文件,目标zImage镜像arch/arm/boot底下
注意:
- 报错:usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x10): multiple definition of ‘yylloc’; scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here collect2: error: ld returned 1 exit status
- 解决方案:降低gcc版本为9并提高其优先级
打包zImage文件:
-
在源码数目录下打包zImage成树莓派可用的xxx.img
-
直接用linux源码包里的工具:
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
-
在本目录生成一个kernel_new.img文件,这个文件就是要放到sd卡中的文件。
数据拷贝
-
需要将U盘连接到虚拟机的位置而不是本机
- 虚拟机-》可移动设备-》找到相应的U盘设备进行连接
-
sudo dmesg查看内核信息,当有设备接入的时候内核会打印信息,可以看到树莓派的sd卡有sdb1和sdb2两个分区【对应fat分区和ext4分区】
- dmesg 是通过读取kernel中ring buffer的数据,然后将其打印到标准输出(standard output-也就是我们的终端界面进行打印).
-
在当前用户下创建两个文件夹:
- mkdir data1
- mkdir data2
-
挂载分区到U盘
- sudo mount /dev/sdb1 data1 一个fat分区,是boot相关的内容,kernel的img
- sudo mount /dev/sdb2 data2 一个是ext4分区,也就是系统的根目录分区。
-
安装modules, 设备驱动文件: 也就是设置hdmi usb wifi io …
-
进入到树莓派linux内核目录中执行
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=[ext4] modules_install
将ext4替换成data2的绝对路径 -
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/fangjiarong/data2 modules_install
-
-
安装更新 kernel.img 文件,在data1文件夹中,镜像名字是kernel7.img【其实就是执行第四步cp,但覆盖前先拷贝】
-
更新之前先备份
cd /home/fangjiarong/data1
cp kernel7.img kernel7OLD.img
- cd 树莓派Linux内核目录下,该目录下有kernel_new.img
- 再把编译新生成的kernel_new.img拷贝到data1,起名kernel7.img
cp kernel_new.img /home/chenlc/data1/kernel7.img
-
查看是否拷贝成功
md5sum kernel_new.img
md5sum /home/chenlc/data1/kernel7.img
-
在树莓派Linux内核目录下安装配置文件
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/
修改为下方
cp arch/arm/boot/dts/.*dtb* /home/chenlc/data1
cp arch/arm/boot/dts/overlays/.*dtb* /home/chenlc/data1/overlays/
cp arch/arm/boot/dts/overlays/README /home/chenlc/data1/overlays/
- 更新完成后把usb卡断开连接,避免占用串口,导致无法通过串口验证该系统是否可以登录,然后修改U盘镜像文件里面的cmdline.txt文件,将其修改为启动串口模式,而不是串口通信模式,插回树莓派即可开机
- 开机后可以用 uname -r 命令查看kernel信息已经改变。