CSR升级介绍

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

架构说明

  1. 服务层sr_upg_service 是单例服务,管理所有板卡的CSR升级对象
  2. 解析层:解析升级配置文件,获取需要升级的CSR信息
  3. 升级层:根据硬件类型选择不同的升级实现
    • sr_upgrade:通用升级,直接控制EEPROM写保护
    • sr_upgrade_with_protect_chip:通过SMBus芯片控制写保护
  4. 硬件层: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 属性表示默认行为,但实际注册到生效管理模块的只有 ResetBMCDelayResetBMC 两种模式。


代码阅读建议

代码实现在general_hardware

推荐阅读顺序

  1. 先了解服务管理

    • sr_upg_service.lua - 理解服务的整体流程和对象管理
  2. 然后了解升级实现

    • 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写入

写入过程分为两个阶段:

  1. 写入文件头:固定128字节的头部信息
  2. 写入数据部分:从指定偏移位置开始写入配置数据(可能包含OEM定制区)

每次写入后都会立即回读数据进行校验,确保写入成功。

写保护管理

为了保证数据安全,写入过程严格遵循以下步骤:

  1. 关闭写保护
  2. 写入数据
  3. 回读校验
  4. 重新打开写保护

常见问题

Q1: CSR升级失败的常见原因?

原因 说明 解决方法
写保护未关闭 EEPROM写保护仍然打开 检查WriteProtect属性,重试关闭
芯片锁超时 其他任务占用芯片 等待其他任务完成,或增加超时时间
数据校验失败 写入数据与回读数据不一致 重试写入(最多3次)
配置文件错误 UID不匹配或文件损坏 检查配置文件和升级包

Q2: 为什么要有芯片锁?

EEPROM芯片通常通过I2C/SMBus总线访问,如果多个任务同时写入,会导致数据混乱。芯片锁确保同一时间只有一个任务可以访问芯片。

Q3: 两种生效模式有什么区别?

  • ResetBMC(立即复位):CSR升级完成后,系统会立即复位BMC,硬件重新读取EEPROM中的CSR数据并应用新配置
  • DelayResetBMC(延迟复位):CSR升级完成后,需要用户手动调用生效接口,系统才会复位BMC,使新的CSR配置生效

两种模式都需要通过复位BMC来使CSR生效,区别在于复位的时机是立即自动触发还是延迟手动触发。