camera内存之---iommu使用(1)

先说下iommu几个名词
iommu_group:代表共享同一个streamid的一组device,也就是多个device可以在同个group
domain :代表一个具体的设备使用iommu的详细spec

Kernel has DMA mapping API fromorigin. ARM defines IOMMU which can be used to connect scattered physicalmemory as a continuous region for devices which needs continue address towork(e.g: DMA). So IOMMU implementations & CMA should work behind kernelDMA mapping API. E.g: dma_alloc_from_contiguous can be implemented by CMA;dma_alloc_coherent can be implemented by IOMMU or by the normal case(just call__get_free_pages). So for device drivers need dma buffers, we should use dmamapping APIs, not call iommu api directly
说明cma可以实现函数dma_alloc_from_contiguous,iommu可以实现dma_alloc_coherent
iommu是实现在dma mapping api下层的驱动,所以我们只需要使用dma mapping的相关api,不需要直接调用iommu接口。

IOMMU,Input-Output Memory Management Unit
网上有些关于使用iommu的好处。
但是我感觉最终要的是用于将物理上分散的内存页映射成 cif、isp可见的连续内存,如果没有iommu需要在kernel预留比较大的cma内存
在rk芯片,所有模块的iommu公用一个驱动

kernel\drivers\iommu\rockchip-iommu.c
kernel\drivers\iommu\rk-iommu.h
定义iommu的结构:

struct rk_iommu_domain {
   
   
	struct list_head iommus;
	struct platform_device *pdev;
	u32 *dt; /* page directory table */
	dma_addr_t dt_dma;
	struct mutex iommus_lock; /* lock for iommus list */
	struct mutex dt_lock; /* lock for modifying page directory table */

	struct iommu_domain domain;
};

struct rk_iommu {
   
   
	struct device *dev;
	void __iomem **bases;
	int num_mmu;
	int *irq;
	int num_irq;
	bool reset_disabled; /* isp iommu reset operation would failed */
	bool skip_read;	     /* rk3126/rk3128 can't read vop iommu registers */
	struct list_head node; /* entry in rk_iommu_domain.iommus */
	struct iommu_domain *domain; /* domain to which iommu is attached */
	struct clk *aclk; /* aclock belong to master */
	struct clk *hclk; /* hclock belong to master */
	struct clk *sclk; /* sclock belong to master */
	struct list_head dev_node;
};

在模块加载的时候调用

static int __init rk_iommu_init(void)
{
   
   
	struct device_node *np;
	int ret;

	np = of_find_matching_node(NULL, rk_iommu_dt_ids);
	if (!np)
		return 0;

	of_node_put(np);
	//初始化iommu bus
	ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
	if (ret)
		return ret;

	ret = platform_driver_register(&rk_iommu_domain_driver);
	if (ret)
		return ret;
	//注册两个驱动
	ret = platform_driver_register(&rk_iommu_driver);
	if (ret)
		platform_driver_unregister(&rk_iommu_domain_driver);
	return ret;
}
<think> 我们正在解决“rkisp1-vir0出现CIF ISP PIC SIZE ERROR错误”的问题。根据引用[2]中的错误日志,我们看到了与ISP节点配置相关的错误。错误信息包括“Enum sensor frame interval failed”和“get isp or ispp info fail”,这表明在获取传感器能力或配置ISP时出现了问题。 结合RK平台ISP处理流程(引用[1]中提到的注册多路sensor输入和虚拟多通道isp-virx),我们可以推断该错误可能与以下原因有关: 1. **图像尺寸不匹配**:ISP处理的分辨率与sensor输出的分辨率不一致。 2. **设备树配置错误**:ISP节点或sensor节点的配置参数(如图像尺寸、数据格式)不正确。 3. **驱动兼容性问题**:sensor驱动与ISP驱动之间的交互出现问题。 ### 解决方法 #### 1. **检查图像分辨率配置** - **验证sensor输出分辨率**:确认sensor驱动中设置的输出分辨率与ISP期望的分辨率一致。在设备树中检查sensor节点的`rockchip,camera-module-*`参数: ```dts &i2c1 { camera-sensor@1a { rockchip,camera-module-width = <1920>; // 实际宽度 rockchip,camera-module-height = <1080>; // 实际高度 }; }; ``` - **调整ISP输入尺寸**:在ISP节点中确保`rockchip,isp-input-width`和`rockchip,isp-input-height`与sensor输出一致: ```dts rkisp1-vir0 { rockchip,isp-input-width = <1920>; rockchip,isp-input-height = <1080>; }; ``` #### 2. **检查数据格式匹配** - 确认sensor输出的数据格式(如`MEDIA_BUS_FMT_SBGGR10_1X10`)与ISP支持的格式一致。在sensor驱动中检查`mbus_code`: ```c static struct v4l2_subdev_video_ops sensor_video_ops = { .s_stream = sensor_s_stream, .g_mbus_config = sensor_g_mbus_config, }; ``` 在ISP驱动中验证支持的格式列表(通常位于`rkisp1.c`的`rkisp1_isp_fmts`数组)。 #### 3. **更新设备树中的ISP参数** 在设备树中为`rkisp1-vir0`节点添加明确的图像尺寸配置: ```dts &rkisp1 { status = "okay"; rkisp1-vir0 { status = "okay"; port@0 { reg = <0>; #address-cells = <1>; #size-cells = <0>; isp0_in: endpoint@0 { reg = <0>; remote-endpoint = <&csidphy_out>; // 确保与MIPI CSI节点连接 // 关键:设置ISP输入尺寸 rockchip,isp-input-width = <1920>; rockchip,isp-input-height = <1080>; }; }; }; }; ``` #### 4. **调试驱动日志** 在内核启动参数中添加`rkisp1`模块的调试日志: ```bash echo "file drivers/media/platform/rockchip/isp/* +p" > /sys/kernel/debug/dynamic_debug/control dmesg -w | grep rkisp # 实时查看ISP驱动日志 ``` 重点检查以下日志: - 分辨率设置流程:`set_fmt`、`s_stream`等调用。 - 错误信息:如`CIF_ISP_PIC_SIZE_ERROR`的具体寄存器值。 #### 5. **验证硬件链路** 检查物理连接: - 确认MIPI数据通道(Lane)数量与设备树中`sensor->csi2`节点的`data-lanes`匹配。 - 使用示波器测量MIPI时钟信号,确保波形稳定(无过冲/振铃)。 ### 错误触发机制分析 `CIF_ISP_PIC_SIZE_ERROR`通常由以下寄存器条件触发: $$ \text{(H_SIZE > 8192) || (V_SIZE > 8192) || (H_SIZE * V_SIZE > 16384 * 1024)} $$ 需确保配置的宽高满足: $$ 0 < \text{H_SIZE} \leq 8192 $$ $$ 0 < \text{V_SIZE} \leq 8192 $$ $$ \text{H_SIZE} \times \text{V_SIZE} \leq 16M \text{ pixels} $$ ### 修复案例 **案例1**:某IMX415传感器配置为3840x2160(4K),但ISP节点未更新尺寸: ```dts // 错误配置(默认1080P) rockchip,isp-input-width = <1920>; rockchip,isp-input-height = <1080>; ``` **修复**:修改为实际分辨率: ```dts rockchip,isp-input-width = <3840>; rockchip,isp-input-height = <2160>; ``` **案例2**:sensor驱动中`frame_size`枚举缺失所需分辨率(引用[2]的`Enum sensor frame interval failed`): ```c // 在驱动中添加支持的分辨率 static const struct imx415_framesize imx415_framesizes[] = { { 3840, 2160, 0x1f, }, // 确保此处索引与设备树匹配 }; ``` ### 总结步骤 | 步骤 | 操作 | 检查点 | |------|--------------------------|----------------------------------| | 1 | 核对sensor输出分辨率 | 设备树/驱动中的宽高值 | | 2 | 同步ISP输入分辨率 | `rockchip,isp-input-*`属性 | | 3 | 验证数据格式(mbus_code)| sensor与ISP驱动支持的格式列表 | | 4 | 检查MIPI链路配置 | 数据通道数量、时钟频率 | > ⚠️ **注意**:修改后需**重启设备**或重新加载ISP驱动: > ```bash > rmmod rkisp1 && modprobe rkisp1 > ``` §§相关问题§§ 1. 如何调试RKISP驱动的分辨率设置流程? 2. RK3568设备树中MIPI-CSI2节点的标准配置是什么? 3. 如何通过v4l2-ctl检查当前ISP接收的图像尺寸? 4. 哪些传感器参数会影响ISP的PIC SIZE错误? [^1]: RKISP平台设备注册流程 [^2]: RKCAMERA错误日志分析 </think> ### 解决RKISP1-VIR0出现"CIF ISP PIC SIZE ERROR"错误的方法 #### 一、错误原因分析 该错误通常由以下原因引起: 1. **图像尺寸不匹配**:ISP输入分辨率与sensor输出分辨率不一致[^2] 2. **寄存器配置错误**:ISP的`CIF_ISP_PIC_SIZE`寄存器设置超出硬件限制 3. **内存分配不足**:ISP处理的图像尺寸超过DMA缓冲区容量 4. **时钟/数据率不匹配**:MIPI传输速率与ISP处理能力不兼容[^1] #### 二、详细解决方法 ##### 1. 检查分辨率配置(设备树) 在sensor节点和ISP节点中确保分辨率一致: ```dts // sensor配置示例 (IMX415) &i2c3 { imx415: camera-sensor@1a { rockchip,camera-module-width = <3840>; // 必须与ISP设置一致 rockchip,camera-module-height = <2160>; }; }; // ISP节点配置 &rkisp { rkisp1-vir0 { rockchip,isp-input-width = <3840>; // 必须等于sensor宽度 rockchip,isp-input-height = <2160>; // 必须等于sensor高度 }; }; ``` > 📌 关键点:使用`dmesg | grep -i "isp"`确认实际生效的分辨率 ##### 2. 验证寄存器限制 ISP尺寸寄存器有严格限制: $$ \text{width} \times \text{height} \leq 8192 \times 8192 $$ $$ \text{width} \times \text{height} \leq \text{ISP\_MEM\_SIZE} $$ 通过寄存器检查当前配置: ```bash # 读取ISP尺寸寄存器 devmem 0xFFB50400 # CIF_ISP_PIC_SIZE寄存器地址 ``` 返回示例: ``` 0x0F000A00 # 表示3840(width=0x0F00) x 2560(height=0x0A00) ``` ##### 3. 调整内存分配 在设备树中增加ISP内存区域: ```dts &isp0_mmu { rockchip,iommu-address = <0x0 0xFF900000>; rockchip,iommu-size = <0x1000000>; // 增加到16MB内存 }; ``` 计算所需内存公式: $$ \text{Buffer Size} = \text{width} \times \text{height} \times \text{bpp} \times \text{extra} $$ 例如:3840x2160@10bit需要: $$ 3840 \times 2160 \times 1.25 \times 1.5 \approx 15.5\text{MB} $$ ##### 4. 检查MIPI配置 确保MIPI速率与ISP处理能力匹配: ```dts &csi2_dphy { rockchip,data-lanes = <4>; // 数据通道数 assigned-clocks = <&cru CLK_MIPI_CAMARAOUT_M1>; assigned-clock-rates = <500000000>; // MIPI时钟频率 }; ``` 验证公式: $$ \text{ISP处理能力} \geq \frac{\text{link\_freq} \times \text{data-lanes}}{2} $$ ##### 5. 调试驱动代码 在内核驱动中检查尺寸设置流程: ```c // drivers/media/platform/rockchip/isp/rkisp1.c static int rkisp1_config_size(struct rkisp1_device *dev) { // 确保以下参数在范围内 width = min_t(u32, width, MAX_ISP_INPUT_WIDTH); // MAX_ISP_INPUT_WIDTH=8192 height = min_t(u32, height, MAX_ISP_INPUT_HEIGHT); // 设置CIF_ISP_PIC_SIZE寄存器 rkisp1_write(dev, RKISP1_CIF_ISP_PIC_SIZE, (width << 16) | height, true); } ``` #### 三、验证步骤 1. 修改设备树后编译并烧写固件 2. 启动后检查内核日志: ```bash dmesg | grep -iE "isp|size|error" ``` 3. 通过media-ctl验证链路配置: ```bash media-ctl -p -d /dev/media0 ``` 4. 使用v4l2-ctl检查格式: ```bash v4l2-ctl -d /dev/video0 --get-fmt-video ``` #### 四、典型解决方案案例 **问题现象**: ``` [ 123.456] rkisp1-vir0: CIF_ISP_PIC_SIZE_ERROR (0x00000100) ``` **解决过程**: 1. 检查发现sensor输出为4000x3000 2. 计算内存需求:4000×3000×1.25×1.5 = 22.5MB > 默认16MB 3. 修改设备树: ```dts &isp0_mmu { rockchip,iommu-size = <0x2000000>; // 增加到32MB }; ``` 4. 同时调整ISP输入尺寸: ```dts rockchip,isp-input-width = <4000>; rockchip,isp-input-height = <3000>; ``` > ⚠️ **注意事项** > 1. RK3568最大支持8192x8192分辨率 > 2. 高分辨率需降低帧率:`v4l2-ctl --set-parm=15` > 3. 修改后需重启ISP模块:`rmmod rkisp1 && modprobe rkisp1`
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值