linux调试技巧(1) : 基于高通平台的寄存器配置读取

本文介绍了在Linux系统下,针对高通平台如何使用工具`/system/bin/r`来读取GPIO寄存器配置,以GPIO37为例,详细解析了寄存器地址计算、读取值的解析过程,包括内部上下拉、功能配置、驱动能力和输出状态的判断。

Linux 调试技巧(1)

平台调试中难免需要查看底层寄存器配置,对于高通某些平台,系统提供了工具读取这些值:
举例说明(高通平台中):
可以使用**/system/bin/r** 这个工具
接下来我以一个gpio为例,去如何读取这个gpio的配置:
我们以gpio37为例:
首先查看gpio37配置的物理地址,在芯片手册中找到:
在这里插入图片描述
其中n可以是0-112,代表msm8909的全部gpio口的配置地址,我们要读gpio37的,那么n=37,需要注意的一点是37需要转换为16进制,十进制37,十六进制就是25,
所以gpio37的配置寄存器地址就是:
0x01000000+0x1000*25 = 0x01025000
通过工具可以读取值:
/system/bin/r 0x01025000
读取值为000002c0
转换成2进制为1011000000
接下来查看每一位代表的含义:
在这里插入图片描述在这里插入图片描述
其中 第0-1位代表的是gpio的内部上下拉,通过看结果可知0-1位都是0,代表了内部没有上下拉(No_PULL)
第2-5位代表这个gpio配置的功能,2-5位都是0,然后查看
在这里插入图片描述

<think>我们正在解决Linux内核中SDIO命令超时错误的调试问题。根据之前的讨论,CMD52错误可能由多种原因引起,包括硬件问题、驱动配置、时钟问题等。现在用户明确要求调试SDIO命令超时错误,我们将结合内核调试方法进行详细说明。 参考之前的回答,我们已经提到过一些调试步骤,如检查硬件连接、软件配置、查看系统日志等。现在我们将更深入地介绍在内核中调试SDIO超时的具体方法。 步骤: 1. 启用内核的SDIO调试功能 2. 分析日志和跟踪 3. 使用动态调试和ftrace 4. 检查驱动代码和硬件寄存器 注意:以下步骤假设你正在使用基于QCM6490的平台,但大部分方法适用于任何Linux内核环境。 --- ### 1. **启用内核的SDIO调试功能** Linux内核提供了MMC子系统的调试选项,可以通过编译时配置和运行时调试级别控制。 - **编译时配置**:确保内核配置了以下选项(通常在`make menuconfig`中设置): ``` CONFIG_MMC_DEBUG=y CONFIG_DEBUG_FS=y ``` - **运行时调整调试级别**:在系统启动后,通过sysfs调整调试级别,可以输出更详细的日志。 ```bash # 设置MMC核心调试级别(0-8,8为最详细) echo 8 > /sys/module/mmc_core/parameters/debug_level # 设置SDHCI驱动调试级别(针对具体控制器驱动,如sdhci-msm) echo 8 > /sys/module/sdhci/parameters/debug_level ``` 调整后,运行`dmesg -w`实时查看日志,执行触发CMD52超时的操作,观察输出。日志中会详细记录每个SDIO命令的发送和响应情况,包括命令参数、响应值和错误码。 例如,一个典型的超时错误日志可能如下: ``` mmc0: CMD52: arg 0x80000, resp=0x000, status=0x80000 (TIMEOUT) ``` 这表示命令在预期时间内没有收到响应。 --- ### 2. **分析日志和跟踪** 如果标准日志不足以定位问题,可以使用更高级的跟踪工具: - **使用ftrace跟踪SDIO命令**: ```bash # 挂载debugfs(如果尚未挂载) mount -t debugfs none /sys/kernel/debug # 启用MMC子系统的跟踪事件 echo 1 > /sys/kernel/debug/tracing/events/mmc/enable # 开始跟踪 echo 1 > /sys/kernel/debug/tracing/tracing_on # 执行触发错误的操作... # 停止跟踪并查看结果 echo 0 > /sys/kernel/debug/tracing/tracing_on cat /sys/kernel/debug/tracing/trace > /tmp/sdio-trace.log ``` 跟踪日志会显示每个SDIO命令的详细调用栈和参数,有助于分析命令执行流程。 --- ### 3. **检查硬件寄存器** 如果怀疑是控制器硬件问题,可以读取SDIO控制器的寄存器状态: - 在QCM6490上,SDIO控制器通常由`sdhci_msm`驱动管理。通过`debugfs`可以查看寄存器: ```bash # 进入SDHCI控制器的debug目录(假设为mmc0) cd /sys/kernel/debug/mmc0/ # 查看寄存器值 cat regs ``` 重点关注以下寄存器(以SDHCI规范为例): - **SDHCI_INT_STATUS**: 中断状态寄存器(超时错误对应`SDHCI_INT_TIMEOUT`位) - **SDHCI_PRESENT_STATE**: 当前状态寄存器,检查命令是否正在执行(`CMD_INHIBIT`位) - **SDHCI_CLOCK_CONTROL**: 时钟控制寄存器,确认时钟是否开启 寄存器值需要参考高通SDHCI控制器的具体文档(如80-NL547-*手册)[^4]。 --- ### 4. **代码级调试** 如果问题在驱动层,需要检查相关驱动代码: - **驱动代码检查点**: - 在`drivers/mmc/host/sdhci-msm.c`中,确认`sdhci_msm_probe`正确初始化了控制器,包括时钟、电压和中断。 - 检查命令超时处理函数(通常为`sdhci_timeout_timer`),看是否有特殊处理逻辑。 - 确认DMA配置是否正确(超时可能与DMA传输有关)。 例如,在QCM6490平台上,可能需要检查特定于平台的初始化代码: ```c static const struct sdhci_msm_offset sdhci_msm_qcm6490_offset = { .core_mmc_dly = 0x10c, // ... 其他寄存器偏移 }; ``` 如果发现代码问题,可能需要打补丁或联系高通支持。 --- ### 5. **常见问题及解决方案** | 问题原因 | 解决方案 | |----------|----------| | 时钟频率过高 | 在设备树中降低`max-frequency`,或添加`mmc-hs200-1_8v`属性[^3] | | 中断未正确处理 | 检查驱动中的中断处理函数(如`sdhci_msm_irq`)是否注册并处理超时中断 | | 电源管理冲突 | 禁用运行时PM测试:`echo on > /sys/bus/mmc/devices/mmc0:0001/power/control` | | 硬件缺陷 | 检查芯片勘误表,可能需要软件规避(如增加延迟) | --- ### 相关问题 1. 如何在Linux内核中启用MMC/SDIO的详细调试日志? 2. 如何通过设备树配置SDIO控制器的时钟和电压? 3. QCM6490平台上的SDIO控制器有哪些已知问题?</think>### Linux内核中调试SDIO命令超时错误的完整指南 在Linux内核中调试SDIO命令超时错误(如CMD52超时)需要系统性的方法。以下是详细的调试流程,结合内核调试工具和代码分析技巧: --- ### 1. **启用内核调试功能** #### (1) 编译时配置 在内核配置中启用关键调试选项: ```bash # 启用MMC/SDIO子系统调试 CONFIG_MMC_DEBUG=y CONFIG_MMC_TRACE=y # 启用动态调试和ftrace CONFIG_DYNAMIC_DEBUG=y CONFIG_FTRACE=y CONFIG_FUNCTION_TRACER=y ``` #### (2) 运行时启用调试输出 ```bash # 设置MMC调试级别(0-3,3为最详细) echo 8 > /sys/module/mmc_core/parameters/debug_level # 启用SDHCI驱动调试 echo -n 'file sdhci.c +p' > /sys/kernel/debug/dynamic_debug/control ``` --- ### 2. **分析内核日志** #### (1) 关键日志标识 在`dmesg`中搜索以下模式: ```bash dmesg | grep -E "CMD[0-9]+|timeout|sdhci|mmc" ``` 典型错误日志示例: ``` mmc0: CMD52: arg 0x80000, resp=0x000, status=0x80000 (TIMEOUT) sdhci: Timeout waiting for hardware interrupt ``` #### (2) 寄存器状态分析 通过debugfs查看控制器状态: ```bash cat /sys/kernel/debug/mmc0/regs ``` 重点关注: - `SDHCI_INT_STATUS`:中断状态寄存器 - `SDHCI_PRESENT_STATE`:当前状态寄存器 - `SDHCI_CLOCK_CONTROL`:时钟控制寄存器 --- ### 3. **使用ftrace跟踪调用栈** ```bash # 配置ftrace echo function > /sys/kernel/debug/tracing/current_tracer echo sdhci_send_command > /sys/kernel/debug/tracing/set_ftrace_filter echo 1 > /sys/kernel/debug/tracing/tracing_on # 触发SDIO操作 mmc_test test /dev/mmcblk0 # 查看跟踪结果 cat /sys/kernel/debug/tracing/trace > sdio_trace.log ``` 分析函数调用时序,特别是`sdhci_send_command()`和`sdhci_timeout_timer()`的执行路径[^2]。 --- ### 4. **代码级调试重点区域** 在驱动源码中检查以下关键点: #### (1) 命令超时处理 `drivers/mmc/host/sdhci.c`: ```c static void sdhci_timeout_timer(struct timer_list *t) { struct sdhci_host *host = from_timer(host, t, timer); pr_err("Timeout waiting for CMD%d completion!\n", host->cmd->opcode); // 添加调试打印 sdhci_dumpregs(host); // 关键:寄存器状态转储 } ``` #### (2) 中断处理逻辑 检查中断是否被正确处理: ```c static irqreturn_t sdhci_irq(int irq, void *dev_id) { if (intmask & SDHCI_INT_TIMEOUT) { pr_warn("SDIO timeout interrupt detected\n"); // 检查中断处理是否完整 } } ``` #### (3) 时钟和延时配置 在QCM6490平台代码中(`drivers/mmc/host/sdhci-msm.c`): ```c static int sdhci_msm_probe(struct platform_device *pdev) { // 检查时钟配置 host->clock = clk_get_rate(host->clk); if (host->clock > 50000000) { // 超过50MHz可能导致不稳定 pr_warn("Clock rate %d may cause timeouts\n", host->clock); } // 检查延时校准 if (of_property_read_u32(pdev->dev.of_node, "qcom,pad-drive-on", &drive_on)) { pr_err("Missing pad drive calibration\n"); // 可能导致时序问题 } } ``` --- ### 5. 硬件级调试技巧 #### (1) 信号完整性检查 - 使用示波器测量SDIO总线的CLK、CMD、DAT0-3信号 - 检查信号质量参数: - 上升/下降时间应 < 5ns - 过冲 < 10% Vdd - 抖动 < 0.2 UI #### (2) 电源稳定性验证 ```bash # 监控SDIO电源 echo 1 > /sys/kernel/debug/regulator/regulator_summary ``` 确保电压波动 < ±5% (3.3V系统要求3.135-3.465V) --- ### 6. 常见问题解决方案 | 问题根源 | 解决方案 | |---------|----------| | 时钟频率过高 | 在设备树中设置`max-frequency = <40000000>;` | | 中断丢失 | 检查`/proc/interrupts`确认中断计数增加 | | 电压不稳 | 添加电源滤波电容(典型值100nF+10μF) | | 驱动bug | 应用补丁:`git cherry-pick a1b2c3d` | > **注**:在QCM6490平台上,SDIO控制器的初始化顺序问题可能导致超时,需检查`drivers/mmc/host/sdhci-msm.c`中的`probe()`函数是否完整执行资源初始化[^2]。 --- ### 相关问题 1. 如何通过设备树配置QCM6490的SDIO控制器参数? 2. Linux内核中SDIO命令重试机制是如何实现的? 3. 如何测量SDIO总线的信号完整性? 4. 在嵌入式系统中,SDIO驱动开发的最佳实践是什么?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值