介绍一下 SD NAND 在 Linux 下的设备驱动。
SD NAND(也称为贴片式 SD 卡)是一种:
封装形式:BGA 封装,直接贴片焊接在 PCB 上
接口:完全兼容 SD 2.0/3.0 协议
内部结构 = NAND Flash + SD 控制器 + 坏块管理 + 磨损均衡
用户空间
↓
块设备层 (/dev/mmcblk0)
↓
MMC 子系统 (drivers/mmc/)
↓
SD NAND 设备
// 1. MMC 主机控制器驱动
drivers/mmc/host/ // 如 sdhci, dw_mmc 等
// 2. MMC 核心层
drivers/mmc/core/
- core.c // 核心功能
- block.c // 块设备接口
- sd.c // SD 协议处理
// 3. SD NAND 识别
drivers/mmc/core/sd.c 中的识别逻辑
// 以 Allwinner 平台为例
&mmc0 {
compatible = "allwinner,sun50i-h5-mmc";
reg = <0x1c0f000 0x1000>;
interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
clock-names = "ahb", "mmc";
resets = <&ccu RST_BUS_MMC0>;
reset-names = "ahb";
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <®_vcc3v3>;
bus-width = <4>;
status = "okay";
// SD NAND 特定参数
max-frequency = <50000000>;
non-removable;
disable-wp;
cap-sd-highspeed;
cap-mmc-highspeed;
};
# 确保启用 MMC 支持
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_DW=y # DesignWare MMC 控制器
# 查看识别到的 SD NAND
dmesg | grep mmc
# 输出示例:
# mmc0: new high speed SDHC card at address 1234
# mmcblk0: mmc0:1234 SA08G 7.40 GiB
# 查看分区
ls /dev/mmcblk*
# /dev/mmcblk0 /dev/mmcblk0p1 /dev/mmcblk0p2
# 查看详细信息
cat /sys/block/mmcblk0/device/{cid,csd,manfid,date}
# 启用调试信息
echo 8 > /proc/sys/kernel/printk
echo "file sd.c +p" > /sys/kernel/debug/dynamic_debug/control
# 查看 MMC 调试信息
cat /sys/kernel/debug/mmc0/ios
# clock: 50000000 Hz
# vdd: 21 (3.3 ~ 3.4 V)
# bus mode: 2 (push-pull)
# chip select: 0 (don't care)
# power mode: 2 (on)
# bus width: 2 (4 bits)
# 检查电压配置
# SD NAND 通常需要 3.3V,部分支持 1.8V
# 调整时序参数(设备树中)
mmc0: sd-uhs-sdr12; sd-uhs-sdr25; sd-uhs-sdr50;
// 在驱动中调整
static struct mmc_host_ops my_ops = {
.request = my_request,
.set_ios = my_set_ios,
.get_ro = my_get_ro,
.get_cd = my_get_cd,
.enable_sdio_irq = my_enable_irq,
};
// 启用 DMA
host->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED;
# 1. 测试写入速度
dd if=/dev/zero of=/mnt/sdnand/test bs=1M count=100 conv=fsync
# 2. 测试读取速度
dd if=/mnt/sdnand/test of=/dev/null bs=1M count=100
# 3. 使用 fio 详细测试
fio --name=randwrite --ioengine=libaio --iodepth=32
--rw=randwrite --bs=4k --direct=1 --size=256M
--numjobs=4 --runtime=60 --group_reporting
# 1. 分区
fdisk /dev/mmcblk0
# 创建两个分区:p1(FAT32) + p2(ext4)
# 2. 格式化
mkfs.vfat /dev/mmcblk0p1
mkfs.ext4 /dev/mmcblk0p2
# 3. 挂载
mount /dev/mmcblk0p2 /mnt/sdnand
# 4. 配置 fstab 自动挂载
echo "/dev/mmcblk0p2 /mnt/sdnand ext4 defaults 0 0" >> /etc/fstab
// 在驱动中添加电源管理
static const struct dev_pm_ops sdhci_pm_ops = {
.suspend = sdhci_suspend,
.resume = sdhci_resume,
.runtime_suspend = sdhci_runtime_suspend,
.runtime_resume = sdhci_runtime_resume,
};
// 设置电源状态
mmc_power_save_host(host);
mmc_power_restore_host(host);
某些 SD NAND 可能需要特殊初始化:
// 示例:发送特定 CMD 序列
static int sdnand_vendor_init(struct mmc_host *host)
{
struct mmc_command cmd = {0};
// 特殊初始化命令
cmd.opcode = 62; // 厂商自定义命令
cmd.arg = 0xEFAC62;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
return mmc_wait_for_cmd(host, &cmd, 0);
}
参考现有驱动:
drivers/mmc/host/sdhci-of-arasan.c
drivers/mmc/host/dw_mmc.c
使用设备树配置参数,避免修改代码
注意时序:不同厂商的 SD NAND 可能需要不同的 setup/hold 时间
错误处理:SD NAND 可能返回不同的错误码,需要完善错误恢复机制
考虑兼容性:有些 SD NAND 在识别时需要特殊电压序列
内核文档:
Documentation/mmc/
Documentation/devicetree/bindings/mmc/
工具:
mmc-utils:用户空间 MMC 工具
stressapptest:压力测试
调试工具:
逻辑分析仪(抓 SD 总线波形)
mmc debugfs 接口
这样你就可以为 SD NAND 开发或调试 Linux 驱动了。
下一篇:没有了!
电话:176-6539-0767
Q Q:135-0379-986
邮箱:xcz@xczmemory.com
地址:深圳市南山区后海大道1021号C座