在嵌入式系统中配置 SDIO 接口与 SD NAND 通信,需结合硬件连接、驱动配置和协议实现。以下是基于 STM32 和 Linux 系统的详细配置方法:
STM32 引脚 | SD NAND 引脚 | 功能描述 |
---|---|---|
SDIO_CLK | CLK | 时钟线(输出) |
SDIO_CMD | CMD | 命令线(双向) |
SDIO_D0 | DATA0 | 数据线 0(双向) |
SDIO_D1 | DATA1 | 数据线 1(双向) |
SDIO_D2 | DATA2 | 数据线 2(双向) |
SDIO_D3 | DATA3 | 数据线 3(双向) |
GPIO | CD | 卡检测(可选) |
3.3V | VCC | 电源 |
GND | GND | 地 |
sdio_init.c
```c
/* SDIO初始化函数 */
void MX_SDIO_SD_Init(void) {
hsd.Instance = SDIO;
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B; // 初始化时使用1位宽
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0; // 初始分频值,产生≤400kHz的时钟
if (HAL_SD_Init(&hsd) != HAL_OK) {
Error_Handler();
}
// 切换到4位宽模式(可选)
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) {
Error_Handler();
}
}
/* MSP初始化回调函数 */
void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(sdHandle->Instance==SDIO) {
/* SDIO时钟使能 */
__HAL_RCC_SDIO_CLK_ENABLE();
/* GPIO端口使能 */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/* 配置GPIO引脚 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* 配置中断 */
HAL_NVIC_SetPriority(SDIO_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
}
}
### **3. Linux系统配置(设备树+驱动)**
#### **3.1 设备树配置(dts文件)**sdhci@40012000 {
compatible = "st,stm32-sdhci";
reg = <0x40012000 0x400>;
interrupts = <0 43 0>;
clocks = <&rcc SDIO>;
clock-names = "sdio";
bus-width = <4>; // 4位宽模式
non-removable; // 非 removable 设备
pinctrl-names = "default";
pinctrl-0 = <&sdmmc1_pins_a>;
status = "okay";
};
#### **3.2 加载驱动模块**# 加载SDIO驱动
modprobe sdhci
modprobe sdhci-stm32
# 查看设备是否被识别
dmesg | grep mmc
#### **3.3 挂载文件系统**# 查看可用块设备
lsblk
# 格式化SD卡(首次使用)
mkfs.ext4 /dev/mmcblk0p1
# 挂载文件系统
mkdir /mnt/sdcard
mount /dev/mmcblk0p1 /mnt/sdcard
### **4. 关键配置参数说明**
1. **时钟配置**:
- 初始化阶段:时钟分频值需设置为产生≤400kHz的时钟
- 初始化后:可提高至最高支持频率(如25MHz/50MHz)
2. **数据宽度**:
- 初始化时使用1位宽模式
- 初始化完成后可切换到4位宽模式以提高性能
3. **电源管理**:
- 支持SDIO的Suspend/Resume功能
- 可配置时钟省电模式(ClockPowerSave)
### **5. 调试与验证方法**
1. **硬件信号检测**:
- 使用示波器观察CLK、CMD、DATA线的信号质量
- 验证初始化阶段时钟频率≤400kHz
2. **软件调试**:
- 打印SDIO命令响应和错误码
- 使用Linux的debugfs查看SDIO控制器状态
3. **功能测试**:
- 执行读写基准测试(如`dd`命令)
- 验证文件系统操作(创建/删除文件)
### **6. 常见问题与解决**
| 问题现象 | 可能原因 | 解决方法 |
|------------------------|-----------------------------|-----------------------------|
| 初始化超时 | 时钟配置错误、硬件连接不良 | 检查分频值,确认引脚连接 |
| 数据传输错误 | 时序不匹配、上拉电阻缺失 | 调整时钟相位,添加/检查上拉 |
| 只能识别SPI模式 | SDIO控制器未正确配置 | 检查设备树或HAL库配置 |
| 高速模式不稳定 | 电源噪声、信号完整性问题 | 添加去耦电容,优化PCB走线 |
通过以上配置,嵌入式系统可通过SDIO接口高效地与SD NAND通信,实现数据存储和读取功能。