Linux驱动开发常用调试工具-------之devmem

 在Linux开发中着实用到的调试工具并不是很多。devmem的方式是提供给驱动开发人员,在应用层能够侦测内存地址中的数据变化,以此来检测驱动中对内存或者相关配置的正确性验证。

        devmem2使用方法:

        devmem2 { address } [ type [ data ] ]

                address : 物理地址

                type :要访问的数据类型 : [b]yte, [h]alfword, [w]ord

                data :想要写入的数据,若为读取操作则省略此参数,若为写入,则必须含有此参数。

        如下就贴出devmem2的源代码一探究竟。

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <string.h>  
  5. #include <errno.h>  
  6. #include <signal.h>  
  7. #include <fcntl.h>  
  8. #include <ctype.h>  
  9. #include <termios.h>  
  10. #include <sys/types.h>  
  11. #include <sys/mman.h>  
  12.     
  13. #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \  
  14.   __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)  
  15.    
  16. #define MAP_SIZE 4096UL  
  17. #define MAP_MASK (MAP_SIZE - 1)  
  18.   
  19. int main(int argc, char **argv) {  
  20.     int fd;  
  21.     void *map_base, *virt_addr;   
  22.     unsigned long read_result, writeval;  
  23.     off_t target;  
  24.     int access_type = 'w';  
  25.       
  26.     if(argc < 2) {//若参数个数少于两个则打印此工具的使用方法  
  27.         fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"  
  28.             "\taddress : memory address to act upon\n"  
  29.             "\ttype    : access operation type : [b]yte, [h]alfword, [w]ord\n"  
  30.             "\tdata    : data to be written\n\n",  
  31.             argv[0]);  
  32.         exit(1);  
  33.     }  
  34.     target = strtoul(argv[1], 0, 0);  
  35.   
  36.     if(argc > 2)  
  37.         access_type = tolower(argv[2][0]);  
  38.   
  39.   
  40.     if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;  
  41.     printf("/dev/mem opened.\n");   
  42.     fflush(stdout);  
  43.       
  44.     /* Map one page */ //将内核空间映射到用户空间  
  45.     map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);  
  46.     if(map_base == (void *) -1) FATAL;  
  47.     printf("Memory mapped at address %p.\n", map_base);   
  48.     fflush(stdout);  
  49.       
  50.     virt_addr = map_base + (target & MAP_MASK);  
  51.     //针对不同的参数获取不同类型内存数据  
  52.     switch(access_type) {  
  53.         case 'b':  
  54.             read_result = *((unsigned char *) virt_addr);  
  55.             break;  
  56.         case 'h':  
  57.             read_result = *((unsigned short *) virt_addr);  
  58.             break;  
  59.         case 'w':  
  60.             read_result = *((unsigned long *) virt_addr);  
  61.             break;  
  62.         default:  
  63.             fprintf(stderr, "Illegal data type '%c'.\n", access_type);  
  64.             exit(2);  
  65.     }  
  66.     printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);   
  67.     fflush(stdout);  
  68.         //若参数大于3个,则说明为写入操作,针对不同参数写入不同类型的数据  
  69.     if(argc > 3) {  
  70.         writeval = strtoul(argv[3], 0, 0);  
  71.         switch(access_type) {  
  72.             case 'b':  
  73.                 *((unsigned char *) virt_addr) = writeval;  
  74.                 read_result = *((unsigned char *) virt_addr);  
  75.                 break;  
  76.             case 'h':  
  77.                 *((unsigned short *) virt_addr) = writeval;  
  78.                 read_result = *((unsigned short *) virt_addr);  
  79.                 break;  
  80.             case 'w':  
  81.                 *((unsigned long *) virt_addr) = writeval;  
  82.                 read_result = *((unsigned long *) virt_addr);  
  83.                 break;  
  84.         }  
  85.         printf("Written 0x%X; readback 0x%X\n", writeval, read_result);   
  86.         fflush(stdout);  
  87.     }  
  88.       
  89.     if(munmap(map_base, MAP_SIZE) == -1) FATAL;  
  90.     close(fd);  
  91.     return 0;  
  92. }  
<think>好的,用户现在想了解关于platform_device的MIPI CSI-2驱动开发或实现的信息。我需要结合之前提供的资料和用户的引用内容来整理答案。首先,用户提到的引用[1]到[4]主要涉及OpenHarmony平台的驱动开发,特别是Hi35xx系列的MIPI CSI实现。用户之前的问题是关于MIPI D-PHY寄存器的访问方法,现在转向了platform_device和MIPI CSI-2驱动开发。 首先,我需要明确platform_device在Linux驱动模型中的角色。platform_device通常用于表示平台设备,这些设备是直接集成在SoC中的,比如MIPI CSI-2控制器。驱动开发需要注册platform_driver,并与platform_device匹配。 接下来,用户的需求是了解如何开发和实现这样的驱动。需要从设备树配置、驱动注册、资源获取、CSI-2控制器初始化和数据传输等方面展开。引用中的代码示例,比如Hi35xxMipiCsiRelease函数,显示了如何从HdfDeviceObject获取MipiCsiCntlr结构,这可能对应于platform_device到驱动的绑定过程。 用户提供的引用[2]提到基于Hi3516DV300开发板的示例,说明需要参考厂商提供的驱动实现,如mipi_csi_hi35xx.c。这可能涉及到平台特定的初始化和资源管理。同时,引用[3]指出依赖的内核模块,如videodev.ko和v4l2-fwnode.ko,说明驱动需要与V4L2框架集成,处理视频流数据。 需要分步骤解释驱动开发的关键点,比如设备树节点的编写,probe函数的实现,时钟和GPIO的配置,以及与V4L2框架的对接。此外,引用[1]中的强制类型转换和资源释放操作,提示在开发中需要注意设备结构体的管理和内存安全。 用户可能还需要了解如何调试驱动,比如使用dmesg查看内核日志,或者通过devmem2工具访问寄存器,这在之前的回答中已经涉及。此外,引用[4]提到Harmony南向开发的资料,可能涉及鸿蒙系统的特定实现,但用户的问题更偏向于通用的Linux平台驱动开发,需要区分清楚。 需要确保回答的结构清晰,涵盖设备树配置、驱动注册、资源管理、初始化和数据传输等关键步骤,并提供代码示例和调试方法。同时,结合用户提供的引用内容,强调厂商特定的实现细节和注意事项,比如HiSilicon的示例代码和资源释放流程。 最后,生成的相关问题需要围绕驱动开发的关键点,如设备树配置、V4L2集成、时钟管理、调试方法等,确保覆盖用户可能关心的其他方面。</think>### MIPI CSI-2 Platform Device驱动开发详解 #### 一、驱动框架设计原理 MIPI CSI-2驱动基于Linux V4L2框架实现(引用[3]依赖`videodev.ko`),其核心是通过`platform_device`描述硬件资源,`platform_driver`实现控制逻辑。关键组件关系如下: $$ \begin{aligned} &\text{platform\_device} \xrightarrow{\text{设备树匹配}} \text{platform\_driver}\\ &\downarrow \text{包含资源}\\ &\text{V4L2\_subdev} \leftarrow \text{CSI-2控制器} \leftarrow \text{MIPI D-PHY} \end{aligned} $$ --- #### 二、关键开发步骤(以HiSilicon平台为例) 1. **设备树配置** ```dts // 硬件资源配置示例(Hi3516DV300) mipi_csi: mipi_csi@0x10000000 { compatible = "hisilicon,hi3516dv300-mipi-csi2"; reg = <0x10000000 0x1000>; interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk_mipi 0>, <&clk_sys 3>; clock-names = "mipi_phy", "sys_mipi"; resets = <&softreset 5>; hisilicon,csi-lanes = <4>; // 4通道配置 status = "okay"; }; ``` *调试要点*:通过`dtc -I fs /sys/firmware/devicetree/base`验证设备树解析 2. **驱动注册与匹配** ```c static const struct of_device_id hi35xx_csi_match[] = { { .compatible = "hisilicon,hi3516dv300-mipi-csi2" }, {} }; static struct platform_driver hi35xx_mipi_csi_driver = { .probe = hi35xx_csi_probe, .remove = hi35xx_csi_remove, .driver = { .name = "hi35xx-mipi-csi", .of_match_table = hi35xx_csi_match, } }; module_platform_driver(hi35xx_mipi_csi_driver); ``` 3. **资源获取与初始化** ```c static int hi35xx_csi_probe(struct platform_device *pdev) { struct csi_private *priv; struct resource *res; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); // 初始化PHY(引用[1]中的Hi35xxMipiCsiRelease) priv->phy = devm_phy_get(&pdev->dev, "mipi_phy"); phy_init(priv->phy); // 注册V4L2 subdev(引用[3]的videodev依赖) v4l2_subdev_init(&priv->subdev, &csi_subdev_ops); priv->subdev.owner = THIS_MODULE; strscpy(priv->subdev.name, dev_name(&pdev->dev), sizeof(priv->subdev.name)); v4l2_device_register_subdev(&priv->v4l2_dev, &priv->subdev); } ``` --- #### 三、数据传输实现要点 1. **DMA缓冲区配置** ```c struct dma_buf_attachment *attach; struct sg_table *sgt; attach = dma_buf_attach(dmabuf, &pdev->dev); sgt = dma_buf_map_attachment(attach, DMA_FROM_DEVICE); // 配置CSI控制器DMA地址 writel(sg_dma_address(sgt->sgl), priv->base + CSI_DMA_ADDR_REG); ``` 2. **帧同步控制** ```c // 使能VSYNC中断(引用[2]状态机实现) writel(CSI_INT_EN_VSYNC, priv->base + CSI_INT_EN_REG); // 中断处理函数 static irqreturn_t csi_isr(int irq, void *dev_id) { u32 status = readl(priv->base + CSI_INT_STATUS_REG); if (status & CSI_INT_VSYNC) { complete(&priv->frame_done); return IRQ_HANDLED; } return IRQ_NONE; } ``` --- #### 四、调试方法与工具 | 调试手段 | 实施方法 | |---------------------------|--------------------------------------------------------------------------| | 寄存器监控 | `devmem2 0x10000004` 读取CSI控制寄存器状态 | | 信号完整性测量 | 使用示波器测量CLK+/CLK-差分信号的眼图(参考D-PHY规范[^1]) | | 数据流验证 | 通过`v4l2-ctl --stream-mmap --stream-count=100`捕获原始帧数据 | | 内核日志分析 | `dmesg | grep csi` 查看驱动加载和中断事件(引用[1]调试流程) | --- ### 相关问题 1. **如何解决MIPI CSI-2驱动中的DMA内存对齐问题?** (需确保缓冲区物理地址64字节对齐,使用`dma_alloc_coherent`分配内存[^2]) 2. **在V4L2框架下如何实现多摄像头切换?** (通过`mediactl`工具配置media pipeline链路,参考引用[3]的mc.ko模块) 3. **如何验证MIPI CSI-2的LP/H状态转换时序?** (使用逻辑分析仪抓取LP11→HS-0→HS-1序列,检查T_LPX/T_HS_PREPARE等参数[^1]) [^1]: MIPI Alliance CSI-2 Specification v3.0 Chapter 6 "Physical Layer Requirements" [^2]: Linux Device Drivers, 3rd Edition Chapter 15 "Memory Mapping and DMA" [^3]: HiSilicon Hi3516DV300 Hardware Design Guide Appendix C "MIPI Interface Timing"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值