You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Petalinux 2020.2(Zynq-7000)CMA分配故障求助

Zynq-7000开发板高分辨率显示CMA分配错误排查与解决

问题描述

自定义Zynq-7000开发板在使用1920x1080及更高分辨率时出现CMA分配失败,1024x768模式可正常运行。2560x1600分辨率下调试输出如下:

[12:09:34:466] xlnx-pl-disp amba_pl:xlnx_pl_disp: surface width(2560), height(1600) and bpp(24)
[12:09:34:474] xlnx-pl-disp amba_pl:xlnx_pl_disp: bytes per line after alignment: 12288000
[12:09:34:480] xlnx-pl-disp amba_pl:xlnx_pl_disp: allocating 12288000 bytes with kzalloc()...
[12:09:34:488] xlnx-pl-disp amba_pl:xlnx_pl_disp: OK
[12:09:34:491] xlnx-pl-disp amba_pl:xlnx_pl_disp: init gem object...
[12:09:34:497] xlnx-pl-disp amba_pl:xlnx_pl_disp: OK
[12:09:34:500] xlnx-pl-disp amba_pl:xlnx_pl_disp: creating mmap offset...
[12:09:34:505] xlnx-pl-disp amba_pl:xlnx_pl_disp: OK
[12:09:34:508] xlnx-pl-disp amba_pl:xlnx_pl_disp: gem cma created with size 12288000
[12:09:34:514] xlnx-pl-disp amba_pl:xlnx_pl_disp: failed to allocate buffer with size 12288000
[12:09:34:522] xlnx-pl-disp amba_pl:xlnx_pl_disp: Failed to create cma gem object (12288000 bytes)
[12:09:34:527] xlnx-pl-disp amba_pl:xlnx_pl_disp: drm_fb_helper_single_fb_probe() returns -12
[12:09:34:536] xlnx-pl-disp amba_pl:xlnx_pl_disp: Failed to set initial hw configuration.
[12:09:34:541] xlnx-pl-disp amba_pl:xlnx_pl_disp: failed to initialize drm fb

经定位,问题出在drm_gem_cma_helper.c的以下代码行:

cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,GFP_KERNEL | __GFP_NOWARN);

已尝试的调整(未解决):

  • 内核配置中增大CMA大小(128MB → 256MB)
  • 内核配置中增加CMA区域数量(7 → 20)
  • 设备树中添加保留内存
  • bootargs中添加coherent_pool选项

排查方向与解决方案

1. 确认CMA区域的物理连续性

高分辨率帧缓冲需要连续物理内存块,即使总CMA大小足够,若内存被碎片化,也无法分配大连续块。可通过以下方式验证:

  • 查看系统启动日志中CMA区域的分配信息,确认是否有足够大的连续空闲块
  • 使用cat /proc/meminfo查看CmaTotal、CmaFree和CmaUsed字段,重点关注空闲连续块的最大尺寸

2. 检查设备树中CMA的配置是否正确

确保设备树中CMA区域的定义覆盖了适合Zynq-7000的物理内存范围,且未与其他保留内存冲突。示例配置:

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    cma@0x10000000 {
        compatible = "shared-dma-pool";
        reg = <0x10000000 0x10000000>; /* 256MB */
        reusable;
        status = "okay";
        linux,cma-default;
    };
};

3. 调整dma_alloc_wc的分配标志

当前使用的GFP_KERNEL | __GFP_NOWARN可能无法应对内存碎片化,尝试添加__GFP_COMP标志(用于分配复合页,允许更大的连续块),修改后的代码:

cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN | __GFP_COMP);

4. 验证Zynq-7000的内存控制器配置

确保PS端的内存控制器正确配置了DDR的大小和映射,避免因硬件层面的内存限制导致无法分配大缓冲区。可通过查看设备树中memory节点或启动日志中的内存检测信息确认。

5. 禁用其他占用大内存的模块

系统中若有其他模块(如视频编解码、DMA驱动)占用了大量连续内存,会影响CMA分配。可临时禁用这些模块,测试高分辨率显示是否正常,以排除内存竞争问题。

6. 调整内核内存分配策略

在内核配置中启用CONFIG_CMA_DEBUG,可以输出更详细的CMA分配日志,帮助定位碎片化问题。同时,可尝试启用CONFIG_CONTIG_ALLOC,增强连续内存分配的能力。

内容的提问来源于stack exchange,提问作者KotNitro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:25:17