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.

[参考译文] TMS320F280041:未正确编译内联函数

Guru**** 2535750 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/989815/tms320f280041-inline-function-not-compiled-properly

器件型号:TMS320F280041

您好!

似乎没有正确编译简单的内联函数。  以下是清除寄存器位的内联函数:

static inline void
CAN_disableMailbox(uint32_t base, uint16_t mbx)
{
    (*((volatile uint32_t *)((uintptr_t)(base + 0U + 0x0U)))) &= ~(((uint32_t) 1U) << (mbx-1U));
}

让我们假设被修改的寄存器的初始值为0。 当上述函数被执行为"内联"时、函数后的寄存器为0xFFFFFF0000、当它被执行为常规静态函数时、寄存器为0x00000000。

我仍在尝试从 ASM 中找出导致此问题的根本原因。

您是否认为上述实施存在问题?

如果我按以下方式展开函数行、它将按预期工作:

uintptr_t ptr = (uintptr_t) (priv->base + 0U + 0x0U);
volatile uint32_t *pptr = (volatile uint32_t *) ptr;
uint32_t reg = *pptr & ~(((uint32_t) 1U) << (mbx - 1U));
*pptr = reg;

但是、它不能以缩写形式工作:

*pptr &= ~(((uint32_t) 1U) << (mbx - 1U));

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

    对于包含调用此函数的源文件,发生此情况时...

    [引用 userid="347262" URL"~/support/microcontrollers/c2000/f/c2000-microcontrollers-forum/989815/tms320f280041-inline-function-not-compiled-properly "]当上述函数作为"内联"实现时,函数后的寄存器为0xFFFFFF0000[/引用]

    (笑声)  请按照文章 How to Submit a Compiler Test Case 中的说明进行操作。  如果在此源文件中有多个对 CAN_disableMailbox 的调用、请指明哪个调用存在此问题。

    谢谢、此致、

    乔治

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

    问题似乎不是内联函数本身、而是具有"volatile uint32_t *"类型指针的表达式:

    // None of the patterns below work correctly when 'ptr' is of
    // "volatile uint32_t *" type and 'val' is of "uint32_t" type
    *ptr = *ptr | val;
    *ptr |= val;
    *ptr = *ptr & ~val;
    *ptr &= ~val;
    
    // This works correctly
    reg = *ptr;
    *ptr = reg | val;
    *ptr = reg & ~val;

    P.S. 我在私人邮件中向您发送了源文件(预处理文件)。

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

    我收到了测试用例。  谢谢你。  很抱歉今天没能参加。  我希望明天能先看一下。

    谢谢、此致、

    乔治

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

    不用担心、我有 权解决问题、但仍想了解这里发生了什么。

    我注意到、在 driverlib 中的 hw_types.h 中、有两个宏:

    #define HWREG(x)                                                              \
            (*((volatile uint32_t *)((uintptr_t)(x))))
    #define HWREG_BP(x)                                                           \
            __byte_peripheral_32((uint32_t *)(x))

    两者之间的区别是什么? 这是否是我遇到问题的根本原因?

    为了提供一些背景信息、我尝试使用 HWREG 宏修改32位 CAN 寄存器、如下所示:

    HWREG(addr) |= val;

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

    我不确定、但我怀疑您受到先前报告的问题 EXT_EP-10160的影响。  您当前使用的是编译器版本18.12.1.LTS。  在版本20.2.4.LTS 中修复了该问题。  更新 编译器一文 介绍了如何更新编译器。  尝试版本20.2.4.LTS 以查看其是否解决了问题、是否可行?

    谢谢、此致、

    乔治

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

    我尝试了20.12.0.STS (最新版本)、但它没有解决问题。 我是否应该尝试使用20.2.4.LTS?

    我在私人邮件中向您发送了更多文件。

    您能在我的最后一封邮件中查看问题吗? 如果我使用 HWREG (x)来修改32位外设寄存器、它似乎不起作用、但是如果我使用 HWREG_BP (x)、它似乎起作用。 这是否是根本原因、两者之间的区别是什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="347262" URL"~/support/microcontrollers/c2000/f/c2000-microcontrollers-forum/989815/tms320f280041-inline-function-not-compiled-properly/3659495 #3659495]\n 似乎如果我使用 HWREG (x)修改32位外设寄存器、它不起作用、但如果我使用 HWREG_BP (x)、它似乎起作用。 这是否是根本原因

    也许吧。  我缺乏专业知识来回答。  我已通知 C2000专家可以提供帮助。

    谢谢、此致、

    乔治

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

    SPRAA85E 第7.1节"eCAN 控制寄存器"(第23页)似乎可以提供这里发生的情况的答案。

    对 eCAN 控制32位寄存器的访问不能被分成两个16位访问、这实际上发生在我的情况下。 下面是对"有问题"代码的反汇编。 请注意对 XAR4的两次16位访问、其中*+ XAR4[0]和*+ XAR4[1]是单个 eCAN 控制寄存器的低16位和高16位。

    000082cd   a9a9   MOVL         ACC, P
    000082ce   8ae3   MOVL         XAR4, *+XAR3[4]
    000082cf   ff55   NOT          ACC
    000082d0   1e46   MOVL         *-SP[6], ACC
    000082d1   9246   MOV          AL, *-SP[6]
    000082d2   c0c4   AND          *+XAR4[0], AL
    000082d3   9245   MOV          AL, *-SP[5]
    000082d4   c0cc   AND          *+XAR4[1], AL
    000082d5   92d1   MOV          AL, *+XAR1[2]
    000082d6   56c1   BF           210, EQ

    另一方面、如果我使用 __byte_peripheral_32 ()编译器内在函数,则访问不会中断。 这是对工作代码的反汇编。 请注意对 eCAN 控制寄存器*+ XAR4[0]的单个32位访问。

    000082cd   8ae3   MOVL         XAR4, *+XAR3[4]
    000082ce   06a6   MOVL         ACC, XAR6
    000082cf   ff55   NOT          ACC
    000082d0   ff5a   MOVL         P, ACC
    000082d1   06c4   MOVL         ACC, *+XAR4[0]
    000082d2   ceab   AND          AL, PL
    000082d3   cfaa   AND          AH, PH
    000082d4   1ec4   MOVL         *+XAR4[0], ACC
    000082d5   92d1   MOV          AL, *+XAR1[2]
    000082d6   56c1   BF           205, EQ

    请您确认这确实可能是我所遇到问题的根本原因吗?

    后续问题:访问32位外设寄存器时、我是否应该始终使用__byte_peripheral_32 ()编译器内在函数? 除了编译器无法(可能)进行某种优化之外、使用此内在函数是否存在任何缺点?

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

    您好、Marko、

    CAN 外设专为8位字节可寻址架构而设计、C2000器件是16位字节机器、添加了一个地址/数据总线桥来转换访问、以便 C28x 能够与 CAN 连接。

    在更高的优化下、编译器可以将对 CAN 寄存器的32位写入转换为两个16位访问、这可能会导致使用使用字节寻址的 CAN 总线桥接器时出现问题

    "__byte_peripheral_32"内在函数是访问此类外设的最佳方式。  内部基本阻止代码将32位转换为两个与字节桥混乱的16位访问。  请参阅以下相关文章  

    https://e2e.ti.com/support/microcontrollers/c2000/f/c2000-microcontrollers-forum/442233/controlsuite-can-change-information/1586639#1586639

    使用此内在函数不会产生其他副作用。

    此致

    Siddharth