1、Linux 系统要启动需要通过 bootloader 程序引导,也就说芯片上电以后先运行一段 bootloader 程序。
2、uboot是一个裸机程序,就是一个bootloader,作用就是用于启用linux或其他系统。uboot最主要的工作就是初始化DDR。
在实际开发中,我们一般不会直接用 uboot 官方的 U-Boot 源码的,一般使用开发板半导体厂商提供的更全面。
区别:
种类 | 描述 |
uboot 官方的 uboot 代码 | 由 uboot 官方维护开发的 uboot 版本,版本更新快,基本包含所有常用的芯片。 |
半导体厂商的 uboot 代码 | 半导体厂商维护的一个 uboot,专门针对自家的芯片,在对自家芯片支持上要比 uboot 官方的好。 |
开发板厂商的 uboot 代码 | 开发板厂商在半导体厂商提供的 uboot 基础上加入了对自家开发板的支持。 |
在解压后的目录下,执行命令:
make distclean
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- stm32mp157d_atk_defcon
fig
make V=1 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- DEVICE_TREE=stm
32mp157d-atk all
其中:
ARCH:指定所使用的平台架构,这里肯定是 arm。
CROSS_COMPILE:所使用的交叉编译器前缀,本教程使用的是交叉编译器前缀为 arm-none-linux-gnueabihf-。
DEVICE_TREE:设备树文件,uboot 也支持设备树,所以在编译的时候需要指定设备树文件,不同的硬件其设备树文件肯定不同。
直接输入“make”命令的话默认使用单线程编译,编译速度会比较慢,可以通过添加“-j”选项来使用多线程编译。
make V=1 DEVICE_TREE=stm32mp157d-atk all -j8 //8 线程编译
编译完成以后的 就会在 uboot 源码目录下生成相应的镜像文件
1、使用 STM32CubeProgrammer 将上面编译出来的 u-boot.stm32 镜像烧写到开发板的 EMMC
里面。
2、完成以后设置开发板上的拨码开关,设置从 EMMC启动,然后用 USB Type-C 线将开发板上的 USB_TTL 接口与电脑连接起来,因为我们要在串口终端里面输入命令来操作 uboot。
uboot 的主要作用是引导 kernel,我们现在已经进入 uboot 的命令行模式了,进入命令行模式以后就可以给 uboot 发号施令了。
信息查询有关的命令有 3 个:bdinfo、printenv 和 version
两个命令:setenv 和 saveenv
setenv 命令用于设置或者修改环境变量的值
saveenv命令 用于保存修改后的环境变量,一般环境变量存放在外部 flash 中,uboot
启动的时候会将环境变量从 flash 读取到 DRAM 中。
内存操作命令就是用于直接对 DRAM 进行读写操作的,常用的内存操作命令有 md、nm、
mm、mw、cp 和 cmp。
md 命令用于显示内存值,格式如下:
md[.b, .w, .l] address [# of objects]
命令中的[.b .w .l]对应 byte、word 和 long,也就是分别以 1 个字节、2 个字节、4 个字节
来显示内存值。address 就是要查看的内存起始地址,[# of objects]表示要查看的数据长度,这个
数据长度单位不是字节,而是跟你所选择的显示格式有关。
nm 命令用于修改指定地址的内存值,命令格式如下:
nm [.b, .w, .l] address
nm 命令同样可以以.b、.w 和.l 来指定操作格式,比如现在以.l 格式修改 0XC0100000 地址
的数据为 0x12345678
mm 命令也是修改指定地址内存值的,使用 mm 修改内存值的时候地址会自增,而使用 nm
命令的话地址不会自增。
命令 mw 用于使用一个指定的数据填充一段内存,命令格式如下:
mw [.b, .w, .l] address value [count]
mw 命令同样以.b、.w 和.l 来指定操作格式,address 表示要填充的内存起始地址,value 为
要填充的数据,count 是填充的长度。比如使用.l 格式将以 0XC0100000 为起始地址的 0x10 个
内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A,命令如下:
mw.l C0100000 0A0A0A0A 10
cp 是数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中,或者把
NorFlash 中的数据拷贝到 DRAM 中。命令格式如下:
cp [.b, .w, .l] source target count
cp 命令同样以.b、.w 和.l 来指定操作格式,source 为源地址,target 为目的地址,count 为
拷贝的长度
uboot 是支持网络的,我们在移植 uboot 的时候一般都要调通网络功能,因为在移植 linux
kernel 的时候需要使用到 uboot 的网络功能做调试。uboot 支持大量的网络相关命令,比如 dhcp、ping、nfs 和 tftpboot
开发板的网络能否使用,是否可以和服务器(Ubuntu 主机)进行通信,通过 ping 命令就可以
验证,直接 ping 服务器的 IP 地址即可
dhcp 用于从路由器获取 IP 地址,前提是开发板得连接到路由器上的,如果开发板是和电
脑直连的,那么 dhcp 命令就会失效
nfs(Network File System)网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,
比如我们将 linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中
的 linux 镜像和设备树下载到开发板的 DRAM 中。
要启动 Linux,需要先将 Linux 镜像文件拷贝到 DRAM 中,如果使用到设备树的话也需要
将设备树拷贝到 DRAM 中。
bootm 命令用于启动 uImage 镜像文件,bootm 命令格式如下:
bootm [addr [arg ...]]
命令 bootm 主要有三个参数,addr 是 Linux 镜像文件在 DRAM 中的位置,后面的“arg…”
表示其他可选的参数,比如要指定 initrd 的话,第二个参数就是 initrd 在 DRAM 中的地址。如
果 Linux 内核使用设备树的话还需要第三个参数,用来指定设备树在 DRAM 中的地址,如果不
需要 initrd 的话第二个参数就用‘-’来代替。
bootz 和 bootm 功能类似,但是 bootz 用于启动 zImage 镜像文件,bootz 命令格式如下:
bootz [addr [initrd[:size]] [fdt]]。
1、获取U-Boot源码打补丁
cd xx///进入 uboot 源码目录
for p in `ls -1 ../*.patch`;do patch -p1 < $p;done //打补丁
2、修改makefile
Makefile 文件里面添加 ARCH 和 CROSS_COMPILE 这两个变量的值
ST 官方 uboot 肯定适配了官方的 STM32MP1 EVK 开发板,我们就编译 EVK 开发板对应的 uboot,编译完成以后将得到的 uboot 可执行文件烧写到 STM32MP1 57开发板中,看看能不能运行,不能的话就要修改 uboot 相应的文件,这就是 uboot 的移植。
编译命令:
make stm32mp15_trusted_defconfig
make DEVICE_TREE=stm32mp157d-ev1 all -j8
uboot 编译成功,生成了 u-boot.bin 和 u-boot.stm32,u-boot.bin 包含了设备树(dtb),也就是将 uboot 镜像和设备树打包在了一起。其中 u-boot.stm32 是在 u-boot.bin前面添加了 256 字节头部信息的可执行文件,是要烧写到开发板里面的。
看是否有问题,若不能正常使用,就需要修改了。
3、在u-boot中添加自己的开发板
在第一次编译uboot时,执行:
make stm32mp15_trusted_defconfig
使用默认配置文件配置一下 uboot,stm32mp15_trusted_defconfig 这个文件保存了默认配置选项
在uboot源码目录下,运行:
cd configs//进入 uboot 的 configs 目录
cp stm32mp15_trusted_defconfig stm32mp15_atk_trusted_defconfig //拷贝
此时在 uboot 的 configs 目录下就存在一个名为“stm32mp15_atk_trusted_defconfig”的默认
配置文件,这个默认配置文件就是给我们开发板使用的。
4、创建默认配置设备树
直接复制 ST 官方 EVK开发板对应的设备树,在 uboot 的源码目录下,运行以下命令:
cd arch/arm/dts///进入 uboot 设备树目录
cp stm32mp157d-ed1.dts stm32mp157d-atk.dts //复制.dts
cp stm32mp15xx-edx.dtsi stm32mp157d-atk.dtsi //复制.dtsi
cp stm32mp157a-ed1-u-boot.dtsi stm32mp157d-atk-u-boot.dtsi //复制.dtsi
①打开stm32mp157d-atk.dts 文件, 将stm32mp15xx-edx.dtsi 这个设备树头文件,我们要将其改为上面创建的 stm32mp15d-atk.dtsi。
②修改电源管理,打开 stm32mp157d-atk-u-boot.dtsi 这个文件,将代码中的的 21~22 行、26~31 行和 51~53 行都删除,修改 stm32mp157d-atk.dtsi 文件,中 90~104 行的 adc 节点、114~125 行的 dac 节点以及 143~298 行的i2c4 节点全部删除掉。然后将 led 和 sd_switch 节点信息,将这两个节点都删除掉。
③向 stm32mp157d-atk.dtsi 文件的根节点‘/’下添加自己的电源管理配置。
vddcore: regulator-vddcore {
compatible = "regulator-fixed";
regulator-name = "vddcore";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};
v3v3: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v8_audio: regulator-v1v8-audio {
compatible = "regulator-fixed";
regulator-name = "v1v8_audio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
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;
};
vdd_usb: regulator-vdd-usb {
compatible = "regulator-fixed";
regulator-name = "vdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
④修改TF卡和EMMC配置
修改 stm32mp157d-atk.dtsi 文件,找到 sdmmc1 和 sdmmc2 这两个节点,进行修改。
⑤添加前面创建的设备树,打开 arch/arm/dts/Makefile文件,找“dtb-$(CONFIG_STM32MP15x)”配置项,然后在此配置项中加入“stm32mp157d-atk.dtb”
其他配置参看正点原子视频教程。
uboot 或 Linux 内核可以通过输入“make menuconfig”来打开图形化配置界面,menuconfig
是一套图形化的配置工具,需要 ncurses 库支持。
首先,安装对应的库:
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev
在打开图形化配置界面之前,要先使用“make xxx_defconfig”对 uboot 进行一次默认配置,只需要一次即可。如果使用“make clean”清理了工程的话就那就需要重新使用“makexxx_defconfig”再对 uboot 进行一次配置。进入 uboot 根目录,输入如下命令:
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- stm32mp15_atk_trusted_d
efconfig
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- menuconfig
如果已经在 uboot 的顶层 Makefile 中定义了 ARCH 和 CROSS_COMPILE 的值,那么上述命令可以简化为:
make stm32mp15_atk_trusted_defconfig
make menuconfig
根据要求,配置对应的选项
图形化配置工具的主要工作就是在.config 下面生成前缀为“CONFIG_”的变量,这些变量
一般都有值,为 y,m 或 n,在 uboot 源码里面会根据这些变量来决定编译哪个文件。
其中,后面进行 Linux 驱动开发的时候可能会涉及到修改 Kconfig,所以可以了解一下相关的语法;
资料参考:正点原子文档以及视频资料