工业级TF卡NAND+北京君正+Rk瑞芯微的应用

发布于:2025-08-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

各位工程师,大家好!今天为大家分享瑞芯微平台(RK3568 开发板)与北京君正平台(X2600E 开发板)下 Linux 系统中 SD NAND 的使用经验。本次分享涉及的环境如下:Ubuntu 版本为 20.04,交叉编译工具链分别为 aarch64-linux-gnu-(适用于瑞芯微平台)和 mips-linux-gnu-(适用于君正平台)。

分享内容分为五个板块:操作 SD NAND 的常用命令、SD 底层协议简要介绍、SD NAND 的三大读写方式、SD NAND 的驱动框架介绍、SD NAND 启动。其中前三个板块无平台差异,适用于所有 Linux 系统;第四个板块以瑞芯微 RK3568 平台为例;第五个板块同时覆盖君正 X2600E 与瑞芯微 RK3568 平台。

目录

一、操作SD NAND的常用命令

二、SD底层协议简要介绍

三、SD NAND 的三大读写方式

1. 使用 dd 命令

2. 通过文件 IO / 标准 IO 读写

3.使用ioctl产生系统调用

四、SD NAND的驱动框架介绍(以瑞芯微 RK3568 驱动源码为例)

五、SD NAND启动


一、操作SD NAND的常用命令

1.查看 SD 设备:可使用lsblkfdisk -l命令,设备节点通常为/dev/mmcblkX/dev/sdX(例如mmcblk0)。

2.挂载分区:命令格式为mount 设备分区 挂载点,示例:mount /dev/mmcblk0p1 /mnt/sdcard

3.卸载分区:命令格式为umount 设备分区/挂载点,示例:umount /dev/mmcblk0p1umount /mnt/sdcard

4.分区管理:通过fdisk 设备节点进入交互管理(例如fdisk /dev/mmcblk0),交互页面常用命令如下:

  • p:打印分区表
  • n:创建新分区
  • d:删除分区
  • t:更改分区类型
  • w:保存更改并退出
  • q:不保存更改退出
  • m:显示帮助菜单
  • l:列出已知分区类型
  • v:验证分区表
  • g:创建空 GPT 分区表
  • o:创建空 DOS 分区表
  • 注意:分区管理前需备份重要数据,更改生效后原有数据将丢失。

5.格式化分区

  • 格式化为 FAT32:mkfs.vfat 设备分区(示例:mkfs.vfat /dev/mmcblk0p1
  • 格式化为 ext4:mkfs.ext4 设备分区(示例:mkfs.ext4 /dev/mmcblk0p2

6.简单读写:可通过cpcatecho等基础命令实现,示例:

  • cp /usr/data/1.txt /mnt/sdcard/2.txt(复制文件)
  • cat /mnt/sdcard/test.c(读取文件内容)
  • echo "测试内容" > /mnt/sdcard/test.txt(写入内容到文件)

二、SD底层协议简要介绍

本部分为后续 “读写方式” 提供理论基础,仅做简要说明及注意事项提示,完整协议可参考《SD2.0 协议标准完整版》(见附件)。

SD驱动中最重要的部分就是初始化,这里描述一下初始化流程

初始化是 SD 驱动的核心环节,需先区分卡类型(SDHC、SDSC、SD1.X、MMC 卡),流程如下:

  • 上电:卡插入卡槽时自动完成;
  • 软复位:发送 CMD0,使卡进入空闲模式;
  • 电压范围询问:发送 CMD8,SDHC/SDSC 卡会回复 R1 响应,SD1.X/MMC 卡无响应;
  • 卡类型区分
    • 若 CMD8 无响应,发送 ACMD41(需先发送 CMD55 告知卡 “后续为应用命令”):
      • 若 ACMD41 无响应,判定为 MMC 卡,发送 CMD1 激活即可完成初始化;
      • 若 ACMD41 有 R1 响应,判定为 SD1.X 卡;
    • 若 CMD8 有 R1 响应,发送 ACMD41 并通过 R3 响应中 OCR 寄存器的 “CCS 位” 区分:
      • CCS 位为 1:SDHC 卡(高容量 V2.0 卡);
      • CCS 位为 0:SDSC 卡(标准 V2.0 卡);
  • 后续统一步骤:发送 CMD2 获取 CID 寄存器值(卡回复 R2 响应),发送 CMD3 使卡获得相对地址,完成初始化。

收到R1响应再区分SDHC和SDSC,然后发送ACMD41,主机告诉SD卡支持高容量,根据返回的R3响应中的OCR寄存器来判断是标准还是高容量,只有当busy位置1时CCS位才有效,CCS位为1是高容量V2.0卡(即SDHC卡),CCS位为0是标准V2.0卡(即SDSC卡),至此区分出了V1.X,标准V2.0,高容量V2.0卡,这三种卡接下来的步骤一致:

发送CMD2获取CID寄存器的值,SD卡会回复R2响应,再发送CMD3,SD卡获得相对地址,流程图如下图所示:

使用SD卡代替SD NAND:发送CMD2获取CID寄存器的值,SD卡会回复R2响应,再发送CMD3,SD卡获得相对地址,流程图所示

然后是数据传输模式,初始化完成后进行数据传输就相对简单了,只需要发送对应的命令即可,流程图如下:

使用SD卡代替SD NAND然后是数据传输模式,初始化完成后进行数据传输就相对简单了,只需要发送对应的命令即可,流程图所示

下面附上常用命令以及响应的图:

SD底层协议简要介绍(由于SD NAND和SD卡遵守相同协议,并且标准协议中使用SD卡来描述,因此以下用词使用SD卡代替SD NAND)附上常用命令以及响应的图

SD底层协议简要介绍(由于SD NAND和SD卡遵守相同协议,并且标准协议中使用SD卡来描述,因此以下用词使用SD卡代替SD NAND)附上常用命令以及响应的图

最后提醒几个需要注意的点:

  • 供电上升时间:上电后需等待 “电压升至总线操作电平且可发送第一条命令” 的时间,需取 “1ms、74 个时钟周期、实际供电上升时间” 三者的最大值。该逻辑在驱动源码mmc_power_up函数(drivers/mmc/core/core.c)中已体现(协议 6.4.1 章节亦有说明)。若未等待此时间,可能导致初始化 “表面成功” 但后续数据传输偶发异常,且异常定位难度较大。

    SD底层协议简要介绍(由于SD NAND和SD卡遵守相同协议,并且标准协议中使用SD卡来描述,因此以下用词使用SD卡代替SD NAND)上电之后有一个时间段叫“供电上升时间”

    • 数据包格式:SD 卡有两种数据包格式,解析寄存器时需注意区分:

      • 常规数据(8bit 字节数据):先发低字节后发高字节,每个字节先发高位后发低位;
      • 宽位数据(多为存储寄存器数据):先发高位后发低位。

    SD底层协议简要介绍(由于SD NAND和SD卡遵守相同协议,并且标准协议中使用SD卡来描述,因此以下用词使用SD卡代替SD NAND)的两种数据包格式,分别是常规数据和宽位数据

    三、SD NAND 的三大读写方式

    SD NAND作为一种存储设备,不外乎就是读和写,同时这也是最重要的,熟悉读写方式对于使用SD NAND开发非常有帮助,因此在这一块会详细介绍;

    1. 使用 dd 命令

    dd命令可灵活适配 “挂载 / 未挂载文件系统” 的场景,具体如下:

    • 已挂载分区(适用于普通文件读写)
      命令格式:sudo dd if=输入文件 of=输出文件 bs=块大小 status=状态信息 其他选项
      示例:sudo dd if=/mnt/sdcard/test.doc of=backup.doc bs=1M count=1(将/mnt/sdcard/test.doc的前 1MB 字节写入backup.doc

    • 未挂载分区(适用于镜像写入、全卡备份 / 擦除等)
      命令格式:sudo dd if=输入设备 of=输出设备 bs=块大小 status=状态信息 其他选项
      示例 1:sudo dd if=sd_back_up.img of=/dev/mmcblk0 bs=4M status=progress(将镜像以 4MB 块大小写入/dev/mmcblk0,并显示进度)
      示例 2:sudo dd if=/dev/mmcblk1p1 of=/root/zboot.img bs=4M status=progress(读取mmcblk1p1设备所有数据到/root/zboot.img

      参数说明:若需限制读写范围,可使用skip(跳过前 N 个块)或count(仅读写 N 个块),例如dd if=/dev/sdX of=/path/to/output.img bs=4M skip=10 count=20(跳过前 10 块,读取 20 块数据)。

      注意:未挂载分区时,dd直接操作原始存储设备,会忽略文件系统结构,可能覆盖数据或损坏文件系统,操作前需备份重要数据;已挂载分区时,dd通过文件系统操作,相对安全。

    2. 通过文件 IO / 标准 IO 读写

    无论是否挂载文件系统,均能通过文件 IO(openwrite等)或标准 IO(fopenfwrite等)操作 SD NAND,两者的差异在于:“通过文件系统” 更安全但效率略低,“直接操作硬件” 效率更高但需避免数据覆盖。以下为两种场景的示例:

    • 示例 1:标准 IO(已挂载文件系统)
      功能:在/mnt/sdcard/下创建test_data.txt,写入 4 次 “0~255” 数据,再读取验证。
      编译命令:aarch64-linux-gnu-gcc test2.c -o test2
      操作:编译后通过sftp root@ip将可执行文件发送至开发板运行,运行结果及程序如下。

      第一个示例:使用标准io(fopen,fwrite,fread,fseek,fclose等)在已挂载文件系统的SD NAND上进行读写

    第一个示例:使用标准io(fopen,fwrite,fread,fseek,fclose等)在已挂载文件系统的SD NAND上进行读写编译命令是aarch64-linux-gnu-gcc test2.c -o test2,编译成功后使用sftp root@ip将test2发送至开发板运行测试,运行结果以及程序图示

    • 示例 2:文件 IO(未挂载文件系统)
      功能:从 SD NAND 第 1000 块开始写入 512 字节数据(内容为 “0~255,0~255”),再读取验证。
      编译命令:aarch64-linux-gnu-gcc test.c -o test
      操作:同示例 1,运行结果如下。

    使用文件io(open,write,read,lseek,close)对未挂载文件系统的SD NAND直接操作

    编译命令是:aarch64-linux-gnu-gcc test.c -o test,编译成功后使用sftp root@ip将test2发送至开发板运行测试,运行结果和程序

    3.使用ioctl产生系统调用

    陷入内核进行处理,前两种方式都容易实现,而且不需要关注底层发送的命令,而ioctl可以对SD NAND进行精细的命令控制来约束NAND的行为,并且在ioctl使用过程中还有一些需要注意的点,如果想要对SD NAND进行最为底层的命令操作,那么ioctl必定是是首选,因此着重介绍这种方式;

    使用ioctl来对SD NAND发送命令,其中最为重要的就是填充struct mmc_ioc_cmd结构体,结构体的详细定义位于kernel/include/uapi/linux/mmc/ioctl.h,其中关于flags即命令标志位掩码的定义位于/include/linux/mmc/core.h文件中的struct mmc_command结构体中,下面对struct mmc_ioc_cmd结构体的各成员作详细介绍,如下图所示:

    使用ioctl产生系统调用,陷入内核进行处理,前两种方式都容易实现,而且不需要关注底层发送的命令,而ioctl可以对SD NAND进行精细的命令控制来约束NAND的行为

    介绍完struct mmc_ioc_cmd结构体后细心的小伙伴会发现了这里面几乎所有的参数都好填充,唯独flags,命令标志位掩码的定义在core.h中,如下图所示:

    介绍完struct mmc_ioc_cmd结构体后细心的小伙伴会发现了这里面几乎所有的参数都好填充,唯独flags,命令标志位掩码的定义在core.h中,如图所示

    那么在编写ioctl的程序时,填充flags需要用到core.h里面的内容,总所周知,linux里面的隔离是很严重的,在应用层调用内核层的定义,这是不允许的,编译会报错,之前刚开发的时候因为这个编译报错还折腾了不少时间,最终的解决办法就是把这些标志位的宏定义复制到自己写的应用程序中,这样就没有报错了,下面提供一份程序

    程序较长,文件名是init.c(见附件),编译命令是:aarch64-linux-gnu-gcc init.c -o init,编译成功后使用sftp root@ip(若有adb功能也可使用adb push)将可执行程序init发送至开发板进行运行测试,文件中包含ioctl使用的详细解释,下面三张图是运行结果截图(前两张)以及使用逻辑分析仪抓取的命令(第三张图),波形文件名是:init.TLW,见附件,两者都与程序一致,运行过程中没有报错,这就是使用ioctl向SD NAND发送底层命令的详细过程;

    CS创世 SD NAND 在 君正平台和 RK 平台的应用使用ioctl向SD NAND发送底层命令的详细过程

    CS创世 SD NAND 在 君正平台和 RK 平台的应用使用ioctl向SD NAND发送底层命令的详细过程

    CS创世 SD NAND 在 君正平台和 RK 平台的应用使用ioctl向SD NAND发送底层命令的详细过程

    关于ioctl的使用,有下面几点需要格外注意,这些都是小编亲身走过的坑,所谓前人栽树,后人乘凉, 也算方便大家“乘凉”了哈哈;

    第一是如果进行的是写操作,例如发送CMD24,CMD25等命令,那么struct mmc_ioc_cmd结构体的write_flag必须要赋值为非零值,如果是0值,那么很容易导致发送命令失败,得到“errno=110 (Connection timed out)”的错误信息,这个错误信息相对常见,意为连接超时,分析函数调用链可知:在__mmc_blk_ioctl_cmd(drivers/mmc/core/block.c)函数中有

    CS创世 SD NAND 在 君正平台和 RK 平台的应用

    根据write_flag的值会进一步增加MMC_DATA_WRITE或MMC_DATA_READ的标志再传到驱动中,因此发送写命令时请务必给write_flag赋非零值;

    第二是在SD卡初始化完成后,开始数据传输前,需要发送ACMD6定义数据总线的宽度,分析源码可知:在mmc_sd_init_card(drivers/mmc/core/sd.c)函数中有如下图所示部分

    在SD卡初始化完成后,开始数据传输前,需要发送ACMD6定义数据总线的宽度,分析源码可知:在mmc_sd_init_card(drivers/mmc/core/sd.c)函数中有如下图所示部分

    SD和主机通常都是同时支持4位数据总线宽度的,在不修改SD驱动的情况下,主机控制器是4位总线宽度,所以如果不发送ACMD6,那么卡会保持默认的1位总线宽度,此时主机和NAND的总线宽度不一致,就会出现“errno=84 (Invalid or incomplete multibyte or wide character)”的错误信息,含义是无效或不完整的多字节或宽字符,解决办法有两种,一种是修改驱动源码,将主机控制器的总线宽度固定为1位,此时可以不发送ACMD6,主机和 SD NAND都使用1位数据总线通信,第二种是发送ACMD6通知卡改变总线宽度为4位,两者都用4位总线传输数据,ACMD6的参数说明如下图,很明显要第二种方式更简单,因此如果遇到errno=84的错误码,检查一下主机和SD NAND的总线宽度是否一致;

    如果遇到errno=84的错误码,检查一下主机和SD NAND的总线宽度是否一致

    第三是频率问题,如果使用ioctl发送cmd时,检查了命令和各项参数都没有错,也没犯上面两种错误,但是运行程序发现就是会报各种错,例如下图(运行的是示例程序init)

    CS创世 SD NAND 在 君正平台和 RK 平台的应用示例程序init

    那么很大概率就是频率太高,SD NAND接受不了,此时需要降频,如下图

    CS创世 SD NAND 在 君正平台和 RK 平台的应用示例程序init

    降低频率后再次运行,运行结果见下图

    CS创世 SD NAND 在 君正平台和 RK 平台的应用示例程序init

    只要多加注意以上三点,相信使用ioctl就没有什么大问题;

    四、SD NAND的驱动框架介绍(以瑞芯微 RK3568 驱动源码为例)

    第一:MMC/SD驱动在linux中的结构层次

    Linux 中 MMC/SD 设备被抽象为块设备,驱动源码位于drivers/mmc目录,包含core(核心层)、card(块设备层)、host(主机控制器层)三个文件夹(RK3568 驱动中corecard合并为core),各层功能如下:

    • card 层:实现 SD NAND 作为块设备的操作逻辑,解决 “如何将 SD NAND 抽象为块设备” 的问题。
    • core 层:实现协议规范(如命令交互、数据传输格式),抽离不同主机控制器的共性,为 host 层提供接口。
    • host 层:直接与硬件交互,负责将 core 层的协议请求转换为寄存器操作、时钟控制等硬件行为,需根据不同主机控制器的硬件资源开发(是驱动开发的核心修改层)。

    core层根据协议规范来构造各种命令,那么命令是怎么发送给SD NAND呢?通过主机控制器。

    主机控制器通过设置SD需要的gpio资源,注册中断资源,使能控制器等等,然后再向上面的核心层增加一个host,这样核心层就能调用具体的硬件操作函数来和SD卡通信了;

    card和core是封装好的共性以及规范,通常是不需要修改的,而host层是直接与硬件打交道,需要控制底层寄存器的,不同的host控制器硬件资源也不一样,因此驱动SD NAND,host层才是应该需要修改开发的,MMC/SD驱动在linux中的结构层次见下图:

    CS创世SD NAND的驱动框架介绍(以瑞芯微平台的RK3568驱动源码为例)

    第二:SD驱动中核心的数据结构举例(SD NAND和SD卡在驱动中使用的数据结构和调用的函数是一致的,并且有不少数据结构命名或函数功能注释翻译过来用SD卡描述更贴切,因此下面描述用词使用SD卡代替SD NAND,不再赘述)

    • struct mmc_host:代表 MMC/SD 主机控制器,核心成员包括:

      • opsstruct mmc_host_ops类型,包含发送命令、设置时钟等硬件操作函数指针;
      • card:指向插入该主机的 SD 卡设备;
      • iosstruct mmc_ios类型,存储当前 IO 状态(时钟频率、总线宽度等);
      • f_min/f_max:主机支持的最小 / 最大时钟频率,直接影响 SD 卡操作频率。
    • struct mmc_card:代表插入的 SD 卡设备,核心成员包括:

      • host:指向连接的主机控制器;
      • rca:相对卡地址(总线上的唯一标识);
      • ocr:操作条件寄存器(存储支持的电压范围等信息);
      • cid:卡标识信息(制造商 ID、产品名称等)。
    • struct mmc_ios:存储主机控制器 IO 状态,核心成员包括clock(当前时钟频率)、bus_width(总线宽度,1/4/8 线可选)、power_mode(电源模式,如MMC_POWER_UP)。

    • struct mmc_host_ops:主机控制器操作集,核心函数指针包括request(添加操作请求到队列)、set_ios(设置 IO 状态)、get_cd(检测卡插入 / 拔出)等。

    • struct mmc_request:代表对 SD 卡的操作请求,核心成员包括cmd(要执行的命令)、data(要传输的数据)。

    第三:host层函数调用关系解析

    CS创世 SD NAND 在 君正平台和 RK 平台的应用 host层函数调用关系解析

    这里主要做了两件事,其一是mmc_alloc_host分配一个mmc_host,其二是mmc_add_host添加一个mmc_host;

    host 层的核心是 “注册主机控制器”,关键流程为:

    1. mmc_alloc_host:分配mmc_host结构体并初始化;
    2. mmc_add_host:将主机控制器添加到内核 MMC 子系统,完成注册后即可响应 core 层的请求。

    第四:卡的检测

        

    CS创世 SD NAND 在 君正平台和 RK 平台的应用:SD卡的检测

    卡的检测需结合 “主动扫描” 与 “中断触发”:

    • 主动扫描:主机控制器初始化后(如dw_mci_init_slot函数中),调用mmc_rescan扫描是否有卡插入;
    • 中断触发:若扫描时无卡,后续卡插入 / 拔出会触发中断,中断处理函数会重新调用mmc_rescan,实现动态检测。

    第五:扫描流程

    CS创世 SD NAND 在 君正平台和 RK 平台的应用:扫描流程

    CS创世 SD NAND 在 君正平台和 RK 平台的应用:扫描流程

    struct mmc_card 结构里面包含了一个 struct device 结构, mmc_alloc_card 不但申请了内存,而且还填充了 struct device 中的几个成员,尤其 card->dev.bus = &mmc_bus_type; 这一句要重点对待,mmc_bus_type的定义如下图

    CS创世 SD NAND 在 君正平台和 RK 平台的应用:mmc_bus_type的定义如下图

    申请一个 mmc_card 结构,并简单初始化后, mmc_init_card 的使命就完成了,然后再调用 mmc_add_card 将这个 card 设备添加到内核。 mmc_add_card 其实很简单,就是调用 device_add 将 card->dev 添加到内核当中去;

    device_add 里面,设备对应的总线会拿着你这个设备和挂在这个总线上的所有驱动程序去匹配( match ),此时会调用 match 函数(如下图),如果匹配到了就会调用总线的 probe 函数或驱动的 probe 函数;

    CS创世 SD NAND总线的 probe 函数或驱动的 probe 函数

    所以match永远不会失败,匹配成功就会执行mmc_bus_probe(定义见下图)

    CS创世 SD NAND在君正平台和RK平台的应用:match永远不会失败,匹配成功就会执行mmc_bus_probe(图示)

    追踪到这里,probe由调用了 drv->probe() ,这就需要知道drv的定义了,struct mmc_driver*drv=to_mmc_driver(dev->driver);match 函数总是返回 1 ,说明挂在这条总线上的 driver 都有可能跑到这里来了,事实的确也是这样的,不过好在挂在这条总线上的 driver 只有一个,定义见下图:

    CS创世 SD NAND在君正平台和RK平台的应用:总线上的 driver 只有一个【图示】

    因此跳转到mmc_bllk_probe函数执行,函数定义如下:

    CS创世 SD NAND在君正平台和RK平台的应用:跳转到mmc_bllk_probe函数执行,函数定义,如图示

    mmc_blk_probe 是 MMC 块设备驱动的核心探测函数,负责将 MMC/SD 卡注册为块设备,使其能够被系统访问,看到这里已经把core,host目录下的文件都牵扯进来了,慢慢再捋一下就能看出从host到core的联系了;

    第五:数据的读写

    在驱动中,向SD卡发送cmd都是通过请求队列来完成的,所有的cmd都会被封装成请求,然后由内核的I/O调度器统一排序,合并或拆分,再下发给硬件驱动,这样避免了驱动直接操作硬件,而是通过标准接口解耦,增强了安全性和可维护性,所以分析cmd的发送首先要定位到request请求队列,关键函数调用流程如下图:

    CS创世 SD NAND在君正平台和RK平台的应用:数据的读写,如图示

    顺便附上上图中提到的两个ops操作集合的赋值:

    CS创世 SD NAND在君正平台和RK平台的应用:数据的读写,如图示

    CS创世 SD NAND在君正平台和RK平台的应用:数据的读写,如图示

    分析到这里,整个SD驱动框架做的事情说简单一些其实就干了两件事,一是卡的扫描检测,而是数据的读写,不过这个过程中涉及到的数据结构和函数调用确实相对复杂,捋清楚驱动框架还是需要静下心来花费时间的;

    五、SD NAND启动

    相同的板卡厂商一般SD NAND启动的流程固定,大致讲一下流程,首先是要制作SD启动卡,即将启动镜像烧录进SD NAND,一般板卡厂商都会有专门的制作工具,只需按照使用方法来制作启动卡即可,如果没有制作工具,那么一般使用dd命令将系统镜像写入卡内(写入时可能有地址参数要求,需要咨询板卡厂商的技术支持),然后是选择启动方式,一般是有几个boot引脚,启动时系统会根据boot引脚的电平组合来选择启动方式,有些开发板可能在选择SD NAND启动时还需要配置其他内核参数,只需咨询对应的技术即可,最后就是验证系统是否能正常从SD启动,数据读写是否正常; 

    首先是君正平台,开发板是x2600e,SD NAND是采用CS256G-AOW;

    第一:制作SD启动卡

    君正的烧录工具支持将启动镜像烧录到SD NAND,先编译准备好启动镜像,然后按照下图顺序进行制作启动卡;

    制作SD启动卡
君正的烧录工具支持将启动镜像烧录到SD NAND,先编译准备好启动镜像,然后按照下图顺序进行制作启动卡

    制作SD启动卡
君正的烧录工具支持将启动镜像烧录到SD NAND,先编译准备好启动镜像,然后按照下图顺序进行制作启动卡

    制作SD启动卡
君正的烧录工具支持将启动镜像烧录到SD NAND,先编译准备好启动镜像,然后按照下图顺序进行制作启动卡

    制作SD启动卡
君正的烧录工具支持将启动镜像烧录到SD NAND,先编译准备好启动镜像,然后按照下图顺序进行制作启动卡

    制作SD启动卡
君正的烧录工具支持将启动镜像烧录到SD NAND,先编译准备好启动镜像,然后按照下图顺序进行制作启动卡

    第二:选择启动方式

    查询芯片手册得知启动方式的选择依据如下图

    CS创世 SD NAND在君正平台和RK平台的应用:选择启动方式
查询芯片手册得知启动方式的选择依据如下图

    再查看原理图如下:

    CS创世 SD NAND在君正平台和RK平台的应用:选择启动方式
查询芯片手册得知启动方式的选择依据原理图

    可知目前的电平组合是001,即选择的是SFC@PD06_3.3V(默认从SPI NAND FLASH启动),现在需要改为从SD启动,那么就要将BOOT_SET0即PD14接低电平,使得电平组合为000,然后就是查看PCB,找到PD14的gpio,再修改硬件将其接地即可;

    第三:验证SD启动

    CS创世 SD NAND在君正平台和RK平台的应用:验证SD启动

    通过上图可知,系统成功从SD NAND启动,然后使用一些简单的读写命令验证是否正常即可,一般而言只要能正常启动系统读写就没问题,因为启动过程中本身就已经包含了对SD进行读写。

    然后就是瑞芯微平台,开发板是RK3568,SD NAND采用CS256G-AOW,也采取相同步骤;

    第一:制作SD启动卡

    首先编译准备好镜像文件,并将其拷贝到windows端(可以将镜像放置共享目录下),然后打开瑞芯微的制作工具SDDiskTool,按照下图所示进行配置:

    CS创世 SD NAND在君正平台和RK平台的应用:制作SD启动卡

    CS创世 SD NAND在君正平台和RK平台的应用:制作SD启动卡

    CS创世 SD NAND在君正平台和RK平台的应用:制作SD启动卡

    正常来说制作过程是2~3分钟,但是也遇到过十分钟左右的,这个可能因SD NAND而异,但是只要没报错,就耐心等待制作完成;

    第二:选择启动方式

    由于咨询技术支持得到的答复是RK对于启动引导不开源,原理也是靠硬件选boot脚,然后在芯片手册上也没找到有关boot引脚配置的部分,所以说明在RK上我们不需要修改硬件,额外配置boot引脚来选择启动方式,后面在rockchip-common.h文件中找到了关于启动方式的优先顺序,如下图:

    CS创世 SD NAND在君正平台和RK平台的应用:选择启动方式

    因此只要启动时在卡槽检测到SD NAND,那么就会优先从SD启动;

    第三:验证SD启动

    CS创世 SD NAND在君正平台和RK平台的应用:验证SD启动

    CS创世 SD NAND在君正平台和RK平台的应用:验证SD启动

    从上面两张图中可以相互印证,系统成功从SD启动;

    启动卡的分区情况如下图:

    CS创世 SD NAND在君正平台和RK平台的应用:验证SD启动

    从mmcblk1p1至mmcblk1p6共6个分区,依次是uboot,misc,boot,recovery,backup和rootfs,前面5个分区一般存储特定数据,不建议用户将数据写入,而mmcblk1p6是根文件系统分区,存储所有系统文件、应用程序、用户数据等,进行用户操作时就是基于这个分区,因此进行读写测试或者存储用户数据建议在此分区进行。

    SD NAND-贴片式TF卡-贴片式SD卡-免费样品包邮-【雷龙发展】 - SD NAND,贴片式TF卡,贴片式SD卡,SPI NAND, PSLC NAND,存储芯片,闪存芯片https://www.longsto.com/分享一些使用的软件:

    串口工具:Windows下:MobaXterm;Ubuntu下:Minicom

    分析内核源码:sourceinsight4

    逻辑分析仪:ATK-Logic 或Acute TravelLogic Analyzer

    除了软件,硬件上的逻辑分析仪,示波器,万用表也可辅助调试验证。

    附件:

    CS创世 SD NAND在君正平台和RK平台的应用:参考例程附件