SS928系统增加内存方式(解析U-Boot和DDR)(干货篇)

SS928系统增加内存方式(解析U-Boot和DDR)(干货篇) 银河☆海然 2025-11-06 08:53:29 157

问题引入

前段时间在SS928中编译ROS的时候出现了内存不足的问题,想起来自己烧录的是8G+64G版本的固件,不应该出现这个问题呢?
使用free -h查看了系统可用内存,发现根本只有不到1G可用:

一一排查

有什么地方会影响到系统的可用内存呢?我们可以从硬件层面和软件层面来一步一步测试。首先我们使用的是SS928V100的开发板,支持的最大容量是8GB,也就是说我们的硬件层是支持8GB的。那么从软件层面入手,嵌入式arm板端Linux系统启动流程如下

graph TD
subgraph SoC 内部芯片
A[电源开启] --> B(BootROM);
end
subgraph 引导加载程序 (Bootloader)
B --> |从 Flash/SD卡 加载| C[U-Boot SPL];
C --> |初始化DDR| D[U-Boot 主体];
end
subgraph 内核与用户空间
D --> |执行 bootcmd| E[加载 Linux 内核 (zImage)];
D --> |执行 bootcmd| F[加载设备树 (DTB)];
E & F --> G{启动内核};
G --> H[内核初始化硬件];
H --> I[挂载根文件系统 (RootFS)];
I --> J[执行第一个用户进程 /sbin/init];
J --> K[启动系统服务与应用];
end

BootROM是厂家编写的代码我们无法修改,于是接着进入U-Boot
U-Boot是引导加载程序,分为U-Boot SPLU-Boot Proper两部分。

  • SPL是一个精简版的U-Boot运行在芯片内部的SRAM中,主要任务是初始化关键外设、DDR内存、加载BL3,并跳转到DDR中U-Boot Proper入口地址。
  • U-Boot Proper首先进行前期板级初始化,首先会在DDR中初始化一些不需要直接写地址的硬件(通过固定寄存器访问的硬件)、为U-Boot规划重定位地址、初始化全局数据gd。接着开始重定位,将U-Boot整个代码段和数据段全部从DDR当前临时位置,拷贝到最终运行位置(通常是DDR的高端地址区域,为内核腾出低端地址空间)。然后进行后期初始化,初始化前期无法初始化的设备,如网络、USB等。

全部初始化完成后,U-Boot进入主循环。首先初始化环境变量,从默认的环境变量或持久化存储(如Flash上的环境变量分区)中加载环境变量。然后启动bootdelay,等待用户是否按下按键。按下按键中断后,用户进入U-Boot命令行界面,可以在里面查看内存、烧写镜像、修改环境变量等;如果没有按下按键,就执行bootcmd环境变量中定义的自动启动命令序列,通常包含load kernel(从存储设备(eMMC等)将操作系统内核镜像和设备树文件加载到DDR内存的指定位置)和booti/bootm(跳转到内核的入口地址,将设备树地址等信息传递给内核,最后将控制权彻底交接给操作系统)

学到更多后便出现了新的问题,内存、DDR到底是什么?我们使用free -h查看到的是什么内存呢?

首先DDR可以表示两个名词:DDR内存芯片和DDR协议。一个是物理实体(内存芯片),一个是通信协议(计算机系统如何与内存芯片通信的协议)。我们在上面提到的DDR都是指DDR内存芯片这一说法。

而上面说的内存,是指DDR内存芯片能存储的空间大小。而我们平时说的”这块板子的内存有多大“的意思,就是说这块板端DDR内存容量有多少。

free -h查看到的,是:Linux 内核的内存管理子系统所识别和管理的、可供内核和应用程序使用的 DDR 内存空间的大小。(呼~)

回归问题

这样我们回到最开始的问题!我们使用free -h查看系统可用内存,发现只有900多MB,而我们硬件DDR内存空间却有整整8G。由我们刚刚学习到的知识,可以从U-Boot启动入手。

在SRAM中SPL进行了初始化DDR内存、Proper进行了重定位后,U-Boot会首先初始化环境变量。那么我们先看看这个环境变量中会不会有与内存相关的部分:

由于SS928死活进不了U-Boot命令行界面,我们就直接在Ubuntu系统里面查看U-Boot的环境变量。进入系统后通过这段命令可以查看U-Boot的环境变量:

fw_printenv

输出的内容如下:

arch=arm
baudrate=115200
board=ss928v100
board_name=ss928v100
bootargs=console=ttyAMA0,115200 clk_ignore_unused rw rootwait rootfstype=ext4 blkdevparts=mmcblk0:512K(uboot),512K(env),1M(logo),20M(kernel),-(rootfs)
bootcmd=setenv bootargs "mem=${os_mem_size} total_mem=${total_mem_size} ${bootargs} ${rootfs_devpart}";run logo_cmd;mmc read 0 ${kernel_addr} ${kernel_start} ${kernel_size};bootm ${kernel_addr}
bootdelay=1
buffer_addr=0x42000000
buffer_size=0x01000000
cpu=armv8
ethact=gmac0
import_addr=0x41000000
jpeg_addr=0x230000000
jpeg_emar_buf=0x234000000
jpeg_size=0x3e728
kernel_addr=0x50000000
kernel_size=0xA000
kernel_start=0x1000
logo_cmd=if test "${logo_show}" = "yes";then mmc read 0 ${jpeg_addr} 0x800 0x800;decjpg 0;setvobg 0 0x0;startvo 0 16 23;startvl 0 ${vobuf} 1920 0 0 1920 1080;fi;
logo_show=yes
os_mem_size=1024M
part_env=0x80000
part_kernel=0x1400000
part_logo=0x100000
part_uboot=0x80000
preboot=setenv part_num 0; setenv partcnt 0; setenv filesize 0; mmc partcnt 1; while test "${part_num}" -le "${partcnt}";do load mmc 1:${part_num} ${import_addr} /boot/env_append.txt; if test "${filesize}" != "0";then env import -t -r ${import_addr} ${filesize}; if test "${append_preboot}" != "";then run append_preboot; fi; exit 0; fi; setexpr part_num ${part_num} + 1; done;
rootfs_devpart=root=/dev/mmcblk0p5
soc=ss928v100
stderr=serial
stdin=serial
stdout=serial
total_mem_size=8G
vendor=vendor
verify=n
vobuf=0x238000000

我们来分块解释:

系统基本信息变量:

内存配置变量:

存储分区信息变量:
这些变量定义了 eMMC 或 SD 卡上的分区布局。

核心启动参数:bootargs

核心启动命令:bootcmd

bootcmd=setenv bootargs "mem=${os_mem_size} total_mem=${total_mem_size} ${bootargs} ${rootfs_devpart}";run logo_cmd;mmc read 0 ${kernel_addr} ${kernel_start} ${kernel_size};bootm ${kernel_addr}

能理解的部分我就不多说了,mmc read 0 ...是指从存储设备读取内核到内存(从MMC设备0的kernel_start开始读取kernel_size个扇区的内容,放到内存的 kernel_addr地址处),bootm ${kernel_addr}就是从内存地址为kernel_addr的位置启动Linux内核

其它功能变量:

功能脚本变量:

解决问题

我们从这个环境变量中就能看出,直接影响我们系统可用内存大小的部分,就是os_mem_size被设置为了1024M。我们将这个内存扩大为4G试试:

fw_setenv os_mem_size 4G
# 重启生效
reboot


可以看到我们成功扩大了内存!不过这里我们设置的4G为什么会少200M左右呢?其实我们刚刚也说过,在U-Boot启动系统的时候,bootcmd会把操作系统内核镜像和设备树传递给DDR,同时在海思这类多媒体SOC中会保留一部分内存:

在这里我们看到SOC确实提前预留了203M的内存,这正是我们缺少的那一部分~

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 2 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
银河☆海然
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区