最近在调试基于杰理方案的嵌入式设备时,遇到一个棘手的存储设备挂载问题:当设备在开机状态下插入SD卡后,如果此时再插入U盘,会出现U盘挂载失败的情况。这个问题在常规测试中并不常见,但在某些特殊存储设备上复现率极高。
经过排查发现,这类特殊存储设备通常是U盘和SD卡二合一的产品。它们通过同一个物理接口(如USB接口)提供两种存储模式切换功能。当这类设备第一次以SD卡模式被识别后,系统会建立对应的设备节点和挂载点。此时若用户拔出设备并切换为U盘模式重新插入,系统无法正确识别模式变更,导致挂载流程失败。
在Linux系统中,存储设备的识别主要经过以下步骤:
对于复合型存储设备,关键在于第二步的协议协商。当设备模式切换后,原有的设备标识可能仍然被系统缓存,导致新插入设备无法正确初始化。
杰理芯片在存储设备管理上做了以下优化:
c复制// 典型设备初始化流程(简化版)
void storage_init() {
detect_device_type(); // 检测设备类型
if (is_sd_card) {
init_sd_host_controller();
} else {
init_usb_host_controller();
}
mount_filesystem();
}
问题就出在detect_device_type()这个环节。当设备被重新插入时,系统可能直接沿用之前的检测结果,而不会重新执行完整的协议协商过程。
对于硬件设计,建议采取以下措施:
在驱动程序中增加强制重新检测的逻辑:
c复制// 修改后的设备检测流程
void storage_detect_reset() {
if (device_reinserted) {
reset_host_controller();
clear_device_cache();
msleep(100); // 确保设备稳定
}
detect_device_type();
}
关键修改点包括:
在应用程序中增加以下处理逻辑:
bash复制#!/bin/sh
# U盘挂载重试脚本
MAX_RETRY=3
COUNT=0
while [ $COUNT -lt $MAX_RETRY ]; do
if mount /dev/sda1 /mnt/usb; then
echo "Mount success"
exit 0
fi
echo "Mount failed, retrying..."
umount /mnt/usb 2>/dev/null
udhcpc -i eth0 -q # 可选:重置USB网络配置
sleep 1
COUNT=$((COUNT+1))
done
echo "Mount failed after $MAX_RETRY attempts"
exit 1
code复制[ 1234.567890] usb 1-1: new high-speed USB device number 4 using xhci-hcd
[ 1234.698765] mmc0: card 0001 removed
[ 1234.712345] mmc0: new ultra SDHC card at address 0001 # 错误识别为SD卡
[ 1234.723456] mmcblk0: mmc0:0001 SU04G 3.69 GiB
从日志可见,系统将U盘错误识别为SD卡,导致后续挂载失败。
应用驱动修改后,关键日志变化:
code复制[ 2345.678901] usb 1-1: new high-speed USB device number 5 using xhci-hcd
[ 2345.789012] usb-storage 1-1:1.0: USB Mass Storage device detected
[ 2345.801234] scsi host2: usb-storage 1-1:1.0
[ 2346.812345] scsi 2:0:0:0: Direct-Access SanDisk Ultra Dual Drive 1.00 PQ: 0 ANSI: 6
设备被正确识别为USB Mass Storage设备,挂载成功。
设备热插拔时序:
系统配置建议:
ini复制# /etc/udev/rules.d/99-storage.rules
ACTION=="add", SUBSYSTEM=="block", RUN+="/usr/bin/retry-mount.sh"
通过udev规则增加挂载重试机制
特殊设备处理:
调试技巧:
udevadm monitor实时观察设备事件lsusb -v和mmc-utils命令验证设备识别结果在实际项目中,我们还发现某些山寨存储设备存在更严重的兼容性问题。对于这类情况,最好的解决方案是在产品说明中明确建议使用经过认证的存储设备。