本文记录Zephyr下rt1052平台usdhc的使用过程中遇到的一些问题和处理方式。
Zephyr提供了rt1052的usdhc驱动,可以通过简单配置就很方便的使用usdhc驱动访问SD卡。但目前usdhc的驱动并不能兼容所有的情况,当SD卡外部硬件不同和使用不同版本的SD卡时会遇到一些问题,本文将说明遇到的问题和处理方式。
Zephyr下如何使用usdhc
1. 修改设备树
Zephyr支持rt1052两个usdhc控制器(参考zephyr\dts\arm\nxp\nxp_rt.dtsi),根据硬件设计选择要使用的usdhc,在board的dts中添加如下内容表示要使用usdhc11
2
3
4&usdhc1 {
status = "okay";
cd-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
};
节点的cd-gpios和pwr-gpios两个属性(参考zephyr\dts\bindings\mmc\nxp,imx-usdhc.yaml)分别用于card detect和power control,并不是必须的,例如我使用的硬件上gpio2.28连接了卡槽的card detect引脚,所以按照硬件将cd-gpio属性加上。硬件上没有使用power控制,因此不添加pwr-gpios属性。
2. 配置
在board的默认配置文件或者app配置文件的prj.conf添加下列配置就会启动usdhc驱动1
2CONFIG_DISK_ACCESS=y
CONFIG_DISK_ACCESS_SDHC=y
如果你插入的卡是FAT格式的,配置完下面选项就可以使用fs_mount/fs_open/fs_close/fs_read/fs_write对SD卡进行操作了1
2CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y
问题及处理方式
1. 不能访问UHS卡
现象
插入UHS卡后启动会提示1
2
3
4
5
6
7[00:00:00.020,000] <inf> usdhc: SD inserted!
[00:00:00.101,000] <err> usdhc: CMD17 Polling ERROR
[00:00:00.101,000] <err> usdhc: USDHC bus device initalization failed!
[00:00:00.101,000] <err> fs: fs mount error (-5)
原因
外部电路没有设计高速电平选择电路。
当SD卡插入时,usdhc先默认以3.3V的电平和SD卡进行通信,并获取SD卡的信息,如果usdhc发现SD卡是UHS高速卡时,会将通信模式切换为高速模式,与SD卡的通信的电平切换为1.8V。
下面是NXP rt1052的参考电路:
原理说明:开始SD0_VSELECT是高电平,Q9的1-3引脚截止,由R46和R52分压反馈,此时NVCC_SD为3.3V。usdhc以3.3v通信完后知道是高速卡后,将SD0_VSELECT拉低,Q9的1-3引脚导通R46,R47变为并联阻值为160K,和R52分压反馈,此时NVCC_SD变为1.8V,SDCard以1.8V开始通信。
下面是我使用硬件的电路:
可以看到NVCC_SD是强制拉到3.3V的,当usdhc要以1.8V工作时,并没有外部硬件去切换工作电平到1.8V,这将导致和SD卡通信失败。
处理方法
在无高速访问的需求下,这样设计硬件够简单,而且costdown。我们可以通过软件禁用usdhc 1.8v,在subsys/disk/disk_access_usdhc.c中将USDHC_SUPPORT_V180_FLAG的值由USDHC_HOST_CTRL_CAP_VS18_MASK改为SDMMCHOST_NOT_SUPPORT。比较灵活的做法参考https://github.com/zephyrproject-rtos/zephyr/pull/29096
2.不能访问1.0的卡
现象
插入1.0的SD卡后不能正常工作,log提示1
Set SD driver strength failed
原因
SD卡规格太低,strength时SD Physical Layer Spec 3.0才引入的CMD,插入1.0的卡当然不支持。
处理方法
要让1.0的卡可以用主要有以下需要处理:
- Spec 1.10之后才支持CMD6
- Spec 3.0之后才支持CMD6 Group3–也就是driver strengthand current limit
修改细节已提交merge,可参考https://github.com/zephyrproject-rtos/zephyr/pull/33917
代码版本
以上的分析全部基于Zephyr 2.4.0,usdhc的驱动代码放在subsys/disk/disk_access_usdhc.c. 但在今年3.23 usdhc被调整到drivers/disk/usdhc.c,调整后的代码位置更合理,详细可以参考这笔提交 https://github.com/zephyrproject-rtos/zephyr/commit/03101e75d8c9bd78731c94a629e98bb46a346fcb#diff-7def323c468f1165c0d0f7ce3731fb874be82c9f1e24ff32071763c33106648f
注意点1
调整后的代码需要将配置CONFIG_DISK_ACCESS_SDHC=y
改为CONFIG_DISK_DRIVER_SDMMC=y
才能正常编译使用。
注意点2
由于https://github.com/zephyrproject-rtos/zephyr/pull/29096 一直没有被merge,因此在代码位置调整后需要另做修改,参考https://github.com/zephyrproject-rtos/zephyr/pull/33917。