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.

[参考译文] TMS570LC4357:使用 f021 API 刷写闪存启动时出现意外的 ECC 错误(ESM 2.3)

Guru**** 2576215 points
Other Parts Discussed in Thread: TMS570LC4357, RM57L843

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/776854/tms570lc4357-unexpected-ecc-errors-esm-2-3-when-flashing-start-of-flash-using-f021-api

器件型号:TMS570LC4357
主题中讨论的其他器件: RM57L843

您好!

我使用 f021通过自动 ECC 生成功能在 HDK 电路板上刷写 TMS570LC4357器件的内部 FPROM。

我在扇区0和1 (前32KB)中刷写了引导、其中包括中断和异常向量。 然后、我有一个从扇区12 (偏移1MB)开始的应用。 我的应用程序使用 f021库来刷写应用程序本身或启动。

该应用程序完全从 RAM 运行(所有函数的 text 和 const)。 只能通过访问闪存 shoud 来获取主中断处理程序(包含到 RAM 中实际处理程序代码的分支)

在对每个块进行编程期间、我始终按8KB 块进行全局屏蔽中断的闪存。

我成功刷写了应用程序本身、没有任何错误。

但是、当尝试刷写引导时、我在该过程中收到意外的总线错误(ESM 2.3、红色 LED)。 尽管如此,引导闪存会正确结束:打开 RST 电源后,将执行更新的引导,并且不会出现进一步的错误。

我还通过 PMU 查看了 cortex 事件、并注意 到前3个写入8KB 的事件为0x6e 和0x71、后8K 块为无。 我还尝试停用 CPU 高速缓存、这并没有改变全局行为、而只是增加了 PMU 记录的事件数量。

ESM 同时指示1.4和2.3错误(这似乎与上面记录的事件一致)、而 EPC 只显示 CAM FIFO (0x5308)中记录的单个地址。

如何进行调试并找出导致意外访问闪存的原因(我想)?

谢谢、

多米尼克

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

    Cortex-R 器件的中断矢量位于闪存扇区0的开头。 在从应用程序执行闪存操作(擦除/写入)之前、请禁用应用程序代码中的中断(IRQ、FIQ)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的回答。

    我很清楚、cortex 在0x18/0x1c 处为 IRQ 和 FIQ 执行中断矢量。 因此,我使用以下编程顺序:

    disable_IRQ ();//禁用 cortex 级别的中断(在 CPSR 中写入位 I)*/
    Fapi_issueODE19 CommandWithAddress (Fapi_EraseSector、Sector_address);
    while (FAPI_CHECK_FSM_READY_BUSY = Fapi_Status_FsmBusy);
    fapi_flushPipeline();
    字节=组宽;
    while (计数> 0)

    fapi_issueProgrammingCommand (dest、src、bytes、0、0、 Fapi_AutoEccGeneration);
    while (fapi_check_FSM_ready_busy =fapi_Status_FsmBusy);
    src +=字节;
    dest +=字节;
    count -=字节;

    enable_IRQ ();


    此外、如果在使用一个空白扇区0的过程中进行 IRQ、我想 CPU 将会崩溃、这是因为不会获取有效的指令!

    相比之下、我看到的是编程成功终止、而 ESM 错误1.4和2.3在编程期间发生。

    另请注意、我不使用 FIQ (从 cortex 复位时禁用、我从不启用它)。

    我曾尝试启用 FIQ 以捕获对0x1C 处的处理程序的调用、以确定 ESM 2.3错误何时发生、因此根据 LR cortex reg、它来自从外部 SDRAM 执行的 Fapi_waitDelay()函数。 所以我有点困惑、不知道在哪里可以进一步了解。

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

    F021 API 用户指南指出,Fapi_waitDelay()函数已被弃用,不应在新项目中使用。

    Fapi_flushPipeline()用于刷新 FMC 管道缓冲区。 此函数假设可以从闪存地址0、0x100、0x200、0x300进行读取。 擦除扇区0后、ECC 区域也会被擦除。 因此、读取扇区0中的任何地址都会导致 ECC 错误。

    您无需在闪存擦除和闪存程序 API 之间调用此函数。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    器件型号:TMS570LC4357

    您好!

    很抱歉、对于原始线程中出现的问题、我没有提供最新建议解决方案的反馈。 我知道它已锁定在"TI 认为已解决"状态、但遗憾的是它没有。

    我们的应用程序更改了一个位、现在在前3个16KB 扇区上刷写的引导功能更加稳定、并且很少需要刷新。 现在、问题变得不太重要。 此外、当闪存引导时、我在 PMCR 寄存器中禁用从 cortex 到 ESM 的 ECC 事件导出、找到了一种权变措施。

    但问题并没有 真正得到解决。 我知道 Fapi_waitDelay()已被弃用,但在我的代码中没有使用它,但它是由 Fapi_flushPipeline()中的 TI 代码内部调用的,根据我在 FIQ 上获得的寄存器上下文,我看到它来自这里,但无论如何,该代码都不能访问闪存。

    根据 QJ Wang 的最新建议,我删除了擦除和编程之间对 Fapi_flushPipeline()的无用调用。 但 ESM 2.3错误仍然会出现。

    现在、在 FIQ 上下文中(在 FIQ 处理程序(0x1c)中中断 JTAG 调试并查看寄存器)、我发现错误发生在我的 RAM 代码中某处的一系列指令上、这些指令肯定不会 访问闪存。

    似乎该错误是异步发生的、而连接到 ESM 的 FIQ 对调查错误的来源毫无帮助。

    谢谢

    多米尼克

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

    对于 TMS570LC4357和 RM57L843器件、始终启用闪存和 SRAM 存储器的 ECC 保护。 这与 TMS570LS 和 RM4系列中的 Hercules 器件不同、其中 ECC 在复位后被禁用、并在软件启用前保持禁用状态。 这意味着在开发过程中、红色 ERR LED 会亮起的可能性大大提高。 发生这种情况的一个常见原因是擦除的闪存充满了 ECC 错误! 因此、如果您擦除整个(4MB)闪存、然后使用引导加载程序对扇区0/1进行编程、则大多数闪存仍将包含 ECC 错误。 跳闸红色错误 LED 所需的一切是从闪存左侧存在 ECC 错误的区域读取。 这可能会意外发生(CPU 执行推测预取)。

    在开发过程中频繁出现 ECC 相关错误的解决方案是对正确的 ECC 值进行编程、即使对于主闪存阵列中未使用的位置也是如此。 实现这一目标的最简单方法是使用链接器来生成 ECC 数据、而不是使用加载程序。

    此外、当引导加载程序尝试将应用程序编程到闪存时、它会首先擦除闪存扇区。 被擦除扇区的未使用部分包含 ECC 错误。 解决方案是将0xFFFFFFF 填充到应用程序、直至其到达扇区边界。

    以下是我的示例:
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1.链接器为整个闪存生成 ECC:

    /*------------------ *
    /*链接器设置 *

    --retain="*(.intvecs)"

    /*用户代码开始(1)*/
    /*用户代码结束*/

    /*------------------ *
    /*内存映射*/
    存储器

    /*用户代码开始(2)*/
    /*用户代码结束*/

    引导程序(X):origin=0x00000000 length=0x00000020 vfill =0xFFFF
    FLASH0 (Rx):origin=0x00000020 length=0x001FFFE0 vfill = 0xffffffff
    FLASH1 (Rx):origin=0x00200000 length=0x00200000 vfill = 0xffffffff
    SRAM (RWX):origin=0x08002000 length=0x0002D000
    堆栈 (RW):origin=0x08000000 length=0x00002000

    /*用户代码开始(3)*/
    ECC_VEC (R):origin=(0xf0400000 +(start (vectors)>> 3))
    length=(size (vectors)>> 3)
    ecc={algoL2R5F021、input_range=vectors}

    ECC_FLA0 (R):origin=(0xf0400000 +(开始(FLASH0)>> 3))
    length=(size (FLASH0)>> 3)
    ecc={algoL2R5F021、input_range=FLASH0}

    ECC_FLA1 (R):origin=(0xf0400000 +(开始(FLASH1)>> 3))
    length=(size (FLASH1)>> 3)
    ecc={algoL2R5F021、input_range=FLASH1}
    /*用户代码结束*/



    /*用户代码开始(4)*/
    ECC

    algoL2R5F021:address_mask = 0xfffffff8 //地址位31:3 */
    汉明_MASK = R4 /*在掩码中使用 R4/R5构建*/
    奇偶校验掩码= 0x0c /*设置哪些 ECC 位为偶校验和奇校验*/
    镜像= F021 /* RM57Lx 和 TMS570LCx 在 F021中编译*/

    /*用户代码结束*/

    /*------------------ *
    /*段配置 *
    部分

    /*用户代码开始(5)*/
    /*用户代码结束*/
    .intvecs:{}>向量

    /* toot 目录为\Debug */
    闪存 API:

    .\f021_Flash_API\02.01.01\source\fapi_UserDefinedFuncations.obj (.text)
    .\source\bl_flash.obj (.text)
    // .\source\BL_dCAN.obj (.text)
    --library=..\..\..\F021_Flash_API\02.01.01\F021_API_CortexR4_BE_L2FMC.lib (.text)
    }palign = 8 load = FLASH0 |FLASH1、run = SRAM、load_start (apiLoadStart)、run_start (apiRunStart)、size (apiLoadSize)

    .text:{} palign =8>FLASH0 |FLASH1 /*已初始化的可执行代码和常量*/
    .const:{}palign =8 load=FLASH0 |FLASH1、run = SRAM、load_start (constLoadStart)、run_start (constRunStart)、size (constLoadSize)/*初始化的常量数据(例如 const flash_sects[.] =)*/
    .cinit:{} palign =8>FLASH0 |FLASH1 /*已初始化的全局和静态变量*/
    .pinit:{} palign =8>FLASH0|FLASH1
    .data :{}> SRAM
    .bss :{}>SRAM
    .sysmem:{}>SRAM

    /*用户代码开始(6)*/

    /*用户代码结束*/
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    2.在应用程序的链接器 cmd 文件中将0xFFFFFFFF 填充到应用程序的示例代码。 在引导加载程序中、在将此应用程序编程到闪存时生成 ECC。

    /*------------------ *
    /*链接器设置 *

    --retain="*(.intvecs)"

    /*用户代码开始(1)*/
    /*用户代码结束*/

    /*------------------ *
    /*内存映射 *

    存储器

    /*用户代码开始(2)*/
    /*用户代码结束*/
    向量(X) :origin=0x00010020 length=0x00000020
    FLASH_CODE (RX):origin=0x00010040 length=0x8000 - 0x40 fill=0xFFFFFFFF /*扇区4/5*用于应用程序/
    FLASH0 (RX):origin=0x00018000 length=0x00200000 - 0x18000
    FLASH1 (RX):origin=0x00200000 length=0x00200000
    堆栈(RW):origin=0x08000000 length=0x00001500
    RAM (RW):origin=0x08001500 length=0x0007EB00

    /*用户代码开始(3)*/

    //向量(X) :origin=0x00010020 length=0x00000020
    // flash_code (RX):origin=0x00010040 length=0x8000 - 0x40 fill=0xFFFFFFFF /*扇区4/5*/
    // FLASH0 (RX):origin=0x00018000 length=0x00200000 - 0x18000

    /*用户代码结束*/


    /*用户代码开始(4)*/
    /*用户代码结束*/


    /*------------------ *
    /*段配置 *

    部分

    /*用户代码开始(5)*/
    /*用户代码结束*/
    .intvecs:{}>向量
    .text align (32):{}> flash_code
    .const align (32):{}> flash_code
    .cinit align (32):{}> flash_code
    .pinit align (32):{}> flash_code
    .bss :{}> RAM
    .data :{}> RAM
    .sysmem:{}>RAM


    /*用户代码开始(6)*/
    //.text align (32):{}> flash_code
    //.const align (32):{}> flash_code
    //.cinit align (32):{}> flash_code
    //.pinit align (32):{}> flash_code

    /*用户代码结束*/


    使用这些方法时、应避免 ESM 错误。

    BTW、最好在跳转到应用程序之前禁用引导加载程序中的中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    感谢你的答复。 我发现 ECC 始终在闪存上启用、并且在被擦除的扇区上是错误的。 因此我在刷写时要特别小心:仅在重新编程完一个完整的扇区之后擦除和取消屏蔽之前屏蔽中断、以及从 RAM 中执行我的所有代码。 我希望它能正常工作。

    第一个扇区是完全闪存的(全部为16KB)、所以填充到 FFFFFFFF 不适用。

    正如您提到的读访问:“这可能会意外发生(CPU 执行推测预取)。” 这是我怀疑发生的情况、但如果是这种情况、这是我的软件中的一个错误、因为它的设计目的是通过从 RAM 执行并屏蔽 IRQ 来避免这种情况、我必须找到它。 我正在为安全关键型应用编写操作系统层、不能依赖误解和权变措施。

    现在我的问题变成了:我可以使用什么调查方法来查找我的错误,因为我认为在 ECC 错误后使用由 ESM 触发的 FIQ 会导致我接近执行不需要的访问的代码,但它不是: 当在 RAM 中执行没有任何闪存访问的代码时、IRQ 一直发生。

    谢谢、此致

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

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

    我担心链路丢失?

    谢谢、此致、
    多米尼克
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Dominique、您好!

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

    您好!

    该线程指出、数据预取可以在地址空间内的任何位置发生。

    如果我的理解有误,请告诉我:

    • 如果访问目标地址的物理无效地址或 MPU 不允许该地址、则中止异常将被屏蔽、不会发生任何情况
    • 如果访问目标是一个有效且允许的地址、则会正常发生。 因此、如果它位于未编程的闪存地址上、则需要触发 ECC 错误。

    如果这是正确的、我们可以推断所有4Mo 内部闪存都应进行完全编程(必要时使用填充):

    • 使用 外部均值(JTAG 探针)
    • 或者、如果使用嵌入式代码(引导加载程序...)进行刷写、则应在闪存操作期间在 cortex 级别禁用 ECC 总线错误事件导出、因为闪存软件本身可能会以不可预测的方式导致此类推测访问并失败。

    也许用户可以在操作结束时忽略闪烁 ECC 错误并将其清除(但在我们的定制电路板设计中不是一个选项、因为 nERROR 与复位相关)、或者配置 L2FMC 忽略已擦除扇区的 ECC 故障?

    管理此问题的首选/推荐方法是什么?

    谢谢、此致

    多米尼克