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.

[参考译文] MSPM0G3519:使用存储体交换时的问题应用手册

Guru**** 2760705 points

Other Parts Discussed in Thread: MSPM0G3519, CCSTUDIO, UNIFLASH

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1603867/mspm0g3519-problems-using-bank-swap-application-note

器件型号: MSPM0G3519
Thread 中讨论的其他器件: CCSTUDIOUNIFLASH

您好!
我尝试根据闪存多组功能应用手册实现存储体交换功能、但遇到了问题。 我使用 CCSTUDIO 20.4.0 和 MSPM0G3519 LaunchPad。  

本应用手册中的 CSC 代码示例位于组 0 中、从 0x0000 0000 开始、我的应用程序地址为 0x0000 0800。 链接器文件会相应地更改。  

我使用 CCSTUDIO 的调试功能将 CSC 编程到 μ µC 中。 随后、我使用 Memory Window 的“Import data from file“功能手动将应用程序编程到 μ µC 中。 现在、软件已启动。  

如果未启用存储体交换、CSC 必须使用 start_app () 函数启动应用程序(也来自应用手册)。 方法是调用“start_app ((uint32_t *)(0x0800))“;但是、这不会启动应用程序、但始终返回 CSC。 当单步执行 start_app () 函数时,我可以看到如何正确地将指向向量表的指针传递给函数。 但是、在执行汇编语言部分后、指针突然变为 0x0000 0000、指向 CSC 的矢量表、而不是应用程序。 这显然会再次启动 CSC。 如果在执行汇编语言部分后手动输入正确的矢量表地址、则应用程序会被正确启动。

我是否需要在 assbler 或编译器中配置任何内容以使 start_app () 正常工作?

此致
Uwe

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

    尊敬的 Uwe:

    我看到我们确实有 MSPM0G3519 的引导管理器代码演示、如果您不对自己进行任何修改、请剂量它有效?

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

    您好、Gary、
    首先、从我的角度来看、引导管理器代码演示非常复杂、可以作为起点、并且这些文档不符合这种复杂性(至少对于我作为 MSPM0 的初学者来说)。

    我无法在不做任何修改的情况下使“客户安全代码“示例正常工作、因为/*检查写保护防火墙已就位*/失败。 但是、在 else-branch(文件“customer_secure_code.c"中“中的第 180 行)中调用函数“start_app ()“后、正确调用了该函数、并按预期执行了位于组 0 中的固件映像。 这对我来说很重要。

    同时、我已进一步分析了问题。 我单步完成了在我的项目中生成的函数 start_app () 的反汇编。 如下所示:

      start_app ()
      0x000003A0  B580         按  {r7、LR}
      0x000003A2  B082         Sub sp   、#0x8
      0x000003A4  9001         STR   r0、[sp、#0x4]
      0x000003A6  9801         LDR   r0、[sp、#0x4]
      0x000003A8  4906         LDR   R1、[PC、#0x18]
      0x000003AA  6008         STR r0   、[R1]
      0x000003AC  9801         LDR   r0、[sp、#0x4]
      0x000003AE  6803         LDR   R3、[r0]
      0x000003B0  469D         MOV   sp、R3
      0x000003B2  9801         LDR   r0、[sp、#0x4]
      0x000003B4  4904         LDR   R1、[PC、#0x10]
      0x000003B6  6008         STR r0   、[R1]
      0x000003B8  9801         LDR   r0、[sp、#0x4]
      0x000003BA  6840         LDR   r0、[r0、#0x4]
      0x000003BC  4780         blx   r0

    可以看到、Reg0 中传递的参数(新矢量表的地址)被放置在堆栈上、稍后堆栈指针会被重新配置、现在新矢量表的地址会从堆栈上错误的位置读回、因为堆栈指针已更改。 在我的工程中避免这种情况的唯一方法是将参数分配给全局变量、使其不放在栈上。

    尽管 C 源代码完全相同、但“客户安全代码“示例中的反汇编看起来完全不同:

      start_app ()
      0x00001AE0  6803         LDR   R3、[r0]
      0x00001AE2  469D         MOV   sp、R3
        第 4923 章         LDR   R1、[PC、#0x8c]
      0x00001AE6  6008.         STR r0   、[R1]
      0x00001AE8  6840         LDR   r0、[r0、#0x4]
      0x00001AEA  4780         blx   r0


    您是否知道导致这种不同编译结果的原因以及如何避免?

    谢谢
    Uwe

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

    我有一个简单的反向交换演示、您可以将其称为以下内容

    e2e.ti.com/.../MSPM0G3519-SWAP-Function.zip

    这将是您容易开始.

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

    我尝试根据随附的.ppt 使用您的示例。 但是、在执行步骤 1(编程“MSPM0G3519_NONMAIN Change.txt“)后、我无法完成步骤 2(编程“MSPM0G3519_BANK0_Example.txt"和“和“MSPM0G3519_BANK1_Example.txt")“)、因为点击“Load Image“ UniFlash 会显示错误消息(请参阅屏幕截图)。 我只能在 DSSM 批量擦除或 DSSM 恢复出厂设置后继续。 我在这里做什么?



    但是、这不是我的主要问题、因为存储体交换在我的应用中是有效的。 更重要的是,为什么函数“start_app ()“的相同 C 源代码会在示例项目和我的项目之间产生不同的编译结果(见我上面的帖子和下面的源代码)。

    static void start_app(uint32_t *vector_table)
    {
        /* The following code resets the SP to the value specified in the
         * provided vector table, and then the Reset Handler is invoked.
         * */
    
        /* Reset the SP with the value stored at vector_table[0] */
        __asm volatile(
            "LDR R3,[%[vectab],#0x0] \n"
            "MOV SP, R3       \n" ::[vectab] "r"(vector_table));
    
        /* Set the Reset Vector to the new vector table (Will be reset to 0x000) */
        SCB->VTOR = (uint32_t) vector_table;
    
        /* Jump to the Reset Handler address at vector_table[1] */
    
        ((void (*)(void))(*(vector_table + 1)))();
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    为什么函数“start_app ()“的相同 C 源代码会在示例项目和我的项目之间产生不同的编译结果(请参见我上面的帖子和下面的源代码)。

    这是因为您/编译器将此类函数放置在不同的地址。 即使将相同的代码放在不同的闪存区域、固件代码也是不同的。

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

    问题不在于代码不同这一事实。 问题在于一个编译结果按预期工作、另一个不能正常工作(因为它将重要信息放置在栈上,并在修改栈指针后尝试读回此信息)。

    因此我想问更准确一点: 应用手册 SPRADN2(“MSPM0 系列中的闪存多组功能“)中的示例的编译先决条件是什么? 是否需要进行任何编译器设置或工程配置?

    您是否在我的上一篇文章中阅读了我关于存储体交换演示的评论? .ppt 中的指令是否不正确或我做了什么错误?

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

    您能帮检查一下您的代码和我们的演示代码是否使用相同的编译器版本?

    另请检查您是否在代码和我们的演示代码之间设置了相同的编译器优化级别。

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

    在这两种情况下、我都使用 TI Clang v4.0.4.LTS。 优化设置不同。 在我的工程中它是“0",“,在、在演示工程中它是“z"。“。

    在我的工程中将其设置为“1"或“或“z"后“后、便可以运行编译结果! 对我来说、这是一种意外行为、至少应在文档中提及。 通常我在不进行优化的情况下开始开发、然后再增加。 尽管现在我知道如何实现工作结果、但这并不是一个合理的选择、因为这会使工程中的其他代码的调试变得困难。

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

    之前的主题(此处)中针对 CSC 示例出现了类似的情况。 在交付时、该示例需要-O2、因为使用-O0 时、asm() 代码使堆栈变干。 该线程具有一些替代编码、可在任何优化级别正常运行。

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

    也可以尝试这种代码

    替换以下代码

    ((void (*)(void))(*(vector_table + 1)))();
     
    使用此代码
    ((void (*)())(*(uint32_t *)((uint32_t) vector_table+ 4)))();
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    结果相同:在更改堆栈指针之前、将 vector_table 放置在堆栈上。

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

    您好 Bruce、

    非常感谢您的提示。

    同时,我找到了一种类似的方法来解决这个问题:我声明了一个全局变量,并将指针分配给这个变量。 我希望它能可靠地工作。 然而,由于这种行为显然是已知的几个月,我希望在应用手册中获得有关所需优化级别的信息(第 2 篇)。

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

    很高兴您找到了一个解决方案。

    在另一个线程中,它(两次)提到“建议使用-O2 ,但我从未找到引用。

    我(个人)更喜欢第二个备选方案、因为它的作用是透明的。 在第一个替代方法中,它根本不是显而易见的(在线程中的解释之外)为什么在静态变量中缓存指针(否则是无用的)解决了这个问题。 但第二个是“最小的变化“。

    我使用我能想到的每个-O 设置测试了这两个设置、因此我非常确定它们是正确的。