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.

[参考译文] MSP430F5438A:勘误表 CPU27似乎也适用于 RET 指令

Guru**** 2539040 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1053953/msp430f5438a-errata-cpu27-seems-to-apply-to-ret-instruction-as-well

器件型号:MSP430F5438A

勘误表 CPU27指出:

当在已启用的中断服务例程内进入低功耗模式时
嵌套中断(通过设置 GIE 位)以及设置低功耗的指令
MODE 后面紧跟 RETI 指令、推至错误的 PC + 2值
在上下文保存期间运行堆栈。 因此、RETI 指令不会在返回时执行
并且 PC 会损坏。

我看到 此代码出现了类似的行为(有时!) 破坏程序计数器:

    /*
     * We cannot use the __bis_SR_register intrinsic here, as the readback
     * from latched_flags into a general purpose register and writing to the
     * SR register is not necessarily atomic.
     * __bis_SR_register(latched_flags);
     */

    __asm__ __volatile__
    (
        "bis.w lpm_latched_flags, SR\n"
        "ret\n"
        :
        :
        : "cc", "memory"
    );

其中"lpm_LATCH_flags"是一个16位整数、包含一些睡眠标志(例如 LPM3 + GIE 或 LPM0 + GIE)。

在"bis.w"和"ret"指令之间添加"nop"后、我没有观察到任何进一步的崩溃。

在我看来、就像 Errata CPU27不是嵌套中断所独有的、而是使用"ret"和"reti"指令。

到目前为止、这是供参考的。

我有第二个问题。 在这种情况下、我尚未观察到它崩溃、但您能确认序列

eint
ret

安全吗? (显然、在这种情况下、任何 LPM 标志都不会被置位)

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

    您好、Thilo、

    感谢您对勘误表 CPU27的反馈。

    关于您的第二个问题、我同意这在勘误表 CPU27中应该是安全的、但在设置 GIE 时需要特别注意。 用户指南第6.6.2.20节"EINT"中有一个具体说明。

    此外、您是否使用 RET 从中断返回? 如果是、您可能会遇到代码问题、因为 RET 和 RETI 会从堆栈中弹出不同的项目。 您可以参阅此主题以了解更多详细信息[link]

    谢谢、

    王国新

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

    谢谢、我知道6.6.2.20、并且 没有此类 DINT/EINT 序列。

    [引用 userid="489743" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1053953/msp430f5438a-errata-cpu27-seems-to-apply-to-ret-instruction-as-well/3898959 #3898959]*此外、您是否使用 RET 从中断返回? 如果是、您可能会遇到代码问题、因为 RET 和 RETI 会从堆栈中弹出不同的项目。 您可以参考此主题以了解更多详细信息

    _asm_()段  会作为中断上下文的一部分执行。 请注意、中断永远不会被禁用、并且在执行"bis.w lpm_latched_flags、 SR"指令之前、一个中断可以立即清除 lpm_latched_flags 中的任何 LPM 标志。

    我已验证 崩溃是由于"设置 LPMX + GIE、SR;RET"导致的、方法是在__ASM__()段之前递增全局计数器变量、并在我的睡眠函数返回后递增第二个全局计数器变量。 如果发生崩溃(PC 损坏)、第二个计数器比第一个计数器少一个。

    下面是完整的函数(sans 计数器、但 nop 看起来是必需的):

    void Lpm_Sleep(void)
    {
    #ifdef __MSP430_HAS_UCS__
        uint8_t sels = UCSCTL4_L & UNSIGNED(SELS_7);
    
        /* Check whether DCO must be kept enabled (LPM0) */
        if(sels == UNSIGNED(SELS__DCOCLK) || sels == UNSIGNED(SELS__DCOCLKDIV))
        {
            if(smclk_req_users > 0U || smclk_users > 0U)
                Atomic_Andn(lpm_latched_flags, UNSIGNED(SCG0) | UNSIGNED(SCG1));
        }
    
        if((!(UCSCTL8 & UNSIGNED(SMCLKREQEN)) && smclk_req_users) || smclk_users)
            UCSCTL6 &= ~UNSIGNED(SMCLKOFF);
        else
            UCSCTL6 |= UNSIGNED(SMCLKOFF);
    #endif
    
        /*
         * We cannot use the __bis_SR_register intrinsic here, as the readback
         * from latched_flags into a general purpose register and writing to the
         * SR register is not necessarily atomic.
         * __bis_SR_register(latched_flags);
         */
    
        __asm__ __volatile__
        (
            "bis.w lpm_latched_flags, SR\n"
            "nop\n"
            :
            :
            : "cc", "memory"
        );
    }
    

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

    您好、Thilo、

    感谢您的澄清。 我会将您的调查结果传递给您。

    关于第二个问题、如果您可以保证 EINT 之后没有 DINT (GIE 设置/清除事件不会背对背发生)、这应该是安全的、如该主题[link]中所述、 根据用户指南第4.6节"指令集说明"、RET 不会影响 GIE 位。

    谢谢、

    王国新