最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

RV1126双摄调试记录

维修 admin 33浏览 0评论

RV1126双摄调试记录

RV1126双摄调试记录

  • IMX577驱动
  • dts修改:
  • 排错分析
  • 整理思路继续分析
  • 结论
  • 解决
    • 解决方案一
    • 解决方案二

硬件方案: 双12M IMX577
分辨率 4048x3040
bayer 大约18MB(视频处理中会多次以该大小分配内存块)

IMX577驱动

imx577 sensor 驱动可从rk3588中移植修改来用。
主要修改以下3点:
1.
把RKMODULE_GET_CHANNEL_INFO宏定义及struct rkmodule_channel_info定义拷过来
2.
实现imx577_g_mbus_config函数,
其中config->type = V4L2_MBUS_CSI2_DPHY;
改为config->type = V4L2_MBUS_CSI2;
3.
把函数挂到v4l2_subdev_video_ops结构体(注意不是v4l2_subdev_pad_ops)

dts修改:

channel 1( sensor -> vicap -> isp):
sensor -> csi_dphy0 -> mipi_csi2 -> rkcif_mipi_lvds
rkcif_mipi_lvds_sditf-> rkisp_vir0
channel 2( sensor -> isp):
sensor -> csi_dphy1 -> rkisp_vir1

排错分析

此时运行ispserver并访问video节点kernel会崩溃:

Unable to handle kernel paging request at virtual address ecc00000[   21.439757] [<b011ba40>] (v7_dma_clean_range) from [<b0116d54>] (__map_sg_chunk+0x268/0x3b8)
[   21.440541] [<b0116d54>] (__map_sg_chunk) from [<b01170c8>] (__iommu_map_sg+0x224/0x238)
[   21.441264] [<b01170c8>] (__iommu_map_sg) from [<b0117114>] (arm_iommu_map_sg+0x18/0x20)
[   21.441982] [<b0117114>] (arm_iommu_map_sg) from [<b07d7c40>] (vb2_dma_sg_dmabuf_ops_map+0xd0/0x14c)
[   21.442789] [<b07d7c40>] (vb2_dma_sg_dmabuf_ops_map) from [<b0683f88>] (dma_buf_map_attachment+0x24/0x48)
[   21.443668] [<b0683f88>] (dma_buf_map_attachment) from [<b07974a4>] (vb2_dma_sg_map_dmabuf+0x28/0x9c)
[   21.444488] [<b07974a4>] (vb2_dma_sg_map_dmabuf) from [<b07d91d0>] (rkispp_event_handle+0x1e0/0x4d8)
[   21.445292] [<b07d91d0>] (rkispp_event_handle) from [<b07d4904>] (bridge_ioctl+0x1cc/0x5cc)
[   21.446029] [<b07d4904>] (bridge_ioctl) from [<b07def24>] (rkispp_start_streaming+0x228/0x56c)
[   21.446820] [<b07def24>] (rkispp_start_streaming) from [<b0791010>] (vb2_start_streaming+0x5c/0x150)
[   21.447629] [<b0791010>] (vb2_start_streaming) from [<b0792698>] (vb2_core_streamon+0x11c/0x15c)
[   21.448412] [<b0792698>] (vb2_core_streamon) from [<b077da30>] (__video_do_ioctl+0x1c8/0x3a0)
[   21.449162] [<b077da30>] (__video_do_ioctl) from [<b07811e0>] (video_usercopy+0x21c/0x650)
[   21.449921] [<b07811e0>] (video_usercopy) from [<b0277a94>] (do_vfs_ioctl+0xac/0x798)
[   21.450645] [<b0277a94>] (do_vfs_ioctl) from [<b02781b4>] (ksys_ioctl+0x34/0x58)
[   21.451310] [<b02781b4>] (ksys_ioctl) from [<b0101000>] (ret_fast_syscall+0x0/0x4c)
[   21.451988] Exception stack(0xda85dfa8 to 0xda85dff0)

kernel启动打印内存布局如下:

[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xed000000 - 0xff800000   ( 296 MB)
[    0.000000]     lowmem  : 0xb0000000 - 0xecc00000   ( 972 MB)
[    0.000000]     pkmap   : 0xafe00000 - 0xb0000000   (   2 MB)
[    0.000000]     modules : 0xaf000000 - 0xafe00000   (  14 MB)
[    0.000000]       .text : 0x(ptrval) - 0x(ptrval)   (12256 kB)
[    0.000000]       .init : 0x(ptrval) - 0x(ptrval)   (1024 kB)
[    0.000000]       .data : 0x(ptrval) - 0x(ptrval)   ( 699 kB)
[    0.000000]        .bss : 0x(ptrval) - 0x(ptrval)   ( 310 kB)

可知vb2_start_streaming过程中在v7_dma_clean_range函数错误访问了lowmem的up边界。
崩溃堆栈可知该崩溃发生在rkispp驱动的attachment dma_buf中
但实际该dma_buf是rkisp_rkispp_bridge驱动在isp中分配通过bridge挂接到rkispp中共用。
追查发现rkisp分配的dma_buf采用的videobuf2-rdma-sg.c分配器,该分配器alloc会从cma-isp(dts中的isp_reserved)中分配连续内存,没有充分利用上scatter/gather机制,通过的dts可知cma-isp仅在VICAP及isp/ispp驱动中被使用,内存使用比较一致,垃圾碎片问题应当不会严重,即便碎片致使分配不到整块大内存也该报错而非分配成功使用崩溃。

整理思路继续分析

deconfig中打开CONFIG_CMA_DEBUGFS=y
此命令会在debugfs中导出cma信息供调试
编译烧写启动系统cat /sys/kernel/debug/cma/cma-isp/base_pfn发现base_pfn基址在187,392,左移12位正好0x2DC00000,有dts的isp_reserved可知该cma大小为256MB,此信息也可通过执行dmesg|grep Reserved得到下面两行信息获得:
[    0.000000] Reserved memory: created CMA memory pool at 0x3f800000, size 8 MiB
[    0.000000] Reserved memory: created CMA memory pool at 0x2dc00000, size 256 MiB
可知该cam-isp范围在0x2DC00000 ~ 0x3DC00000
通过内存布局可知lowmem在0xB0000000 ~ 0xECC00000
# cma.cfor (;;) {mutex_lock(&cma->lock);bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap,bitmap_maxno, start, bitmap_count, mask,offset);if (bitmap_no >= bitmap_maxno) {mutex_unlock(&cma->lock);break;}bitmap_set(cma->bitmap, bitmap_no, bitmap_count);/** It's safe to drop the lock here. We've marked this region for* our exclusive use. If the migration fails we will take the* lock again and unmark it.*/mutex_unlock(&cma->lock);pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);if (cma->inactive) {ret = 0;page = pfn_to_page(pfn);break;}。。。}

以上代码可知,在cma->inactive为True时cma分配内存直接简单映射到lowmem,inactive在dts默认被设置故成立(取消设置影响较大,不建议),而追踪cma 区域初始化代码发现cma的start地址总是在有效物理内存区域top_down而分配,且未考虑vmalloc对lowmem的挤压。
综合考虑两个内存范围:
cma-isp phys 0x2DC00000 ~ 0x3DC00000
lowmem virtual 0xB0000000 ~ 0xECC00000
故cma分配的物理内存可能超出lowmem高址16MB,即cma在尾端认为尚有足够内存分配,然而在lowmem却越界,故而崩溃。

结论

cma空间布局仅考虑物理内存可用空间优先高址分配,映射到lowmem使用,而32bit linux系统lowmem通常涵盖不完物理内存,导致cma分配的内存在lowmem存在映射越zone的风险,同时vmalloc也会挤压lowmem空间使问题恶化。

解决

解决方案一

既然问题是cma空间布局跟lowmem存在不协调风险,那么分配时能够控制start,end主动与既知lowmem区域协调最好不过。

# rv1126_xxxx.dts
&isp_reserved {alloc-ranges = <0x10000000 0x10000000>;size = <0x10000000>;
};

以上dts配置控制cma分配区域,避免与lowmem出现差集。
该方案依然使用cma,保留性能优势,然而cma也存在使内存利用不充分的弊端。

解决方案二

直接使用系统内存配合sg机制

# driver/media/platform/rockchip/isp/hw.c
static int rkisp_hw_probe(struct platform_device *pdev) {......if (is_mem_reserved) {/* reserved memory using rdma_sg */hw_dev->mem_ops = &vb2_rdma_sg_memops;hw_dev->is_dma_sg_ops = true;} else if (hw_dev->is_mmu) {hw_dev->mem_ops = &vb2_dma_sg_memops;hw_dev->is_dma_sg_ops = true;} else {hw_dev->mem_ops = &vb2_dma_contig_memops;}......
}

以上源码可知rkisp/hw驱动可通过is_mem_reserved控制使用哪个分配器,默认的vb2_rdma_sg_memops会从预留的cma分配连续物理/虚拟空间, 其中vb2_dma_sg_memops分配器可凭借list方式从系统内存分散申请dma空间,不要求连续,理论性能弱于cma但实际视频处理帧率并未有明显变化,该方式能更充分利用内存资源。
至于is_mem_reserved,追踪源码即知可通过dts的rkisp节点的memory-region字段有无间接被设置。
以下为具体修改:

# rv1126.dtsi
rkisp {...# memory-region = <&isp_reserved>;...
};

RV1126双摄调试记录

RV1126双摄调试记录

  • IMX577驱动
  • dts修改:
  • 排错分析
  • 整理思路继续分析
  • 结论
  • 解决
    • 解决方案一
    • 解决方案二

硬件方案: 双12M IMX577
分辨率 4048x3040
bayer 大约18MB(视频处理中会多次以该大小分配内存块)

IMX577驱动

imx577 sensor 驱动可从rk3588中移植修改来用。
主要修改以下3点:
1.
把RKMODULE_GET_CHANNEL_INFO宏定义及struct rkmodule_channel_info定义拷过来
2.
实现imx577_g_mbus_config函数,
其中config->type = V4L2_MBUS_CSI2_DPHY;
改为config->type = V4L2_MBUS_CSI2;
3.
把函数挂到v4l2_subdev_video_ops结构体(注意不是v4l2_subdev_pad_ops)

dts修改:

channel 1( sensor -> vicap -> isp):
sensor -> csi_dphy0 -> mipi_csi2 -> rkcif_mipi_lvds
rkcif_mipi_lvds_sditf-> rkisp_vir0
channel 2( sensor -> isp):
sensor -> csi_dphy1 -> rkisp_vir1

排错分析

此时运行ispserver并访问video节点kernel会崩溃:

Unable to handle kernel paging request at virtual address ecc00000[   21.439757] [<b011ba40>] (v7_dma_clean_range) from [<b0116d54>] (__map_sg_chunk+0x268/0x3b8)
[   21.440541] [<b0116d54>] (__map_sg_chunk) from [<b01170c8>] (__iommu_map_sg+0x224/0x238)
[   21.441264] [<b01170c8>] (__iommu_map_sg) from [<b0117114>] (arm_iommu_map_sg+0x18/0x20)
[   21.441982] [<b0117114>] (arm_iommu_map_sg) from [<b07d7c40>] (vb2_dma_sg_dmabuf_ops_map+0xd0/0x14c)
[   21.442789] [<b07d7c40>] (vb2_dma_sg_dmabuf_ops_map) from [<b0683f88>] (dma_buf_map_attachment+0x24/0x48)
[   21.443668] [<b0683f88>] (dma_buf_map_attachment) from [<b07974a4>] (vb2_dma_sg_map_dmabuf+0x28/0x9c)
[   21.444488] [<b07974a4>] (vb2_dma_sg_map_dmabuf) from [<b07d91d0>] (rkispp_event_handle+0x1e0/0x4d8)
[   21.445292] [<b07d91d0>] (rkispp_event_handle) from [<b07d4904>] (bridge_ioctl+0x1cc/0x5cc)
[   21.446029] [<b07d4904>] (bridge_ioctl) from [<b07def24>] (rkispp_start_streaming+0x228/0x56c)
[   21.446820] [<b07def24>] (rkispp_start_streaming) from [<b0791010>] (vb2_start_streaming+0x5c/0x150)
[   21.447629] [<b0791010>] (vb2_start_streaming) from [<b0792698>] (vb2_core_streamon+0x11c/0x15c)
[   21.448412] [<b0792698>] (vb2_core_streamon) from [<b077da30>] (__video_do_ioctl+0x1c8/0x3a0)
[   21.449162] [<b077da30>] (__video_do_ioctl) from [<b07811e0>] (video_usercopy+0x21c/0x650)
[   21.449921] [<b07811e0>] (video_usercopy) from [<b0277a94>] (do_vfs_ioctl+0xac/0x798)
[   21.450645] [<b0277a94>] (do_vfs_ioctl) from [<b02781b4>] (ksys_ioctl+0x34/0x58)
[   21.451310] [<b02781b4>] (ksys_ioctl) from [<b0101000>] (ret_fast_syscall+0x0/0x4c)
[   21.451988] Exception stack(0xda85dfa8 to 0xda85dff0)

kernel启动打印内存布局如下:

[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xed000000 - 0xff800000   ( 296 MB)
[    0.000000]     lowmem  : 0xb0000000 - 0xecc00000   ( 972 MB)
[    0.000000]     pkmap   : 0xafe00000 - 0xb0000000   (   2 MB)
[    0.000000]     modules : 0xaf000000 - 0xafe00000   (  14 MB)
[    0.000000]       .text : 0x(ptrval) - 0x(ptrval)   (12256 kB)
[    0.000000]       .init : 0x(ptrval) - 0x(ptrval)   (1024 kB)
[    0.000000]       .data : 0x(ptrval) - 0x(ptrval)   ( 699 kB)
[    0.000000]        .bss : 0x(ptrval) - 0x(ptrval)   ( 310 kB)

可知vb2_start_streaming过程中在v7_dma_clean_range函数错误访问了lowmem的up边界。
崩溃堆栈可知该崩溃发生在rkispp驱动的attachment dma_buf中
但实际该dma_buf是rkisp_rkispp_bridge驱动在isp中分配通过bridge挂接到rkispp中共用。
追查发现rkisp分配的dma_buf采用的videobuf2-rdma-sg.c分配器,该分配器alloc会从cma-isp(dts中的isp_reserved)中分配连续内存,没有充分利用上scatter/gather机制,通过的dts可知cma-isp仅在VICAP及isp/ispp驱动中被使用,内存使用比较一致,垃圾碎片问题应当不会严重,即便碎片致使分配不到整块大内存也该报错而非分配成功使用崩溃。

整理思路继续分析

deconfig中打开CONFIG_CMA_DEBUGFS=y
此命令会在debugfs中导出cma信息供调试
编译烧写启动系统cat /sys/kernel/debug/cma/cma-isp/base_pfn发现base_pfn基址在187,392,左移12位正好0x2DC00000,有dts的isp_reserved可知该cma大小为256MB,此信息也可通过执行dmesg|grep Reserved得到下面两行信息获得:
[    0.000000] Reserved memory: created CMA memory pool at 0x3f800000, size 8 MiB
[    0.000000] Reserved memory: created CMA memory pool at 0x2dc00000, size 256 MiB
可知该cam-isp范围在0x2DC00000 ~ 0x3DC00000
通过内存布局可知lowmem在0xB0000000 ~ 0xECC00000
# cma.cfor (;;) {mutex_lock(&cma->lock);bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap,bitmap_maxno, start, bitmap_count, mask,offset);if (bitmap_no >= bitmap_maxno) {mutex_unlock(&cma->lock);break;}bitmap_set(cma->bitmap, bitmap_no, bitmap_count);/** It's safe to drop the lock here. We've marked this region for* our exclusive use. If the migration fails we will take the* lock again and unmark it.*/mutex_unlock(&cma->lock);pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);if (cma->inactive) {ret = 0;page = pfn_to_page(pfn);break;}。。。}

以上代码可知,在cma->inactive为True时cma分配内存直接简单映射到lowmem,inactive在dts默认被设置故成立(取消设置影响较大,不建议),而追踪cma 区域初始化代码发现cma的start地址总是在有效物理内存区域top_down而分配,且未考虑vmalloc对lowmem的挤压。
综合考虑两个内存范围:
cma-isp phys 0x2DC00000 ~ 0x3DC00000
lowmem virtual 0xB0000000 ~ 0xECC00000
故cma分配的物理内存可能超出lowmem高址16MB,即cma在尾端认为尚有足够内存分配,然而在lowmem却越界,故而崩溃。

结论

cma空间布局仅考虑物理内存可用空间优先高址分配,映射到lowmem使用,而32bit linux系统lowmem通常涵盖不完物理内存,导致cma分配的内存在lowmem存在映射越zone的风险,同时vmalloc也会挤压lowmem空间使问题恶化。

解决

解决方案一

既然问题是cma空间布局跟lowmem存在不协调风险,那么分配时能够控制start,end主动与既知lowmem区域协调最好不过。

# rv1126_xxxx.dts
&isp_reserved {alloc-ranges = <0x10000000 0x10000000>;size = <0x10000000>;
};

以上dts配置控制cma分配区域,避免与lowmem出现差集。
该方案依然使用cma,保留性能优势,然而cma也存在使内存利用不充分的弊端。

解决方案二

直接使用系统内存配合sg机制

# driver/media/platform/rockchip/isp/hw.c
static int rkisp_hw_probe(struct platform_device *pdev) {......if (is_mem_reserved) {/* reserved memory using rdma_sg */hw_dev->mem_ops = &vb2_rdma_sg_memops;hw_dev->is_dma_sg_ops = true;} else if (hw_dev->is_mmu) {hw_dev->mem_ops = &vb2_dma_sg_memops;hw_dev->is_dma_sg_ops = true;} else {hw_dev->mem_ops = &vb2_dma_contig_memops;}......
}

以上源码可知rkisp/hw驱动可通过is_mem_reserved控制使用哪个分配器,默认的vb2_rdma_sg_memops会从预留的cma分配连续物理/虚拟空间, 其中vb2_dma_sg_memops分配器可凭借list方式从系统内存分散申请dma空间,不要求连续,理论性能弱于cma但实际视频处理帧率并未有明显变化,该方式能更充分利用内存资源。
至于is_mem_reserved,追踪源码即知可通过dts的rkisp节点的memory-region字段有无间接被设置。
以下为具体修改:

# rv1126.dtsi
rkisp {...# memory-region = <&isp_reserved>;...
};

与本文相关的文章

发布评论

评论列表 (0)

  1. 暂无评论