前节概述
前一篇文章我们已经可以拉起linux并且运行led闪烁程序,并规划了内存:
片内2MB Flash存放uboot,放在0x08000000
片外32MB QSPI Flash按地址存放:
0x040000 kernel (0x27B0F0)
0x340000 dtb (0x3E4B)
0x380000 rootfs (0x261C40) ← 结束于 0x5E1C40
0x680000 data 分区起始
现在我们要让uboot自己拉起操作系统就需要规划一块新的区域存放环境变量,即
0x000000 - 0x002000(8KB)(环境变量占用)
目前:
0x002000 - 0x040000(248KB空闲)
理论成立,开始修改configs吧
修改规定
(0x2000) CONFIG_ENV_SIZE:环境变量实际占用总字节大小
(0x1000)CONFIG_ENV_SECT_SIZE:Flash 扇区擦除粒度大小(扇区物理大小)
修改配置头文件
cpp
vim include/configs/stm32h747_cb.h
#ifndef __CONFIG_H
#define __CONFIG_H
#include <config.h>
#include <linux/sizes.h>
#define CONFIG_SYS_BOOTMAPSZ SZ_16M
#define CONFIG_SYS_FLASH_BASE 0x08000000
#define CONFIG_SYS_INIT_SP_ADDR 0x24040000
#define CONFIG_SYS_SDRAM_BASE 0xD0000000
#define CONFIG_SYS_HZ_CLOCK 1000000
#define CONFIG_SYS_MAXARGS 32
#define CONFIG_ENV_OFFSET 0x00000
#define CONFIG_ENV_SIZE 0x2000
#define CONFIG_ENV_SECT_SIZE 0x1000
#define CONFIG_EXTRA_ENV_SETTINGS \
"kernel_addr_r=0xD0008000\0" \
"fdtfile=stm32h747_cb.dtb\0" \
"fdt_addr_r=0xD0408000\0" \
"scriptaddr=0xD0418000\0" \
"pxefile_addr_r=0xD0428000\0" \
"ramdisk_addr_r=0xD0438000\0"
#endif /* __CONFIG_H */
修改deconfig
vim configs/stm32h747_cb_defconfig
检查下方配置是否存在
CONFIG_BOOTDELAY=3
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n"
CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_CMD_SAVEENV=y
完整内容如下:
CONFIG_ARM=y
CONFIG_ARCH_STM32=y
CONFIG_SYS_TEXT_BASE=0x08000000
CONFIG_SYS_MALLOC_LEN=0x100000
CONFIG_SYS_MALLOC_F_LEN=0xF00
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x2000
CONFIG_DEFAULT_DEVICE_TREE="stm32h747_cb"
CONFIG_STM32H7=y
CONFIG_TARGET_STM32H747_CB=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_SYS_LOAD_ADDR=0xd0400000
CONFIG_BOOTDELAY=3
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n"
CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_DEFAULT_FDT_FILE="stm32h747_cb"
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_SYS_PROMPT="U-Boot > "
CONFIG_CMD_GPT=y
CONFIG_CMD_MMC=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_CACHE=y
CONFIG_CMD_TIMER=y
CONFIG_CMD_EXT4_WRITE=y
# CONFIG_ISO_PARTITION is not set
CONFIG_OF_CONTROL=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
# CONFIG_NET is not set
CONFIG_STM32_SDMMC2=y
# CONFIG_PINCTRL_FULL is not set
CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_STM32_USART=y
CONFIG_DEBUG_UART=y
CONFIG_DEBUG_UART_STM32=y
CONFIG_DEBUG_UART_BASE=0x40011000
CONFIG_DEBUG_UART_CLOCK=64000000
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_SPI_MEM=y
CONFIG_STM32_QSPI=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_MTD=y
CONFIG_SKIP_RELOCATE_UBOOT=y
CONFIG_POSITION_INDEPENDENT=y
# CONFIG_MMC is not set
# CONFIG_CMD_MMC is not set
# CONFIG_DM_MMC is not set
# CONFIG_STM32_SDMMC2 is not set
# CONFIG_DISTRO_DEFAULTS is not set
CONFIG_CMD_SF=y
CONFIG_SPI_FLASH_JEDEC=y
CONFIG_DM_SPI_FLASH=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_CMD_SAVEENV=y
编译uboot
注意此前不设置配置直接编译,出现配置未生成到uboot文件的情况,所以要执行以下操作:(注意交叉编译选择:arm-none-eabi-gcc)
cd ~/demo/claude/u-boot
make stm32h747_cb_defconfig
make CROSS_COMPILE=arm-none-eabi- -j$(nproc)
编译过程中有一些需要输入的请求:
Environment offset (ENV_OFFSET) [] (NEW) 0x0
Environment Size (ENV_SIZE) [0x2000] 0x2000
Environment Sector-Size (ENV_SECT_SIZE) [] (NEW) 0x1000
编译完成:使用cubeProgrammer烧录吧
admins@admins:~/demo/claude/u-boot$ ls -la u-boot.bin
-rw-rw-r-- 1 admins admins 189696 Jun 20 21:18 u-boot.bin
admins@admins:~/demo/claude/u-boot$ crc32 u-boot.bin
1c907b70
烧录uboot
按照指示烧录,输入env help,出现env save视为成功

配置环境变量
设置启动读取地址,并启动:
setenv bootcmd 'sf probe; sf read 0xD0400000 0x40000 0x27B0F0; sf read 0xD0700000 0x340000 0x3E4B; sf read 0xD0800000 0x380000 0x261E40; bootm 0xD0400000 0xD0800000 0xD0700000'
setenv bootargs 'console=ttySTM0,115200 earlycon=stm32-usart,mmio32,0x40011000 root=/dev/ram rdinit=/sbin/init'
env save
取消uboot拉起操作:
env default -a
env save

设置linux自启动服务程序
问题1、启动linux总是卡在认证阶段
vim ~/demo/claude/buildroot-2023.11/output/target/etc/inittab
console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL
改为:
console::respawn:/bin/login -f root
把 ~/demo/claude/buildroot-2023.11/output/target/etc/inittab的文件
复制一份到 board/overlay/etc中
mkdir -p ~/demo/claude/buildroot-2023.11/board/overlay/etc
cat > ~/demo/claude/buildroot-2023.11/board/overlay/etc/inittab << 'EOF'
# /etc/inittab
#
# Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
#
# Note: BusyBox init doesn't support runlevels. The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id == tty to run on, or empty for /dev/console
# runlevels == ignored
# action == one of sysinit, respawn, askfirst, wait, and once
# process == program to run
# Startup the system
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
::sysinit:/bin/mkdir -p /run/lock/subsys
#::sysinit:/sbin/swapon -a
null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
::sysinit:/bin/hostname -F /etc/hostname
# now run any rc scripts
::sysinit:/etc/init.d/rcS
# Put a getty on the serial port
console::respawn:/bin/login -f root
# Stuff to do for the 3-finger salute
#::ctrlaltdel:/sbin/reboot
# Stuff to do before rebooting
::shutdown:/etc/init.d/rcK
#::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
EOF
问题2、led闪烁程序无法自动启动
看一下现在的自启动脚本内容:(发现操作系统顺序执行/etc/init.d/S??*开头的文件)
cat ~/demo/claude/buildroot-2023.11/output/target/etc/init.d/rcS
#!/bin/sh
# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do
# Ignore dangling symlinks (if any).
[ ! -f "$i" ] && continue
case "$i" in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set start
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i start
;;
esac
done
===========
创建自动启动led脚本:
S99led: S 开头表示"启动时执行",数字 99 决定执行顺序(数字越大越靠后执行,99 基本保证它在其他系统服务都起来之后才跑)。
加 &: led 程序是个死循环,不会自己退出,如果不加 & 放后台执行,整个 rcS 脚本会卡在这一行,导致后面的开机流程(包括最终弹出登录提示)全部卡住。
mkdir -p ~
/demo/claude/buildroot-2023.11/board/overlay/etc/init.d
cat > ~/demo/claude/buildroot-2023.11/board/overlay/etc/init.d/S99led << 'EOF'
#!/bin/sh
/usr/bin/led &
EOF
chmod +x ~/demo/claude/buildroot-2023.11/board/overlay/etc/init.d/S99led
打包rootfs
cd ~/demo/claude/buildroot-2023.11
make
mkimage -A arm -O linux -T ramdisk -C none -n "rootfs" -d output/images/rootfs.cpio output/images/rootfs.cpio.bin
stat -c %s output/images/rootfs.cpio.bin | xargs printf "0x%X\n"
crc32 output/images/rootfs.cpio.bin
admins@admins:~/demo/claude/buildroot-2023.11$ stat -c %s output/images/rootfs.cpio.bin | xargs printf "0x%X\n"
0x261E40
admins@admins:~/demo/claude/buildroot-2023.11$ crc32 output/images/rootfs.cpio.bin
e84aa2de
烧录rootfs
oady 0xD0400000
发送新的 rootfs.cpio.bin,收完验证:
crc32 0xD0400000 0x261E40
确认是 e84aa2de 再继续:
sf probe
sf erase 0x380000 0x300000
sf write 0xD0400000 0x380000 0x261E40
最后配置环境变量使得自动启动
setenv bootcmd 'sf probe; sf read 0xD0400000 0x40000 0x27B0F0; sf read 0xD0700000 0x340000 0x3E4B; sf read 0xD0800000 0x380000 0x261E40; bootm 0xD0400000 0xD0800000 0xD0700000'
setenv bootargs 'console=ttySTM0,115200 earlycon=stm32-usart,mmio32,0x40011000 root=/dev/ram rdinit=/sbin/init'
env save
全文完