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.

[参考译文] MSP430FR2476:通过 RTC 中断从 LPM3.5模式唤醒并不总是有效

Guru**** 2513185 points
Other Parts Discussed in Thread: MSP430FR2476

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1112217/msp430fr2476-waking-up-from-lpm3-5-mode-via-rtc-interrupt-does-not-always-work

器件型号:MSP430FR2476

您好!

我们设计了采用 MSP430FR2476的电路板、该电路板在大多数时间都以低功耗模式运行。 RTC 中断每分钟从 LPM3模式唤醒一次控制器、如果控制器处于 LPM3.5模式、则每30分钟唤醒一次控制器以更新日期和时间。 控制器在无活动两小时后进入 LPM3.5。 通常、固件工作正常、日期/时间正确。 但有时(几天后)控制器不会从 LPM3.5唤醒。 只有复位才能再次启动控制器。 它们不应该是电源问题、因为电池已满、复位后、控制器再次正常工作。 不幸的是,无法以明确的方式追踪问题。 有时、它发生在一天之后、有时发生在几天后。

进入 LPM3.5的代码:

WDT_A_hold(WDT_A_BASE);                  // Disable Watchdog
PMMCTL0_H = PMMPW_H;                 // Open PMM Registers for write
PMMCTL0_L |= PMMREGOFF;                  // Disable power regulator
__bis_SR_register(LPM3_bits + GIE); // Enter LPM3.5, with interrupts enabled
__no_operation();                 // Do nothing (just for debugging)

我们的初始化函数:

void BL_Init()
{
    // Configure FRAM write protection
    SYSCFG0 = PFWP | DFWP | FRWPPW | FRWPOA5 | FRWPOA4 | FRWPOA3 | FRWPOA2 | FRWPOA1 | FRWPOA0;

    SysCtl_enableFRAMWrite(SYSCTL_FRAMWRITEPROTECTION_DATA | SYSCTL_FRAMWRITEPROTECTION_PROGRAM);

    // Wake up routine according to datasheet section 1.4.3.3 (Wake up from LPM3.5)
    // 1. Init RTC, but do not enable interrupts
    // Get current time from ConfigReg
    rtcTime_t currTimeBuf = GetConfigRegister().Timestamp;
    __time64_t timeBuf;
    ConvertToUTCTimeType(&timeBuf, &currTimeBuf);
    // Initialize RTC with Deep Sleep Timings
    RTC_init(RTC_BASE, (uint16_t) RTC_INT_DEEP_SLEEP_SECONDS * RTC_FREQUENCY, RTC_CLOCKPREDIVIDER_1024);
    // Add current time in rtccnt
    uint16_t time = RTCCNT + FRAM_GetRTCDivError();
    timeBuf += time / RTC_FREQUENCY;
    FRAM_SetRTCDivError(time % RTC_FREQUENCY);
    // Start and reset RTC
    RTC_start(RTC_BASE, RTC_CLOCKSOURCE_XT1CLK);
    ConvertFromUTCTimeType(&currTimeBuf, timeBuf);
    SetConfigRegisterTimeStamp(&currTimeBuf);
    //2. Initialize Port registers, without enabling interrupts
    GPIO_Init();
    //3. LF Crystal
    Clk_Init();
    //4. Clear the LOCKLPM bit
    PM5CTL0 &= ~LOCKLPM5;
    //5. Enable port interrupts as necessary
    GPIO_EnableInterrupts();
    //6. Enable module interrupts
    ADC_Init();

    RTC_enableInterrupt(RTC_BASE, RTC_OVERFLOW_INTERRUPT);

    Hardware_Version hwVersion = ReadHardwareVersion();
    //7. After enabling the port and module interrupts, the wakeup interrupt is serviced as normal interrupt
    __enable_interrupt();
    
    ...
}

是否有办法找出为何阻止唤醒?


此致

Christian

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

    尊敬的 Christian:  

    只是为了缩小可能性、因为您无法始终如一地重现错误似乎有点奇怪、您是否尝试在另一个 FR2476上运行相同的代码?  

    您从时钟源看到了什么行为? 是否有不一致之处?  

    此致、  

    Henok

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

    您好、Henok、

    是的、我们在使用相同固件的多个电路板上遇到了此问题。 奇怪的是、如果我添加进一步的调试输出以缩小错误范围、则不会发生错误。 但这不是解决方案、因为误差可能会在较长的时间后发生。 因此、我们必须找到该误差。

    我还认为时钟源可能是错误源。 我用冷却喷雾器和热气枪在电路板上造成了严重的温度波动、但不会出现此错误。

    感谢您的建议!

    Christian

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

    Christian、  

    嗯、好的、那么代码肯定会有问题。 这类问题对我来说有点陌生、我将与队友联系。  

    您使用的是 VLOCLK 还是 XT1CLK?

    同时、您能否共享 RTC 中断服务例程? 我想看看如何实施这项计划。

    此致、  

    Henok

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

    您好、Henok、

    我在周五进行了进一步测试、大约三小时后实际调试版本也会出现唤醒问题。 这是在第一次进入 LPM3.5后首次发生。

    我们将 XT1CLK 用于 RTC:

    RTC_start(RTC_BASE, RTC_CLOCKSOURCE_XT1CLK);

    我们的 RTC ISR:

    /*
     * RTC-overflow after every minute -> add 60 seconds to utcTimestamp
     * Overflow after RTC_INT_SECONDS in LPM3
     * Overflow after RTC_INT_DEEP_SLEEP_SECONDS in LPM3.5
     */
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(RTC_VECTOR)))
    #endif
    void RTC_ISR(void)
    {
    
        rtcTime_t currTimeBuf;
        __time64_t secTimeBuf;
        static uint8_t rtc_minuteDiv = 0;
        switch (__even_in_range(RTCIV, 2))
        {
        case 0:
            break;  //No interrupt pending
        case 2:         //RTC overflow/interrupt pending
    
            // ISR is called every minute and will store the 60s in utcTimeStamp
            if (GetStatusRegister().ContinuousMode_EN){
                secSince1970value += RTC_INT_SECONDS;
                // FRAM must not be edited, as RAM is not lost during continuous mode operation
            }else{
                currTimeBuf = GetConfigRegister().Timestamp;
                ConvertToUTCTimeType(&secTimeBuf, &currTimeBuf);
                if(GetStatusRegister().DeepSleep_EN){
                    secTimeBuf += RTC_INT_DEEP_SLEEP_SECONDS;
                    RTC_ADC_ISR(); // This is called every wake up during LPM3.5, as rtc_minuteDiv is lost
                }else{
                    secTimeBuf += RTC_INT_SECONDS;
                    secSince1970value += RTC_INT_SECONDS;
                }
                ConvertFromUTCTimeType(&currTimeBuf, secTimeBuf);
                SetConfigRegisterTimeStamp(&currTimeBuf);
            }
            rtc_temperatureFlag = true;
            rtc_lightFlag = true;
    
            rtc_minuteDiv++;
            if (rtc_minuteDiv >= RTC_INT_ADC_MIN) // this part is called every hour, during LPM3
            {
                rtc_minuteDiv = 0;
                RTC_ADC_ISR();
            }
    
            // Wake-up controller
            __bic_SR_register_on_exit(LPM3_bits);
            break;
            
        default:
            FRAM_SetErrorCode(ERR_RTC_ISR_NOT_HANDLED);
            GPIO_ToggleDebugPin(DEBUG_ERROR_3);
            break;
        }
    }
    

    感谢您的帮助!

    Christian

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

    尊敬的 Christian:  

    感谢您的分享。 将在24小时内返回给您。  

    此致、  

    Henok

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

    您好、Christian、很抱歉耽误您的时间、这是一个非常繁忙的星期。  

    代码中的任何内容都不会弹出、因此这里 是一个选项。

    您可以将 RTC 扩展到更快的时间吗? 例如、不必等待3小时、让唤醒速度更快地递增。 让我们看看我们是否了解故障所在。 假设您将所有内容扩展到相同的程度(例如、缩短10倍的周期)、我们应该在更快的时间看到相同的行为。  

    此致、  

    Henok

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

    您好、Henok、

    很抱歉、我忘记提到我们已经用系数10扩展了所有内容。 我还认为这种情况会更频繁发生、但使用较快的版本时、问题从未发生过。

    我们在晶体上进行了更多测量、但时钟信号始终保持稳定。

    在进入 LPM3.5时,我发现与用户指南有一个偏差。 第1.4.3.1节规定、在进入 LPM3.5之前、应清除通用中断使能(GIE)。 因此、我更改了以下代码:

    // Enter LPM3.5
    while (1)
    {
        WDT_A_hold(WDT_A_BASE);                 // Disable Watchdog
        __bic_SR_register(GIE);                 //  clear the GIE bit
        PMMCTL0_H = PMMPW_H;                    // Open PMM Registers for write
        PMMCTL0_L |= PMMREGOFF;                 // Disable power regulator
        __bis_SR_register(LPM3_bits | GIE);     // Enter LPM3.5, with interrupts enabled
        __no_operation();                       // Do nothing (just for debugging)
    }

    这样做是否正常?

    奇怪的是、如果我不再次启用 GIE、控制器仍然会被 GPIO 或 RTC 中断唤醒。 这是正确的行为吗?

    此致、

    Christian

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

    尊敬的 Christian:  

    我 不认为第5行是必要的。 我正在查看我们的其中一个 RTC 示例、但我没有在那里看到它。  

    您是否正在研究此示例?  https://dev.ti.com/tirex/explore/node?node=AHHV7PMTsKxeoPY6Yj2nEA__IOGqZri__LATEST

    还需要在 while 循环中进行这些初始化吗? 这些通常在主设置中。

    此致、  

    Henok

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

    我不知道你原来的问题的答案、但对于你的其他问题:

    1) 1)禁用(第1.4.3.1节、步骤(8))就我所知、只是为了避免在 LPM 设置期间中断(接下来的3行)。 尽管如此、如果您有许多杂散中断、我想忘记这么做可能会导致间歇性故障。

    2) 2) GIE 在 LPMx.5模式下不工作、因为 CPU 已断电。 在 LPM 线上设置 GIE 是为了实现引脚唤醒、它来自第8.3.3节(b)"注意"、以避免在前3条代码行中 WAKEUP 引脚转换的竞争、从而在以后无法识别转换。 使能允许 ISR 在 LPM 之前(在最后时刻)运行。 我没有看到 RTC 唤醒的类似说明、因此我认为这不适用。

    [编辑:我忘记问:如何知道它没有被唤醒? (例如)它是否可能确实唤醒、但随后发生故障? 这种区别有助于了解朝向哪个方向。]

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

    您好、Henok、

    正如 Bruce 提到的、我希望避免在 LPM 设置期间被中断。 我将测试在今天进入 LPM 设置期间发生中断时是否会出现问题。

    是的、我知道这个示例、它与我们使用的序列完全相同。 唯一的区别是我们没有区分从 LPM3.5发出还是常规复位。 正常情况下不会重置设备。

    不需要 while 环路。 只有在首次出错时才能确保进入 LPM3.5。 但你是对的。 如果进入 LPM3.5时出现问题,则第二次、第三次...时间也可能会失败。 这会导致无限循环。 我将移除 while 环路。 如果进入 LPM3.5确实有问题、我可以测量电流消耗曲线。

    谢谢

    Christian

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

    您好、Bruce、

    非常感谢您的回答。

    我们的板可以通过 SPI 接口进行通信。 因此、我们有一个 GPIO 引脚来唤醒控制器并将其保持在连续模式。 如果问题发生、则通过 GPIO 引脚唤醒也不起作用、SPI 通信失败。

    我还将测量电流消耗曲线、以分析控制器是处于 LPM3、LPM3.5还是正常模式。 但问题很少发生,以至于我还没有对它进行测量。

    此致、

    Christian

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

    Christian、  

    [引用 userid="525397" URL"~μ C/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/low-power-microcontrollers-forum/1112217/msp430fr2476-rast-wing-from-lpm3-5-mode-via rtc-interrc-do-do-do-we-do-do-we-do-we-where-trads/4130017"、以避免在上述设置过程中中断 Bruce 130017"、如我所述 L1300417"。 我将测试在今天进入 LPM 设置期间发生中断时是否会出现问题。

    我也想看看您从中找到的内容。 这似乎是问题所在。

    [引用 userid="525397" URL"~μ C/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/low-power-microcontrollers-forum/1112217/msp430fr2476-rast-wing-from-lpm3-5-mode-via rtc-interrc-do-do-do-we-do-do-dow-use-work /4130017]如果第三次进入 PM43.5,则第三次出现故障,如果第三次进入 PM4175.5',则第三次出现故障。 这会导致无限循环。 我将删除 while 循环。

    我同意、这是我对 while 循环的关注。

    请告诉我您的发现。 我也会继续寻找。

    此致、  

    Henok

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

    您好、Henok、

    我尝试通过在进入 LPM3.5期间触发几个中断来重现 while 循环的问题、但并未发生。 我已移除 while 环路并开始长期测试。 一个安装程序在一周内运行、没有任何问题。 我们将使用多个设置重复此测试、以确保问题得到解决。

    我还有一个问题:如果控制器无法进入 LPM3.5、我想触发软件复位。 最佳解决方案是什么? 我将 LPM3位清零以唤醒控制器、并将 PMMCTL0寄存器中的软件 POR 位置位(请参阅下面的代码)。 这是可以的、还是有更好的解决方案?

    此致、

    Christian

    // Enter LPM3.5
    WDT_A_hold(WDT_A_BASE);             // Disable Watchdog
    __bic_SR_register(GIE);             // Clear the GIE bit
    PMMCTL0_H = PMMPW_H;                // Open PMM Registers for write
    PMMCTL0_L |= PMMREGOFF;             // Disable power regulator
    __bis_SR_register(LPM3_bits + GIE); // Enter LPM3.5, with interrupts enabled
    __no_operation();                   // Do nothing (just for debugging)
    // The following code shall not be reached in normal cases, only if entering LPM3.5 mode fails
    __bic_SR_register(LPM3_bits);
    // Trigger a reset by software
    PMMCTL0 = PMMPW|PMMSWPOR;

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

    尊敬的 Christian:  

    很棒! 看起来我们在找一个地方。

    因此、有几种方法可以像使用那样使用 PMM、或实现看门狗计时器。  

    在看门狗情况下、当 CPU 未馈送 PUC 时、会发生 PUC 复位。 由于您在此处设置间隔、因此它实际上可能比执行 POR 更快。  

    此致、  

    Henok