6.6. SD/eMMC 启动

芯片有三个 SDMC 控制器,每一个控制器的设计使用目的各有不同:

控制器

说明

SDMC0

设计对接 eMMC

SDMC1

设计对接 SD 卡

SDMC2

设计对接其他 SDIO 设备,如 SDIO WiFi

BROM 程序只会尝试从 SDMC0 和 SDMC1 进行启动,不会检查 SDMC2 接口。

eMMC:

  • 支持 eMMC1.2 ~eMMC 5.1

  • 默认使用 26MHz 和4线模式读取数据,如果读取数据过程失败,则尝试 6MHz 和 1线模式

  • 从 UDA 分区启动,不支持从 eMMC 的两个 Boot partition 分区启动

SD Card:

  • 支持 SD 1.0 以及以后的版本

  • 工作电压 3.3V

  • 默认使用 25MHz 和4线模式启动,如果读取数据过程失败,则尝试 6MHz 和 1线模式

  • 主要用于开发者调试、工厂量产和升级

6.6.1. 分区和启动流程

固件在 SD/eMMC 中统一使用 GPT (GUID Partition Table) 的方式进行分区存储,默认的存储分区排列如下表。

分区

用途

boot-spl0

u-boot-spl.bin

boot-spl1

u-boot-spl.bin

u-boot

u-boot.bin

kernel

zImage/kernel.itb/…

rootfs

Rootfs.ext4/…

这里只关心 BROM 涉及的前面两个分区,后续的分区以及内容可以根据不同的应用进行规划。 前面两个分区用来保存第一级引导程序及其备份程序,大小固定为每个分区 128KB。

区域

大小/位置

GPT Header

17KB(LBA0 ~ LBA33)

Partition0

128KB(LBA34 ~ LBA289)

Partition1

128KB(LBA290 ~ LBA545)

BROM 尝试从 SD/eMMC 启动时,首先从 LBA34 的位置读取数据尝试启动,如果失败,则再尝试从 LBA290 的位置读取数据。 这里 Logic Block 大小512 Byte。

前面两个分区 boot-spl0, boot-spl1 的内容是一样的。

../../_images/mmc_boot_read_spl.png

图 6.3 SD/eMMC 读取启动固件

6.6.2. SDMC 控制器初始化

在 SD/eMMC启动的过程中,首先要对控制器进行初始化,主要几个步骤:

  1. Pinmux 配置

  2. SDMC时钟频率初始化

  3. SDMC内部 DMA 初始化

  4. Reset SDMC(FIFO/DMA)

  5. 清除 SDMC内部中断,配置 DMA trigger threshold

6.6.3. SD/eMMC 类型识别

在进行数据读取前,首先要识别当前插入的卡的类型。

../../_images/mmc_boot_identification.png

图 6.4 SD/eMMC 的类型识别

在卡识别阶段,设置频率为 400KHz,1-bit 模式。

区分 SD 卡和 eMMC 时,可以在 IDLE 状态下,通过发送 CMD8 的方式进行测试。从 SD v2.0 开始, SD 卡都支持 CMD8 (SD_CMD_SEND_IF_COND),而在 IDLE 状态下 eMMC 是不响应该命令的,因此通过测试则表明该卡为 SD。

对于 eMMC,在上电后进入 IDLE 状态(由于没有启用 Boot partition,直接进入 IDLE 状态), 在该状态下卡响应 CMD1(MMC_CMD_SEND_OP_COND),而 SD 卡是不响应该命令的。

因此通过在 IDLE 状态发送不同命令,可以区分具体是什么类型的卡。

6.6.4. SD 卡版本的识别

SD 卡识别需要获取的信息包括:

  • 卡的版本类型

  • 卡的容量类型 High Capacity or Standard Capacity

  • 支持的工作电压

../../_images/mmc_sd_cap_ident.png

图 6.5 SD 卡能力的识别

ACMD41 (APP_SEND_OP_COND) 是 SD 卡开始初始化的命令,通过该命令让 SD 开始初始化, 并且读取关于 SD 卡的OCR(Operation Conditions Register)信息。

发送 ACMD41 命令时,需要将参数中的 HCS(Host Capacity Support) 比特设置为1, 表示 Host 支持SDHC 或 SDXC。

ACMD41 命令需要重复发送,轮询 SD 卡是否初始化完成。通过读取 Response 中的 OCR 寄存器 Busy 比特位判断是否完成初始化,值为1表示已经完成初始化。

最后通过 OCR 寄存器的 CCS(Card Capacity Status) 比特位来判断该卡是否为 SDHC 或 SDXC.

由于 BROM 不会使用 UHS-1 的模式进行工作,因此不需要关心其他信息。

6.6.5. SD 卡的配置

../../_images/mmc_sd_config_flow.png

图 6.6 SD 卡配置流程

在进行卡的配置时,主机首先需要发送 CMD2(ALL_SEND_CID),读取卡的唯一 ID, 并且让卡进入 Identification 状态。

然后主机发送 CMD3(SEND_RELATIVE_ADDR) 命令,询问卡的地址 RCA(Relative Card Address), 该地址在后续的传输模式中需要使用,用来寻址要进行操作的卡。

发送 CMD9 (SEND_CSD),让卡发送 CSD(Card Specific Data)。CSD 提供了如何访问 SD 卡的信息, 可以读取到关于 Read block length 相关的信息。

发送 CMD7(SELECT_CARD) 命令,通过指定 RCA 来选中具体的 SD 卡,并且让 SD 卡进入传输模式。

发送 CMD51(APP_SEND_SCR) 命令,读取卡的 SCR(SD Configuration Register) 。 SCR 包含卡实现的Spec 版本,数据总线位宽等信息。

通过上述配置和命令读取的信息,可以确定当前 SD 卡的确切版本,以及数据位宽信息。

6.6.6. eMMC 的版本识别和配置

../../_images/mmc_emmc_version_ident.png

图 6.7 eMMC 的版本识别和配置

上述流程中,获取eMMC 相关信息的地方有两个,分别是发送 CMD9 读取 CSD 和 CMD8 读取 ext CSD。 通过读取的 CSD 数据,可以获取关于 eMMC 的详细版本信息,以及其他参数。

经过上述流程,eMMC 进行了初始化,并且进入传输模式,可以进行数据传输。

6.6.7. SD/eMMC 数据的读取

../../_images/mmc_data_read_flow.png

图 6.8 SD/eMMC 数据读取流程

BROM 在读取 SD/eMMC 数据时,以 Block 为单位,统一使用 READ_MULTI_BLOCK 命令进行读取。 读取完毕后发送 STOP_TRANSMISSION 结束读取动作。

在读取数据的策略上,采取兼容性较好的方式进行。

对于 SD 卡,首先通过 400KHz 和 1 线模式进行识别和配置;数据传输时首先使用 SD Legacy 的方式, 25MHz 和 4 线模式尝试读取;如果读取失败,则转为 6MHz 和 1 线模式进行读取。如果都失败则放弃。

对于 eMMC,首先通过 400KHz 和 1 线模式进行识别和配置;数据传输时首先使用 MMC HS 的方式, 26MHz 和 4 线模式尝试读取;如果读取失败,则转为 6MHz 和 1 线模式进行读取。如果都失败则放弃。

为了实现的简单和兼容性上的考虑,其他更快的模式并没有使用。

6.6.8. eMMC 启动的烧录配置

eMMC 烧录时需要确认下列Ext CSD 配置。 PARTITION_CONFIG(Ext CSD[179) 应该保持默认配置:

../../_images/emmc_ext_csd_cfg.png

其中:

  • BOOT_ACK: 0x0, No boot acknowledge send(Default)

  • BOOT_PARTITION_ENABLE: 0x0, Device not boot enabled(Default)

  • PARTITION_ACCESS: 0x0, No access to boot partition(Default)