预留内存使用说明
一 概述
预留内存的目的是根据各个场景的不同, 需要预留一些内存给一些功能单独使用, 方便使用以及调试, 各方面的预留内存可以让对应模块的内存申请独有化, 减少多次申请导致的内存碎片以及让调试过程中能更好的配置自己模块所需要的内存大小,提高整体的稳定性
reserved_memory:h264解码
rmem:lcd, jpeg编解码, 2d
lcd_mem:快启时rtos的显示内存
二 预留内存方式
2.1 rmem
说明:rmem的内存由libhardware2的rmem相关接口进行调用申请, 主要提供给一些需要申请大内存的驱动或场景使用
例如lcd, jpeg编解码, 2d, 应用层上还经常使用rmem的接口申请带有物理地址的内存, 用于给一些需要硬件参与的驱动直接调用
配置方法:位于bootloader/uboot-x2000/boards.cfg中配置, 在所用配置的options里加上RMEM_MB=XXX
详细内存位置划分看第三章
boards.cfg中使用的配置以ad100_evb_v10_nor_5.10_defconfig为例
bhu@bhu-PC:~/work/build/configs$ grep -nr "uboot" ad100_evb_v10_nor_5.10_defconfig
3:APP_uboot_toolchain_dir=../tools/toolchains/mips-gcc720-glibc229
4:APP_uboot_dir=../bootloader/uboot-x2000
5:APP_uboot_config=ad100_base_xImage_sfc_nor
ad100_base_xImage_sfc_nor mips xburst2 ad100_base ingenic ad100 ad100_base:AD100N_DDR,SPL_SFC_NOR,ENV_IS_IN_SFC,MTD_SFCNOR,SPL_OS_BOOT,NOR_SPL_BOOT_OS,RMEM_MB=8
iconfig配置:需要选中两个,第一个是驱动的选项,第二个是驱动对应的调用
查看:烧录进入板子后可通过cat /proc/cmdline查看配置的rmem
计算方法:以下分别用上lcd, jpeg编解码, 2d时所需要的内存, 这里提供简单的基本算法,实际使用应该尽量往高一点计算
lcd为720p的屏幕, 并且fb只配置一层, 然后为2个buffer时
(720 ×1280 × 4) × 2 = 7372800 (lcd的内存是按ARGB的32位申请的,因此需要乘4)
jpeg解码需要输入源和输出源
输入 1280 × 720 = 921600 (jpeg图片最大按宽 * 高计算)
输出 1280 × 720 × 4 = 3686400 (ARGB的大小)
总大小为 921600 + 3686400 = 4608000
(多程序多线程调用时需要多一倍)
jpeg编码需要输入源和输出源
输入 1280 × 720 × 4 = 3686400 (ARGB的大小)
输出 1280 × 720 = 921600 (jpeg图片最大按宽 * 高计算)
总大小为 3686400 + 921600 = 4608000
(多程序多线程调用时需要多一倍)
2d的功能比较多,由各个功能不同决定内存大小不同,此处以旋转为例子 (2d的接口支持用已申请的物理地址进行运算, 例如当你直接将一个源旋转到lcd的物理地址上时,则可以免去目标地址的内存申请)
输入 1280 × 720 × 3 / 2 = 1382400 (旋转前的源大小)
输出 720 × 1280 × 3 / 2 = 1382400 (旋转后的目标大小)
总大小为 1382400 + 1382400 = 2764800
以上示例lcd, jpeg编解码, 2d的内存合计是7372800 + 4608000 + 4608000 + 2764800 = 19353600 (18.46M),实际数值应该高于此值
2.2 LCD_MEM
说明:lcd_mem是快速启动时, 分配给rtos使用的显示内存, linux会接管rtos_lcd内存
配置方法:位于bootloader/uboot-x2000/boards.cfg中配置,在所用配置的options里加上LCD_MEM_MB=XXX, 与rtos配置大小需要一致
如上⾯linux分配的LCD_MEM_MB=4, 则对应的值为 0x400000. 固件加载的地址计算公式为:0x80000000 + ddr_size - rtos_size
ad100 的 ddr_size 为 64MB, 则固件加载的地址为 0x80000000 + 0x4000000 - 0x400000 =0x83c00000
详细内存位置划分看第三章
查看:烧录进入板子后可通过在Linux系统里cat /proc/cmdline查看配置的LCD_MEM_MB
计算方法:根据fb驱动配置的帧数*分辨率
lcd为720p的屏幕, 并且fb只配置一层, 然后为2个buffer时
(720 × 1280 × 4) × 2 = 7372800 (lcd的内存是按ARGB的32位申请的,因此需要乘4)
2.3 reserved_memory
说明:reserved_memory是kernel里配置的, 由设备树上分配的一项预留内存, 通常用于内核里驱动的内存使用
不同于RMEM, 该段内存主要用于给h264解码内存使用, h264解码是一个相对独立且内存消耗较大的驱动
单独用此功能分配内存可以更好的管理内存分配, 并且避免在使用内存较频繁之后产生内存碎片, 申请不到编解码所需要的连续内存导致错误
配置方法:位于kernel/kernel/module_drivers/dts/对应的dts文件, 通过增加下述字段使用
dts文件查询, 以ad100_evb_v10_nor_5.10_defconfig为例
bhu@bhu-PC:~/ad100/build/configs$ grep -nr "kernel" ad100_evb_v10_nor_5.10_defconfig
6:APP_kernel_dir=../kernel/kernel
7:APP_kernel_config=ad100_module_base_linux_sfc_nor_defconfig
bhu@bhu-PC:~/ad100/build/configs$ grep -nr ".dts" ../../kernel/kernel/arch/mips/configs/ad100_module_base_linux_sfc_nor_defconfig
247:CONFIG_DT_AD100_MODULE_BASE_DTS_FILE="ad100_module_base.dts"
/ {
compatible = "ingenic,ad100";
/*chosen {
bootargs = "console=ttyS0,115200 mem=64M@0x0ip=off init=/linuxrc ubi.mtd=2 root=ubi0:rootfs ubi.mtd=3 rootfstype=ubifs rw flashtype=nand";
};*/
/*
reserved_mem@0x2E00000: 对应预留内存地址起始位置为0x2E00000
reg = <0x2E00000 0xA00000>: 分别对应起始位置为0x2E00000, 大小为0xA00000
配置的凭据以此芯片ad100为例, 内存总大小为64M, 即总大小为0x4000000
ad100通用对应的uboot配置里设置了RMEM_MB=8, 因此总地址的后8M会被RMEM占用, 则剩余内存大小为0x3800000
由此当我们分配10M预留内存给reserved_memory时, 起始地址则为0x3800000-0xA00000 = 0x2E00000, 大小为0xA00000
如果需要改变此区域大小, 需要同时修改起始地址和大小(reserved_mem@0x2E00000 和 reg = <0x2E00000 0xA00000> 的地址需要一起修改)
需要用到该地址申请内存的驱动, 需要加上 memory-region=<&reserved_memory>; 详细参考下面 felix 等的用法
*/
/*reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges =<>;
reserved_memory: reserved_mem@0x2E00000{
compatible = "shared-dma-pool";
reg = <0x2E00000 0xA00000>;
};
};*/
/* 加上 memory-region=<&reserved_memory>; 表示会用上方设置的预留内存地址和大小作为内存申请 */
&felix {
status = "okay";
/* memory-region=<&reserved_memory>; */
};
查看:需要在烧录后通过free进行比较
计算方法:解码1080p的视频,需要预留的内存大小dec_mem为
frame_size = 1920 × 1080 × 3 / 2 = 3110400
felix->max_frames_buffer = 6 (默认等于6,可以通过修改模块参数的值来修改,例如:echo 3 > /sys/module/ingenic_felix/parameters/max_frame_buffers)
dec_mem = (max_frames_buffer + 1) × frame_size = (6 + 1) × 3110400 = 20.8M
同理算出720p需要内存为 (6 + 1) × 1280 × 720 × 3 / 2 = 9.2M
注:
- 计算出来的内存为极限值,需要多预留
- 此为使用libhardware2 接口内存计算方式,若使用ffmpeg以ffmpeg实际使用为准
- 可以根据实际剩余内存,修改预留大小,实际剩余内存见第一次解码后的打印
# cmd_h264_decode infile=/usr/data/1_360p.h264 width=640 height=360
[ 131.920557] max available: 22937600
[ 131.920802] min available: 22937600
[ 131.922487] min available: 21524480
[ 131.922735] min available: 21405696
[ 131.922971] min available: 21168128
[ 131.923205] min available: 21049344
[ 131.926647] min available: 21041152
[ 131.926893] min available: 20922368
[ 131.927129] min available: 20684800
[ 131.927363] min available: 20566016
[ 131.943413] min available: 20557824
[ 131.943660] min available: 20439040
[ 131.943897] min available: 20201472
[ 131.944131] min available: 20082688
[ 131.960334] min available: 20074496
[ 131.960582] min available: 19955712
[ 131.960818] min available: 19718144
[ 131.961052] min available: 19599360 //解码后实际剩余内存
[ 162.415004] step3 D-PHY PLL unlocked warning (This log can be temporarily ignored)
三 总体空间划分
图中mem和lcd_mem和rmem的顺序是固定的
lcd_mem和rmem的起始位置会随大小直接更改, 设置为0时则不使用
reserved_memory是mem里单独分开的一部分, 可以是这段里的任何位置,最好是直接放在mem的末尾
需要注意的是reserved_memory需要配置起始地址和大小, 因此放在末尾的时候需要注意rmem和lcd_mem如果改大的话, 需要把reserved_memory的起始位置顺位往前改动一些, 否则将会出现部分交叉导致异常
计算方法:
# cat /proc/cmdline
console=ttyS2,3000000n8 mem=44M@0x0 rmem=16M@0x2c00000 lcd_mem=4M@0x3c00000 init=/linuxrc flashtype=nor clk_ignore_unused root=/dev/mtdblock_bbt_ro2 rootfstype=squashfs ro lpj=11935744
mem可用空间为0-44M, 如果给reserved_memory分配20M(0x1400000), 则起始位置为0x2c00000-0x1400000=0x1800000, dts文件修改如下
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges =<>;
reserved_memory: reserved_mem@0x1800000{
compatible = "shared-dma-pool";
reg = <0x1800000 0x1400000>;
};
};