其他分享
首页 > 其他分享> > 2021-09-10

2021-09-10

作者:互联网

STM32H743ZIT6移植uboot

Stm32H743移植linux
1, 首先在Linux系统下安装交叉编译环境
下载Cortex-M系列的交叉编译环境:https://launchpad.net/gcc-arm-embedded
在这里插入图片描述

下载对应系统的文件
解压 tar –xjf gcc-arm-none-eabi-10.3-2021.07-x86_64-linux.tar.bz2
解压后的文件拷贝到/user/local
Sudo cp gcc-arm-none-eabi-10.3-2021.07 /user/local
修改环境变量 sudo vim /etc/profile
文件最后增加export PATH=$PATH:/usr/local/ gcc-arm-none-eabi-10.3-2021.07/bin
在这里插入图片描述

运行source /etc/profile使环境变量生效
要想在其他位置生效,重启系统即可
在这里插入图片描述

安装完成
用hello world 验证
直接编译会报错
在这里插入图片描述

可能是默认的libc缺少某些标准函数,需要使用–specs选项。arm-none-eabi-gcc配套的readme文件中有关于libc库及–specs选项的解释,如https://launchpadlibrarian.net/287100883/readme.txt。使用前建议阅读一下readme文件)
使用arm-none-eabi-gcc --specs=nosys.specs -o main main.c编译
查看文件信息:file main
在这里插入图片描述

表示交叉编译环境安装成功
2, 编译uboot
首先去uboot官网下载最新uboot源码
http://www.denx.de/wiki/U-Boot/
在这里插入图片描述

进入源码
在这里插入图片描述

选择FTP
在这里插入图片描述

选择自己想要下载的版本
解压:tar –xjf u-boot-2021.07.tar.bz2
在这里插入图片描述

查看configs目录
在这里插入图片描述

uboot支持stm32H743,先使用默认配置文件
Makefile 文件增加交叉编译器
在这里插入图片描述

执行make stm32h743-disco_defconfig得到.config文件
make –j4编译uboot
在这里插入图片描述

使用STLink烧录u-boot.bin文件到H7的芯片上,串口没有打印信息
首先怀疑串口引脚配置不同
初始化串口的函数没有对串口引脚的配置,查看uboot编译,发现是通过设备树进行引脚配置,所以找到对应的设备树arch/arm/dts/stm32h743i-disco.dts
查看配置发现与自己板子上的串口引脚不匹配,修改为自己板子上的引脚配置
在这里插入图片描述

重新烧录,串口还是没有打印,发现是.bin文件不匹配,因为使用了设备树,所以要使用u-boot-dtb.bin文件。
使用STLink烧录u-boot-dtb.bin文件到flash中
stm32h743属于ARMV7M架构
在这里插入图片描述

串口成功打印uboot信息。
打印信息只有少部分,没有完全打印,分析uboot启动流程
3, 分析启动流程
首先分析u-boot.lds链接脚本
在这里插入图片描述

Uboot代码当前的入口点:_start,真正的.text段是从.vectors开始的
_start 在文件 arch/arm/lib/vectors.S 中有定义。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

_start后面的就是中断向量表
可以看出,直接跳转到了reset,reset位于arch/arm/cpu/armv7m/start.S文件中
在这里插入图片描述

跳转到第一个C程序,main函数,位于arch/arm/lib/crt0.S文件中
在这里插入图片描述

默认使用的外部DDR内存,需要修改为内部SDRAM
在这里插入图片描述

使用AXI-SRAM 起始地址0x2400 0000 大小 0x8 0000
CONFIG_SYS_INIT_SP_ADDR 修改SP指针初始化的地址为0x2401 0000
在这里插入图片描述

board_init_f_alloc_reserve 函数主要是留出早期的malloc内存区域和gd内存区域
SYS_MALLOC_F_LEN 0xF00
#define CONFIG_SYS_MALLOC_F_LEN 0xF00 (include/generated /autoconf.h)
GD_SIZE 216
#define GD_SIZE 216 (include/generated/generic-asm-offsets.h)
返回最新的top值 0x2401 0000-0xF00-0xE0(16字节对齐) = 0x2400 F020
r9寄存器存放着全局变量gd的地址,设置gd所指向的位置
调用函数 board_init_f_init_reserve,此函数在文件common/init/board_init.c 中有定义
此函数用于初始化gd,其实就是清零处理
还设置了gd->malloc_base为基地址+gd大小,再做16字节对齐 = 0x2400 F100
最终gd->malloc_base= 0x2400 F100这个就是early malloc的起始地址。
在这里插入图片描述

进入board_init_f函数,进入uboot第一阶段的初始化。
在这里插入图片描述

board_init_f 函数主要的作用:
初始化一系列外设,比如串口、定时器,或者打印一些消息等,init_sequence_f 初始化列表里面包含了一系列的初始化函数。
去掉条件编译以后的 init_sequence_f 定义如下:
setup_mon_len, __bss_end-_start 得到uboot总长度 _start为我们.text的首地址
0x 0803 2fe0-0x0800 0000=0x3 2fe0
fdtdec_setup, 加载设备树以及设备树地址
initf_malloc, 设置内存池的大小 为0xF00
initf_bootstage
setup_spl_handoff,
arch_cpu_init,
mach_cpu_init,
initf_dm,
arch_cpu_init_dm,
timer_init,
env_init,
init_baud_rate, 设置串口速率115200
serial_init, 初始化串口 serial_uclass 通过设备树方式初始化串口
console_init_f, 设置gd->have_console为1,打开控制台
display_options, 打印uboot版本以及编译信息
display_text_info
checkcpu,
show_board_info, 打印板子信息
INIT_FUNC_WATCHDOG_INIT
INIT_FUNC_WATCHDOG_RESET
announce_dram_init, 打印DRAM
dram_init, ram_size=0x80000 ram_base=0x2400 0000
需要在设备树文件中修改对应的memory节点,根据选择的SRAM的地址和大小
在这里插入图片描述

INIT_FUNC_WATCHDOG_RESET
INIT_FUNC_WATCHDOG_RESET
INIT_FUNC_WATCHDOG_RESET
setup_dest_addr, ram_top=0x2408 0000 relocaddr=0x2408 0000
reserve_round_4k, 4K向下对齐
arch_reserve_mmu, 页表64K对齐relocaddr=0x2407 0000
reserve_video,
reserve_trace,
reserve_uboot, start_addr_sp= relocaddr =relocaddr-uboot长度(0x32fe0)=0x2403 D000
在这里插入图片描述

reserve_malloc, 保留一段堆空间(也就是堆的大小100K)start_addr_sp=0x2402 2000
默认值为(11024 1024)1M的大小,由于单片机的SRAM大小不够,修改为100K(11001024)
在这里插入图片描述

reserve_board, 保留bd的空间(大小0x50)start_addr_sp=0x24021fb0
reserve_global_data, 设置新的gd地址(大小0xE0)start_addr_sp=0x24021ed0
reserve_fdt, 设备树大小size 0x5760 start_addr_sp= 0x24010770
reserve_bootstage,
reserve_bloblist,
reserve_arch,
reserve_stacks, 预留16字节start_addr_sp= 0x24010750
dram_init_banksize, 起始地址0x2400 0000
show_dram_config, 打印DRAM大小0x8 0000(512K)
INIT_FUNC_WATCHDOG_RESET
setup_bdinfo,
display_new_sp,
INIT_FUNC_WATCHDOG_RESET
reloc_fdt, 重定位设备树,把设备树段拷贝到新的位置
reloc_bootstage,
reloc_bloblist,
setup_reloc, 重定位gd_t
clear_bss,
最终内存分布:
在这里插入图片描述
在这里插入图片描述

board_init_f中的内容就已经分析完了。
接下来就剩下uboot本身的搬移和bss段的初始化
调用函数 relocate_code 代码重定位函数,将uboot拷贝到SRAM中去
在这里插入图片描述

这三句代码重点分析一下:
adr是个位置无关的加载指令,无论here的链接地址是多少,adr加载的都是当前pc
+偏移,然后得到新的规划的uboot和旧的uboot之间的偏移量给r0
之后把偏移和旧的uboot的here加起来,最终得到新的uboot里面的here地址,然后
放进lr,等进入后面的relocate_code函数,返回来的时候就直接返回到新的uboot的 代码段运行了。
在这里插入图片描述

R0 = relocaddr
R1 = 0x0800 0000 uboot存储在flash中的地址
R2 = 0x0803 0324 uboot存储在flash中的结束的地址
R4 = reloc_off
在这里插入图片描述

循环拷贝flash中的uboot到SRAM中uboot预留的空间中去
调用函数relocate_vectors 对中断向量表做重定位
函数代码位于 arch/arm/lib/relocate.S文件中
uboot第一部分的初始化工作到这里就完成了
总结:主要的工作就是把flash中的uboot搬移到SRAM中,同时初始化了一些底层的配置,把一些参数保存在了全局变量gd中,方便后面使用。
Flash 起始地址 0x0800 0000 大小 0x20 0000 1MB 终止地址 0x0820 0000
SRAM 起始地址 0x2400 0000 大小 0x08 0000 512KB 终止地址 0x2408 0000

在这里插入图片描述
在这里插入图片描述

Uboot第二阶段初始化:
gd的地址和当前新的uboot的起始地址传参给board_init_r
在这里插入图片描述

进入board_init_r函数中
在这里插入图片描述

进入初始化列表init_sequence_r中
得到列表中定义的执行的重要函数
initr_trace
initr_reloc 标记已经重定位成功,malloc初始化
initr_caches 使能cache
initr_reloc_global_data 初始化全局变量monitor_flash_len = _end - __image_copy_start
initr_malloc 初始化堆的大小 定义为100K
initr_bootstage 把动态内存分配的bootargs处理一下
initr_dm 驱动模型初始化 uboot增加设备树以后特有的
board_init gd->bd->bi_boot_params = gd->bd->bi_dram[0].start + 0x100;
stdio_init_tables 初始化一下设备链表
serial_initialize 再一次初始化串口,并标记串口初始化成功
initr_mmc 初始化MMC或者SD卡,默认的MMC控制器和自己板子的不同,修改对应
的设备树MMC控制器引脚,初始化SD卡完成
stdio_add_devices 增加标准输出
initr_net 网口模块初始化,目前没有解决问题,后续继续研究
run_main_loop 最后的大循环函数
在这里插入图片描述

在这里插入图片描述

bootstage_mark_name函数调用了show_boot_progress,利用它显示启动进程(progress),
这里为空函数
cli_init 用来初始化hush shell使用的一些变量
bootdelay_process 从环境变量中取出bootdelay和bootcmd的配置值
bootdelay为uboot的启动延时值,计数期间没有干预,将执行bootcmd配置的命令
cli_process_fdt 环境变量里有bootcmd,fdt如果有,fdt会覆盖env里面的
autoboot_commands 执行倒计时函数,没按键进入bootcmd
cli_loop 进入uboot命令行中
在这里插入图片描述

到这里,uboot移植已完成,运行print命令打印环境变量

在这里插入图片描述

标签:10,uboot,初始化,09,init,gd,2021,0000,reserve
来源: https://blog.csdn.net/qq_38724361/article/details/120216011