4.4.6. ION 系统调试指南
4.4.6.1. 概述
ION 系统 是 Linux 内核
X5 BSP 系统
BPU 子系统
HIFI 子系统( DSP)
开发者
通过 hbmem 接口 分配 ION 内存
ION 内存区域
ION 内存
管理子系统 使用 独立 的 内存 区域:在 设备树 中 保留 的 区域,专门 作为 ION 系统 , 详细 见 ION 区域 调整 方法 Linux 系统
中 通用 的 内存 分配器 是 无法 从 ION 内存 区域 分配内存 的,比如 内核 态 的 kmalloc 和 vmalloc 以及 用户 态 的 malloc 等。 ION 内存
管理子系统 为 每个 区域 都 起 了 不同 的 名字: carveout、chunk、cma_reserved、ion_cma、system、system_contig。X5 BSP 中
主要 使用 3 个 ION 区域: cma_reserved、carveout、ion_cmacma_reserved主要为 多媒体系统 提供 内存 carveout主要为 BPU 子系统 提供 内存 ion_cma作为备用 的 区域,当 上述 两个 区域 没有 空间 时, ION 管理子系统 会 自动 从 ion_cma区域中 申请 内存
注意:关于 ION 区域
ION 区域
是 一种 动态 分配内存 的 区域,软件 中 常用 heap(堆)的 数据结构 管理 动态 分配内存 的 区域,所以 本 文档 和 调试 日志 中 每个 ION 区域 也 称作 heap 区域 ION 是 Google 在 Android 中
实现 的 开源 的 内存 管理系统, ION 区域 名称 的 解释 详细 见 The Android ION memory allocator
ION 内存的特点
| 功能 | 描述 |
|---|---|
| 内存 |
ION 提供 |
| 连续 |
ION 内存 |
| 设备 |
ION 允许 |
| 进程 |
支持 |
| 零 |
多个 |
ION 区域分配规则
ION 管理子系统
ION 整体
解决办法: ION 管理子系统
当
指定 cma_reserved 区域 并且 这个 区域 没有 内存 时: 优先选择 carveout 区域 ,其次 是 ion_cma 区域 当
指定 carveout 区域 并且 这个 区域 没有 内存 时: 优先选择 cma_reserved 区域 ,其次 是 ion_cma 区域 当
指定 ion_cma 区域 并且 这个 区域 没有 内存 时:选择 cma_reserved 区域
注意: ion_cma 区域
指定具体 ION 区域的方法
多媒体系统
和 BPU 的 软件 框架 内部 指定 了 首选 ION 区域,如下 表 所示:
| 模块 | 首选 ION 区域 |
|---|---|
| 多媒体系统 | cma_reserved 区域 |
| BPU 系统 | carveout 区域 |
注意:
OSD 模块
比较 特殊, OSD 模块 属于 多媒体系统 中 的 硬件加速 单元,但是 默认 从 carveout 区域 分配 空间 开发者
通过 hbmem 接口 分配 ION 内存 时 通过 Flag 参数 可以 指定 首选 ION 区域
4.4.6.2. ION 使用方法
ION 区域大小调整方法
ION 区域
所以 Kernel 的
1G 大小
的 DDR 的 默认 ION 区域 配置 2G 大小
的 DDR 的 默认 ION 区域 配置 大于
等于 4G 大小 的 DDR 的 默认 ION 区域 配置
上述
miniboot 启动
过程 中 会 识别 到 当前 DDR 的 容量,并 保存 到 寄存器 中 uboot 启动
过程 中,根据 miniboot 保存 到 寄存器 中 的 值,知道 当前 的 DDR 容量,然后 解析 Kernel 设备树 文件 得到 当前 DDR 容量 对应 的 ION 内存 的 默认 配置
以上
注意: uboot 命令行
Linux 设备树中 调整 ION 区域的方法
BSP 源码arch/arm64/boot/dts/hobot/x5-memory.dtsi 中
/ {
[...]
reserved-memory {
[...]
/* UBoot will enable corresponding node when ddr size is confirmed */
ion_reserved_1g: ion_reserved_1g@A4100000 {
compatible = "ion-pool";
reg = <0x0 0xA4100000 0x0 0x07000000>; /* 112MiB */
status = "disabled";
};
ion_carveout_1g: ion_carveout_1g@AB100000 {
compatible = "ion-carveout";
[...]
};
ion_cma_1g: ion_cma_1g@B2100000 {
compatible = "ion-cma";
[...]
};
ion_reserved_2g: ion_reserved_2g@A4100000 {
compatible = "ion-pool";
[...]
};
ion_carveout_2g: ion_carveout_2g@C4100000 {
compatible = "ion-carveout";
[...]
};
ion_cma_2g: ion_cma_2g@E4100000 {
compatible = "ion-cma";
[...]
};
ion_reserved_ge4g: ion_reserved_ge4g@A4100000 {
compatible = "ion-pool";
[...]
};
ion_carveout_ge4g: ion_carveout_ge4g@E4100000 {
compatible = "ion-carveout";
[...]
};
ion_cma_ge4g: ion_cma_ge4g@124100000 {
compatible = "ion-cma";
[...]
};
};
};
开发者
| DDR 容量 | ION 区域 |
|---|---|
| 1G | 1. cma_reserved 区域: ion_reserved_1g 2. carveout 区域: ion_carveout_1g 3. ion_cma 区域: ion_cma_1g |
| 2G | 1. cma_reserved 区域: ion_reserved_2g 2. carveout 区域: ion_carveout_2g 3. ion_cma 区域: ion_cma_2g |
| 大于 |
1. cma_reserved 区域: ion_reserved_ge4g 2. carveout 区域: ion_carveout_ge4g 3. ion_cma 区域: ion_cma_ge4g |
uboot 中调整 ION 区域的方法
ION 调试手段
X5 BSP 提供
ION 区域
的 角度(内存 提供者): 描述 每个 ION 区域
的 信息 比如
总共 多少,使用 了 多少,以及 每 一次 具体 分配 的 内存 块 的 信息
client 的
角度(内存 使用者): client 表示
使用者 的 身份 标识,比如 进程 ID 、 VPU、 JPU 、等 展示 client 整体
占用 的 大小 和 每 一次 具体 分配 的 内存 块 的 信息
查看各个 ION 区域的统计信息
命令
单独
查看 每个 ION 区域 的 统计 信息
cat /sys/kernel/debug/ion/heaps/ion_cma
cat /sys/kernel/debug/ion/heaps/cma_reserved
cat /sys/kernel/debug/ion/heaps/carveout
查看
所有 ION 区域 的 统计 信息
cat /sys/kernel/debug/ion/heaps/all_heap_info
其中 ion_cma、 cma_reserved、 carveout 对应
以 /sys/kernel/debug/ion/heaps/cma_reserved 为例:
root@buildroot:~# cat /sys/kernel/debug/ion/heaps/cma_reserved
-------------------------------------------------------------------------
the heap id is 6
-------------------------------------------------------------------------
-------------------------------------------------------------------------
cma_reserved heap total size 536870912
-------------------------------------------------------------------------
heap name client pid size
-------------------------------------------------------------------------
cma_reserved udevd 294 1134592
cma_reserved udevd 307 3145728
-------------------------------------------------------------------------
allocations (info is from last known client):
udevd 294 gpu 4096 1
udevd 294 gpu 4096 1
udevd 294 gpu 4096 1
udevd 294 gpu 8192 1
udevd 294 gpu 1114112 1
udevd 307 vpu 3145728 1
-------------------------------------------------------------------------
total orphaned 0
total 4280320
-------------------------------------------------------------------------
第一
部分 打印 的 heap id是 ION 子系统内部 对 各个 不同 类型 的 ION 区域 的 编号,详细 请 参考 BSP 源码 包 的 文件 kernel/include/uapi/ion.h内的 enum ion_heap_type。第二
部分 打印 的 heap total size是当前 ION 区域 在 系统 内 预留 的 总 大小(注意:单位 为 byte, 10 进制)。 第三
部分 打印: 每
一列 的 含义 可以 参考 标题。 备注:
client列为udevd时,说明这部分 内存 分配 时 的 用户 层 进程 为 udevd,一般 是 在 自动 加载 驱动 ko 后,驱动 初始化 时 通过 ION 申请 的 内存。
第四
部分 打印 展示 了 每个 进程 的 每 一次 具体 分配 和 分配 的 大小: 第一列
打印 的 是 进程 应用 名 第二列
打印 的 是 PID(注意,这里 的 PID 在 每次 启动 都 有 可能 不同,上 列 打印 仅供参考 )。 第三列
打印 的 是 X5 ION 系统 自定义 的 模块 标识符,模块 标识 的 来源 是 client 发起 分配 时 传递 的 Flag。 第四
列 打印 的 是 分配 的 大小(注意:单位 为 byte, 10 进制)。 第五
列 打印 的 是 被 分配 的 内 存在 内核 内 被 引用 的 次数。
第五
部分 是 数据 总结: total orphaned打印的 是 没有 client 使用,但是 没有 被 释放 的 内存大小。 total打印的 是 当前 heap 总共 被 分配 出去 内存大小(单位 为 byte, 10 进制)。
查看从 ION 申请了内存的 client 的统计信息
X5 设备/sys/kernel/debug/ion/clients/ 目录
注意:以下 client 的
root@buildroot:~# ls /sys/kernel/debug/ion/clients/
1114-0 display-0 dsp0-0 galcore-0 jpu-0 vio_driver_ion-0 vpu-0 vsi_cam_drv_ion-0
上述
| 文件名 | client | 描述 |
|---|---|---|
| 1114-0 | 进程 ID | 使用 |
| display-0 | 显示 |
- |
| dsp0-0 | DSP | - |
| galcore-0 | GPU | 2DGPU 和 3DGPU 使用 |
| jpu-0 | JPU | - |
| osd_driver_ion-0 | OSD | - |
| vio_driver_ion-0 | Camera 相关 |
Camera 相关 |
| vpu-0 | 显示 |
- |
| vsi_cam_drv_ion-0 | Camera 子系统 |
Camera 子系统 |
每个 client 的cat /sys/kernel/debug/ion/clients/<client name> 来
root@buildroot:~# cat /sys/kernel/debug/ion/clients/galcore-0
heap_name: size_in_bytes : handle refcount : handle import : buffer ptr : buffer refcount : buffer share id : buffer share count
cma_reserved: 1000 : 1 : 1 : 4302dede : 2: 2 : 1
cma_reserved: 1000 : 1 : 1 : 417b1a04 : 2: 3 : 1
cma_reserved: 1000 : 1 : 1 : f8c13b57 : 2: 4 : 1
cma_reserved: 2000 : 1 : 1 : f2a1d186 : 2: 5 : 1
cma_reserved: 110000 : 1 : 1 : 3b5dd773 : 2: 6 : 1
-------------------------------------------------------------------------
total 115000
-------------------------------------------------------------------------
size in bytes: 单次申请 的 ION 内存 的 大小:单位 是 byte, 16 进制 buffer ptr: 单次申请 的 ION 内存 的 物理地址 total: 当前 client 占用的 ION 区域 的 总体 大小:单位 是 byte, 16 进制
ION 区域名称对应表
ION 区域
| ION 区域 |
设备树 |
hbmem 接口 |
|---|---|---|
| cma_reserved | ion_reserved_xg | HB_MEM_USAGE_PRIV_HEAP_2_RESERVERD HB_MEM_USAGE_PRIV_HEAP_2_RESERVED |
| carveout | ion_carveout_xg | HB_MEM_USAGE_PRIV_HEAP_RESERVERD HB_MEM_USAGE_PRIV_HEAP_RESERVED |
| ion_cma | ion_cma_xg | HB_MEM_USAGE_PRIV_HEAP_DMA |
表头
中 xg: 表示 Linux Kernel 设备树 中 关于 ion 保留空间 节点 名 后缀,由于 针对 不同 DDR 容量,进行 了 不同 的 默认 定义,所以 使用 xg 来 表示 容量 比如 ion_reserved_xg 表示
的 设备树 节点: ion_reserved_1g、 ion_reserved_2g、 ion_reserved_ge4g
4.4.6.3. 根据业务场景调整 ION 区域大小
X5 BSP 中 ION 区域
理论
计算 ION 资源 占用 情况 实际
运行 程序,通过 ION 调试 手段 验证 步骤 一 的 理论值 是否 正确 根据
理论值 设置 ION 区域
理论计算 ION 资源占用情况
摄像头接入相关的模块
摄像头
第一
部分:HBN 框架 摄像头
接入 相关 的 模块 是 通过 HBN 框架接入到 客户程序 中 的 VIN、 ISP、 VSE、 GDC 都
会 被 抽象 成 一个 Node 节点,多个 Node 连接成 一个 Vflow Node 之间
数据 传递 的 方式:上游 Node 的 图像 数据 存储 到 输出 队列 中,下游 节点 从 上游 节点 的 输出 队列 中 获取 图像 数据 Node 输出
队列 的 存储空间 是从 ION 中 申请 的 HBN 框架提供了 参数 可以 配置 每个 Node 节点 输出 队列 的 缓存 个数,详细 见 hbn_buf_alloc_attr_t 结构 体 的 buffers_num 成员
第二
部分:后台 服务程序 上电后, 摄像头
接入 相关 模块 的 后台 服务程序 会 自动 启动 后台
服务程序 也 会 从 ION 中 申请 内存
HBN 框架
下面HBN 框架 接入
其中 GDC 比较
GDC BIN 文件占用 ION 资源的大小 = 4K_ALIGN( BIN 文件大小 )
| 模块 | 占用 |
格式 |
|---|---|---|
| VIN | ( 4K_ALIGN(宽 * 高 * 2 ) + 4096 )* 缓存 |
RAW10/RAW12/RAW16 |
| ISP | ( 4K_ALIGN(宽 * 高 * 1.5 ) + 4096 )* 缓存 |
NV12 |
| VSE | ( 4K_ALIGN(宽 * 高 * 1.5 ) + 4096 )* 缓存 |
NV12 |
| GDC | ( 4K_ALIGN(宽 * 高 * 1.5 ) + 4096 )* 缓存 |
NV12 |
| OSD | ( 4K_ALIGN(宽 * 高 )* 2 | VGA8 |
| ( 4K_ALIGN(宽 * 高 * 1.5 )* 2 | NV12 | |
| ( 4K_ALIGN(宽 * 高 * 3 )* 2 | SW_VGA4 | |
| ( 4K_ALIGN( 2 * 高 * sizeof(uint32_t))* 2 | POLYGON |
缓存
个数: Node 节点 输出 队列 的 缓存 个数 , 详细 见 hbn_buf_alloc_attr_t 结构 体 的 buffers_num 成员 宽
和 高:当前 节点 处理 的 图像 或 区域 (OSD) 的 分辨率 的 宽 和 高 4K_ALIGN: 按照 4K 的对齐 运算 ,ION 区域 分配 的 最小 单位 是 4K
后台服务程序
| 功能 | 占用 |
|---|---|
| 固定 |
0xAF1000 (11,472,896) |
| ISP 基础 |
(0x38000) * N + 0x102000 |
| VSE 基础 |
0x8000 * N + 0x2000 |
| 开启 3DNR 功能 | TotalSize = 宽 * 高 * 2 (4K_ALIGN(TotalSize) + 4K_ALIGN(TotalSize / 4)) * N |
4K_ALIGN: 按照 4K 的对齐 运算 N:标识 Vflow 的
数量
VPU
H264 编码
| 功能 | 占用 |
描述 |
|---|---|---|
| sei 自定义 |
16384 * 5 | - |
| customMap | 262144 | - |
| vui | 16384 | - |
| Motion Vector 运动 |
4K_ALIGN(( 64_ALIGN( 长 ) * 64_ALIGN(宽) / 32)* 2 ) + 4096 | - |
| FBC Luma table buffer | 4K_ALIGN(( 256_ALIGN( 长 ) * 64_ALIGN(宽) / 32)* 2 ) + 4096 | - |
| FBC Chroma table buffer | 4K_ALIGN(( 256_ALIGN( 长 /2) * 64_ALIGN(宽)/32)* 2) + 4096 | - |
| Sub-sampled buffer for ME( 运动 |
4K_ALIGN(( Allign32( 长 /4) * Allign4(宽/4))* 2) + 4096 | - |
| MediaCodec 软件 |
4K_ALIGN(长 * 宽 * 位深 (NV12 的 |
举例: 1080P 的 |
| MediaCodec 软件 |
4K_ALIGN(长 * 宽 * 位深 (NV12 的 |
外部 |
| task buffer | 计算 |
- |
| 重建 |
计算 |
- |
task buffer与重建帧和参考帧的计算 逻辑 比较复杂,计算结果 只 依赖 图像 的 分辨率,可 根据 实际 图像 分辨率 参考 如下 的 表格,
如果表格 中 没有 包含 指定 的 分辨率,可以 根据 如下 表格 进行 估算
| 分辨率 | 摄像头 |
task buffer | 重建 |
|---|---|---|---|
| 3840*2160 | imx415 | 61501440 | 12443648 * 2 |
| 1920*1080 | sc230 | 16560128 | 3,112,960* 2 |
| 1088*1280 | sc132 | 16494592 | 2088960 *2 |
| 1600*1200 | sc202 | 16547840 | 2883584 *2 |
| 640*480 | sc035 | 16396288 | 462848* 2 |
H265 编码
| 功能 | 占用 |
描述 |
|---|---|---|
| sei 自定义 |
16384 * 5 | - |
| vui | 16384 | - |
| Motion Vector 运动 |
4K_ALIGN(( 64_ALIGN( 长 ) * 64_ALIGN(宽) / 32)* 2 ) + 4096 | - |
| FBC Luma table buffer | 4K_ALIGN(( 256_ALIGN( 长 ) * 64_ALIGN(宽) / 32)* 2 ) + 4096 | - |
| FBC Chroma table buffer | 4K_ALIGN(( 256_ALIGN( 长 /2) * 64_ALIGN(宽)/32)* 2) + 4096 | - |
| Sub-sampled buffer for ME( 运动 |
4K_ALIGN(( Allign32( 长 /4) * Allign4(宽/4))* 2) + 4096 | - |
| MediaCodec 软件 |
4K_ALIGN(长 * 宽 * 位深 (NV12 的 |
举例: 1080P 的 |
| MediaCodec 软件 |
4K_ALIGN(长 * 宽 * 位深 (NV12 的 |
外部 |
| task buffer | 计算 |
- |
| 重建 |
计算 |
- |
task buffer与重建帧和参考帧的计算 逻辑 比较复杂,计算结果 只 依赖 图像 的 分辨率,可 根据 实际 图像 分辨率 参考 如下 的 表格,
如果表格 中 没有 包含 指定 的 分辨率,可以 根据 如下 表格 进行 估算
| 分辨率 | 摄像头 |
task buffer | 重建 |
|---|---|---|---|
| 3840*2160 | imx415 | 60968960 | 12443648 * 2 |
| 1920*1080 | sc230 | 16461824 | 3112960 * 2 |
| 1088*1280 | sc132 | 16445440 | 2088960 *2 |
| 1600*1200 | sc202 | 16457728 | 2883584 *2 |
| 640*480 | sc035 | 16420864 | 462848 * 2 |
BPU
| 功能 | 占用 |
描述 |
|---|---|---|
| 固定 |
32768 * 2 | 只要 |
| 模型 |
4K_ALIGN( 模型 |
只会 |
| 模型 |
模型 (4K_ALIGN( [ 模型 4K_ALIGN( [ 模型 |
只要hbSysAllocCachedMem 接口,就 |
| 模型 |
模型 4K_ALIGN(output[0].AlignedByteSize) + 4K_ALIGN(output[1].AlignedByteSize) + 4K_ALIGN(output[2].AlignedByteSize) + |
只要hbSysAllocCachedMem 接口,就 |
模型
输入 Buffer 大小:通过 接口 hbSysAllocCachedMem申请,存储送入 模型 的 图片 模型
输出 Buffer 大小:通过 接口 hbSysAllocCachedMem申请,存储模型 的 输出 结果 AlignedByteSize: BPU 软件框架 中 结构 体 hbDNNTensorProperties中的 成员 变量 alignedByteSize
注意: BPU 占用 ION 资源
情况 1 :在
某些 模型 中,运行 时 BPU 的 软件 框架 会 额外 从 ION 申请 一个 堆 区域,例如 yolov5。 情况 2 :有
的 模型 的 输出 算子 需要 额外 ION 内存,比如 yolov5
验证理论值
正式
由 查看
但是
摄像头
接入 模块(除 OSD 和 后台 服务)整体 作为 一个 client, 无法 查看 每个 模块 的 ION 占用,所以 需要 借助 其他 方式 BPU 模块:没有
对应 的 client,需要 通过 其他 方式 其他
模块: VPU、 VPU、 GPU、 OSD 等 有 对应 的 client 节点
摄像头接入模块
由于vio_driver_ion-0, 所以
为了
在 HBN 软件
接口 中 指定 不同 的 Flag,从而 all_heap_info中体现 出 不同 的 名字 。 查看
all_heap_info节点信息 并 按照 各个 模块 的 名字 进行 过滤。
以 VIN 模块cimdma)
如下
root@buildroot:~# cat /sys/kernel/debug/ion/heaps/all_heap_info |grep cimdma
sunrise_camera 1070 cimdma 4096 1
sunrise_camera 1070 cimdma 4149248 0
sunrise_camera 1070 cimdma 4096 1
sunrise_camera 1070 cimdma 4149248 0
sunrise_camera 1070 cimdma 4096 1
sunrise_camera 1070 cimdma 4149248 0
| 模块 | 标识 | 描述 | HBN 软件 |
|---|---|---|---|
| VIN | cimdma | - | HB_MEM_USAGE_HW_CIM |
| ISP | isp_yuv | - | HB_MEM_USAGE_HW_ISP |
| VSE | other(cma_reserved) | - | 未定义,使用 |
| GDC | gdc | - | HB_MEM_USAGE_HW_GDC_OUT |
| GDC BIN 文件 | gdcfb | - | HB_MEM_USAGE_HW_GDC |
HBN 软件接口中指定 Flag: 详细见 hbn_buf_alloc_attr_t 结构 体 的 buffers_num 成员
BPU 模块
如下
root@buildroot:~# cat /sys/kernel/debug/ion/heaps/all_heap_info |grep bpu
sunrise_camera 1070 bpu 32768 0
sunrise_camera 1070 bpu 9486336 0
sunrise_camera 1070 bpu 4259840 0
sunrise_camera 1070 bpu 7864320 0
sunrise_camera 1070 bpu 4096 0
sunrise_camera 1070 bpu 4259840 0
sunrise_camera 1070 bpu 4096 0
sunrise_camera 1070 bpu 4096 0
sunrise_camera 1070 bpu 32768 0
sunrise_camera 1070 bpu 229376 0
sunrise_camera 1070 bpu 229376 0
sunrise_camera 1070 bpu 454656 0
sunrise_camera 1070 bpu 229376 0
sunrise_camera 1070 bpu 454656 0
sunrise_camera 1070 bpu 454656 0
sunrise_camera 1070 bpu 454656 0
sunrise_camera 1070 bpu 229376 0
sunrise_camera 1070 bpu 454656 0
sunrise_camera 1070 bpu 229376 0
sunrise_camera 1095 bpu 450560 0
sunrise_camera 1095 bpu 450560 0
sunrise_camera 1095 bpu 1802240 0
sunrise_camera 1095 bpu 7200768 0
sunrise_camera 1095 bpu 450560 0
sunrise_camera 1095 bpu 1802240 0
sunrise_camera 1095 bpu 7200768 0
sunrise_camera 1095 bpu 450560 0
sunrise_camera 1095 bpu 1802240 0
sunrise_camera 1095 bpu 7200768 0
sunrise_camera 1095 bpu 7200768 0
sunrise_camera 1095 bpu 1802240 0
sunrise_camera 1095 bpu 450560 0
sunrise_camera 1095 bpu 7200768 0
sunrise_camera 1095 bpu 1802240 0
其他模块
如下total 5f0000 表示 Display 占用 ION 资源
root@buildroot:~# cat /sys/kernel/debug/ion/clients/display-0 |grep "total"
total 5f0000
| 模块 | client 文件 |
|---|---|
| VPU | vpu-0 |
| JPG/MJPEG | jpu-0 |
| GPU | galcore-0 |
| Display | display-0 |
| OSD | osd_driver_ion-0 |
| DSP | dsp0-0 |
| 摄像头 |
vsi_cam_drv_ion-0 |
修改 ION 区域并生效
快速
调试 的 方法 : 通过 uboot 命令行 配置 ,参考 uboot 中 调整 ION 区域 的 方法 正式
使用 的 方法:修改 设备树 重新 编译 镜像,参考 Linux 中 调整 ION 区域 的 方法