This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS570LS1224:使用“应急存根“进行现场安全引导加载程序更新

Guru**** 2862450 points

Other Parts Discussed in Thread: TMS570LS1224

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1572279/tms570ls1224-field-safe-bootloader-update-with-a-rescue-stub

器件型号:TMS570LS1224


工具/软件:

我们必须更新器件 引导加载程序 (BL) 取代 CAN、 不会用力 更新过程中功率下降时的设备。 所有已部署的装置都运行 A 单 BL、矢量位于 0x0000_0000 。 我们不能更改车队的内存布局。

为什么我们选择“救援残桩“(而不是双 BL / A/B 方案)

  • 兼容性: 现有器件期望 BL 位于 0x0000(扇区 0 向量)。 移动 BL 向量或添加第二个 BL 区域会破坏已部署的映像并使服务变得复杂。

  • 闪存预算和复杂性: A/B(双 BL)需要额外的保留闪存、重复的初始化(VIM/ESM/MPU/缓存)、交叉签名/回滚逻辑。 我们的限制是“最小变化、最大安全性“。

  • 失效防护第一条指令: 小巧 存根 置于 Sector0 之外、可让 第一次获取就在复位后 决定:“BL 有效? →Jump BL;else→留在更新程序中重新编程 BL。“ 这样即使在 BL 擦除期间电源耗尽、砖形窗口也能保持较小的尺寸。

组件和地址

  • 引导加载程序 (BL): 住在 Bank0/Sector0; 0x0000_0000 处的矢量 ; BL 条目_c_int00 () 当前在 0x0000_8258 (来自 bl.map)。

  • BL Updater 应用程序: 一个对新 BL 进行编程的小应用程序。 它自己的向量位于处 0x0002_0020 ;中的代码 0x0002_0140 向上;包括 a 救援残桩 AT 0x0002_0040 (单独的段,保留在链接器中).rescue_stub

  • 救援存根(在更新程序中): 极小的 ARM 代码。 复位时:

    • 读数 A 检查单词 在 BL 区域中(例如 0x0000_0100 )。

    • 如果已擦除/无效→、则分支到 更新程序 (在 _c_int000x0002_EB7C )。

    • 否则→分支到 BL (在 _c_int000x0000_8258 )。

    • 我们还在分支之前添加了干净的移交措施(禁用 IRQ/FIQ、DSB/ISB)。

如何实现 BL 更新程序 立即生效(分步操作)

  1. 启动: 将 F021 闪存 API 和所需的常量复制到 SRAM (在擦除/编程期间、我们从不从闪存执行闪存 API)。

  2. 为扇区 0 矢量打补丁一次:

    • 我们 擦除扇区 0 然后进行编程 在单个 32 字节 F021 调用中为 0x0000..0x001F (AutoECC 打开)。

    • AT 0x0000 我们写一个 B 0x0002_0040(长分支)、因此 RESET 可获取 救援残桩 首先、

    • 我们尝试了 0x04..0x1F 的两个变体:
      (a) 复制 BL 的原文、或
      (b) 制造 全部八个条目 (0x00..0x1C) 分支到存根以捕获任何早期异常。

  3. 程序 BL 主体: 我们编写新的 BL 从 0x0000_0020 上升 以 4 KB 块表示。 我们钳制擦除/编程范围、因此 不会再次擦除扇区 0 (即我们在单个 32 字节写入后不会触摸 0x0000..0x001F)。

  4. 切换到 BL: 电子产品

    • 执行操作 清理分支 BL _c_int00(禁用 IRQ/FIQ、DSB/ISB、设置 VBAR=0,然后)BX

    • 触发器 A 热复位 (SYSECR) 就在矢量补丁之后,这通常是更简单/更简洁的 R 类。
      我们已经对两者进行了测试。

  5. 功率限制: 我们还进行电源检查 (KL30)、以避免在输入过低时尝试使用 BL 闪存(我们可以保持功率~50ms;完整的 BL 擦除+编程为~160ms)。

观察到的行为(问题)

  • IF 单独对 BL 进行编程 (通过 J-Flash)、 冷下电上电 每次引导 BL。

  • IF 运行更新程序 、修补程序矢量、程序 BL body 和 热复位 BL 出现一次 (发送 CAN 横幅)。

  • 但在 A 上 冷下电上电 、BL 无法引导 (无 CAN 横幅)。

  • a. 读回 展示了 仅有差异 VS 是已知良好的 BL 映像 前 0x20 字节 (我们修补后的向量)。 IF 恢复原始 BL 0x00..0x1F 、冷启动再次工作。

  • 如果我们尝试对 0x0000 进行较小的编程、F021 FSM 可能会停止;写入 一次调用中的整个 32 个字节 避免这种情况(建议 ECC/短语对齐灵敏度)。

我们已经尝试/考虑过的问题

  • 进行开发 全部 8 个向量条目 指向存根(以避免在半初始化 BL 中出现异常)。

  • 执行操作 清洁手柄 (在分支到 BL 之前禁用 IRQ/FIQ、DSB/ISB、VBAR 写入)。

  • 或者、 矢量贴片、然后立即热复位 让 BL 从干净的石板开始。

  • 确保 0x0000 处的长分支使用正确的结果 调制 24 最远距离 0x0002_0040 (在±32 MB 以内;正常)。

  • 确认两个.map 文件中的 BL 条目地址并保留 LSB= 0(ARM 状态)

为什么不“从一个 BL 跳到另一个 BL“而不是一个残桩?

  • 我们只有 一个 BL 已部署单位的区域为 0x0000。 简介 A. 第二个 BL (A/B) 需要新的矢量策略(重定位 VBAR 或镜像第二个矢量表)并重新定位字段布局。

  • 存根 让我们继续 所有传统假设 (0x0 处的 BL 向量)但仍会添加 A 失效防护 尽早作出决定。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Arslan:

    对延迟的回复表示歉意!  
    我们有自己的内部人工智能、可以分析与控制器相关的所有文档以及过去的所有问题以提供建议。 在第一个层面上、我使用此 AI 解决您的问题、下面是我从工具中获得的一些有用建议:

    该问题似乎与闪存编程、ECC(纠错码)和冷启动行为之间的交互有关。 让我细分要点并提出一个解决方案:

    1. 闪存编程和 ECC 注意事项:
    • TMS570LS1224 具有 144 位编程宽度 (128 位数据+ 16 位 ECC)(3)
    • 存储体数据宽度为 16 字节 (128/8)(3)
    • 对闪存进行编程时、起始地址加上字节数不得超过存储体数据宽度 (3)
    1. 矢量表和冷启动行为:
    • 引导加载程序矢量必须位于 0x0000_0000、以确保与已部署单元的兼容性
    • 只有闪存在冷复位后保留数据 (8)
    • 救援残桩方法是有效的、但实现需要仔细考虑闪存编程限制
    1. 根本原因分析:“BL 出现一次但在冷开机循环时无法启动“的问题可能源于:
    • 对矢量表进行编程时的 ECC/短语对齐灵敏度
    • 对 0x0000..0x001F 的 32 字节单次写入可能无法正确处理 ECC 生成
    • 闪存编程宽度约束可能会影响矢量表完整性
    1. 建议的解决方案:下面是一种可解决冷启动问题的修改方法:

    1. For the rescue stub implementation:
       - Program the first 32 bytes (0x0000-0x001F) in a single F021 call with AutoECC
       - Ensure the branch instruction at 0x0000 is properly aligned within the 16-byte bank width
       - Make all vector entries (0x00-0x1C) branch to the stub for consistency
    
    2. For flash programming:
       if ((Address % 16) + BytesToProgram <= 0x0F) {
          // Can program directly in one operation
          Flash_Program(Address, Data, BytesToProgram);
       } else {
          // Split the programming into bank-aligned chunks
          uint8_t firstChunkSize = 16 - (Address % 16);
          Flash_Program(Address, Data, firstChunkSize);
          Flash_Program(Address + firstChunkSize, 
                       Data + firstChunkSize,
                       BytesToProgram - firstChunkSize);
       }

    1. 其他建议:
    • 验证是否已启用并正确配置 ECC 生成
    • 考虑将闪存仿真 EEPROM(费用)用于状态字段 (5)
    • 在分支之前实施适当的干净切换措施(禁用 IRQ/FIQ、DSB/ISB)
    • 在写入后添加对编程矢量表内容的验证

    --
    此致、
    Jagadish。