海思平台开发小技巧:OS和MMZ内存分配

海思平台开发小技巧:OS和MMZ内存分配 UncleRoderick 2025-04-19 22:10:47 696

前言:

​ OS内存和MMZ内存分配,是海思平台开发过程中经常会遇到的操作,许多新手对这个配置会感到困惑,不知道这些参数是怎么计算的,以下以SS928平台为例,对内存分配进行解析,同时对load脚本进行优化,更便于开发。文章最后会附上SS928、Hi3519DV500、SS528平台优化后的load脚本,可按需下载使用。

文章目录

一、内存组成

​ 海思平台内存主要由OS内存和MMZ内存组成,不同平台有细微差异,例如SS928平台有DSP和RISCV核,也会分配内存给这些核,所有的内存都是基于硬件DDR分配的,不能超出硬件范围。

​ 其中OS内存,即Linux系统所使用的内存,由uboot参数中的mem参数决定如图1-1,MMZ内存则由load脚本中的mmz_size参数决定,如图1-2。

​ 什么时候需要修改内存分配?简单的来说就是当OS内存不够用时,从MMZ内存中分配内存给OS,反之则从OS内存中分配内存给MMZ。

​ 如何判断是否能从OS/MMZ中分配内存?在所有应用和MPP模块相关业务都运行起来的前提下,OS内存使用情况可以通过free命令查看,如图1-3,MMZ内存使用情况可以通过/proc/umap/media-mem查看,如图1-4。

​ 如果OS内存和MMZ内存都不够用时,应用程序需调整内存分配相关代码,MPP部分则考虑开启内存节省功能,例如在线模式和卷绕模式,以及优化相关业务流程以节省MMZ内存开销。

图1-1 uboot OS内存


图1-2 MMZ内存


图1-3 OS内存使用情况



图1-4 剩余MMZ内存


二、load脚本解析

​ 以SS928平台load脚本为例,如图2-1,内存分配主要由以下几部分组成:

mem_total:硬件DDR总内存,由板子贴的DDR决定。
mem_start:硬件DDR起始地址,从芯片手册可知,如图2-2。
ipcm_mem_size:核间通信共享内存,SS928有ARM/DSP/RISCV多个核,这些核之间进行通信的共享内存。
dsp_mem_size:DSP内存,DSP核的内存。
mcu_mem_size:MCU内存,RISCV核的内存。
os_mem_size:OS内存,即Linux系统使用的内存。

mmz_start:媒体内存MMZ起始地址,由MPP媒体处理平台管理,分配给各个模块使用。
mmz_size:媒体内存MMZ内存大小

reserve_mem_size:保留内存,无具体使用用途。

​ 如何计算mmz_start地址:

mmz_size=mem_total-ipcm_mem_size-dsp_mem_size-mcu_mem_size-os_mem_size
        =4096-2-64-192-512
        =3328
mmz_start=mem_start+(ipcm_mem_size+dsp_mem_size+mcu_mem_size+os_mem_size)x1024x1024
         =0x40000000+(2+64+192+512)x1024x1024
         =0x40000000+768x1024x1024
         =0x40000000+0x30000000
         =0x70000000

图2-1 SS928平台load脚本


图2-2 SS928平台DDR内存起始地址


三、load脚本优化

​ 在实际使用场景中,可以对load脚本做些优化,提高便利性,以下为一些优化建议:

​ 注意:load脚本优化之后,执行时不再需要带内存参数。

1.修改驱动文件路径

​ 默认load脚本中,是以相对路径加载驱动,可以优化成以绝对路径加载驱动,如图3-1所示。

①.新增变量ko_path
ko_path=/ko

②.替换脚本中加载驱动命令
'    insmod ' -> '    insmod $ko_path/'

#以'    insmod '去替换可以避免修改脚本中非加载驱动的部分insmod字段。

图3-1 优化ko路径


2.修改自动计算MMZ内存

​ 在实际开发过程中,如果需要修改OS和MMZ分配,得同时修改uboot参数和load脚本参数才能达到目的。如果在load脚本中添加从uboot参数中解析OS内存操作,那就可以简化内存分配操作,只需要修改uboot参数即可,以下为操作过程:

①.uboot中添加总内存total_mem

​ 添加total_mem主要是为了适配不同DDR的板子时,只需要修改uboot的这个参数即可修改总内存大小而不需要修改load脚本,如果没有total_mem参数,则默认采有load脚本中的mem_total参数。

​ 为简化脚本解析,uboot的mem和total_mem参数必须以M/G结尾,同时total_mem参数必须在mem之后。

​ 修改uboot参数在进入uboot后,先执行printenv查看当前参数,然后在原有参数基础上修改后用setenv设置新的参数,再执行saveenv保存参数,最后再执行printenv查看下参数是否正确修改,如图3-2所示。如果uboot参数是由单独的分区烧录,则对应修改生成分区前的文件即可在固件烧录时完成配置。

图3-2 修改uboot参数


②.load脚本修改

​ 在load脚本中添加以下两个函数即可从uboot参数中提取OS内存和总内存。

function get_mem_size_from_cmdline() {
    input="$1"
    default_size="$2"
    number=$(echo "$input" | sed 's/\([0-9]\+\).*/\1/')
    suffix=$(echo "$input" | sed 's/[^MG]//g')

    if [ -z "$suffix" ]; then
        echo "$default_size"
        return
    fi

    if [ -z "$number" ]; then
        echo "$default_size"
        return
    fi

    if [ "$suffix" = "M" ]; then
        echo "$number"
    elif [ "$suffix" = "G" ]; then
        result=$(($number * 1024))
        echo "$result"
    else
        echo "Invalid suffix: $suffix"
        return 1
    fi
}

function extract_and_update_mem_sizes() {
    # 从 /proc/cmdline 提取 mem 和 total_mem 参数
    cmd_mem_size=$(cat /proc/cmdline | grep -oE 'mem=[0-9]+[MG]' | head -n 1 | sed 's/mem=//')
    cmd_total_mem_size=$(cat /proc/cmdline | grep -oE 'total_mem=[0-9]+[MG]' | head -n 1 | sed 's/total_mem=//')

    # 如果 cmd_mem_size 为空,则使用默认值
    if [ -z "$cmd_mem_size" ]; then
        os_mem_size=$(get_mem_size_from_cmdline "" "$os_mem_size")
    else
        os_mem_size=$(get_mem_size_from_cmdline "$cmd_mem_size" "$os_mem_size")
    fi

    # 如果 cmd_total_mem_size 为空,则使用默认值
    if [ -z "$cmd_total_mem_size" ]; then
        mem_total=$(get_mem_size_from_cmdline "" "$mem_total")
    else
        mem_total=$(get_mem_size_from_cmdline "$cmd_total_mem_size" "$mem_total")
    fi

    echo "os_mem_size: $os_mem_size"
    echo "mem_total: $mem_total"
}

​ 在得到OS内存和总内存之后,以下函数可以计算mmz_start和mmz_size参数,注意,SS928平台有比较多的内存参数,如果是其他平台,对应修改计算公式。

function calc_mmz_info()
{
    mmz_start=`echo "$mem_start $os_mem_size $mcu_mem_size $dsp_mem_size $ipcm_mem_size" |
    awk 'BEGIN { temp = 0; }
    {
            temp = $1/1024/1024 + $2 + $3 + $4 + $5;
    }
    END { printf("0x%x00000\n", temp); }'`

    mmz_size=`echo "$mem_total $os_mem_size $mcu_mem_size $dsp_mem_size $ipcm_mem_size $reserve_mem_size" |
    awk 'BEGIN { temp = 0; }
    {
            temp = $1 - $2 - $3 - $4 - $5 - $6;
    }
    END { printf("%dM\n", temp); }'`
    echo "mmz_start: $mmz_start, mmz_size: $mmz_size"
}

​ 在添加以上函数之后,需增加函数执行代码,主要需要加到加载ko动作之前,如图3-3所示。

extract_and_update_mem_sizes;
calc_mmz_info;

图3-3 添加函数执行


四、其他海思平台配置参考

1.SS524/SS528/SS626芯片参考

​ SS524/SS528/SS626这些平台内存分区相对较少,如图4-1,可以简化函数中的相关操作,附件提供修改后的SS528平台的load脚本参考。

图4-1 SS528平台参考


2.Hi3519DV500/Hi3516DV500/Hi3516CV610芯片参考

​ Hi3519DV500/Hi3516DV500/Hi3516CV610这些平台简化了参数,需要修改脚本添加参数,以Hi3519DV500平台为例,如图3-2 所示,附件提供修改后的Hi3519DV500平台的load脚本参考。

图4-2 Hi3519DV500平台参考


3.其他老芯片参考

​ 其他比较老的海思芯片,例如Hi3559AV100/Hi3516DV300/Hi3521DV100等经典型号,均可以参考以上操作自行修改。

优化后的load脚本附件:

五、附件下载

通过网盘分享的文件:load脚本优化
链接: https://pan.baidu.com/s/1yZnnAIRL7B9Hdq15F9tvlw?pwd=fy93 提取码: fy93 
--来自百度网盘超级会员v8的分享
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 5 5 评论 打赏
评论
1个
内容存在敏感词
手气红包
  • 毛巾卷 2025-04-21 09:31:51
    回复
    学习了
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
UncleRoderick
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

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

举报反馈

举报类型

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

详细说明

审核成功

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

审核失败

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

小包子的红包

恭喜发财,大吉大利

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

    易百纳技术社区