NVMe-eMMC Bridge 芯片固件开发(六):SSD 通用概念与实现

概述

本文介绍 SSD 主控固件开发中的核心概念,结合 NVMe-eMMC Bridge 项目的实际代码实现,涵盖:

  • SMART 健康信息监控:寿命估计、读写统计、温度监控
  • 磨损均衡(Wear Leveling):eMMC 内置 FTL 与寿命预警
  • Disk Model Name 动态控制:运行时组装设备名称
  • Namespace 管理:多命名空间动态配置
  • 固件更新机制:NVMe Firmware Download/Commit 与 eMMC FFU

1. SMART 健康信息机制

1.1 SMART 信息架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌─────────────────────────────────────────────────────────────────────┐
│ SMART Information Framework │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
│ │ NVMe Host │───▶│ SMART Get Log │───▶│ Log Page │ │
│ │ (Get Log 02h) │ │ Page 02h │ │ Response │ │
│ └─────────────────┘ └──────────────────┘ └───────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ smart_data (RAM) │ │
│ │ ┌─────────────────┬─────────────────┬─────────────────────┐ │ │
│ │ │ critical_warning│ percentage_used │ power_on_hours │ │ │
│ │ │ temperature │ data_units_read │ data_units_written │ │ │
│ │ │ power_cycles │ host_read_cmds │ host_write_cmds │ │ │
│ │ └─────────────────┴─────────────────┴─────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ │ Timer更新 │ IO操作更新 │ 初始化读取 │
│ ▼ ▼ ▼ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────────┐ │
│ │smart_info_ │ │smart_info_ │ │smart_info_ │ │
│ │update_by_timer │ │update_by_ops │ │init │ │
│ └────────────────┘ └────────────────┘ └────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ eMMC Reserved Block Storage │ │
│ │ (掉电持久化 SMART 数据) │ │
│ └────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

1.2 SMART 数据结构定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// smart_info.h - NVMe SMART 健康信息数据结构
typedef struct {
u32 available_spare:8; // 可用备用空间百分比
u32 available_space_threshold:8; // 备用空间阈值
u32 critical_warning_and_temperature; // 关键警告 + 复合温度
u32 percentage_used; // 寿命使用百分比

// 128-bit 计数器(支持超大容量统计)
u64 data_units_read_low; // 读取数据单元(低64位)
u64 data_units_read_high;
u64 data_units_written_low; // 写入数据单元
u64 data_units_written_high;
u64 host_read_commands_low; // 主机读命令计数
u64 host_read_commands_high;
u64 host_write_commands_low; // 主机写命令计数
u64 host_write_commands_high;
u64 controller_busy_time_low; // 控制器忙时间(分钟)
u64 controller_busy_time_high;
u64 power_cycles_low; // 上电次数
u64 power_cycles_high;
u64 power_on_hours_low; // 上电小时数
u64 power_on_hours_high;
u64 unsafe_shutdowns_low; // 非安全关机次数
u64 unsafe_shutdowns_high;
u64 media_and_data_integrity_errors_low; // 介质错误
u64 media_and_data_integrity_errors_high;
u64 number_of_error_information_log_entries_low;
u64 number_of_error_information_log_entries_high;
u32 warning_composite_temperature_time;
} smart_health_info_data_t;

1.3 SMART 数据更新流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
┌─────────────────────────────────────────────────────────────────┐
│ SMART 数据更新机制 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Timer 中断触发更新 │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────────┐ │ │
│ │ │ 1小时定时 │───▶│power_on_ │───▶│ 运行时间 +1 │ │ │
│ │ │ │ │hours +1 │ │ │ │ │
│ │ └───────────┘ └───────────┘ └───────────────┘ │ │
│ │ │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────────┐ │ │
│ │ │ 1分钟定时 │───▶│controller_│───▶│ 忙时间累计 │ │ │
│ │ │ (忙状态) │ │busy +1 │ │ │ │ │
│ │ └───────────┘ └───────────┘ └───────────────┘ │ │
│ │ │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────────┐ │ │
│ │ │ 1小时定时 │───▶│ Writeback │───▶│ 持久化到eMMC │ │ │
│ │ │ │ │ to eMMC │ │ │ │ │
│ │ └───────────┘ └───────────┘ └───────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ IO 操作触发更新 │ │
│ │ │ │
│ │ NVMe Read ──▶ data_units_read += block_count │ │
│ │ host_read_commands++ │ │
│ │ │ │
│ │ NVMe Write ─▶ data_units_written += block_count │ │
│ │ host_write_commands++ │ │
│ │ │ │
│ │ Power On ───▶ power_cycles++ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

1.4 核心实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// smart_info.c - SMART 信息初始化(从 eMMC 加载持久化数据)
void smart_info_init(smart_rw_emmc_p smart_rw, smart_health_info_data_p smart_data)
{
smart_rw->rw_opt = READ_EMMC;
smart_rw->rw_size = EMMC_BLOCK_SIZE;
smart_rw->addr_ram = smart_rw->temp_buffer;

// 选择 eMMC 保留块地址(根据配置选择不同偏移)
if (fw_param.emmc_resv_blk_mod)
smart_rw->addr_offset = EMMC_RESERVE_BLOCK4_OFFSET;
else
smart_rw->addr_offset = EMMC_RESERVE_BLOCK2_OFFSET;

// 从 eMMC 读取 SMART 数据
smart_info_emmc_rw(smart_rw, smart_data);
}

// Timer 触发的 SMART 更新
void smart_info_update_by_timer(timer_flags_p timer_flags,
smart_rw_emmc_p smart_rw,
smart_health_info_data_p smart_data)
{
// 定时写回 eMMC(1小时周期)
if (timer_flags->smart_info.smartinfo_update_emmc_flag == 1) {
timer_flags->smart_info.smartinfo_update_emmc_flag = 0;
smart_info_writeback(smart_rw, smart_data);
}
// 运行小时数更新(1小时周期)
if (timer_flags->smart_info.smartinfo_power_on_hour_flag == 1) {
timer_flags->smart_info.smartinfo_power_on_hour_flag = 0;
smart_data->power_on_hours_low += 1;
}
// 忙时间更新(1分钟周期,在控制器忙时)
if (timer_flags->smart_info.smartinfo_busy_time_flag == 1) {
timer_flags->smart_info.smartinfo_busy_time_flag = 0;
smart_data->controller_busy_time_low += 1;
}
}

// IO 操作触发的 SMART 更新
void smart_info_update_by_ops(u8 info_id, u16 cnt, smart_health_info_data_p smart_data)
{
switch (info_id) {
case ID_DATA_UNIT_READ:
smart_data->data_units_read_low += cnt; // 单位:1000 blocks
break;
case ID_DATA_UNIT_WRITE:
smart_data->data_units_written_low += cnt;
break;
case ID_HOST_READ_CMD:
smart_data->host_read_commands_low += cnt;
break;
case ID_HOST_WRITE_CMD:
smart_data->host_write_commands_low += cnt;
break;
case ID_POWER_CYCLE:
smart_data->power_cycles_low += cnt;
break;
case ID_CRITICAL_WARN:
smart_data->critical_warning_and_temperature |= cnt << 2;
break;
case ID_PERCENTAGE_USED:
smart_data->percentage_used = cnt << 8;
break;
case ID_MEDIA_DATA_ERROR:
smart_data->media_and_data_integrity_errors_low += cnt;
break;
}
}

2. 磨损均衡与寿命监控

2.1 eMMC 内部磨损均衡

NVMe-eMMC Bridge 不直接实现 FTL(闪存转换层),磨损均衡由 eMMC 内部控制器完成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
┌────────────────────────────────────────────────────────────────────┐
│ eMMC 磨损均衡架构 │
├────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ NVMe Host │ │
│ └────────────────────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ NVMe-eMMC Bridge (本项目) │ │
│ │ • LBA 地址直传给 eMMC │ │
│ │ • 不维护映射表,无 GC 开销 │ │
│ │ • 通过 EXT_CSD 读取寿命信息 │ │
│ └────────────────────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ eMMC 内部控制器 │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ FTL 层 │ │ │
│ │ │ • 逻辑-物理地址映射 │ │ │
│ │ │ • 动态磨损均衡 (Dynamic WL) │ │ │
│ │ │ • 静态磨损均衡 (Static WL) │ │ │
│ │ │ • 坏块管理 + 备用块 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ NAND Flash │ │ │
│ │ │ Block 0 Block 1 Block 2 ... Block N │ │ │
│ │ │ [PE:100] [PE:50] [PE:200] [PE:150] │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘

PE = Program/Erase 擦写次数

2.2 寿命信息获取

从 eMMC EXT_CSD 寄存器读取寿命估计值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// emmc_support_functions.c - eMMC 寿命查询
void emmc_features_query(u8 card_slot)
{
// 初始化温度信息
init_capability_temperature(card_slot);

// 检查 PRE_EOL(预警寿命结束)
// EXT_CSD[267]: PRE_EOL_INFO
// 0x00 = 未定义
// 0x01 = 正常
// 0x02 = 消耗警告(80%)
// 0x03 = 紧急(90%+)
if (card_info.ext_csd[267] == 0x03 ||
card_info.ext_csd[268] == 0x0B ||
card_info.ext_csd[269] == 0x0B) {
card_info.crit_warn[card_slot] = 1; // 设置关键警告
}

// DEVICE_LIFE_TIME_EST_TYP_A [268]: SLC 寿命估计
// DEVICE_LIFE_TIME_EST_TYP_B [269]: MLC 寿命估计
// value * 10 = 已使用寿命百分比
u8 emmc_life_used_value = card_info.ext_csd[268] | card_info.ext_csd[269];

// 值范围 0x01~0x0B:
// 0x01 = 0%~10% 已使用
// 0x0B = 100% 已使用(或超过)
card_info.perc_used[card_slot] = 10 * (emmc_life_used_value > 0 ?
emmc_life_used_value - 1 : 1);

// 读取 eMMC 固件版本
fn_memcpy(&card_info.firmware_version[card_slot][0],
&card_info.ext_csd[254], 8);
}

2.3 寿命信息报告到 SMART

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 将 eMMC 寿命映射到 NVMe SMART Percentage Used
void report_percentage_used_to_smart()
{
u8 first_card_id = (card_num == 1) ? 1 : 0;

// 取两张卡中较大的磨损值
u8 max_perc_used = (card_info.perc_used[0] > card_info.perc_used[1]) ?
card_info.perc_used[0] : card_info.perc_used[1];

smart_info_update_by_ops(ID_PERCENTAGE_USED, max_perc_used, &smart_data);

// 如果任一卡有预警,设置 critical warning
if (card_info.crit_warn[0] || card_info.crit_warn[1]) {
smart_info_update_by_ops(ID_CRITICAL_WARN, 1, &smart_data);
}
}

3. Disk Model Name 动态控制

3.1 动态组装架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌───────────────────────────────────────────────────────────────────────┐
│ Model Name 动态组装机制 │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ fw_param.model_number_field_enable (位掩码控制) │
│ ┌───┬───┬───┬───┬───┬───┬───┬───┐ │
│ │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
│ └───┴───┴───┴───┴───┴───┴───┴───┘ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ └── VEN_NAME (厂商名称) │
│ │ │ │ │ │ │ └────── OEM_NAME (OEM 定制) │
│ │ │ │ │ │ └────────── EMMC_MID (eMMC 制造商) │
│ │ │ │ │ └────────────── EMMC_PNM (eMMC 产品名) │
│ │ │ │ └────────────────── EMMC_FW_VER (eMMC 固件版本) │
│ │ │ └────────────────────── EMMC_CAPACITY (容量) │
│ │ └────────────────────────── POSTFIX (后缀字符串) │
│ └────────────────────────────── Reserved │
│ │
│ 组装示例 (model_number_field_enable = 0x3D): │
│ ┌─────────┬─────────┬─────────┬─────────┬─────────┐ │
│ │ BAYHUB │ Samsung │ HBG4e2 │ 256GB │ SSD │ = 39字符 │
│ │ (VEN) │ (OEM) │ (PNM) │ (CAP) │ (POST) │ │
│ └─────────┴─────────┴─────────┴─────────┴─────────┘ │
│ │
│ NVMe Identify Controller 报告: "BAYHUB Samsung HBG4e2 256GB SSD" │
│ │
└───────────────────────────────────────────────────────────────────────┘

3.2 动态组装实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// system.c - Model Name 动态组装
static void model_name_init()
{
// 方式1:如果配置文件预设了固定 model_number,直接使用
if (*(u32 *)(&fw_param.model_number[0]) != 0) {
fn_memcpy((byte *)BBS_MODEL_NUMBER_ADDR,
(byte *)fw_param.model_number, 40);
return;
}

// 方式2:根据 field_enable 位掩码动态组装
byte mn_str[40] = {0};
mn_field_t mn_field = {0};

// 检查各字段使能位,依次组装
if (assert_mn_field_enable(MN_BIT_ENABLE_MASK_VEN_NAME)) {
// 填充厂商名称: "BAYHUB "
mn_field.ven_len = create_mn_ven_str(mn_str + mn_field.total_len);
mn_field.total_len += mn_field.ven_len;
}

if (assert_mn_field_enable(MN_BIT_ENABLE_MASK_OEM_NAME)) {
// 填充 OEM 定制名称
mn_field.oem_len = create_mn_oem_str(mn_str + mn_field.total_len);
mn_field.total_len += mn_field.oem_len;
}

if (assert_mn_field_enable(MN_BIT_ENABLE_MASK_EMMC_MID)) {
// 填充 eMMC 制造商 ID (从 CID 寄存器读取)
mn_field.emmc_mid_len = create_mn_card_manufactid_str(mn_str + mn_field.total_len);
mn_field.total_len += mn_field.emmc_mid_len;
}

if (assert_mn_field_enable(MN_BIT_ENABLE_MASK_EMMC_PNM)) {
// 填充 eMMC 产品名称 (从 CID 寄存器读取)
mn_field.emmc_pnm_len = create_mn_card_productname_str(mn_str + mn_field.total_len);
mn_field.total_len += mn_field.emmc_pnm_len;
}

if (assert_mn_field_enable(MN_BIT_ENABLE_MASK_EMMC_CAPACITY)) {
// 填充容量字符串: "128GB"、"256GB" 等
mn_field.emmc_capacity_len = create_mn_card_capacity_str(mn_str + mn_field.total_len);
mn_field.total_len += mn_field.emmc_capacity_len;
}

if (assert_mn_field_enable(MN_BIT_ENABLE_MASK_POSTFIX)) {
// 填充后缀: "SSD"、"NVMe" 等
mn_field.postfix_len = create_mn_postfix_str(mn_str + mn_field.total_len);
mn_field.total_len += mn_field.postfix_len;
}

// 溢出检测:NVMe 规范限制 40 字节
if (mn_field.total_len > 40) {
LOG(ERROR, LOG_ERROR_STR, MODEL_NAME_OVERFLOW);
return;
}

// 写入硬件寄存器
fn_memcpy((byte *)BBS_MODEL_NUMBER_ADDR, mn_str, mn_field.total_len);
}

// 辅助函数:从 eMMC CID 寄存器读取制造商名称
static u8 create_mn_card_manufactid_str(byte *str)
{
byte first_card_id = (card_num == 1) ? 1 : 0;
u8 mid = card_info.cid[first_card_id].mid; // Manufacturer ID

// 常见 eMMC 制造商 ID 映射
switch (mid) {
case 0x13: fn_strcpy(str, "Micron "); return 7;
case 0x15: fn_strcpy(str, "Samsung "); return 8;
case 0x45: fn_strcpy(str, "SanDisk "); return 8;
case 0x90: fn_strcpy(str, "Hynix "); return 6;
case 0xFE: fn_strcpy(str, "Toshiba "); return 8;
default: fn_strcpy(str, "Unknown "); return 8;
}
}

4. Namespace 管理

4.1 多命名空间架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
┌────────────────────────────────────────────────────────────────────────┐
│ Namespace 动态配置架构 │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Namespace 配置方式 │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ DEFAULT_SINGLE_NS : 两张 eMMC 合并为单命名空间 │ │
│ │ DEFAULT_DUAL_NS : 两张 eMMC 各自独立命名空间 │ │
│ │ DEFAULT_HIDE_NS : 隐藏指定 eMMC 卡 │ │
│ │ DYNAMIC_HIDE_NS : BIOS 运行时动态配置 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ DYNAMIC_HIDE_NS 使用场景: │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ BIOS Stage ┌─────────────────────────────┐ │ │
│ │ │ │ BBS 0x80 寄存器 (Stick Reg) │ │ │
│ │ │ ① 检测双卡容量 │ [7:0] Namespace 配置值 │ │ │
│ │ │ │ 0xAA = 双命名空间 │ │ │
│ │ ▼ │ 0x55 = 单命名空间合并 │ │ │
│ │ ② 决定 Namespace 配置 ────▶│ 0x11 = 隐藏 eMMC0 │ │ │
│ │ │ │ 0x22 = 隐藏 eMMC1 │ │ │
│ │ │ ③ 写入 BBS 0x80 │ 0x00 = 隐藏全部 │ │ │
│ │ │ └─────────────────────────────┘ │ │
│ │ ▼ │ │
│ │ ④ 发送 CC.EN ────▶ FW 读取 BBS 0x80 配置 Namespace │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ⑤ F12 显示磁盘(正确容量) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ OS Stage (Windows/Linux) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ OS 看到正确的 Namespace 配置 │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘

4.2 Namespace 配置实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// namespace.c - Namespace 动态映射
static void namespace_mapping_init()
{
ns_emmc_map.namespace_class = fw_param.namespace_class;
ns_emmc_map.emmc_num = get_card_num();

// 读取 BIOS 设置的寄存器值
ns_emmc_map.bbs_reg_val = (get_reg(BAYBRIDGE_NVME_CONTROLLER_BASE, 0x4C) >> 24) & 0xFF;

switch (ns_emmc_map.emmc_num) {
case 2: // 双卡配置
if (ns_emmc_map.namespace_class == DYNAMIC_HIDE_NS) {
switch (ns_emmc_map.bbs_reg_val) {
case ALL_CARD_AS_SINGLE_NS: // 0x55
ns_emmc_map.case_id = DOUBLE_EMMC_TOTAL_NS;
break;
case DUAL_CARD_AS_DUAL_NS: // 0xAA
ns_emmc_map.case_id = DOUBLE_EMMC_DOUBLE_NS;
break;
case DUAL_CARD_HIDE_EMMC0: // 0x11
ns_emmc_map.case_id = DOUBLE_EMMC_HIDE_NS0;
break;
case DUAL_CARD_HIDE_EMMC1: // 0x22
ns_emmc_map.case_id = DOUBLE_EMMC_HIDE_NS1;
break;
case ALL_CARD_HIDE_ALL_NS: // 0x00
ns_emmc_map.case_id = DOUBLE_EMMC_NO_NS;
break;
case BBS_0X80_DEFAULT:
// BIOS 未设置,等待配置
ns_emmc_map.case_id = WAIT_CFG_NS;
while (poll_ns_change() != 0); // 轮询等待 BIOS 设置
break;
}
}
break;
// ... 单卡情况处理
}
}

// Modern Standby 恢复时从 eMMC 恢复 Namespace 配置
void restore_dynamic_ns_from_modern_standby()
{
u32 buffer[128];
u32 bbs_reg_val;

// 只处理动态 Namespace 模式
if (ns_emmc_map.namespace_class != DYNAMIC_HIDE_NS)
return;

// 检查当前寄存器值,如果非默认则跳过(表示已由 BIOS 设置)
bbs_reg_val = (get_reg(BAYBRIDGE_NVME_CONTROLLER_BASE, 0x4C) >> 24) & 0xFF;
if (bbs_reg_val != BBS_0X80_DEFAULT)
return;

// 从 eMMC 保留块读取备份的配置
emmc_usersblock_readwrite(buffer, EMMC_RESERVE_BLOCK3_OFFSET,
EMMC_BLOCK_SIZE, READ_EMMC);
bbs_reg_val = buffer[0];

// 恢复有效的 Namespace 配置到寄存器
if (bbs_reg_val == DUAL_CARD_HIDE_EMMC0 ||
bbs_reg_val == DUAL_CARD_HIDE_EMMC1 ||
bbs_reg_val == DUAL_CARD_AS_DUAL_NS ||
bbs_reg_val == ALL_CARD_AS_SINGLE_NS) {
set_reg(BAYBRIDGE_NVME_CONTROLLER_BASE, 0x4C, 0xFF000000, bbs_reg_val << 24);
}
}

5. 固件更新机制

5.1 固件更新架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
┌──────────────────────────────────────────────────────────────────────────┐
│ 固件更新流程架构 │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ NVMe Admin Commands │ │
│ │ ┌──────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ Firmware Image │ │ Firmware Commit │ │ │
│ │ │ Download (07h) │ │ (10h) │ │ │
│ │ │ • 分块传输 FW 数据 │ │ • 验证 FW 完整性 │ │ │
│ │ │ • 写入目标 Slot │ │ • 激活新固件 Slot │ │ │
│ │ └──────────────────────┘ └──────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 存储目标 (Firmware Slots) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Slot 1 │ │ Slot 2 │ │ Slot 3 │ │ │
│ │ │ eMMC Boot │ │ eMMC Boot │ │ SPI Flash │ │ │
│ │ │ Partition 1 │ │ Partition 2 │ │ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Slot 4 │ │ Slot 5 │ ← FFU (Field Firmware │ │
│ │ │ eMMC0 FFU │ │ eMMC1 FFU │ Update for eMMC chip) │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ FW Header 结构 (512 Bytes) │ │
│ │ │ │
│ │ Offset Field Description │ │
│ │ ────────────────────────────────────────────────────────── │ │
│ │ DWORD0 FW Size + Parity 固件大小 + 奇偶校验 │ │
│ │ DWORD1~7 Reserved 保留 │ │
│ │ DWORD32 Target Slot [7:4] 目标 Slot 编号 │ │
│ │ DWORD33+ SPI Config SPI Flash 配置参数 │ │
│ │ ... FW Binary 固件二进制数据 │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────┘

5.2 固件下载流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
┌──────────────────────────────────────────────────────────────────┐
│ Firmware Download 状态机 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ IDLE │◀────────────────────────────────────────────┐ │
│ └──────┬──────┘ │ │
│ │ 收到 FW Download (offset=0) │ │
│ ▼ │ │
│ ┌─────────────────────────────┐ │ │
│ │ PARSE_HEADER │ │ │
│ │ • 解析 FW Size (DWORD0) │ │ │
│ │ • 奇偶校验 Header │ │ │
│ │ • 提取目标 Slot ID │ │ │
│ └──────────────┬──────────────┘ │ │
│ │ Header 有效 │ │
│ ▼ │ │
│ ┌─────────────────────────────┐ │ │
│ │ PREPARE_TARGET │ │ │
│ │ • Slot 1/2: 切换 eMMC 分区 │ │ │
│ │ • Slot 3: 擦除 SPI Flash │ │ │
│ │ • Slot 4/5: 初始化 FFU │ │ │
│ └──────────────┬──────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────────────────────┐ │ │
│ │ DOWNLOADING │◀─────────┐ │ │
│ │ • 接收 4KB 数据块 │ │ │ │
│ │ • 写入目标存储 │ │ 还有更多数据 │ │
│ │ • 更新 Offset │──────────┘ │ │
│ └──────────────┬──────────────┘ │ │
│ │ Offset == FW Size │ │
│ ▼ │ │
│ ┌─────────────────────────────┐ │ │
│ │ WAIT_COMMIT │ │ │
│ │ • 等待 FW Commit 命令 │ │ │
│ └──────────────┬──────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────────────────────┐ │ │
│ │ COMMITTED │─────────────────────────────┘ │
│ │ • 验证完整性 │ │
│ │ • 设置激活 Slot 寄存器 │ │
│ │ • 等待 Controller Reset │ │
│ └─────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘

5.3 核心实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// firmware_image_download.c - FW Header 校验
static boolean check_fw_header(u32 offset, u32 *completion_status)
{
// 读取 DWORD0: FW Size + Parity
global_fw_update_data.firmware_head_dword0 = global_fw_update_data.buffer[0];

// 空值检查(未烧录或擦除状态)
if (global_fw_update_data.firmware_head_dword0 == 0 ||
global_fw_update_data.firmware_head_dword0 == 0xFFFFFFFF) {
*completion_status = 0x107; // Invalid FW Image
return FALSE;
}

// 奇偶校验(4字节异或)
if (parity_check(1, (u32)&global_fw_update_data.firmware_head_dword0) != 0) {
*completion_status = 0x107;
return FALSE;
}

// 提取 FW Size(低24位)
global_fw_update_data.size = global_fw_update_data.firmware_head_dword0 & 0x00FFFFFF;

// 提取目标 Slot ID(DWORD32 的高4位)
global_fw_update_data.slot_id = (global_fw_update_data.buffer[32] >> 24) & 0x0F;

// 首次下载时清除 DWORD0,等待 Commit 时写回
if (offset == 0) {
global_fw_update_data.buffer[0] = 0x0;
global_fw_update_data.firmware_data_need_validation = 1;
}

return TRUE;
}

// firmware_commit.c - FW Commit 处理
void firmware_commit_process_update(command_p command)
{
u16 completion_status = 0;
u32 fw_slot = command->firmware_commit_dw10.firmware_slot;

// Slot 0 表示让控制器自动选择
if (fw_slot == 0 && global_fw_update_data.slot_id != 0) {
fw_slot = global_fw_update_data.slot_id;
}

// Slot 4/5: eMMC FFU
#if BB_FFU_SUPPORTED
if ((fw_slot == 4 || fw_slot == 5) && global_emmc_ffu_data.emmc_ffu_state_flg > 0) {
emmc_ffu_commit_process(command, completion_status);
return;
}
#endif

// 验证 FW 数据完整性
if (global_fw_update_data.firmware_data_need_validation) {
// 检查下载大小是否匹配
if (!global_fw_update_data.size ||
global_fw_update_data.size + FW_HEAD_SIZE != ((global_fw_update_data.offset + 1) << 2)) {
completion_status = 0x107; // Invalid FW Image
goto exit;
}

// 根据 Slot 写入 DWORD0 完成下载
if (fw_slot == 3) {
// SPI Flash
set_pinshare_mode(MODE_SPI);
u32 *dest = (u32 *)BAYBRIDGE_EEPROM_BASE;
*dest = global_fw_update_data.firmware_head_dword0;
} else if (fw_slot == 1 || fw_slot == 2) {
// eMMC Boot Partition
commit_firmware_update(fw_slot, global_fw_update_data.first_block,
0, sizeof(global_fw_update_data.first_block), 0);
}
}

// 设置激活 Slot 寄存器
if (completion_status == 0) {
u32 value = BAYBRIDGE_REG_FOR_ACTIVATED_SLOT & 0xFFFFFFFC;
BAYBRIDGE_REG_FOR_ACTIVATED_SLOT = value | fw_slot;
}

exit:
fn_memset(&global_fw_update_data, 0, sizeof(global_fw_update_data));
send_complete(command->command_identifier, 0, 0, completion_status);
}

6. Get Log Page 实现

6.1 支持的 Log Page 类型

Log Page ID 名称 描述
01h Error Information 错误信息日志
02h SMART / Health 健康状态信息
03h Firmware Slot 固件槽位信息
05h Commands Supported 支持的命令集
C0h Vendor Specific 厂商自定义(读取配置参数)

6.2 Log Page 处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// get_log_page.c - Log Page 分发处理
void get_log_page_process(command_p command)
{
u32 bytes_to_return = ((command->get_log_page_dw10.number_of_dwords_lower & 0xFFF) + 1) << 2;

// 检查 DMA 资源可用性
if (emmc_firmware_executing_task_completion != 1) {
// 暂存命令,等待 DMA 释放
store_admin_command(command, FUNC_TYPE_GET_LOGPAGE);
return;
}

fn_memset_4bytes((void *)BAYBRIDGE_DATA_BUFFER, 0, 0x1000);

switch (command->get_log_page_dw10.log_page_identifier) {
case 0x01: // Error Information
error_information_process(command, bytes_to_return);
break;

case 0x02: // SMART / Health Information
smart_health_information_process(command, bytes_to_return);
break;

case 0x03: // Firmware Slot Information
firmware_slot_information_process(command, bytes_to_return);
break;

case 0x05: // Commands Supported and Effects
commands_supported_and_effects(command, bytes_to_return);
break;

case 0xC0: // Vendor Specific: Read FW Parameters
read_out_header_parameter_process(command, bytes_to_return);
break;

default:
send_complete(command->command_identifier, 0, 0,
DO_NOT_RETRY | SCT_GENERIC_COMMAND_STATUS | SC_INVALID_FIELD_IN_COMMAND);
break;
}
}

// SMART Health Information 响应
static void smart_health_information_process(command_p command, u32 bytes_to_return)
{
smart_health_information_log_t info = {0};

// 填充 SMART 数据
info.critical_warning_and_temperature = smart_data.critical_warning_and_temperature;
info.percentage_used = smart_data.percentage_used;

// 填充可用空间百分比
info.critical_warning_and_temperature |= 0x64 << 24; // available_space = 100%
info.percentage_used |= 0x0A; // available_space_threshold = 10%

// 读写统计(需要字节序转换)
info.data_units_read_low = leon2_cpu_64bits_swap(smart_data.data_units_read_low);
info.data_units_written_low = leon2_cpu_64bits_swap(smart_data.data_units_written_low);
info.host_read_commands_low = leon2_cpu_64bits_swap(smart_data.host_read_commands_low);
info.host_write_commands_low = leon2_cpu_64bits_swap(smart_data.host_write_commands_low);
info.power_cycles_low = leon2_cpu_64bits_swap(smart_data.power_cycles_low);
info.power_on_hours_low = leon2_cpu_64bits_swap(smart_data.power_on_hours_low);

// DMA 传输响应数据
fn_memcpy_4bytes((void *)BAYBRIDGE_DATA_BUFFER, &info, bytes_to_return);
dma_data_transfer(command->prp.prp_entry1, command->prp.prp_entry2, bytes_to_return, 1, 1);
send_complete(command->command_identifier, 0, 0, 0);
}

7. 要点总结

7.1 SMART 信息实现要点

要点 说明
数据持久化 SMART 数据存储在 eMMC 保留块,掉电不丢失
定时更新 使用硬件 Timer 周期性更新运行时间和忙时间
IO 统计 每次读写操作实时更新统计计数器
大数值处理 128-bit 计数器支持 EB 级别数据量统计

7.2 磨损均衡相关

概念 Bridge 芯片的实现方式
FTL 层 不实现,由 eMMC 内部处理
磨损均衡 透传给 eMMC,读取 EXT_CSD 获取寿命信息
寿命估计 EXT_CSD[268/269] → SMART Percentage Used
预警机制 EXT_CSD[267] == 0x03 → Critical Warning

7.3 Model Name 动态控制

  • 位掩码设计:通过 model_number_field_enable 灵活控制显示字段
  • 运行时组装:从 eMMC CID/EXT_CSD 读取信息,动态拼接
  • OEM 定制:支持客户预设字符串覆盖自动检测值

7.4 固件更新安全性

机制 作用
奇偶校验 DWORD0 校验防止数据损坏
分步写入 先写数据,Commit 时才写 DWORD0
多 Slot 设计 支持回退到备份固件
FFU 支持 可在线更新 eMMC 芯片固件

8. 参考规范

  • NVMe Base Specification 1.4:Get Log Page, Firmware Update
  • eMMC 5.1 (JEDEC JESD84-B51):EXT_CSD Device Life Time 字段
  • SPARC LEON2:32-bit Timer 实现