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.

[参考译文] CC2340R5:OAD -在调试器中运行持久应用程序擦除闪存页、并在块传输过程中对闪存页进行编程正常、但当在调试器之外运行时、这些页会被擦除、但不会被编程!

Guru**** 2595805 points
Other Parts Discussed in Thread: UNIFLASH, CC2340R5, SYSCONFIG

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1354207/cc2340r5-oad---running-persistent-app-in-debugger-erases-and-programs-flash-pages-ok-during-the-block-transfer-process-but-when-running-outside-of-the-debugger-the-pages-get-erased-but-not-programmed

器件型号:CC2340R5
Thread 中讨论的其他器件:UNIFLASHSysConfig

OAD Yikes! [SDK 7.40]

这是一个很难的问题。 在 CSS 调试器中调试持久应用程序时、当每个块从应用程序传输到设备时、持久应用程序会在此过程中成功擦除和编程每个2KB 页。 在 hte 下载的末尾设置断点、我可以看到从0x32000到其末尾的主应用程序范围的闪存的正确内容(所有标头和程序数据都完好无损)。  太棒了!

因此、我将 MCU 引导、持久应用和主应用刷写到器件中、然后引导到主应用程序(运行状况良好)中、该应用程序会将器件置于 OAD 状态、使主应用程序 HDR 无效、然后启动持久应用程序 int eh 器件。 移动应用程序会看到持久应用程序、连接并开始 OAD 流程。 验证图像标头后、模块开始从应用移至器件。 这看起来与调试器中一样(对人类来说)。

但是、在 OAD 下载周期结束时、MCU 引导会引导回 OAD 持久应用程序、而不是主应用程序。 事实上、主应用的所有扇区都会被擦除、但不会进行编程。

顺便使用 UNIFLASH、当我们将所有三个代码映像编程到闪存中后、可以导出闪存映像并与完整的闪存映像进行比较。  

我们看到的是、如果我们在调试器中启动、刷写过程会起作用、如果通过 MCU 引导在调试器外部、那么我们只会看到已擦除的页面(在两种情况下都激活了相同的持久应用代码)。

现在、显而易见的项目是检查 CCFG 中针对每个组件的设置、它们均设置为相同(CSS 中的默认设置)、需要特别注意 syscfg 中用于 MCU 引导的设置、因为该十六进制文件输出将提供 CCFG。  

通过观察调试器/后置调试器中的内容、我们可以看到唯一的区别是、在调试期间和通过 MCU 引导(关闭调试器)引导之后处于活动状态的 CCFG 映像是引导 cfg 记录和引导记录(SP、VT、EP)的指针及其 CRC 值。 这看起来很正常、我们的结论是、运行调试器或正常运行时、我们的闪存保护设置与之相同。

经过多次检查、我们唯一能够想到的是在调试器中运行的情况下、mainapp 的闪存区域已被擦除(将 OUT 文件下载到目标期间)。 当在调试器之外运行时、每个必须擦除的页中都已经编程了实际代码。 不确定该差异是否会因擦除周期中的一些时序差异而影响我们的问题。

希望有人对此问题提供一些意见、这是向我们的生产团队发布新 CC2340R5项目的最后一步、令人有点惊讶的是、通过 CSS 获得的结果与完全耗尽编程闪存的情况不同。

有什么想法?

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

    尊敬的 Stuart:

    感谢您与我们联系... 确实是一个很难的地方... 但我们会弄清楚:)

    Unknown 说:
    在路上使用 UNIFLASH、可以导出闪存映像、并在我们将所有三个代码映像编程到闪存中后将其与完整的闪存映像进行比较。  [/报价]

    为了确保我能够理解-当您顺便说一句的使用 UNIFLASH 时、这是否意味着您已经让 OAD 过程完成并在复位之前停止执行、并最终找到了3个映像?
    与附加了调试器的下载相比、闪存内容有什么不同?
    我们是否应该在复位后结束闪存擦除?
    在这种情况下、是否是因为某种原因或其他原因(CRC 错误、映像修订等)器件一直在永久映像上引导?

    为了进一步调查该问题、我想您可以尝试将调试器连接到一个正在运行的目标(https://software-dl.ti.com/simplelink/esd/simplelink_lowpower_f3_sdk/7.40.00.64/exports/docs/ble5stack/ble_user_guide/html/ble-stack-5.x-guide/debugging-index-cc23xx.html#connect-the-debugger-to-a-running-target)。 战略性地放置一些锁(即 volatile int x = 0;while (!x);)应该允许您在特定点步入代码、并更接近该问题的根本原因。
    然后、这个方法最终应该使您能够识别触发闪存擦除的函数。

    我希望这将有所帮助、

    此致、

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

    您好、Clement、

    为了确保我能够理解-当您 顺便说一句的使用 UNIFLASH 时 、这是否意味着您已经让 OAD 过程完成并在复位之前停止执行、并最终找到了3个映像?
    与附加了调试器的下载相比、闪存内容有什么不同?

    当未在调试器上运行时、我使用 UNIFLASH 读取整个闪存内容、然后使用比较实用程序查看在我尝试 OAD 之前和运行 OAD 之后之间的差异。 例如:1)在将所有组件刷写到器件中并通过 MCUBOOT >>主应用程序运行一次后导出的十六进制文件的两个视图;2)在从主应用程序跳转到 OAD 持久应用程序并完成 OAD 传输过程后导出的十六进制文件的两个视图。

      

    在此比较中、我们看到的是应用头位于0x32000处的区域、其中的代码位于 OAD 进程之前、然后在 OAD 完成后、闪存页会被擦除但不会进行编程。  

    但是、如果我通过运行调试器和"调试"持久应用程序来执行此操作、并在 OAD 下载结束时设置断点、则可以使用内存浏览器查看相应区域中的主应用程序标题和代码 (即使调试器中的下载过程首先擦除所有芯片闪存)因此我知道通过调试器、所有页面都按预期进行编程。  疯狂的

    很自然、我认为通过 MCUBoot 的路径可能是一个问题、因此我比较了由我的完整闪存映像(MCUBOOT + PERSISTENT APP + MAINAPP)设置的 CCFG 和调试期间闪存加载程序编程的 CCFG 区域。 原因如下:

     

    执行摘要是指向入口点的指针、bootcfg 记录中的 CRC 是唯一的区别、大概是在闪存加载报告以下情况时设置的:

    在调查代码(全部源自标准 "basic_persistent_LP_EM_CC2340R5_freertos_ticlang"项目 Update_Erase)时、不存在对函数 Status_t Slot (uint8 imageSlot)的引用、该函数会重叠预期的主应用区域(@ 0x32000)。 因此、我的结论是这些页正在被擦除、但没有编程。

    有一件事在任何文档中都不清楚、是在 syscfg 中正确使用这些设置、以及扇区的位何时应为1或0。 它将有助于很多添加一些线程的正确使用这些,因此我们都可以避免在调试会话中加载的闪存使用过程中对 NVS 区域进行重排,通常是为我们的应用程序正确配置的。

    这是所有三个组件(MCUBoot、persistent app 和 main app)所使用的当前设置。 我最初认为我是在 syscfg 中错误配置这些选项导致出现该问题的。  

    我将探索如何使用连接到正在运行的目标和一些陷阱来查看是否能发现确切的问题;如果调试会话与从完整闪存映像运行不同、其结果会非常复杂(并阻止最终版本投入生产)。

    感谢您的想法和评论。

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

    您好!

    感谢您提供高质量的描述。 请随时更新您对跑步目标的调查。

    同时、我想了解调试模式可能会影响行为的原因。 我能想到的几个要素是:

    -电源电压-闪存写入需要相当多的电力,并可能失败,如果电压下降。 是否有任何理由认为在 调试模式之外运行时电压电源较弱?
    检查闪存写入操作返回的状态有助于识别问题

    -执行时间- 闪存写入需要时间才能完成。 调试模式会减慢代码执行速度。 我能想到的一种情况是、图像正在被写入、但在复位发出之前、最后一个字节没有时间被完全写入。 因此、在下一次启动时、映像 CRC 不正确并且映像被擦除  

    说到 SysConfig 配置、一切似乎都正确。
    此外、我同意您关于针对闪存保护设置提供更好文档的反馈。 以下是我建议在以后的一篇文章中添加的内容:

    • 主扇区0-31 (每个位代表0-31范围内的一个扇区、当设置为1时、该扇区受到保护、不会在软件执行期间触发写入和擦除。 例如、设置此域为0x00000005可以保护扇区0和2、即地址范围0x0到0x7FF 和0x1000到0x17FF、以防止软件执行期间的擦除和写入。)
    • 主扇区32-255 (每个位代表32-255范围中的八个扇区、当设置为1时、扇区范围受到保护、不会在软件执行期间触发写入和擦除。 例如、将该域设置为0x00000005可以保护扇区32到39和48到55、即地址范围0x10000到0x13FFF 和0x18000到0x1BFFF、以在软件执行期间进行擦除和写入。)
    • 擦除/保留、主扇区0-31 (每个位代表0-31范围内的一个扇区、当设置为1时、在执行闪存擦除时该扇区被保留。 例如、将此字段设置为0x00000005会保留扇区0和2、即当器件闪存被擦除时、地址范围为0x0到0x7FF 和0x1000到0x17FF。)
    • 擦除/保留、主扇区32-255 (每个位代表32-255范围中的八个扇区、当设置为1时、执行闪存擦除时会保留扇区范围。 例如、将该字段设置为0x00000005会保留扇区32至39和48至55、即擦除器件闪存时地址范围0x10000至0x13FFF 和0x18000至0x1BFFF。)

    我希望这将有所帮助、

    此致、

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

    您好、Clement、

    感谢您的出色表现、我将用它来改进片上和 persistent 模型的调试过程。  在使用 UNIFLASH 将三个组件构建到闪存中后、我通过连接到目标、已成为热调试专家。 事实证明、我们的问题涉及几个层面:

    1. MCUBOOT 需要使用适当的开关设置重新编译,在调试该级别时,我们发现 imgtool.exe 和报头管理存在问题,需要解决一些问题。

    2.事实证明:MCU 引导是由于尾部问题而擦除我们的闪存映像;它在几乎任何调试会话中都是如此之快,以至于您很容易看不到它,因此我们现在可以针对该过程使用一些技巧和方法。 如果未验证拖车是否正常、并且设置了错误的开关、MCU 将覆盖图像。

    3.问题是 IMGTOOL 没有将用于完整性检查的正确尾部尺寸填充到图像标头中(设置为 len=zero)。 因此、当我们在 PERSISTENT 应用中协商以确定要传输的块数量时、拖车长度会不正确、因此在下一个引导周期中、MCU 引导会使映像无效、然后覆盖映像 (因为已在定制 MCU 引导配置中设置了回滚选项)。

    4.为解决长度问题,我们调整了移动应用程序来计算和填充电视线区域的长度,并修改了 SW_UPDATE.c,以便通过永久性应用程序传输的图像长度是正确的。 一旦我们有适当长度的拖车伴随着图像的阿罗特空气,然后一切工作根据需要。

    令人欣慰的是、我们的工厂现在已经为下一批产品准备了固件文件、并且没有留下任何有关该流程的奥秘。

     借此机会、我将更加详细地 介绍对 SW_UPDATe.c 所做的更改(现在、我们正在项目中使用本地更正版本)。  

    Tnx。