MI SYS Debug SOP
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.0 | 12/21/2023 |
前言¶
本文为FAE及软件开发相关人员而写,旨在介绍开发过程中客户遇到MI SYS相关问题时,如何自行进行初步排查,确定是Sigmastar SDK问题后再提供相关信息给RD分析。
1. MMU 踩内存问题¶
-
出现以下log,说明发生了MMU踩内存。
[MI WRN] MI_SYS_Mma_MmuCallback[227]: [MI_SYS_Mma_MmuCallback] Status=0x2, PhyAddr=0x40070000, ClientId=0x70,Name=CPU_CA35 IsWrite=0
- Status
- 触发该回调的原因,当前值为0x2,属于非法读写操作。
-
PhyAddr
- 访问触发异常的entry起始地址,当前值为0x40070000
-
ClientId
- 模块id,当前值为0x70
-
Name
- 模块名,当前值为CPU
-
IsWrite
- 读写操作,1是写,0是读,当前值为0,是读操作。
- Status
-
分析
-
运行应用前输入以下命令收集mma内存申请和释放的详细信息
echo debug_mmu debug_log 1 > /proc/mi_modules/mi_sys/mi_sys0
若PhyAddr位于某个已经释放的 buff的fr和ed之间,说明模块访问了已经释放的内存。
al:64000 sz:cac0 ed:70ac0 na:app-mmaAlloc fr:64000 sz:cac0 ed:70ac0 na:app-mmaAlloc [MI WRN] MI_SYS_Mma_MmuCallback[227]: [MI_SYS_Mma_MmuCallback] Status=0x2, PhyAddr=0x40070000, ClientId=0x70,Name=CPU_CA35 IsWrite=0
由log可知,PhyAddr= 0x40070000,vpa的起始地址由/proc/mi_modules/mi_sys_mma/mma_heap_name0可得,当前vpa起始地址为0x40000000,所以PhyAddr相对vpa的起始地址的偏移地址为 0x70000,是在free的内存范围内(0x70000在0x64000-0x70ac0范围内),大概率是cpu 访问了释放后的app-mmaAlloc buff。
-
若MmuCallback打印的PhyAddr不在已经free掉的内存地址范围中,怀疑是log太多,部分log被冲掉,此时已经确定踩内存的模块,那么可以只过滤对应模块的内存分配信息。
echo debug_mmu debug_log [enable/disable] [enable/disable free] [enable/disable alloc] [module id list] > /proc/mi_modules/mi_sys/mi_sys0
例子:
- enable vif ai alloc/free buf log
echo debug_mmu debug_log 1 1 1 4,6 > /proc/mi_modules/mi_sys/mi_sys0
- enable vif ai alloc/free buf log
-
若上述没有发现踩到free的buff,那么打开debugMmu进行debug,修改/config/modparam.json文件,在E_MI_MODULE_ID_SYS增加{"debugMmu" : 1},然后重启机器,运行应用。
"E_MI_MODULE_ID_SYS" : { "cmdQBufSize" : 400, "debugmmu": 1 },
这时当HW多读或多写时可以100%抓到,打印类似以下log。
al:1480000 sz:320000 ed:17a0000 na:vde_rec_0_0_0 [MI WRN] MI_SYS_Mma_MmuCallback[425]: [MI_SYS_Mma_MmuCallback] Status=0x2, PhyAddr=0x401780000, ClientId=0x38,Name=VENC0_CODEC0_R IsWrite=0
首先计算出entry size:在开机后,cat /proc/mi_modules/mi_sys_mma/mma_heap_name0,其中heap_info 的length 除以 freeEntryNum 就是entry size。 此时mmu entry size 设置为128K ,若 PhyAddr+entry size=ed,那么可以说明模块发生了内存越界访问。上述log中,0x17a0000(ed)=0x1780000+0x20000(entry size),说明VENC0_CODEC0_R模块发生了内存越界访问。
-
根据Name找对应模块owner,提供以上打印的log并告诉以上分析结论。
-
2. MIU Protect问题¶
当遇到如下log时,代表发生了miu protect:
[HAL MIU ERR] [hal_miu_protect_show_hit_info@1301] [PROTECT] IP hit protect address. Hit block 32, address: 0x400800000<->0x400802000, whitelist: [CPU_CA55, ] Hit count: 1 Hit IP : 0x45 - BDMA Hit MMU address: 0x400800000<->0x40080000f
可以遵循如下步骤进行分析定位:
- 出现miu protcect的原因:“IP hit protect address”代表白名单之外的IP访问了受保护的地址;“IP write out of dram”代表IP访问了超出dram范围的地址或出现了MMU踩内存问题,需关闭kernel panic后观察是否出现MMU踩内存打印,进一步确认原因。(关闭kernel的方法见第5点)
- 通过log中的信息,可以得知出问题的ip是bdma,他访问了block 32(该block地址范围是0x400800000<->0x400802000,白名单中设置了只允许CPU_CA55访问)中的0x400800000<->0x40080000f地址
- 寻求bdma ip owner的帮助,需要提供log以及当前场景下bdma的使用情况、传参调用等信息
- 默认在发生miu protect后出现kernel panic,如果不希望发生问题时panic,可以通过将modparam.json中的 "g_bEnableMiuPanic" 字段设为false实现,设置完后需要重启或重新加载mi_sys.ko
- 当前系统的miu protect情况可以通过cat /proc/mi_modules/mi_sys_mma/miu_protect获得,默认的策略是保护kernel lx_mem中除mma之外的所有内存,将bsp相关的ip设置为白名单,stream pipe相关的ip不允许访问
3. 帧率不足问题¶
帧率不足问题具体表现为:
播放器拉流看对应的fps没有达到设定的数值
若出现帧率不足问题,可以遵循如下步骤进行分析定位:
1.watch -n 1 'cat /proc/mi_modules/mi_venc/mi_venc*'
---------------------------- OutputPort of dev: 0 ----------------------------- ChnId CODEC Profile BufSize MinAllocSize RefNum bByFrame FrameCnt DropCnt ReEncCnt RingUnreadCnt RingTotalCnt UsrLockedCnt 0 H265 0 4147200 7273 0 1 871390 0 0 0 0 0 -----------------------------------Input port common info for mi_venc only dump enabled port----------------------------------- ChnId PassId PortId user_buf_quota UsrInjectQ_cnt BindInQ_cnt TotalPendingBuf_size usrLockedInjectCnt 0 0 0 4 0 4 37601280 0 ChnId PassId PortId curWorkingQ_cnt workingTask_cnt lazzyRewindTask_cnt 0 0 0 3 1 0
查看 RingUnreadCnt/RingTotalCnt/UsrInjectQ_cnt/BindInQ_cnt 是否在2~4 变化,如果有,那说明是 APP 取流不够快,想证明确实是 APP 取流不够快,可以直接在 mi venc 内部就 drop 掉编码好的 es.
echo drop_out a d > /proc/mi_modules/mi_venc/mi_venc0
此时再观察 mi venc procfs 里面的 Fps_1s 字段,看帧率是否提上来了.
ChnId State EnPred base enhance MaxStreamCnt Fps_1s kbps1s Fps10s kbps10s lastQp 0 0 0 0 0 3 29.99 964 29.98 929 20
2.从后级模块往前级模块依次cat /proc/mi_modules/mi_xxx/mi_xxx*
查看 InputPort 的 DropCnt 是否持续增加,持续增加说明是对应模块内部丢帧了
ChnId State EnPred base enhance MaxStreamCnt Fps_1s kbps1s Fps10s kbps10s lastQp 0 0 0 0 0 3 12.99 964 13.58 929 20
继续看GetIntoMaxCnt/GetIntoMmaLackCnt/GetIntoTotalCnt/GetIntoFrcCnt 是否在持续增长
ChnId PassId PortId GetFrame/Ms FPS FinishCnt RewindCnt GetTotalCnt GetOkCnt GetIntoMaxCnt GetIntoMmaLackCnt GetIntoTotalCnt GetIntoFrcCnt 0 0 0 13/1071 12.13 982123 10 1903946 982133 0 0 921813 0
-- GetIntoMaxCnt 增长说明MaxEnqTasks 用满了,可以设大试试。若有效则需要和对应的MI模块owner沟通,让MI模块owner 在驱动中修改MaxEnqTasks。
echo set_Max_EnqTasks <eModuleId> <u8DevId> <u8PassId> <u16ChannelId> <EnqTasksNum> > /proc/mi_modules/mi_sys/mi_sys0 echo set_Max_EnqTasks 23 0 1 0 5 > /proc/mi_modules/mi_sys/mi_sys0
--GetIntoMmaLackCnt 增长说明MMA不够用了,可以bootargs设大试试,若有效则修改defconfig中CONFIG_MMA_MEM_SIZE字段的值为调整后的大小。
--GetIntoTotalCnt 增长说明output port 的缓存可能不足,可以设大试试。若有效则修改APP代码,修改MI模块output port depth。若无效,则有可能是后级模块处理太慢,导致buffer堆积在后级模块,这时候需要分析后级模块处理慢的原因。
echo set_ouputport_depth [Modid] [Devid] [Chnid] [Passid] [Portid] u32UserFrameDepth u32BufQueueDepth > > /proc/mi_modules/mi_sys/mi_sys0 echo set_ouputport_depth23 0 0 1 0 0 6 > /proc/mi_modules/mi_sys/mi_sys0
--GetIntoFrcCnt 增长说明是由于帧率控制导致的丢帧,一般来说就是一定存在帧率控制。
3.根据第2步区分出是哪个模块跟原因,就可以找模块owner具体分析了,看模块HW 耗时是否正常,BW 是否正常,pipe是否超过规格
- 进入sdk/verify/mi_demo目录,make source/miu_server
- 将sdk/verify/mi_demo/out/arm/app/prog_miu_server拷贝到板端
- 在板端运行./prog_miu_server
- 使用 BWLA Tool 工具连接版端,查看 BW 数据
4. MMA内存不足问题¶
mma内存不足问题具体表现为:
- 应用或模块在调用MI_SYS_MMA_Alloc等内存分配接口时返回失败
- 模块发生丢帧,通过对应模块的proc info发现“GetIntoMmaLackCnt”字段在增加
- 其他
cat /proc/mi_modules/mi_sys_mma/mma_heap_name0查看系统当前的mma使用情况,重点关注"length" "avail" "used" "HighPeak"四个字段。若avail小于要分配的大小,或length-HighPeak小于要分配的大小,代表可能出现内存不足问题;否则,代表可能出现内存碎片问题
若出现内存不足问题,可以遵循如下步骤进行分析定位:
-
加大mma内存:
- 如果是pure linux系统,修改环境变量bootargs字段,将mma_heap_name0的sz加大
- 如果是dual os系统,可以通过修改环境变量 bootargs 去增大 mma_size,并相应地减小 LX_MEM、mma_base 的大小。其中 LX_MEM 要求1M 对齐。bootargs_rtos 的mma_base、mma_size 和 bootargs 的mma_base、mma_size 要保持一致。
-
检查/proc/mi_modules/mi_sys_mma/mma_heap_name0中内存的具体使用情况,review是否存在内存泄漏等(mma buffer是否在一直增加、销毁pipeline之后是否有mma buffer没有被回收)。
-
/proc/mi_modules/mi_sys_mma/mma_heap_name0无法呈现出内存分配释放的动态信息,可使用以下命令进一步确认。当申请mma buffer 失败时,会打印当前mma heap的内存信息。可进一步分析是内存不足、泄露还是碎片化。
echo MI_SYS_Chunk_DumpMgrPrintk > /proc/mi_modules/mi_debug/debug_func
echo 7 > /proc/mi_modules/mi_debug/debug_level
-
调整pipeline,模块间尽量使用realtime,hwring等节省内存的绑定方式
-
提供场景图、/proc/mi_modules/mi_sys_mma/mma_heap_name0信息和kmsg打印给mi_sys owner分析给出结论
若出现内存碎片问题,可以遵循如下步骤进行分析定位:
- 开启mmu,可以通过将modparam.json中的 "bEnableMmu" 字段设为true实现,设置完后需要重启或重新加载mi_sys.ko
- 优化应用,使用私有池,将碎片化问题限制在一定范围内。(私有池的使用请参考 MI SYS API中 MI_S32 MI_SYS_ConfigPrivateMMAPool()接口的使用说明)
- 增加mma 内存
5. CMDQ 相关问题¶
5.1. cmdq timeout¶
当cmdq 出现timeout时,通常是因为hw 中断没有产生/某个寄存器设定不符合预期,此时会有如下的信息输出到串口:
[CMDQ]cmdq(0) ERR: WAIT_TRIG_TIMEOUT (0x00000400) [CMDQ]Cmd data = 0x2000 : 0x0000 : 0x0000 : 0xFFFE [CMDQ]Cmd:WAIT, dbg:0, adr:000000, dat:0000, mask:fffe [CMDQ]Wait command timeout. Trigger_Bus Bit [0] Event [ISP_CMDQ_DONE] [CMDQ]dram(s, e, w, r)=(0x40000000, 0x40003ff0, 0x40000020, 0x40000020) sram(w,r)=(002,002) [CMDQ]cmdq(7) ERR: POLLEQ_TIMEOUT (0x00000200) [CMDQ]Cmd data = 0x3008 : 0x94F8 : 0xFF00 : 0x00FF [CMDQ]Cmd:POLLEQ, dbg:0, adr:1129f0, dat:ff00, mask:00ff [CMDQ]Poll eq command timeout. Bank:0x1129; Offset:0x78; Value:0xff00; Mask:0x00ff [CMDQ]dram(s, e, w, r)=(0x4001c000, 0x4001fff0, 0x4001c030, 0x4001c030) sram(w,r)=(003,003)
首先确定是哪个模块的cmdq的问题,有以下两种方式:
5.1.1. wait trigger timeout¶
当timeout类型是WAIT_TRIG_TIMEOUT时,会有Event [ISP_CMDQ_DONE],即可判断是ISP的问题
5.1.2. other¶
此外,在每次log的第一行含有cmdq id,表示发生timeout 的cmdq id。我们可以通过 cat /proc/mi_modules/mi_xx/mi_xx 查看指定模块使用的cmdq id,如下:
----------------------CMDQ kickoff counter----------------------- DevId current_buf_size Peak_buf_size 0 0 0 each dev buf info: offset length used_flag task_name
与出问题的cmdq id比较,确定是哪个模块,最后找对应模块的sw owner,将log与运行场景交给他分析。