树莓派linux源码获取、源码配置、内核编译(arm64,arm32)

  • Post author:
  • Post category:linux




ps:本篇涉及的Linux内核源码是针对于树莓派的



源码获取


  • Raspberry Pi · GitHub

    • 使用命令:uname -r查看自己树莓派的是什么版本,选择合适的版本

        • v8+:64位
        • v8l+:32位
    • 解压:unzip linux-rpi-6.1.yzip



源码目录树分析

  • 使用tree命令分析源码文件可以知道整个源码有5116个目录,78967个文件

    • Linux系统是一个开源的支持多平台多架构(如:ARM、X86、PowerPc……)的系统,可以移植性非常高。
    • Linux内核编译出来的大小一般就几M的占用内存,整个源码很大是因为涵盖了多平台代码的结果。
    • 正因为支持多平台多架构,其实很多代码并需要不参与编译,所以编译之前要配置,配置成适合的目标平台来用

  • 内核源码结构



源码配置



配置源码的目的

  • 驱动代码的编写的前提(驱动代码的编译)需要一个提前编译好的内核(编译内核前必须配置)
  • 配置的最终目的会生成.config文件,该文指导makefile去把有用的东西组织成内核



配置方式

  1. 厂家配Linux内核源码,比如说买了树莓派,提供了树莓派Linux内核源码(源码里有厂家的config)

    • cp 厂家.config拷贝成.config来使用
  2. make menuconfig一项项配置,通常是基于厂家的config来配置

    • make menuconfig一项项配置,通常是基于厂家的config来配置
  3. 自己来完成(一般厂家来做的事)



分别介绍32位arm和64位arm的配置步骤

linux源码中有很多工程

  • 树莓派1的工程是bcmrpi_defconfig;
  • 树莓派2、3的工程是bcm2709_defconfig。
  • 树莓派4的工程是bcm2711_defconfig。


交叉编译工具

  • 32位:arm-linux-gnueabihf-
  • 64位:aarch64-linux-gnu-



32位(源码目录下进行)

  • 配置config

    • 运行:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make bcm2711_defconfig

      • arm:指定arm架构
      • CROSS_COMPILE=arm-linux-gnueabihf-:指定编译器
      • KERNEL=kernel7l:树莓派厂家要求的(树莓派1-3都是kernel7,树莓派4是kernel7l)
      • make bcm2711_defconfig:主要核心指令

        • 此命令功能是获取bcm2711_defconfig的配置到 .config里。
  • 自定义配置(如果不需要则不用进行这一步)

    • 运行:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make menuconfig
    • 这一步如果没有成功可能是没有安装ncurses库

      • sudo apt-get install libncurses5-dev libncursesw5-dev
    • 执行命令后出现界面(方向键切换,回车键选择或是进入子菜单)

      • 驱动加载的两种方式

        • *(Y)编译进内核 zImage包含了驱动

        • M模块方式生成驱动文件,系统启动后,通过命令inmosd xxx.ko加载

        • 补充


          • 后面有箭头说明有子菜单

          • [ ]里面空的说明不编译进内核(选择性,不编译那么多进内核内核镜像就小,M模式也是让内核变小的一种方式)

  • 编译

    • ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make -j4 zImage modules dtbs

      • arm:指定ARM架构
      • CROSS_COMPILE=arm-linux-gnueabihf-:指定编译器
      • KERNEL=kernel7l:树莓派1-3都是kernel7,树莓派4-32位kernel7l
      • -j4指定4核编译(指定用多少电脑资源进行编译)
      • zImage:生成内核镜像
      • modules:驱动模块
      • detbs:生成配置文件
    • 成功后

      • 内核源码目录下生成
      • 真正的目标文件是zImage:在/arch/arm/boot路径下,需要将其打包成.img结尾的镜像文件
    • 打包zImage文件

      • ./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img(在源码目录下进行)

        • 成功后会在本目录生成一个kernel_new.img文件,这个文件就是要放到树莓派boot目录下的文件。
      • 出现错误

        • 原因:打包工具mkknlimg被淘汰了

        • 解决1(已经验证)

          • 重新下载源码Linux-rpi-4.14.y.zip(低版本的), 在文件夹scripts里找到打包工具mkknlimg拷贝到5.15版本的的scripts文件夹下
        • 解决2(未验证,会报错没有python2)

        • tool_master工具包找到imagetool-uncompressed.py

          • sudo ./(imagetool-uncompressed.py的绝对路径) /zImage(绝对路径)
  • 拷贝相关文件

    1. 装有树莓派系统的sd卡有两个分区

      • 一个是fat分区,是boot相关的内容,kernel的img文件就放在这个分区里(可以不用root权限操作)

      • 一个是ext4分区,也就是系统的根目录分区(需要root权限操作)

    2. 将树莓派的SD卡拔出用读卡器连接ubuntu,并挂载

      • 使用命令dmesg打印内核信息查看ubuntu将读卡器识别成sdb或是sdc亦或其他

      • sudo mount /dev/需要挂载的分区 挂载到的文件夹

        sudo mount /dev/sdb1(这个不一定是sdb1,也有可能是sdc1,不能有/) data1 (这个是fat分区

        sudo mount /dev/sdb2(这个不一定是sdb2,也有可能是sdc2,不能有/) data2 (这个是ext4分区

    3. 安装modules(涉及设备驱动文件:HDMI,USB,WIFI等等)


      • 这一步很重要,如果内核更换了,设备文件没有更换,那么所有的设备驱动都是不能用的(设备驱动文件是有版本的,要和内核版本一致才能用)
      • sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make INSTALL_MOD_PATH=**/home/theone/Desktop/USB/**data2(绝对路径) modules_install
    4. 更新kernel.img文件

      • 法一:前面已经用 mkknlimg 工具打包kernel_new.img文件了,把它复制到boot分区并配置使用即可(推荐使用这种)

        • cp kernel_new.img /home/theone/Desktop/USB/data1/
        • 编辑data1/config.txt文件。在最后一行加入kernel=kernel_new.img
      • 法二:直接将kernel_new.img文件以

        kernel7.img名字

        复制到data1分区进行覆盖(这种方法最好要备份配置之前的树莓派kernel7.img文件)(不推荐使用这种)

        • cp kernel_new.img /home/theone/Desktop/USB/data1/kernel7.img
        • 复制完之后进行校验

          • md5sum kernel_new.img
          • md5sum /home/theone/Desktop/USB/data1/kernel7.img
        • 一致的话说明复制成功
    5. 复制其他文件

      • cp arch/arm/boot/dts/.*dtb /home/theone/Desktop/USB/data1
      • cp arch/arm/boot/dts/overlays/.

        dtb

        /home/theone/Desktop/USB/data1/overlays/
      • cp arch/arm/boot/dts/overlays/README /home/theone/Desktop/USB/data1/overlays/
    6. sudo umount mnt/data1

      sudo umount mnt/data2



64位(源码目录下进行)

  • 输入以下命令以构建源和设备树文件

    • cd 源文件名(来到获取的源文件目录)

      KERNEL=kernel8

      make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
  • 使用配置构建

    • make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs -j4
  • 将树莓派的SD卡拔出用读卡器连接ubuntu,并挂载

    • 使用命令sudo dmesg打印内核信息查看ubuntu将读卡器识别成sdb或是sdc亦或其他

      • 在内核源码目录下

        • mkdir mnt
        • mkdir mnt/fat32
        • mkdir mnt/ext4
        • sudo mount /dev/sdb1 mnt/fat32
        • sudo mount /dev/sdb2 mnt/ext4
  • 将内核模块安装到 SD 卡上(挂载成功后执行)

    • sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=mnt/ext4 modules_install
  • 将内核和设备树 blob 复制到 SD 卡上,确保备份旧内核(我选择使用这一方法:将内核复制到同一位置,但使用不同的文件名而不是覆盖文件。然后,编辑文件config.txt以选择树莓派将启动的内核)

    • 将编译生成的内核镜像拷贝到树莓派的fat32分区做为的内核命名为:kernel8_new.img

      • sudo cp arch/arm64/boot/Image mnt/fat32/kernel8_new.img
    • 拷贝其他文件

      • sudo cp arch/arm64/boot/dts/broadcom/*.dtb mnt/fat32/

      • sudo cp arch/arm64/boot/dts/overlays/

        .dtb

        mnt/fat32/overlays/

      • sudo cp arch/arm64/boot/dts/overlays/README mnt/fat32/overlays/

    • 编辑文件mnt/fat32/config.txt,指定内核为新内核

        • 补充:kernel=kernel8_new.img(

          不能有多余的符号,空格也不能有,如上图所示是错误的没有指定内核成功的,如果还不行那就放在最后一行

          )
    • 卸载

      • sudo umount mnt/fat32

        sudo umount mnt/ext4
    • 结果



可能遇到的问题

    • sudo apt-get install flex
  1. 错误: /bin/sh: 1: bision: not foung

    • sudo apt-get install bison
    • sudo apt-get install libssl-dev



参考


Raspberry Pi 文档 – Linux 内核



版权声明:本文为aieiji123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。