CSR升级介绍
什么是CSR?
CSR(Component Self-description Record) 全称"硬件自描述记录",是一种存储在EEPROM芯片中的硬件配置数据文件。
通俗解释
单板上的每个硬件器件(如基础板、网卡、风扇板等)都有一个"身份证",这个"身份证"里记录了:
- 器件的型号、序列号
- 生产日期、制造商信息
- 硬件配置参数
- 版本信息等
这个"身份证"就是CSR文件,它被存储在EEPROM这种断电也不会丢失数据的存储芯片中。
说明:除了CSR外,还有PSR(Product Self-description Record,产品自描述记录)。两者的文件格式和升级流程完全相同,代码中统一处理。
CSR的适用范围
有EEPROM的器件案例就可以支持,当前支持的都是鲲鹏下的天池规范的单板
为什么需要升级CSR?
| 场景 | 说明 |
|---|---|
| 硬件配置更新 | 板卡参数调整需要更新CSR数据 |
| 版本升级 | CSR格式或内容需要升级 |
| Bug修复 | 修正错误的配置信息 |
| 功能扩展 | 新增硬件特性需要记录到CSR |
模块作用
本模块实现了CSR文件的自动升级功能,主要作用包括:
| 功能 | 说明 |
|---|---|
| 版本管理 | 注册CSR版本到固件清单,便于查询和管理 |
| 升级包解析 | 解析升级配置文件,识别需要升级的CSR文件 |
| EEPROM写入 | 将新的CSR数据写入EEPROM芯片 |
| 写保护控制 | 自动管理EEPROM的写保护机制,确保数据安全 |
| 数据校验 | 写入后回读数据,确保升级成功 |
| 生效管理 | 支持两种模式:立即复位BMC(ResetBMC)或延迟复位BMC(DelayResetBMC) |
目录结构
src/lualib/sr_upg_service/
├── sr_upg_service.lua # CSR升级服务(单例),管理所有CSR对象
├── parser_cfg.lua # 升级配置文件解析器
└── class/
├── sr_upgrade.lua # CSR升级基类(通用EEPROM写入逻辑)
└── sr_upgrade_with_protect_chip.lua # 带写保护芯片的CSR升级(支持SMBus控制)
整体架构
flowchart TB
subgraph External["外部接口"]
FW["固件管理服务"]
end
subgraph Service["服务层"]
SRService["sr_upg_service<br/>CSR升级服务(单例)"]
end
subgraph ParserLayer["解析层"]
ParserCfg["parser_cfg<br/>配置文件解析"]
end
subgraph Upgrade["升级层"]
SRBase["sr_upgrade<br/>CSR升级基类"]
SRProtect["sr_upgrade_with_protect_chip<br/>带写保护芯片的CSR升级"]
end
subgraph Hardware["硬件层"]
EEPROM["EEPROM芯片<br/>存储CSR数据"]
ProtectChip["写保护控制芯片<br/>(SMBus)"]
end
FW --> SRService
SRService --> ParserCfg
SRService --> SRBase
SRService --> SRProtect
SRBase --> EEPROM
SRProtect --> EEPROM
SRProtect --> ProtectChip
架构说明
- 服务层:
sr_upg_service是单例服务,管理所有板卡的CSR升级对象 - 解析层:解析升级配置文件,获取需要升级的CSR信息
- 升级层:根据硬件类型选择不同的升级实现
sr_upgrade:通用升级,直接控制EEPROM写保护sr_upgrade_with_protect_chip:通过SMBus芯片控制写保护
- 硬件层:EEPROM芯片和写保护控制芯片
升级流程
CSR升级遵循标准的三阶段流程:Prepare(准备)→ Process(处理)→ Finish(完成)
流程概览
flowchart TB
Start([收到升级请求]) --> Prepare
subgraph Prepare["阶段一:Prepare(准备)"]
P1["解析配置文件"]
P2["识别CSR组件"]
P3["设置生效模式"]
P1 --> P2 --> P3
end
Prepare --> Process
subgraph Process["阶段二:Process(处理)"]
PR1["解压升级包"]
PR2["匹配CSR对象"]
PR3["关闭写保护"]
PR4["写入CSR数据到EEPROM"]
PR5["回读并校验数据"]
PR6["打开写保护"]
PR7["更新版本信息"]
PR1 --> PR2 --> PR3 --> PR4 --> PR5 --> PR6 --> PR7
end
Process --> Finish
subgraph Finish["阶段三:Finish(完成)"]
F1["注册生效策略"]
F2["返回升级结果"]
F1 --> F2
end
Finish --> Check{生效模式?}
Check -->|"ResetBMC"| End1([立即复位BMC<br/>CSR生效])
Check -->|"DelayResetBMC"| End2([等待调用生效接口<br/>复位BMC])
EEPROM写入详细流程
flowchart TB
Start([开始写入]) --> GetLock["获取芯片锁<br/>(防止并发写入)"]
GetLock --> CloseProtect["关闭写保护"]
CloseProtect --> WriteHeader["写入SR文件头<br/>(128字节)"]
WriteHeader --> CheckHeader["回读并校验文件头"]
CheckHeader --> WriteData["写入SR数据<br/>(从偏移位置开始)"]
WriteData --> CheckData["回读并校验数据"]
CheckData --> OpenProtect["打开写保护"]
OpenProtect --> ReleaseLock["释放芯片锁"]
ReleaseLock --> Success{是否成功?}
Success -->|是| End1([升级成功])
Success -->|否| Retry{重试次数<3?}
Retry -->|是| WriteHeader
Retry -->|否| End2([升级失败])
升级时序图
sequenceDiagram
participant Client as 外部请求
participant Service as sr_upg_service
participant SRObj as sr_upgrade对象
participant EEPROM as EEPROM芯片
Note over Client,EEPROM: Prepare 阶段
Client->>Service: 升级准备请求
Service->>Service: 解析配置文件
Service->>Service: 识别SR组件
Service-->>Client: 返回准备结果
Note over Client,EEPROM: Process 阶段
Client->>Service: 升级处理请求
Service->>Service: 解压升级包
Service->>SRObj: upgrade(bin_path)
SRObj->>SRObj: 获取芯片锁
SRObj->>EEPROM: 关闭写保护
SRObj->>EEPROM: 写入文件头
SRObj->>EEPROM: 回读校验
SRObj->>EEPROM: 写入数据
SRObj->>EEPROM: 回读校验
SRObj->>EEPROM: 打开写保护
SRObj->>SRObj: 释放芯片锁
SRObj-->>Service: 返回升级结果
Service-->>Client: 返回处理结果
Note over Client,EEPROM: Finish 阶段
Client->>Service: 升级完成请求
Service->>Service: 注册生效策略
Service-->>Client: 返回最终结果
核心概念
CSR文件结构
CSR文件是一个二进制文件,包含以下几个部分:
flowchart LR
subgraph CSR["CSR文件结构(EEPROM中)"]
direction TB
H["文件头<br/>Header<br/>128字节"]
OEM["OEM定制区<br/>(可选)"]
DATA["数据区<br/>(硬件配置信息)"]
Sign["数字签名区"]
H --> OEM --> DATA --> Sign
end
文件头(Header)关键字段
| 字段 | 大小 | 说明 |
|---|---|---|
| standard_code | 12字节 | 标准代码标识 |
| spec_version | 1字节 | 规范版本 |
| inner_area_offset | 2字节 | OEM定制区偏移(单位:8字节) |
| csr_offset | 2字节 | 数据区偏移1(单位:8字节) |
| psr_offset | 2字节 | 数据区偏移2(单位:8字节) |
| sr_version | 2字节 | SR版本号 |
| component_uid | 24字节 | 组件唯一标识符 |
写保护机制
EEPROM芯片通常带有写保护功能,防止意外修改数据。
两种写保护控制方式
flowchart LR
subgraph Method1["方式一:直接控制"]
M1["通过EEPROM对象<br/>的WriteProtect属性<br/>直接控制"]
end
subgraph Method2["方式二:通过SMBus芯片"]
M2["通过独立的<br/>WriteProtectChip<br/>(SMBus协议)控制"]
end
Method1 --> EEPROM1["EEPROM芯片"]
Method2 --> Chip["写保护控制芯片"] --> EEPROM2["EEPROM芯片"]
| 控制方式 | 实现类 | 适用场景 |
|---|---|---|
| 直接控制 | sr_upgrade |
EEPROM对象自带WriteProtect属性 |
| SMBus控制 | sr_upgrade_with_protect_chip |
通过独立的SMBus芯片控制写保护 |
芯片锁机制
为了防止多个升级任务同时操作同一个EEPROM芯片,使用了**芯片锁(chip_lock)**机制:
sequenceDiagram
participant Task1 as 升级任务1
participant Lock as 芯片锁管理器
participant Task2 as 升级任务2
Task1->>Lock: 请求芯片锁(超时600秒)
Lock-->>Task1: 获取成功
Task1->>Task1: 执行升级...
Task2->>Lock: 请求芯片锁
Lock-->>Task2: 等待中...
Task1->>Lock: 释放芯片锁
Lock-->>Task2: 获取成功
Task2->>Task2: 执行升级...
生效模式
CSR升级支持两种生效模式:
| 模式 | 注册值 | 说明 |
|---|---|---|
| 立即复位生效 | ResetBMC |
升级完成后立即复位BMC,CSR生效 |
| 延迟复位生效 | DelayResetBMC |
升级完成后,需要调用生效接口才会复位BMC,使CSR生效 |
说明:代码内部使用
Immediately属性表示默认行为,但实际注册到生效管理模块的只有ResetBMC和DelayResetBMC两种模式。
代码阅读建议
代码实现在general_hardware仓
推荐阅读顺序
-
先了解服务管理
sr_upg_service.lua- 理解服务的整体流程和对象管理
-
然后了解升级实现
sr_upgrade.lua- 核心升级逻辑(EEPROM写入)sr_upgrade_with_protect_chip.lua- 带写保护芯片的扩展
关键入口点
| 功能 | 入口文件 | 入口函数 |
|---|---|---|
| CSR对象创建 | sr_upg_service.lua |
on_add_object() |
| 升级准备 | sr_upg_service.lua |
on_upgrade_prepare() |
| 升级处理 | sr_upg_service.lua |
on_upgrade_process() |
| 升级完成 | sr_upg_service.lua |
on_upgrade_finish() |
| EEPROM写入 | sr_upgrade.lua |
upgrade() |
| 版本查询 | sr_upgrade.lua |
get_version() |
类关系图
classDiagram
class sr_upg_service {
<<singleton>>
CSR升级服务
}
class sr_upgrade {
CSR升级基类
}
class sr_upgrade_with_protect_chip {
带写保护芯片的CSR升级
}
class parser_cfg {
配置文件解析
}
sr_upg_service --> parser_cfg
sr_upg_service --> sr_upgrade
sr_upg_service --> sr_upgrade_with_protect_chip
sr_upgrade_with_protect_chip --|> sr_upgrade
核心处理步骤
对象创建
系统根据配置中是否有 WriteProtectChip 字段,自动选择合适的升级方式:
- 有WriteProtectChip:使用SMBus协议控制独立的写保护芯片
- 无WriteProtectChip:直接通过EEPROM对象控制写保护
EEPROM写入
写入过程分为两个阶段:
- 写入文件头:固定128字节的头部信息
- 写入数据部分:从指定偏移位置开始写入配置数据(可能包含OEM定制区)
每次写入后都会立即回读数据进行校验,确保写入成功。
写保护管理
为了保证数据安全,写入过程严格遵循以下步骤:
- 关闭写保护
- 写入数据
- 回读校验
- 重新打开写保护
常见问题
Q1: CSR升级失败的常见原因?
| 原因 | 说明 | 解决方法 |
|---|---|---|
| 写保护未关闭 | EEPROM写保护仍然打开 | 检查WriteProtect属性,重试关闭 |
| 芯片锁超时 | 其他任务占用芯片 | 等待其他任务完成,或增加超时时间 |
| 数据校验失败 | 写入数据与回读数据不一致 | 重试写入(最多3次) |
| 配置文件错误 | UID不匹配或文件损坏 | 检查配置文件和升级包 |
Q2: 为什么要有芯片锁?
EEPROM芯片通常通过I2C/SMBus总线访问,如果多个任务同时写入,会导致数据混乱。芯片锁确保同一时间只有一个任务可以访问芯片。
Q3: 两种生效模式有什么区别?
- ResetBMC(立即复位):CSR升级完成后,系统会立即复位BMC,硬件重新读取EEPROM中的CSR数据并应用新配置
- DelayResetBMC(延迟复位):CSR升级完成后,需要用户手动调用生效接口,系统才会复位BMC,使新的CSR配置生效
两种模式都需要通过复位BMC来使CSR生效,区别在于复位的时机是立即自动触发还是延迟手动触发。