02. MT7981设备引导程序初探

联系邮箱:li_cloud6630@qq.com

从一牛网上拷贝过来的芯片的框图如下:

具体的规格可以从这个链接里面看:

plain 复制代码
https://bbs.16rd.com/thread-599254-1-1.html

从图上和搜到的一些资料,这种芯片大概是支持spi-nor,spi-nand,emmc,uart等启动。用的最多的也就是这四种,然后根据做成的产品的不同的规格来定用的启动方式,uart启动应该是救砖用的,挺好的功能。

那么从github上下载下来代码,开始研究下吧,正好我手上前三种启动方式的设备都有,然后最后再试一下uart启动。

github链接如下所示:(现在的commit id是9a7ac6d

plain 复制代码
https://github.com/hanwckf/bl-mt798x.git

固件编译

版本已经更新到了20250711,不过我们使用20230718-09eda825这个版本,然后atf使用20240117-bacca82a8这个版本。以spim-nor举例来说,从配置文件mt7981_spim_nor_rfb_defconfig中可以看到,当前版本的分区定义为:

plain 复制代码
CONFIG_MTDPARTS_DEFAULT="nor0:256k(bl2),64k(u-boot-env),704k(factory),512k(fip),-(firmware)"

这里firmware分区的大小是改过来了,早期的版本都是写死的。然后这里给到fip分区的默认的大小是512k。我们主要编译的固件是bl2和fip。

然后配置文件中也并没有给failsafe的使能,估计是加上后对于spim-nor来说,uboot太大了。我们先不加了。

编译u-boot
编译spim-nor

进入uboot目录,常规的uboot编译命令:

plain 复制代码
$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- mt7981_spim_nor_rfb_defconfig
$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- 
编译spim-nand
plain 复制代码
$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- mt7981_spim_nand_rfb_defconfig
$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- 
编译mmc
plain 复制代码
$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- mt7981_emmc_rfb_defconfig
$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- 

然后根目录下生成了u-boot.bin。这个就是我们用到的uboot文件。

记住这个uboot镜像的位置,对于ATF的路径来说,我的是../uboot-mtk-20230718-09eda825/u-boot.bin。

编译atf
atf配置

进入atf目录,执行make menuconfig后,按照提示修改其配置文件,我手上的设备规格是内存DDR4,容量为1GB。

配置文件最后会在build目录下生成,我的配置文件以spim-nor举例,其它启动介质请按需要修改。

plain 复制代码
# _PLAT_MT7622 is not set
# _PLAT_MT7629 is not set
_PLAT_MT7981=y
# _PLAT_MT7986 is not set
# _PLAT_MT7988 is not set
PLAT="mt7981"
_SUPPORTS_DDR4=y
# _DRAM_DDR3 is not set
_DRAM_DDR4=y
DRAM_USE_DDR4=1
_SUPPORTS_DDR3_256MB=y
_SUPPORTS_DDR3_512MB=y
_SUPPORTS_DDR4_512MB=y
_SUPPORTS_DDR4_1GB=y
_SUPPORTS_DDR3_FREQ=y
_SUPPORTS_DDR3_1866=y
_SUPPORTS_DDR3_2133=y
_DEFAULT_DDR3_2133=y
_SUPPORTS_DRAM_DEBUG_LOG=y

#
# Advanced DRAM configurations
#
_DRAM_SIZE_AUTO=y
# _DRAM_SIZE_512MB is not set
# _DRAM_SIZE_1GB is not set
_MT7981_BOARD_BGA=y
BOARD_BGA=1
# _DRAM_DEBUG_LOG is not set
# end of Advanced DRAM configurations

_SUPPORTS_BOOT_DEVICE_SPIM_NAND=y
_SUPPORTS_BOOT_DEVICE_EMMC_SD=y
_DEFAULT_BOOT_DEVICE_SPIM_NAND=y
_BOOT_DEVICE_SPI_NOR=y
# _BOOT_DEVICE_SNFI_NAND is not set
# _BOOT_DEVICE_SPIM_NAND is not set
# _BOOT_DEVICE_EMMC is not set
# _BOOT_DEVICE_SD is not set
# _BOOT_DEVICE_RAM is not set

#
# Advanced boot device configuration
#
_BROM_NAND_HEADER_HSM=y
_DEFAULT_NAND_NMBM=y
# _ENABLE_OVERRIDE_FIP_BASE is not set
# _ENABLE_OVERRIDE_FIP_SIZE is not set
# end of Advanced boot device configuration

BOOT_DEVICE="nor"

#
# Platform configurations
#
_SUPPORTS_EMERG_MEM_DUMP=y
# _ENABLE_EMERG_MEM_DUMP is not set
# _ENABLE_JTAG is not set
# end of Platform configurations

_BUILD_FIP=y
BL33="../uboot-mtk-20230718-09eda825/u-boot.bin"

#
# Advanced build configurations
#
# _ENABLE_BL2_COMPRESS is not set
# _ENABLE_FIP_COMPRESS is not set
# _USE_MKIMAGE is not set
# end of Advanced build configurations

_SUPPORTS_AR_V2=y
# _ENABLE_SBC is not set
CROSS_COMPILE="/usr/bin/aarch64-linux-gnu-"
# _LOG_LEVEL_NONE is not set
# _LOG_LEVEL_ERROR is not set
# _LOG_LEVEL_NOTICE is not set
_LOG_LEVEL_WARNING=y
# _LOG_LEVEL_INFO is not set
# _LOG_LEVEL_VERBOSE is not set
LOG_LEVEL=30

然后在build/mt7981/release/下面会生成bl2.img和fip.bin

plain 复制代码
$ ls build/mt7981/release/
bl2  bl2.bin  bl2.img  bl31  bl31.bin  fdts  fip.bin  lib  libc  libfdt  libwrapper  romlib

将二者拷贝到tftp目录,然后我们在设备上更新一下试试。

常见错误
openssl/evp.h
plain 复制代码
include/image.h:1435:12: fatal error: openssl/evp.h: No such file or directory

直接执行sudo apt-get install -y libssl-dev。

设备更新引导程序

引导程序主要是两部分,一个是bl2.img,一个是fip.bin。通常我们使用tftp的方式来进行更新,比如进入uboot命令行,输入bootmenu可以出现如下选择界面,具体的选项如下图所示。然后如果设备上已经有引导程序的话,并且分区和我们编译的镜像保持一致,可以用以下方法进行更新,spim-nor,spim-nand,emmc这几种规格的设备,方式都是一样的。如果分区不一样的话,最好是先进入系统备份下Factory分区,这个很重要。然后参考下一章救砖来刷,或者是从自己做的系统里面更新。本节只分享串口刷机。

可以用mtd list查看当前的分区情况:

更新BL2
更新FIP

这时候就可以执行reset或者断电重启了。

重启

这时候发现已经改过来了,然后那个g9a7ac6d6d是我本地的版本。

更新成功。

救砖刷机

如果不小心把bl2或者fip什么的给刷错了起不来了,这时候也不用慌,我们还可以ram启动,通过串口把bl2和fip加载到芯片上来运行。

擦除flash

我的flash是32M的,那么比如我们可以执行这几条命令把flash擦了:

plain 复制代码
MT7981> sf probe
MT7981> sf erase 0 +2000000

这样的话,我再次重启发现设备成砖了。

这时候我们千万不要慌,只要还有打印就能救回来。

编译ram启动的bl2

uboot还是那个uboot,bl2的配置文件需要改一下,参考配置如下所示:

plain 复制代码
# _PLAT_MT7622 is not set
# _PLAT_MT7629 is not set
_PLAT_MT7981=y
# _PLAT_MT7986 is not set
# _PLAT_MT7988 is not set
PLAT="mt7981"
_SUPPORTS_DDR4=y
# _DRAM_DDR3 is not set
_DRAM_DDR4=y
DRAM_USE_DDR4=1
_SUPPORTS_DDR3_256MB=y
_SUPPORTS_DDR3_512MB=y
_SUPPORTS_DDR4_512MB=y
_SUPPORTS_DDR4_1GB=y
_SUPPORTS_DDR3_FREQ=y
_SUPPORTS_DDR3_1866=y
_SUPPORTS_DDR3_2133=y
_DEFAULT_DDR3_2133=y
_SUPPORTS_DRAM_DEBUG_LOG=y

#
# Advanced DRAM configurations
#
_DRAM_SIZE_AUTO=y
# _DRAM_SIZE_512MB is not set
# _DRAM_SIZE_1GB is not set
_MT7981_BOARD_BGA=y
BOARD_BGA=1
# _DRAM_DEBUG_LOG is not set
# end of Advanced DRAM configurations

_SUPPORTS_BOOT_DEVICE_SPIM_NAND=y
_SUPPORTS_BOOT_DEVICE_EMMC_SD=y
_DEFAULT_BOOT_DEVICE_SPIM_NAND=y
# _BOOT_DEVICE_SPI_NOR is not set
# _BOOT_DEVICE_SNFI_NAND is not set
# _BOOT_DEVICE_SPIM_NAND is not set
# _BOOT_DEVICE_EMMC is not set
# _BOOT_DEVICE_SD is not set
_BOOT_DEVICE_RAM=y

#
# Advanced boot device configuration
#
_BROM_NAND_HEADER_HSM=y
# _RAM_BOOT_DEBUGGER_HOOK is not set
_RAM_BOOT_RAM_BOOT_UART_DL=y
RAM_BOOT_UART_DL=1
_DEFAULT_NAND_NMBM=y
# end of Advanced boot device configuration

BOOT_DEVICE="ram"

#
# Platform configurations
#
_SUPPORTS_EMERG_MEM_DUMP=y
# _ENABLE_EMERG_MEM_DUMP is not set
# _ENABLE_JTAG is not set
# end of Platform configurations

_BUILD_FIP=y
BL33="../uboot-mtk-20230718-09eda825/u-boot.bin"

#
# Advanced build configurations
#
# _ENABLE_BL2_COMPRESS is not set
# _ENABLE_FIP_COMPRESS is not set
# _USE_MKIMAGE is not set
# end of Advanced build configurations

_SUPPORTS_AR_V2=y
# _ENABLE_SBC is not set
CROSS_COMPILE="/usr/bin/aarch64-linux-gnu-"
# _LOG_LEVEL_NONE is not set
# _LOG_LEVEL_ERROR is not set
# _LOG_LEVEL_NOTICE is not set
_LOG_LEVEL_WARNING=y
# _LOG_LEVEL_INFO is not set
# _LOG_LEVEL_VERBOSE is not set
LOG_LEVEL=30

把这里改掉就可以了。然后执行make编译出来镜像,注意这里的bl2名称为bl2.bin。

通过ram加载

我用的机器是ubuntu,我这里就直接用ubuntu了,然后也可以用windows,详细的过程参考这个文章:

plain 复制代码
https://www.cnblogs.com/p123/p/18046679

别看写的挺多的,主要就是编译出ram加载的引导程序,编译出正常的启动引导程序,然后执行个命令。

编译mtk_uartboot

这里按照文章里面的命令一步步的来就可以。

plain 复制代码
$ sudo apt install aptitude
$ sudo aptitude install rust-all
$ cargo build --verbose --locked --release --target x86_64-unknown-linux-gnu
$ sudo cp target/x86_64-unknown-linux-gnu/release/mtk_uartboot /usr/sbin/
执行ram启动命令

执行以下命令:

plain 复制代码
$ sudo mtk_uartboot -s /dev/ttyUSB0 -p build/mt7981/release/bl2.bin -a -f build/mt7981/release/fip.bin --brom-load-baudrate 115200 --bl2-load-baudrate 115200

然后会出现:

plain 复制代码
mtk_uartboot - 0.1.1
Using serial port: /dev/ttyUSB0
Handshake...

这时候给设备上电就可以了。它会自动检测到设备并且通过串口发送bl2和fip。

这样就可以了。

烧写flash

由于flash里面没什么东西,所以通过串口加载完后倒计时结束不会启动系统,就停下了。

然后此时就可以往flash里面写bl2和fip了,跟上一章步骤是一样的。

烧写的时候注意下别把ram引导的bl2写进去就行。

烧写完后重启,满血复活啦。

总结

引导程序bl2和fip,只要是引导介质和内存规格(DDR3/DDR4)可以对应的上。基本上mt7981的设备都可以用这套软件,而且基本上来说bl2和fip的位置和大小也都差不多。

总之在刷机之前,最好先把factory分区备份下,那里面主要是存有无线参数校准的一些信息。其它的都是跟各厂家自己的功能相关的。

那么我们也把刚才编译生成的镜像重新命名一下吧,就当成是一个区分。

相关推荐
Hello阿尔法7 小时前
基于 NFS 的文件共享实现
linux·嵌入式
爱的si念2 天前
嵌入式ARM64 基于RK3588原生SDK添加用户配置选项./build lunch & debian
linux·debian·嵌入式
大聪明-PLUS2 天前
像 Docker 一样创建虚拟网络
linux·嵌入式·arm·smarc
Zero_Era2 天前
LKT4202UGM重新定义物联网设备安全标准
物联网·安全·嵌入式
我是海飞2 天前
外置flash提示音打包脚本
运维·服务器·音视频·嵌入式
小白嘎嘎2 天前
CAN总线学习
单片机·嵌入式硬件·嵌入式
夜月yeyue2 天前
嵌入式 Linux 启动流程详解 (以 ARM + U-Boot 为例)
linux·单片机·udp·嵌入式·uboot·bootloard
闻道且行之3 天前
嵌入式|Linux中打开视频流的两种方式V4l2和opencv
linux·笔记·opencv·嵌入式
我是海飞3 天前
Tensorflow Lite 的yes/no语音识别音频预处理模型训练教程
python·学习·tensorflow·音视频·嵌入式·语音识别