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 的内容是一样的。
6.6.2. SDMC 控制器初始化
在 SD/eMMC启动的过程中,首先要对控制器进行初始化,主要几个步骤:
Pinmux 配置
SDMC时钟频率初始化
SDMC内部 DMA 初始化
Reset SDMC(FIFO/DMA)
清除 SDMC内部中断,配置 DMA trigger threshold
6.6.3. 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
支持的工作电压
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 卡的配置
在进行卡的配置时,主机首先需要发送 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 的版本识别和配置
上述流程中,获取eMMC 相关信息的地方有两个,分别是发送 CMD9 读取 CSD 和 CMD8 读取 ext CSD。 通过读取的 CSD 数据,可以获取关于 eMMC 的详细版本信息,以及其他参数。
经过上述流程,eMMC 进行了初始化,并且进入传输模式,可以进行数据传输。
6.6.7. 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) 应该保持默认配置:
其中:
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)