ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RK3576 SD卡GPIO检测实战:设备树配置与避坑指南

RK3576 SD卡GPIO检测实战:设备树配置与避坑指南 1. 项目缘起为什么一块SD卡让我在RK3576上折腾了三天RK3576这颗芯片最近在嵌入式圈子里热度不低四核A72加四核A53的八核架构自带6TOPS算力的NPU视频编解码能力也够看做边缘计算盒子、工业HMI、智能NVR这类产品都挺合适。我手上这个项目是一个带屏的工业数据采集终端主控选的就是RK3576系统跑的是Linux存储方案上考虑到现场维护的便利性设计成了eMMC做主系统盘、SD卡做数据导出和固件升级的辅助通道。问题就出在这个SD卡上。板子打样回来第一次上电eMMC里的系统正常启动但插上SD卡之后系统毫无反应/dev/mmcblk*下面根本看不到新设备。我当时第一反应是硬件虚焊拿万用表量了SD卡座的各个引脚供电、地、时钟、命令线都通卡座也没问题。换了几张不同品牌不同容量的卡现象完全一致。这就不是卡的问题了得往驱动和硬件检测逻辑上找。这个坑的核心其实就两个关键词CD检测和GPIO。SD卡座上的Card Detect引脚也就是CD脚负责告诉主控“卡插进去了”。很多参考设计里这个脚是直接接到主控的SDMMC控制器的CD专用引脚上由控制器硬件自动处理插拔检测。但RK3576的SDMMC控制器引脚复用比较紧张我这块板子为了给其他外设让路把CD脚接到了普通GPIO上需要软件层面自己去轮询或者用中断的方式检测电平变化再手动触发扫描。参考设计的设备树里没有配这个GPIO检测逻辑驱动自然就不知道卡插进来了。这篇文章我会把整个排查过程、设备树配置、GPIO检测的两种实现方式轮询和中断、以及中间踩过的几个隐蔽的坑完整地拆开讲一遍。如果你也在用RK3576或者类似的瑞芯微平台做SD卡相关的开发尤其是CD脚没走专用通道的情况这篇内容应该能帮你省下不少时间。即使你用的是STM32或者其他平台GPIO检测SD卡插拔的思路也是通用的底层逻辑一样。2. 先搞清楚RK3576的SD卡检测机制到底怎么工作的2.1 SD卡插拔检测的三种常见方案在动手改代码之前得先把SD卡检测这件事的几种实现方式理清楚。不同方案对应的硬件设计和软件配置完全不同搞错了方向就是白费功夫。方案一专用CD引脚硬件检测。这是最省事的方式。SD卡座上的CD引脚直接连到SoC的SDMMC控制器对应的CD专用引脚上。控制器内部有去抖电路检测到电平变化后自动产生中断内核的MMC子系统收到中断后自动完成卡的枚举和初始化。软件层面几乎不需要做额外配置设备树里把CD引脚配好就行。缺点是占用一个专用引脚对于引脚资源紧张的项目不太友好。方案二普通GPIO检测。CD脚接到任意一个普通GPIO上软件通过轮询或者GPIO中断的方式检测电平变化然后在中断处理或者轮询回调里调用MMC子系统的接口去重新扫描卡。这种方式灵活引脚随便选但需要自己写检测逻辑而且去抖、中断触发方式这些细节都得自己处理。我这次踩坑就是踩在这个方案上。方案三无CD检测纯软件轮询。有些低成本方案干脆不接CD脚靠定时器周期性调用mmc_rescan去扫描。这种方式最省硬件成本但实时性差而且频繁扫描对系统有额外开销。工业场景下不太推荐消费类产品里偶尔能见到。三种方案的对比可以看下面这个表对比项专用CD引脚普通GPIO检测纯软件轮询硬件成本占用专用引脚占用普通GPIO不占引脚实时性高硬件中断中高GPIO中断低取决于轮询周期软件复杂度低中低去抖处理控制器硬件完成需软件处理无需处理适用场景引脚资源充足引脚紧张但需实时性低成本、实时性要求低我这块板子用的是方案二CD脚接在了GPIO3_D2上。选这个脚没什么特殊原因就是PCB布线的时候这个脚离SD卡座最近走线最短信号完整性好一些。2.2 RK3576的SDMMC控制器和GPIO子系统概况RK3576有三个SDMMC控制器SDMMC0一般接eMMCSDMMC1和SDMMC2可以接SD卡或者SDIO设备。我这里的SD卡接在SDMMC1上。每个控制器都有对应的CD引脚复用选项但正如前面说的我这块板子没用专用CD引脚。RK3576的GPIO分为5组GPIO0到GPIO4每组32个引脚分为A、B、C、D四个bank每个bank 8个引脚。命名规则是GPIOx_Yz比如GPIO3_D2就是第3组的D bank的第2个引脚。在Linux内核里这个引脚对应的全局编号需要换算一下计算公式是全局编号 组号 × 32 bank偏移 引脚号。GPIO3_D2的bank偏移是D bank也就是3×824所以全局编号是3×32242122。这个换算在配置设备树和调试的时候经常用到记不住的话可以在板子上通过cat /sys/kernel/debug/gpio来查看实际编号。内核的MMC子系统对SD卡检测有一套标准框架。当使用GPIO检测时设备树里需要配置cd-gpios属性MMC子系统会自动注册一个GPIO中断或者轮询定时器来处理检测。但这里有个关键点MMC子系统对CD GPIO的默认假设是低电平有效也就是卡插入时CD脚被拉低。如果你的硬件设计是卡插入时CD脚为高电平就需要在设备树里加cd-inverted属性来反转极性。这个细节后面会详细说因为我就是在这里栽了跟头。2.3 设备树中SD卡节点的关键属性解析RK3576的设备树里SDMMC1节点大概长这样这是参考设计的原始配置sdmmc1 { status okay; bus-width 4; cap-sd-highspeed; cap-mmc-highspeed; disable-wp; vmmc-supply vcc_sd; vqmmc-supply vccio_sd; pinctrl-names default; pinctrl-0 sdmmc1_bus4 sdmmc1_cmd sdmmc1_clk; };这里面几个关键属性需要解释一下。bus-width 4表示使用4位数据总线SD卡支持1位和4位模式4位模式下读写速度更快。cap-sd-highspeed和cap-mmc-highspeed是能力声明告诉内核这个控制器支持高速模式。disable-wp是禁用写保护检测因为我的卡座没有写保护引脚。vmmc-supply和vqmmc-supply分别是卡座供电和IO电平供电这两个电源域必须配对否则卡可能上电了但IO电平不对导致通信失败。最关键的是这个配置里没有cd-gpios属性。没有这个属性MMC子系统就认为这个控制器没有卡检测功能不会去扫描卡。这就是为什么插卡没反应的根本原因。参考设计可能默认用的是专用CD引脚或者干脆没做检测但对于我的硬件来说必须手动加上GPIO检测的配置。3. 动手改设备树从零配置GPIO卡检测3.1 第一步确认GPIO引脚编号和电气特性改设备树之前先把硬件层面的信息确认清楚。我拿着原理图对照了三遍确认CD脚接在GPIO3_D2上卡座内部CD开关的一端接地另一端接GPIO3_D2并有一个10K的上拉电阻到3.3V。这意味着卡未插入时CD开关断开GPIO被上拉电阻拉高读到高电平卡插入时CD开关闭合GPIO被拉到地读到低电平。这是标准的低电平有效设计。这里有个容易搞错的地方有些卡座的CD开关是反过来的卡插入时断开、拔出时闭合。所以一定要对着卡座的规格书和原理图确认清楚不能凭经验想当然。我有个朋友就是没看规格书默认所有卡座都是插入拉低结果调了半天检测逻辑反了。确认了电气特性之后GPIO的全局编号也要算对。前面算过GPIO3_D2对应全局编号122但设备树里一般不直接写全局编号而是用gpio3 RK_PD2 GPIO_ACTIVE_LOW这种形式。RK_PD2是瑞芯微平台特有的宏定义表示D bank的第2个引脚。GPIO_ACTIVE_LOW表示低电平有效也就是卡插入时读到低电平算“激活”状态。3.2 第二步编写cd-gpios属性并处理极性在设备树里加上CD检测的配置改完之后的sdmmc1节点是这样的sdmmc1 { status okay; bus-width 4; cap-sd-highspeed; cap-mmc-highspeed; disable-wp; cd-gpios gpio3 RK_PD2 GPIO_ACTIVE_LOW; vmmc-supply vcc_sd; vqmmc-supply vccio_sd; pinctrl-names default; pinctrl-0 sdmmc1_bus4 sdmmc1_cmd sdmmc1_clk; };cd-gpios这一行就是核心。GPIO_ACTIVE_LOW告诉MMC子系统这个GPIO低电平表示卡插入。MMC子系统会根据这个配置自动注册一个GPIO中断如果GPIO控制器支持中断的话在中断处理函数里做去抖然后调用mmc_detect_change触发卡扫描。但这里有个坑MMC子系统对CD GPIO的去抖时间是固定的默认是200ms左右。如果你的卡座机械特性比较差插拔时抖动时间超过这个值可能会出现误检测。不过大多数标准卡座都没问题我这次也没遇到去抖相关的问题。还有一个更隐蔽的坑GPIO_ACTIVE_LOW和cd-inverted的区别。有些老版本的内核或者某些平台的MMC驱动对CD GPIO极性的处理方式不一样。GPIO_ACTIVE_LOW是在GPIO子系统层面做极性反转而cd-inverted是在MMC子系统层面做反转。如果两个都配了极性就反了两次等于没反。我一开始就是既配了GPIO_ACTIVE_LOW又加了cd-inverted结果插卡检测不到、拔卡反而检测到了查了半天才发现是极性搞反了。正确的做法是只用其中一个推荐用GPIO_ACTIVE_LOW因为这是GPIO子系统的标准做法兼容性更好。3.3 第三步编译、烧录和验证设备树改完之后编译内核和设备树烧录到板子上。验证步骤分几步走首先看内核启动日志里有没有SDMMC1控制器的初始化信息dmesg | grep -i mmc1\|sdmmc1正常的话应该能看到类似这样的输出[ 2.345678] dwmmc_rockchip fe2c0000.mmc: IDMAC supports 32-bit address mode. [ 2.356789] dwmmc_rockchip fe2c0000.mmc: Using internal DMA controller. [ 2.367890] dwmmc_rockchip fe2c0000.mmc: Version ID is 270a [ 2.378901] dwmmc_rockchip fe2c0000.mmc: DW MMC controller at irq 47,32 bit host data width,256 deep fifo [ 2.389012] dwmmc_rockchip fe2c0000.mmc: GPIO lookup for consumer cd [ 2.390123] dwmmc_rockchip fe2c0000.mmc: using lookup table for device gpio3 [ 2.391234] dwmmc_rockchip fe2c0000.mmc: mmc_gpiod_request_cd: requesting CD GPIO [ 2.392345] dwmmc_rockchip fe2c0000.mmc: Got CD GPIO看到“Got CD GPIO”就说明GPIO检测配置生效了。然后插卡再看dmesgdmesg | tail -20应该能看到卡被识别、分区被扫描的日志。同时/dev/下面会出现mmcblk1和mmcblk1p1这样的设备节点。如果插卡后dmesg没有任何新输出说明中断没触发或者检测逻辑有问题需要进一步排查。还可以通过sysfs手动查看CD GPIO的当前状态cat /sys/kernel/debug/gpio | grep -i cd\|gpio3这个命令会列出所有GPIO的状态找到GPIO3_D2对应的那一行看看它的方向、电平和是否被申请。如果显示“used”且方向是“in”说明GPIO已经被MMC驱动申请了配置没问题。4. 轮询还是中断两种GPIO检测方式的取舍与实现4.1 中断方式的原理和配置要点MMC子系统默认优先使用GPIO中断来检测卡插拔。当设备树里配置了cd-gpios并且GPIO控制器支持中断时内核会自动注册一个中断处理函数。卡插入或拔出时GPIO电平变化触发中断中断处理函数里做去抖然后通知MMC核心层去扫描卡。中断方式的优点是实时性高、CPU占用低。卡插进去几乎立刻就能识别不需要CPU一直去查询GPIO状态。但中断方式对硬件有要求GPIO必须支持中断功能。RK3576的大部分GPIO都支持中断但有些特殊功能引脚可能不支持配置前需要查一下芯片手册。中断方式还有一个坑中断触发类型的选择。对于CD检测理论上应该配置成双边沿触发IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING这样插卡和拔卡都能检测到。但有些GPIO控制器的双边沿中断支持不完善可能会出现丢中断的情况。如果遇到插卡能检测到、拔卡检测不到或者反过来可以尝试改成单边沿触发然后在中断处理里读取GPIO电平来判断是插入还是拔出。在设备树里中断方式的配置就是前面写的cd-gpios属性不需要额外配置中断类型MMC子系统会自动处理。但如果你想手动指定中断触发方式可以在GPIO节点里配置interrupts属性不过一般不建议这么做让MMC子系统自动处理就好。4.2 轮询方式的适用场景和实现方法如果GPIO不支持中断或者中断方式不稳定可以退回到轮询方式。轮询方式下内核会启动一个定时器周期性默认也是200ms左右读取CD GPIO的电平如果发现电平变化就触发卡扫描。轮询方式的配置很简单在设备树里加上broken-cd属性或者cd-gpios配合no-1-8-v之类的属性。但更常见的做法是直接用cd-gpios如果GPIO不支持中断MMC子系统会自动降级为轮询模式。也可以通过/sys/module/mmc_core/parameters/下面的参数来调整轮询周期不过这个参数是全局的会影响所有MMC控制器一般不建议改。轮询方式的缺点是CPU占用比中断方式高而且实时性取决于轮询周期。200ms的周期对于大多数场景够用了但如果你的应用要求卡插入后立刻响应轮询方式可能不够快。另外轮询方式下如果卡座接触不良导致电平抖动可能会产生多次误触发需要在应用层做额外的去抖处理。我实测下来RK3576的GPIO3_D2是支持中断的所以最终用的是中断方式。但为了验证轮询方式的可行性我也试过在设备树里把cd-gpios去掉、改用broken-cd属性然后手动在应用层用定时器去读GPIO并调用mmc_rescan。这种方式能用但代码量大、维护麻烦不推荐。4.3 两种方式的实测对比为了给后续项目选型提供参考我花了一个下午做了个简单的对比测试。测试方法是插卡和拔卡各20次记录从物理动作到系统识别到卡的时间差以及CPU占用情况。对比项中断方式轮询方式插卡识别平均延迟约120ms约200ms拔卡识别平均延迟约130ms约210ms识别成功率20次20/2020/20空闲时CPU占用接近0%约0.3%配置复杂度低中对GPIO中断的依赖需要不需要从数据看中断方式在延迟和CPU占用上都优于轮询方式配置也更简单。所以只要GPIO支持中断优先用中断方式。轮询方式作为备选方案在GPIO不支持中断或者中断不稳定时使用。5. 踩坑实录那些让我熬夜的隐蔽问题5.1 坑一GPIO被其他驱动占用导致申请失败设备树改完第一次编译烧录dmesg里没有出现“Got CD GPIO”反而报了一个错误dwmmc_rockchip fe2c0000.mmc: Failed to request CD GPIO: -16错误码-16是-EBUSY表示GPIO已经被其他驱动占用了。我查了一下/sys/kernel/debug/gpio发现GPIO3_D2确实被标记为“used”但不知道被谁用了。后来翻设备树发现这个引脚在另一个节点里被配置成了某个外设的功能引脚虽然那个外设没有使能status disabled但pinctrl配置还是占用了这个引脚。解决办法是在那个外设的pinctrl配置里把这个引脚去掉或者把那个外设的pinctrl-names改成不包含这个引脚的配置。我选择的是后者因为那个外设以后可能还会用到只是暂时不用这个引脚。改完之后重新编译烧录GPIO申请成功。这个坑的教训是设备树里的pinctrl配置是全局的即使设备没有使能pinctrl占用的引脚也可能影响其他驱动。所以在配置GPIO复用时一定要全局搜索这个引脚的所有引用确保没有冲突。5.2 坑二电平抖动导致反复插拔误检测解决了GPIO占用问题之后插卡能识别了但出现了一个新问题卡插着不动的时候dmesg里偶尔会冒出“card removed”然后紧接着“card inserted”的日志也就是系统认为卡被拔了又插了。这就是典型的电平抖动问题。SD卡座的CD开关是机械触点插拔过程中会有几十毫秒的抖动。虽然MMC子系统有去抖处理但去抖时间可能不够长或者抖动持续时间超过了去抖窗口。我拿示波器抓了一下CD脚的电平波形发现插卡瞬间有大约50ms的抖动而MMC子系统的去抖时间默认是20ms左右不够用。解决办法有两个硬件上加RC滤波电路软件上增加去抖时间。硬件改板来不及了我选择在软件层面处理。MMC子系统的去抖时间可以通过设备树里的debounce-interval属性来配置单位是毫秒。我在sdmmc1节点里加了一行debounce-interval 100;把去抖时间设成100ms比实测的抖动时间长一倍留足余量。改完之后重新测试反复插拔50次没有再出现误检测。这里要注意debounce-interval属性不是所有MMC驱动都支持需要确认你用的驱动版本有没有实现这个属性的解析。RK3576的内核版本是5.10和6.1这两个版本都支持。5.3 坑三卡插入后系统识别到了但挂载失败卡检测问题解决之后又遇到一个更奇怪的现象dmesg里能看到卡被识别、分区被扫描但/dev/mmcblk1p1就是挂载不上报错“wrong fs type”或者“cant read superblock”。换了几张卡都一样但同样的卡插到电脑上能正常读写。这个问题排查了很久最后发现是SD卡供电不足导致的。我的板子SD卡座的供电是从一个LDO出来的LDO的输入是3.3V输出也是3.3V但LDO的电流能力只有150mA。SD卡在初始化阶段和高速读写时瞬时电流可能超过200mA导致电压跌落卡工作不稳定。用万用表量了一下卡座供电脚在卡初始化时的电压果然跌到了2.8V左右。解决办法是把LDO换成电流能力更大的型号或者直接从主电源3.3V轨供电如果主电源纹波够小的话。我换了一个500mA的LDO问题解决。这个坑的隐蔽之处在于卡能被识别说明CMD线和数据线的通信是正常的但供电不足可能导致卡在后续的高速读写阶段出错。所以看到卡识别了但挂载失败除了查文件系统也要查一下供电。5.4 坑四热插拔时文件系统损坏工业现场经常需要热插拔SD卡导出数据但热插拔如果处理不当很容易导致文件系统损坏。我测试的时候就遇到过卡正在写入数据时直接拔出来再插回去就挂载不上了提示文件系统错误。这个问题的根源是写入缓存没有及时刷到卡上。Linux对块设备的写入是先写到页缓存再由内核的flush线程异步刷到设备。如果卡被拔出时还有脏页没刷完文件系统就会不一致。解决办法有几个层面。应用层面在拔卡之前先执行sync命令确保所有数据都刷到卡上。系统层面可以配置/etc/fstab里的挂载选项加上sync或者dirsync让写入同步进行但这样会严重影响性能。更好的做法是用udev规则监听卡的拔出事件在拔出前自动执行sync和umount。我最终采用的是应用层方案在UI上做一个“安全弹出”按钮用户点击后先sync再umount然后提示可以拔卡了。同时在内核层面把SD卡的写缓存策略调保守一些减少数据丢失的风险。6. 常见问题速查与排查思路6.1 插卡无反应排查流程插卡后系统没有任何反应/dev/下没有新设备dmesg也没有新日志。这种情况按以下顺序排查确认设备树里有没有配cd-gpios。没有配的话MMC子系统根本不会去检测卡。用dtc反编译设备树或者直接看源码确认。确认GPIO编号和极性对不对。用cat /sys/kernel/debug/gpio查看GPIO状态插卡和拔卡时电平有没有变化。如果电平不变说明硬件连接有问题或者GPIO配置错了。确认GPIO有没有被其他驱动占用。dmesg里搜“Failed to request CD GPIO”如果有这个错误说明GPIO被占了需要解决冲突。确认SDMMC控制器有没有使能。设备树里status是不是okaypinctrl配置对不对。确认供电是否正常。量一下卡座供电脚在插卡时的电压如果跌得厉害可能是供电能力不足。6.2 卡识别了但挂载失败排查流程dmesg里能看到卡被识别、分区被扫描但挂载时报错。按以下顺序排查确认文件系统类型。用fdisk -l /dev/mmcblk1查看分区表用blkid /dev/mmcblk1p1查看文件系统类型。如果文件系统类型是exfat或ntfs需要确认内核有没有编译对应的驱动。确认供电是否稳定。前面说过供电不足会导致卡在高速读写阶段出错。量一下卡座供电脚在读写时的电压。确认卡本身有没有问题。把卡插到电脑上格式化一下再插回板子试试。如果电脑上也读不出来说明卡坏了。确认有没有文件系统错误。用fsck检查一下文件系统如果有错误就修复。6.3 反复插拔误检测排查流程卡插着不动但系统反复报“card removed”和“card inserted”。按以下顺序排查确认去抖时间够不够。用示波器抓CD脚波形看抖动持续时间。如果超过默认去抖时间在设备树里加debounce-interval属性。确认GPIO上拉电阻是否合适。上拉电阻太大比如100K会导致电平上升沿变缓容易受干扰。一般用10K比较合适。确认有没有电磁干扰。SD卡时钟线的高频信号可能耦合到CD线上导致误触发。可以在CD线上加一个小电容滤波或者调整PCB布局让CD线远离时钟线。6.4 常见问题速查表现象可能原因排查方法解决方案插卡无反应未配cd-gpios检查设备树添加cd-gpios属性插卡无反应GPIO被占用dmesg搜“Failed to request”解决pinctrl冲突插卡无反应供电不足量卡座供电电压换大电流LDO识别但挂载失败文件系统不支持blkid查看类型编译对应驱动识别但挂载失败供电不稳量读写时电压换大电流LDO反复误检测去抖不够示波器抓波形加debounce-interval反复误检测上拉电阻太大查原理图换10K上拉热插拔后损坏缓存未刷检查挂载选项拔卡前sync7. 几个提高稳定性的实操技巧7.1 在应用层做二次确认内核层面的检测虽然已经做了去抖但在工业现场这种电磁环境复杂的地方偶尔还是会出现误检测。我在应用层加了一个二次确认的逻辑收到内核的卡插入事件后不立刻开始读写而是先等500ms然后读取CD GPIO的状态确认卡确实还在再开始操作。这个逻辑用poll或者epoll监听/sys/class/mmc_host/mmc1/下面的状态文件就能实现。7.2 配置udev规则自动挂载手动挂载太麻烦可以用udev规则实现自动挂载。在/etc/udev/rules.d/下面新建一个规则文件内容大概是这样KERNELmmcblk1p1, SUBSYSTEMblock, ACTIONadd, RUN/bin/mount -t auto /dev/mmcblk1p1 /mnt/sdcard KERNELmmcblk1p1, SUBSYSTEMblock, ACTIONremove, RUN/bin/umount /mnt/sdcard这样插卡自动挂载、拔卡自动卸载。但要注意拔卡时如果还有进程在访问挂载点umount会失败导致文件系统损坏。所以更安全的做法是在remove动作里先sync再umount -llazy umount或者干脆不自动卸载由应用层处理。7.3 定期检查卡的健康状态SD卡是有寿命的尤其是工业场景下频繁写入很容易坏。可以定期用smartctl或者mmc extcsd read命令读取卡的寿命信息。不过不是所有卡都支持这些命令比较通用的做法是定期往卡上写一个测试文件再读出来校验数据一致性。如果发现读写错误率上升就及时更换卡。7.4 保留一个应急的串口终端调试SD卡问题的时候最怕的就是系统起不来或者卡死连日志都看不到。我的做法是在板子上留一个串口调试口并且把内核的console参数配到串口上。这样即使系统卡死也能通过串口看到最后的日志定位问题。另外在eMMC里保留一个最小系统万一SD卡相关配置导致系统起不来可以从eMMC启动进去改配置。8. 最后再聊几句掏心窝的话RK3576这颗芯片整体来说还是比较好用的性能强、接口丰富但瑞芯微的SDK里有些参考设计的配置比较“理想化”默认你的硬件和参考板一模一样。一旦硬件设计有改动尤其是GPIO复用和引脚分配上的改动就需要自己动手改设备树和驱动配置。SD卡检测这个坑本质上就是参考设计用了专用CD引脚而我的硬件用了普通GPIO中间的差异需要软件来填补。我个人的经验是拿到一个新平台先把所有外设的引脚分配表过一遍确认哪些引脚是复用的、哪些有冲突。然后在设备树里把每个外设的pinctrl配置都检查一遍确保没有引脚被重复申请。这个工作看起来繁琐但能避免后面大量的调试时间。我这次如果一开始就做了这个检查至少能省下一天的时间。另外调试硬件相关的问题示波器和万用表真的不能省。很多问题看日志是看不出来的必须上仪器量波形、量电压。我这次遇到的电平抖动和供电不足都是靠示波器才定位到的。软件工程师也要会用基本的硬件调试工具这个技能在嵌入式领域特别重要。SD卡热插拔的文件系统保护也是个老生常谈的问题但每次做项目都会遇到。我的建议是不管项目需求里有没有“安全弹出”这个功能都加上。用户可能不会用但至少你提供了这个选项出了问题也有个说法。同时在内核层面把写缓存策略调保守一些宁可牺牲一点性能也要保证数据安全。工业场景下数据丢了比性能慢一点严重得多。
返回列表