Linux内核-配置及编译

来自华清远见研发中心
FarSight讨论 | 贡献2021年3月24日 (三) 15:05的版本 配置tftp

(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转至: 导航搜索

解压内核

建立源码目录

linux@ubuntu:$ cd ~/ FS-MP1A/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/linux-stm32mp-5.4.31-r0
48-1-1-1.png

该目录下以patch结尾的文件为ST官方提供的补丁文件,l linux-5.4.31.tar.xz为标准linux源码包。

解压标准内核源码包

linux@ubuntu:$ tar -xvf linux-5.4.31.tar.xz
48-1-1-2.png

进入内核源码目录下

linux@ubuntu:$ cd linux-5.4.31
48-1-1-3.png

添加STMicroelectronics官方补丁

解压linux内核源码后得到的是Linux社区的标准内核源码,接下来需要将ST官方提供的源码补丁添加到标准内核中。

linux@ubuntu:$ for p in `ls -1 ../*.patch`; do patch -p1 < $p; done

该命令会将上层目录下所有的patch补丁文件应用到当前的内核中。

生成标准板配置文件

生成multi_v7_defconfig默认配置

linux@ubuntu:$ make ARCH=arm multi_v7_defconfig "fragment*.config"

在默认multi_v7_defconfig配置中加入ST官方提供的fragment config

linux@ubuntu:$ for f in `ls -1 ../fragment*.config`; do scripts/kconfig/merge_config.sh -m -r .config $f; done
linux@ubuntu:$ yes '' | make ARCH=arm oldconfig

生成自己的默认配置文件

linux@ubuntu:$ cp .config arch/arm/configs/stm32_fsmp1a_defconfig

取消git中的SHA1

linux@ubuntu:$ echo "" > .scmversion

配置内核

导入交叉编译工具链(如果还未安装SDK可参考《SDK工具链安装》章节进行安装)

linux@ubuntu:$ source /opt/st/stm32mp1/2.6-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

验证开发工具是否安装正确,显示版本信息如下图所示。

linux@ubuntu:$ $CC --version
48-1-4-1.png

在编译前如果需要编译额外的功能或者驱动,可以使用meunconfig来对内核进行配置。

linux@ubuntu:$ make menuconfig
48-1-4-2.png

可以在如上菜单中对内核进行详细的配置。

编译内核

linux@ubuntu:$ make -j4 ARCH=arm uImage vmlinux LOADADDR=0xC2000040
48-1-5-1.png

编译后在内核源码目录下,能够在生成一个vmlinux文件,该文件是没有经过压缩的内核镜像,这个镜像导出了所有的内核符号可以用作仿真调试。

48-1-5-2.png

此外在arch/arm/boot目录下还生成了一个uImage文件,这就是经过压缩的内核镜像。可以用作系统启动。

48-1-5-4.png

编译内核模块

linux@ubuntu:$ make ARCH=arm modules

该操作会将内核中配置为模块的源码进行编译,最终得到ko文件。

48-1-6-1.png

生成设备树

以参考板DK1设备树文件stm32mp15xx-dkx.dtsi和stm32mp157a-dk1.dts为参考,增加stm32mp15xx-fsmp1x.dtsi和stm32mp157a-fsmp1a.dts:

对stm32mp15xx-fsmp1x.dtsi内容进行整理,去掉没有被使用的节点信息和明显与FS-MP1A的硬件没有关系的节点信息。下文内容是删掉了所有暂不使用的节点信息,整理出一个相对简单的设备树文件,确保内核可以正常启动。后续各个外设移植时会陆续增加文件的相关内容。

在arch/arm/boot/dts/ 目录下新建

stm32mp15xx-fsmp1x.dtsi:

#include "stm32mp157-m4-srm.dtsi"
#include "stm32mp157-m4-srm-pinctrl.dtsi"
#include <dt-bindings/mfd/st,stpmic1.h>

/ {
    memory@c0000000 {
        device_type = "memory";
        reg = <0xc0000000 0x20000000>;
    };

    reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;

        mcuram2: mcuram2@10000000 {
            compatible = "shared-dma-pool";
            reg = <0x10000000 0x40000>;
            no-map;
        };

        vdev0vring0: vdev0vring0@10040000 {
            compatible = "shared-dma-pool";
            reg = <0x10040000 0x1000>;
            no-map;
        };

        vdev0vring1: vdev0vring1@10041000 {
            compatible = "shared-dma-pool";
            reg = <0x10041000 0x1000>;
            no-map;
        };

        vdev0buffer: vdev0buffer@10042000 {
            compatible = "shared-dma-pool";
            reg = <0x10042000 0x4000>;
            no-map;
        };

        mcuram: mcuram@30000000 {
            compatible = "shared-dma-pool";
            reg = <0x30000000 0x40000>;
            no-map;
        };

        retram: retram@38000000 {
            compatible = "shared-dma-pool";
            reg = <0x38000000 0x10000>;
            no-map;
        };
    };

    vin: vin {
        compatible = "regulator-fixed";
        regulator-name = "vin";
        regulator-min-microvolt = <5000000>;
        regulator-max-microvolt = <5000000>;
        regulator-always-on;
    };

    v3v3: regulator-3p3v {
        compatible = "regulator-fixed";
        regulator-name = "v3v3";
        regulator-min-microvolt = <3300000>;
        regulator-max-microvolt = <3300000>;
        regulator-always-on;
        regulator-boot-on;
    };

    vdd: regulator-vdd {
         compatible = "regulator-fixed";
         regulator-name = "vdd";
         regulator-min-microvolt = <3300000>;
         regulator-max-microvolt = <3300000>;
         regulator-always-on;
         regulator-boot-on;
     };

};

/*HDMI CEC控制器*/
&cec {
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&cec_pins_b>;
    pinctrl-1 = <&cec_pins_sleep_b>;
    status = "okay";
};

/*循环冗余校验计算单元*/
&crc1 {
    status = "okay";
};

&dma1 {
    sram = <&dma_pool>;
};

&dma2 {
    sram = <&dma_pool>;
};
/*数字钟温度传感器*/
&dts {
    status = "okay";
};
/*图像处理单元*/
&gpu {
    contiguous-area = <&gpu_reserved>;
    status = "okay";
};
/*哈希处理器*/
&hash1 {
    status = "okay";
};

/*处理器间通信控制器*/
&ipcc {
    status = "okay";
};

/*看门狗*/
&iwdg2 {
    timeout-sec = <32>;
    status = "okay";
};

/*随机数发生器*/
&rng1 {
    status = "okay";
};

/*实时时钟*/
&rtc {
    status = "okay";
};

/*sdmmc1 TF卡*/
&sdmmc1 {
    pinctrl-names = "default", "opendrain", "sleep";
    pinctrl-0 = <&sdmmc1_b4_pins_a>;
    pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
    pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
    cd-gpios = <&gpioh 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
    disable-wp;
    st,neg-edge;
    bus-width = <4>;
    vmmc-supply = <&v3v3>;
    status = "okay";
};

&sram {
    dma_pool: dma_pool@0 {
        reg = <0x50000 0x10000>;
        pool;
    };
};

/*命令行终端*/
&uart4 {
    pinctrl-names = "default", "sleep", "idle";
    pinctrl-0 = <&uart4_pins_a>;
    pinctrl-1 = <&uart4_sleep_pins_a>;
    pinctrl-2 = <&uart4_idle_pins_a>;
    pinctrl-3 = <&uart4_pins_a>;
    /delete-property/dmas;
    /delete-property/dma-names;
    status = "okay";
};

/*电源基准缓冲器*/
&vrefbuf {
    regulator-min-microvolt = <2500000>;
    regulator-max-microvolt = <2500000>;
    vdda-supply = <&vdd>;
    status = "okay";
};

在arch/arm/boot/dts/ 目录下新建

stm32mp157a-fsmp1a.dts:

/dts-v1/;
#include "stm32mp157.dtsi"
#include "stm32mp15xa.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxaa-pinctrl.dtsi"
#include "stm32mp15xx-fsmp1x.dtsi"
/ {
    model = "HQYJ STM32MP157 FSMP1A Discovery Board";
    compatible = "st,stm32mp157a-dk1", "st,stm32mp157";

    aliases {
        serial0 = &uart4;
    };

    chosen {
        stdout-path = "serial0:115200n8";
    };

    reserved-memory {
        gpu_reserved: gpu@da000000 {
            reg = <0xda000000 0x4000000>;
            no-map;
        };

        optee_memory: optee@0xde000000 {
            reg = <0xde000000 0x02000000>;
            no-map;
        };
    };
};

&optee {
    status = "okay";
};

由于添加了新文件需修改Makefile才能编译,修改arch/arm/boot/dts/Makefile,添加stm32mp157a-fsmp1a.dts的编译选项(红色字体部分为添加内容):

dtb-$(CONFIG_ARCH_STM32) += \
stm32f429-disco.dtb \
…….
stm32h743i-disco.dtb \
stm32mp157a-avenger96.dtb \
stm32mp157a-dk1.dtb \

stm32mp157a-fsmp1a.dtb \

stm32mp157d-dk1.dtb \

重新编译设备树文件

linux@ubuntu:$ make ARCH=arm dtbs

编译完成后会在arch/arm/boot/dts/目录下生成stm32mp157c-fsmp1a.dtb文件

48-1-7-1.png

将编译好的设备树文件与内核的uImage文件,复制到ubuntu主机的/tftpboot文件夹下,当使用tftp方式下载内核与设备树文件时会用到。

linux@ubuntu:$ cp arch/arm/boot/uImage /tftpboot/
linux@ubuntu:$ cp arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb /tftpboot/

配置tftp

在linux系统移植中,我们使用tftp下载的方式来验证结果。使用tftp下载需要构建pxelinux相关的目录。此部分可参考《通过tftp方式下载linux内核及设备树》章节进行搭建。

如果环境搭建已经搭建完成,需要将ubuntu主机中的/tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17文件内容,暂时替换为如下内容,在后续的移植过程中会根据不同的需求进行修改。

/tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17

# Generic Distro Configuration file generated by OpenEmbedded
menu title Select the boot mode
TIMEOUT 20
DEFAULT stm32mp157a-fsmp1a-emmc
LABEL stm32mp157a-fsmp1a-emmc
KERNEL /uImage
FDT /stm32mp157a-fsmp1a.dtb
APPEND root=/dev/mmcblk1p4 rootwait rw console=ttySTM0,115200

修改01-00-80-e1-42-60-17文件后,继续按照《通过tftp方式下载linux内核及设备树》章节中的描述进行启动。
由于目前还未对源码进行任何修改,在内核启动过程中会停留在如下地方。

48-1-8-1.png

后续会通过对系统源码的修改,逐渐完成整个系统的启动和对外围设备的驱动。