树莓派系统默认安装的是ARM32位的系统,可是从树莓派3开始是支持ARM64位系统的,官方既然不给64位系统, 那只好咱们本身来编译了。linux
网上其实有不少树莓派3B的编译64位内核,我都试了一遍,所有启动不了,也不是说写得不对,只不过好像不适用于我,搞了我三四天,很愁人;因此我下面的步骤也不保证每一个人均可以成功,由于每一个人的状况都不同,形成的问题也不同,因此出现问题只能靠本身百度或者Google了。git
并且有不少笔记只是把内核编译为64位,可是文件系统仍是官方的32位,并不能称为真正的64位系统,因此我后面也把根文件系统也构建为64位的了。github
笔记在记载的时候不免有遗漏的,若是有哪一个步骤不太对,欢迎留言,及时修改。bootstrap
若是不想这么麻烦,想直接使用64位的系统,能够下载已经开源的64位系统:Debian-Pi-Aarch64,这个是第三方的,不是树莓派官方提供的。ubuntu
经过vm虚拟机安装的虚拟环境Linux,如何安装网上一搜就有了,按照步骤安装便可。vim
编译机:Ubuntu 18.04-desktop-amd64bash
想要编译64位的内核,只能在64位的机器上来编译。架构
经过交叉编译器生成64位的内核(Kernel)app
定义:交叉编译器(英语:Cross compiler)是指一个在某个系统平台下能够产生另外一个系统平台的可执行文件的编译器async
这句话个人理解形象一点解释就是:
Ubuntu 18.04-amd64:定制服装加工工厂(某个系统平台)
交叉编译器:制做衣服的机器(编译器)
linux源码(kernel):服装材料(可执行文件的源码)
树莓派4B:人(另外一个平台)
有了以上,如今我要给人作一件衣服,那么我须要找一个专门给人作衣服的工厂,把服装材料给工厂后,制做衣服的机器作出来的衣服,人就能够穿了。
每一个人理解的都不同,只要记住上面专业的定义就行了,本身怎么理解按本身的来就能够了。
就如上面定义的同样,那四样咱们都须要先获取到才能够制做;Ubuntu确定先要安装好;树莓派固然也要准备好。
能够用普通用户,尽可能不要用root用户来执行,等须要用到root用户时,再切换到root用户来执行
下载上面连接中的 gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz,有可能更新了,日期和版本会变化。 或者用命令下载
$ sudo wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz
复制代码
建立一个工做目录,后续的操做都在工做目录中操做
$ mkdir ~/build && cd ~/build
$ sudo apt-get install lrzsz
# 把下载好的文件上传并解压
$ rz
$ sudo tar -xvf gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz -C /usr/src/
$ cd /usr/src/ && sudo mv gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu aarch64-linux-gnu
$ sudo vi /etc/profile
or
$ sudo vi ~/.bashrc
# 末尾添加如下内容
export ARCH_HOME=/usr/src/aarch64-linux-gnu
export PATH=$PATH:$ARCH_HOME/bin
$ source /etc/profile
or
$ source ~/.bashrc
复制代码
Note:若是是在普通用户下,还须要切换到root下再配置一遍,普通用户也须要配置
raspberry如今默认的就是4.19版本,不过更高的版本也是有的,看本身下载哪一个更改一下版本就能够了,Raspberry官方的github下载超级慢,我是把Raspberry Linux迁移到了国内码云上,这样下载起来就很快了;有区别的就是官方更新,不会更新到个人码云的仓库上,想要最新的代码,能够先把官方的fork到本身的github,再迁移到本身的码云,把连接更换成本身的就能够了,下面的命令选择一个下载就能够了
$ cd ~/build
$ sudo apt-get install git
# 官方的github地址
$ git clone --depth=1 --branch rpi-4.19.y https://github.com/raspberrypi/linux
# 码云的地址
$ git clone --depth=1 --branch rpi-4.19.y https://gitee.com/nzwxl/linux
复制代码
$ sudo apt-get install git bison flex libssl-dev zip libncurses-dev make
复制代码
libncurses-dev依赖是支持后面menuconfig的
# 若是源码文件不叫linux,能够mv 改为linux或者你想要的的名字
$ cd linux
# 在编译以前能够先进行清除命令,以保证清洁的环境,若是在编译的环节出错或者操做失误,能够运行此命令从新开始。
$ make distclean
# 编译.config,ARCH要配置成arm64,若是不配置则默认为开发机的x86了,CROSS_COMPILE指定编译器
# bcm2711_defconfig在 arch/arm64/configs/bcm2711_defconfig,它会本身根据Makefile本身去找这个文件
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
# 在当前的.config基础上开始裁剪内核,若是没有要裁剪的按ESC两次退出便可,主要是我也没太了解,等我了解了再记
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
# 开始编译内核, 参数-j5的意思是 使用多处理器同时编译内核,数字最大为:cpu的核数 × 1.5,可自行修改
$ make -j5 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
复制代码
中间不报错的话,大概会在1个小时左右,会在目录 arch/arm64/boot 中生成 Image 二进制内核文件;若是制做的是32为内核,会在 arch/arm/boot 生成zImage 二进制内核;同时会在linux目录中生成最原始的内核文件vmlimux。
vmlinunx:最原始的linux内核文件。
zImage: 通过压缩和去掉调试信息的可加载二进制内核文件。
Image:没有通过压缩的可加载二进制内核文件。
有关更多关于内核文件可Google。
这个modules在后面的根文件系统(rootfs)中用的到,先安装到 ~/build 工做目录中,记得把 [user] 替换为本身的用户名
$ cd ~/build/linux
# 切换到root用户下
$ su
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/home/[user]/build/ modules_install
$ su [user]
复制代码
由于树莓派官方的 bootloader 是不开源的,可是提供了可使用的boot目录下全部的东西,一样的我由于网速的缘由下载太慢,迁移到了码云上。
$ cd ~/build
$ git clone --depth=1 https://github.com/raspberrypi/firmware/
or
$ git clone --depth=1 https://gitee.com/nzwxl/firmware/
# firmware/boot 下就是须要的文件了
$ ls firmware/boot
复制代码
如何制做ARM64的rootfs我在另外一篇笔记中记录了,到此步骤能够继续按照那篇笔记顺序操做,等rootfs制做完,回到此笔记与下一个步骤衔接
经烧录后显示,1000M的话已经使用了90%,因此要是有许多要作的事情,或者上传一些东西的话,最好建立个比较大一点的映像文件
$ cd ~/build
$ fallocate -l 1000M rootfs.img
# 分区
$ fdisk rootfs.img
a.输入o。这将清除映像文件上的任何分区。
b.键入p以列出分区。应该没有分区。
c.键入n,而后p为primary,1表示驱动器上的第一个分区,按ENTER接受默认的第一个扇区,而后为最后一个扇区键入+ 100M。
d.键入t,而后c将第一个分区设置为键入W95 FAT32(LBA)。
e.键入n,而后p表示主驱动器,2表示驱动器上的第二个分区,而后按两次ENTER键接受默认的第一个和最后一个扇区。
f.写入分区表并键入w退出。
# 可经过命令查看设置好的分区
$ fdisk -l rootfs.img
复制代码
在linux中,若是映像文件(.img)含有分区表的话,使用mount是挂在不上的;可使用kpartx挂载; X是你显示的数字,Y也是数字,每一个人不必定相同,第一个 loopXpY 是上面分区后的第一个分区,第二个就是第二个分区
$ sudo apt-get install kpartx
$ sudo kpartx -av rootfs.img
add map loopXpY (254:0): 0 204800 linear 7:0 2048
add map loopXpY (254:1): 0 407552 linear 7:0 206848
# 这两个设备能够在 /dev/mapper/ 目录中看到
$ ls /dev/mapper/
复制代码
$ sudo mkfs.vfat -n BOOT /dev/mapper/loop5p1
$ sudo mkfs.ext4 -F -L -O "^has_journal" ROOTFS /dev/mapper/loop5p2
# 第一个命令中的-n 参数就是指定LABEL,能够经过 man mkfs.vfat 查看参数详情
# 第二个命令的 -F 是强制的意思(理解的不对能够纠正我),-L 指定LABEL 一样能够经过man mkfs.ext4 查看参数详情
复制代码
通过格式化分区后,如今咱们能够挂载loopXpY设备到文件
$ sudo mkdir {/mnt/loopXp1,/mnt/loopXp2}
$ sudo mount /dev/mapper/loop5p1 /mnt/loopXp1
$ sudo mount /dev/mapper/loop5p2 /mnt/loopXp2
复制代码
$ cd ~/build
# 复制boot所需文件
$ sudo cp -r firmware/boot/* /mnt/loopXp1/
$ sudo cp linux/arch/arm64/boot/dts/broadcom/*.dtb /mnt/loopXp1
$ sudo cp linux/arch/arm64/boot/dts/overlays/*.dtb* /mnt/loopXp1/overlays/
$ sudo cp linux/arch/arm64/boot/dts/overlays/README /mnt/loopXp1/overlays/
# 复制内核
$ sudo cp linux/arch/arm64/boot/Image /mnt/loopXp1/kernel8.img
复制代码
编写cmdline.txt
# 添加内容并保存退出
$ sudo vim /mnt/loopXp1/cmdline.txt
console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait fsck.repair=yes
复制代码
编写config.txt
# 添加内容并保存退出
$ sudo vim /mnt/loopXp1/config.txt
# 以64位读取内核
arm_64bit=1
# 想要以ARMV8的模式启动,设置此选项
arm_control=0x200
# 内核的名字
kernel=kernel8.img
# u-boot进行引导kernel时延迟几秒
boot_delay=1
# 关闭蓝牙功能
# See /boot/overlays/README for all available options
dtoverlay=disable-bt
# 开启音频snd_bcm2835
dtparam=audio=on
复制代码
$ sudo apt-get install rsync
$ cd ~/build/linux-rootfs/
# 开始同步
$ sudo rsync -HPavz -q ./ /mnt/loopXp2
复制代码
rsync参数详解: rsync命令
若是想要第一分区中的boot目录在系统启动后显示文件,须要在 /etc/fstab 中添加如下内容:
$ sudo vim /mnt/loopXp2/etc/fstab
<file system> <mount point> <type> <options> <dump> <pass>
LABEL=BOOT /boot vfat defaults 0 1
复制代码
由于在编译kernel时已经把modules安装到了工做目录build中了,直接复制到第二分区中就能够了,若是不放心,能够用安装modules的命令安装到第二分区下,更改下路径就能够了。
$ cd ~/build
$ sudo cp -r lib/modules/ /mnt/loopXp2/lib/
复制代码
$ cd ~/build
$ sync
$ sudo umount /mnt/loopXp1/
$ sudo umount /mnt/loopXp2/
$ sudo kpartx -dv rootfs.img
复制代码
把 rootfs.img 下载到windowns下 烧录到SD卡中,烧录SD卡的方式可参考:
启动Raspberry后经过命令查看内核版本为64位