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.

[参考译文] TMS320F28388D:在 RAM 中放置内联函数(C2000ware 4.02、ARM 工具链 TI v20.02.7LTS)

Guru**** 2585275 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1213509/tms320f28388d-placing-inline-functions-in-ram-c2000ware-4-02-arm-toolchain-ti-v20-02-7lts

器件型号:TMS320F28388D
主题中讨论的其他器件:C2000WARE

为了更新 F28388D CM 内核的固件、需要从固件更新期间未擦除的存储器执行更新代码。

我的更新过程涉及通过 IPC 和消息 RAM 从 CPU2刷写数据。 这使用了在 ipc.h 中声明为内联的 ipc_waitForFlag()等函数

在链接器命令文件中、显示了以下命令行

将编程期间所需的全部内容放入 RAM。

最终、我设法使用以下优化设置使整个过程正常运行:

使用此选项、内联函数会正确内联、一切都从 RAM 执行:

但在调试期间

 我观察到 IPC_waitForFlag()跳转到闪存(已被擦除):

现在的问题:即使优化功能已关闭、如何将这些内联函数放置在 RAM 中?

此致

Johannes

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

    您好!

     我观察到, ipc_waitForFlag()跳进闪存(已被擦除):

    由于您将整个代码从闪存写入 RAM、除非此函数从未复制到 RAM 中、否则开启或关闭优化应该无关紧要。 如果这个函数不是您复制到 RAM 的两个库的一部分、那么您需要在链接器 cmd 文件中明确提及这一点以便复制到 RAM 中。

    此致、

    Vivek Singh

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

    尊敬的 Vivek Singh:

    完成

    #pragma code_section (IPC_ackFlagRtoL、".TI.ramfunc")
    #pragma code_section (IPC_waitForFlag、".TI.ramfunc")
    #pragma code_section (IPC_isFlagBusyRtoL、".TI.ramfunc")
    #pragma CODE_SECTION (GPIO_writePin、".TI.ramfunc")
    #pragma code_section (GPIO_isPinValid、".TI.ramfunc")
    #pragma code_section (Flash_releasePumpSemaphore、".TI.ramfunc")
    #pragma code_section (Flash_laimPumpSemaphore、".TI.ramfunc")

    我的代码也可以在优化关闭的情况下运行。

    我发现这一要求非常违反直觉!

    在我看来、这些函数是 driverlib (或闪存 API)的一部分、当我使用链接器命令文件请求将这些库放置在 RAM 中时、工具链应将它们放入 RAM 中。

    此致

    Johannes

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这些函数是 driverlib (或闪存 API)的一部分,当我使用链接器命令文件请求将这些库放置在 RAM 时,工具链应将它们放置在 RAM 中[/引号]

    我同意。  我将重点关注总体问题的一小部分。  我相信解决这一问题将会解决其余问题。

    您第一篇文章的第一个屏幕截图显示了链接器命令文件中的几行内容。  它会创建输出段 .TI.ramfunc 。  库中所有目标文件的目录结构 F2838x_CM_FlashAPI.lib 重复使用该函数 .text 输入段应该是其中的一部分  .TI.ramfunc 。  但事实并非如此。  而是 .text 来自库中引入的目标文件的输入段  F2838x_CM_FlashAPI.lib 重复使用该函数 输出部分的一部分。  (可能是另一个输出节 .text ,但这不是问题的直接部分。  为什么?

    我试图在小规模上重现此问题。  但我不能。  

    请添加选项 -- emit_references=link_references 您的 CCS 项目中。  下方显示了一个屏幕截图。  再次构建项目。  这会使链接器创建一个报告、该报告除其他外显示各段如何相互引用。  它包含在名为的文件中 link_references.txt 通常位于以当前构建配置命名的目录中 调试 。  将该文件与链接器映射文件一同放入 zip 文件中、并 该 zip 文件附加到下一篇文章中。

    谢谢。此致、

    -George.

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

    您好、George、

    感谢您的答复。 我将附加链接器输出文件 e2e.ti.com/.../link_5F00_references.zip (在进行优化和不进行优化的情况下生成)

    我真的不太了解映射文件(在关闭优化的情况下生成)的所有详细信息、但以下行(与内联函数相关)看起来有点可疑:

                     00207af4   00000008    fw_update_cm.obj (.tramp.ipc_waitForFlag.1)
                     00207afc   00000008    fw_update_cm.obj (.tramp.ipc_ackFlagRtoL.1)

    此致

    Johannes

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

    您好、Johannes:

    没错--看起来链接器在未优化的情况下正在为 IPC_waitForFlag 创建 far 调用 trampoline,而且实际上根据映射文件,它看起来像 IPC_waitForFlag 不包含在.TI.ramfunc 中,而是包含在标准.text 输出段中。 它本身正在拆分(根据您所说的内容、可能在闪存中)。  我怀疑这就是为什么为 IPC_waitForFlag 使用显式 CODE_SECTION pragma 是有效的、因为它以显式方式强制进行放置。

    从映射文件所指示的情况来看、这些对象似乎并不是您已创建的 driverlib_cm.lib 库的一部分。  您能否澄清库结构、并尝试在链接器命令文件中专门将这些目标文件中的.text 段作为.TI.ramfunc 输出段定义的一部分?

    -艾伦

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

    您好、Alan!

    对于我的工程、我没有创建 driverlib_cm.lib、我只是从 C2000ware 4.02中将一个复制到工程中。

    我不明白你所说的"澄清图书馆结构"是什么意思。

    请查看随附的示例工程(基于 C2000ware 4.02中的 led ex1_blinky 示例)。 e2e.ti.com/.../inline_5F00_function_5F00_placement_5F00_problem.zip

    我的修改如下:

    构建配置从 RAM 更改为闪存。

    使用将 driverlib_cm.lib 放置到 RAM 中

    我已经在项目的 CM 部分中添加了一个函数 foo()来演示问题:

    GPIO_writePin ()被放置在闪存中,而非内联函数 IPC_readCommand ()被正确放置在 RAM 中。

    我希望这有助于进一步调查该问题。

    此致

    Johannes

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

    您好、Johannes:

    我要求 您澄清 driverlib_cm.lib 的内容、因为在工程的非优化版本中、 似乎存在对 其他目标文件中 放入 ROM 的函数的调用。  例如、IPC_waitForFlag 似乎在 Ethernet_cm.obj 中定义、它不是 driverlib_cm.lib 的一部分(如果我错、请回答正确)、但它正在被.TI.ramfunc 中的某个对象调用(并从 RAM 运行)。  这是从您发送的 link_references.txt 中备份的、这表明 IPC_waitForFlag 正在从 FW_copy_from_CPU2 ()中调用、该文件放置在.TI.ramfunc 中(并从 RAM 运行):

    section .text:ipc_waitForFlag:fw_update_cm.obj:

    分区大小:40.

    未定义符号

    输入基准:
    在偏移处从符号到符号的段
    ---------------- ---------------- ---------------- ----------------
    .TI.ramfunc:fw_copy_from_cpu2:fw_update_cm.obj fw_copy_from_CPU2 IPC_waitForFlag 40.  

    上述问题:"在我看来、这些函数是 driverlib (或闪存 API)的一部分、当我使用链接器命令文件请求将这些库放置在 RAM 中时、工具链应将它们放入 RAM 中"、  我的建议是确保 使用链接器命令文件放置方法在.TI.ramfunc 中也包含所引用函数的定义。  如果您在其中包含了 ethernet_cm.obj 和 fw_update_cm.obj、会出现什么情况?

    .TI.ramfunc : {
        -l F2838x_CM_FlashAPI.lib(.text)
        -l driverlib_cm.lib(.text,.const)
        ethernet_cm.obj(.text)
        fw_update_cm.obj(.text)
    } LOAD = CMBANK0_SECTOR0 | CMBANK0_SECTOR1, ...

    否则、您最终会得到返回到闪存中的 far call trampolines、这听起来好像是您的问题的根源。

    请注意、在.TI.ramfunc 中放置了 Ethernet_cm.obj 和 fw_update_cm.obj 中的其他函数、但这是因为使用了 C SECTION pragma 将它们放置在那里。

    -艾伦

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

    您好、Alan!

    、会发生类似以下的情况:

    作为这些函数(IPC_waitForFlag、IPC_ackFlagRtoL、...) 声明为静态内联、它们不是 driverlib_cm.lib 的一部分、但其编译版本会包含在 C 源代码使用它们的每个目标文件中(包括它们在中定义的标头)。

    只要优化被打开、它们就会被内联、只要使用它们的函数被放置在 RAM 中、被内联的东西也会被放置在那里。

    当优化关闭时、编译器不会内联它们、而是创建可调用函数、并将它们放入需要它们的每个目标文件中。

    最后、链接器选择其中一个将其放入 out 文件。 (但哪一个呢?)

    这只是一个有经验的猜测。。。 我不是编译器专家!

    我的问题是、这种行为在很大程度上是无法预料的: 我使用 driverlib 函数、将 driverlib 的.text 段放入 RAM 中、但还需要将项目的一些其他目标文件的.text 段放入 RAM 中、以便将某些 driverlib 函数(静态内联函数)放入 RAM 中。 这种做法违反了直觉!

    此外、我无法控制哪些"其他目标文件"最终会包含这些函数。 至少,我还不知道该怎么做!

    此致、

    Johannes

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

    您错误地假定 a 静态内联 函数始终继承调用方的段。  你的描述基本上是正确的...

    作为这些函数(IPC_waitForFlag、IPC_ackFlagRtoL、...) 声明为静态内联、它们不是 driverlib_cm.lib 的一部分、但其编译版本会包含在 C 源代码使用它们的每个目标文件中(包括它们在中定义的标头)。

    只要优化被打开、它们就会被内联、只要使用它们的函数被放置在 RAM 中、被内联的东西也会被放置在那里。

    当优化关闭时、编译器不会内联它们、而是创建可调用函数、并将它们放入需要它们的每个目标文件中。

    [/报价]

    正确、直到完成最后一句的最后部分。  在包含头文件的每个文件中创建可调用函数、如所示 静态内联 函数的定义。  只要假装就是 内联 是的一部分 静态内联 忽略该函数。  请参阅这些部分 静态 放置在中的函数不是由调用方决定的、而是由任何的编译器的默认设置决定的 静态 停止。   

    此行为非常意外

    我理解您为什么这样思考。  不过、这不是它的工作方式。

    我有一个解决方案可以提出。  应用编译器构建选项 --- ramfunc=on 不适用于整个项目、而适用于包含头文件的 C 文件 静态内联 通信功能。  针对文件特定选项使用 CCS 功能执行此操作。  下方显示了一个屏幕截图。  显示将选项应用于文件  led_ex1_c28x_cm_blinky_cm.c 创建一个目标配置文件。  

    谢谢。此致、

    -George.   

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

    您好、George、

    感谢您花时间解释并尝试找到解决方案。

    我尝试了你的建议:"应用编译器构建选项--ramfunc=on 不是整个项目,而是对包含带有静态内联函数的头文件的 C 文件。" 这意味着必须将此选项应用于包含 driverlib_cm.h 的每个文件! 在本例中,这也包括了文件的 main ()。 这不起作用,因为将.TI.ramfunc 代码从闪存复制到 RAM (在 main()的开头)的代码必须从闪存执行。

    所以, 我只对包含固件更新内容的文件应用了--ramfunc=on 选项,即使在优化关闭的情况下,该选项现在似乎也可以工作。 即使我对解决方案不完全满意、我也会将问题标记为已解决。

    此致、

    Johannes