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.

[参考译文] MSP430FR2433:从 LPM3.5唤醒时、更新 RTC_ISR 函数中 FRAM 中的 PERSISTENT 变量?

Guru**** 2524550 points
Other Parts Discussed in Thread: MSP430FR2433

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1118033/msp430fr2433-updating-persistent-variable-in-fram-in-rtc_isr-function-when-waking-up-from-lpm3-5

器件型号:MSP430FR2433

您好!

我正在使用 MSP430FR2433 MCU、它 配置为进入 LPM3.5并使用 RTC 中断每1秒唤醒一次。 现在、我尝试在 RTC_ISR 中的每次 RTC 唤醒时更新 FRAM 中存储的 PERSISTENT 变量、但这些变量在 RTC_ISR 函数中不会更新。  因此 、我 在每次 RTC 唤醒后尝试更新主函数中的变量、这次它正确更新。

我认为这可能是由于 MCU 在能够完成 FRAM 更新过程之前会处于睡眠状态、 因此、我 在寻找 FRAM 寄存器来检查操作是否正在进行、但我无法在系列用户指南或任何示例中的任何位置找到它。

谢谢

Jeevant Sah

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

    对 FRAM 的写入(实际上)是瞬时的、因此(据我所知)没有"正在写入"标志。  

    在 LPM3.5唤醒期间、由于初始中断被禁用、RTC ISR 实际上在 main ()被输入一段时间后被调用。 因此、它们会有所不同、这似乎很奇怪。 如何在每种情况下关闭写保护? 您可能需要 PFWP=0、因为"TI.persistent"部分通常放在程序 FRAM 中。

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

    您好、Bruce、

    感谢您的快速回复。

    我使用以下 RTC_ISR 代码来更新变量:

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = RTC_VECTOR
    __interrupt void RTC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch(__even_in_range(RTCIV, RTCIV_RTCIF))
        {
            case RTCIV_NONE : break;            // No interrupt pending
            case RTCIV_RTCIF:                   // RTC Overflow
    
                SYSCFG0 = FRWPPW | DFWP;            // Program FRAM write enable
                incrementSeconds();                 // This function increment seconds persistent variable in assembly language
                SYSCFG0 = FRWPPW | PFWP | DFWP;     // Program FRAM write protected (not writable)
                
                break;
            default:          break;
        }
    }

    我使用此代码在 main 中更新它:

    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop WDT
    
        initGpio();                             // Configure GPIO
    
        // Initialize XT1 32kHz crystal
        P2SEL0 |= BIT0 | BIT1;                  // set XT1 pin as second function
        do
        {
            CSCTL7 &= ~(XT1OFFG | DCOFFG);      // Clear XT1 and DCO fault flag
            SFRIFG1 &= ~OFIFG;
        } while (SFRIFG1 & OFIFG);              // Test oscillator fault flag
    
        // First determine whether we are coming out of an LPMx.5 or a regular RESET.
        if (SYSRSTIV == SYSRSTIV_LPM5WU)        // When woken up from LPM3.5, reinit
        {
            // If MCU wakes up from LPM3.5, re-init and then return to LPM3.5 again.
            
            SYSCFG0 = FRWPPW | DFWP;            // Program FRAM write enable
            incrementSeconds();                 // This function increment seconds persistent variable in assembly language
            SYSCFG0 = FRWPPW | PFWP | DFWP;     // Program FRAM write protected (not writable)
    
            __enable_interrupt();               // The RTC interrupt should trigger now...
        }
        else
        {
            // Device powered up from a cold start.
            // It configures the device and puts the device into LPM3.5
    
            // Initialize RTC
            // Interrupt and reset happen every 1024/32768 * 32 = 1 sec.
            RTCMOD = 32-1;
            RTCCTL = RTCSS__XT1CLK | RTCSR | RTCPS__1024 | RTCIE;
    
        }
    
        // Enter LPM3.5 mode with interrupts enabled. Note that this operation does
        // not return. The LPM3.5 will exit through a RESET event, resulting in a
        // re-start of the code.
    
    
        PMMCTL0_H = PMMPW_H;                    // Open PMM Registers for write
        PMMCTL0_L |= PMMREGOFF;                 // and set PMMREGOFF
        __bis_SR_register(LPM3_bits | GIE);
        __no_operation();
    
        return 0;
    }

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

    这似乎足够奇怪、我在 Launchpad 上运行它、我看到 FRAM 从 ISR 更新中更新。

    我填了一些空白:我从 VLOCLK (无晶振)运行 RTC、而我的增量 Seconds()只是"++seconds";

    我怀疑在您发布的代码之外有什么事情发生。

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

    您好!

    由于您进入的 LPM 低于 LPM0、FRAM 控制器会关闭 FRAM 电源、因此您可能需要启用它并等待它恢复写入。

    话虽如此、请查看我们的 Compute Through Power Loss (CTPL) FRAM 库。 它有一个示例、说明您要尝试实现的确切情形。

    https://dev.ti.com/tirex/explore/node?node=AASKcgTluVTGDhQHM5IVkw__IOGqZri__LATEST 

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

    尊敬的 Jace:

    这不应该是问题、因为从主函数调用时代码运行正常、但对于 ISR、问题不是、正如 Bruce 在前面所述、ISR 有时在调用主函数后调用、 因此、我假设 ISR 被称为 FRAM 时、应准备好使用。

    我仍然会尝试启用它并在更新变量之前添加一些延迟、并检查它是否正常工作。

    关于 CTPL、它使用的存储器比常规代码多得多、我不需要存储 MCU 的整个状态、因此我更希望对某些变量使用 persistent、并为其他代码保存存储器。

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

    我认为你可能是布鲁斯, 因为我 的增量 Seconds()更复杂,只有++秒,我 明天会尝试一下 Jace 的想法,如果不起作用,我明天会在这里发布完整的代码,并提供完整的解释。

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

    您好!

    我要附加整个项目。

    在此项目中、我尝试将此 RTC 日历(链路)与 MSP430FR2433配合使用、并通过使用 RTC 中断每秒调用递增秒函数(在 RTC_Calender.asm 中)来更新时间。 MCU 保持在 LPM3.5以降低电流消耗、仅在触发 RTC 中断时唤醒。 为了使 RTC 日历库的变量在 LPM3.5期间保持在存储器中、我已使用".usect ".TI.persistent"在 RTC_Calendar.asm 文件中将库变量设置为永久性、并且我仅在禁用 FRAM 写保护时更新它们、并尽快重新启用它 变量已更新。

    以下是我在 RTC_Calendar.asm 中更新的代码:

    ;Updated persistent Variables									;Old variables
    TI_year						.usect ".TI.persistent", 2,2		;.bss TI_year, 2,2
    TI_second					.usect ".TI.persistent", 1			;.bss TI_second, 1
    TI_minute					.usect ".TI.persistent", 1			;.bss TI_minute, 1
    TI_hour						.usect ".TI.persistent", 1			;.bss TI_hour, 1
    TI_day						.usect ".TI.persistent", 1			;.bss TI_day, 1
    TI_month					.usect ".TI.persistent", 1			;.bss TI_month, 1
    TI_PM						.usect ".TI.persistent", 1			;.bss TI_PM, 1
    TI_FebDays					.usect ".TI.persistent", 1			;.bss TI_FebDays, 1
    TI_dayOfWeek				.usect ".TI.persistent", 1			;.bss TI_dayOfWeek, 1
    TI_dayLightZone				.usect ".TI.persistent", 1			;.bss TI_dayLightZone, 1
    TI_dayLightSavings			.usect ".TI.persistent", 1			;.bss TI_dayLightSavings, 1

    项目文件: e2e.ti.com/.../RTC_5F00_Calendar_5F00_AutoUpdate.zip

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

    您好、Jeevant、  

    我强烈 建议您将 CTPL 库用于此类应用。 由于 LPM3.5能够保存外设的状态、它将帮助您简化实现代码并基本上将其变为 LPM3模式。 请记住、当以 LPMx.5模式唤醒时、您将经历完全复位、因此我们的所有外设和变量都将重新启动、然后您将再次从头开始启动代码。借助 CTPL 库、您将开始执行离开的代码、就像更高的 LPM 一样。  

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

    尊敬的 Jace:

    感谢您的建议、但使用 CTPL 对我不起作用、因为它使用大量 FRAM 空间来保存各种变量以保存状态。 CTPL 库本身占用16KB 中的4KB 闪存来运行、这对于我正在构建的应用程序来说太大了、因此我没有足够的内存来执行其他活动。 这就是我无法使用 CTPL 的原因。

    我所需要的只是一种解决这个特定问题的方法、因为这将为我解决很多问题。 如果您知道如何解决这个问题、请告诉我。

    如果这种执行此任务的方法是错误的、请建议我如何使用内存用量较少的 CTPL。

    谢谢

    Jeevant Sah

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

    汇编代码是为 MSP430 (非 X)编写的、但 FR2433是 msp430x。 编译器仅识别一个或另一个(全局)、因此您无法真正混合它们。

    在这种情况下、使用 CALLA 调用 RTC 函数、但它们使用 RET (而不是 RETA)返回、因此栈被丢弃、返回结果进入 limbo。 最终、CPU 复位(不表示 LPM3.5)、并且您重新初始化 FRAM 变量、因此看起来没有更新完成。

    主系统更新的原因是它不返回、因此不会注意到堆栈偏差。

    我将所有 RET-s 更改为 RETA-s、将(内部)调用更改为 CALLA (可能将20个位置全部放在一起)、程序按预期运行。 据我们所知、我们无法使用汇编器选项来实现这一点。

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

    您好、Bruce、

    感谢您的解决方案。 它的工作方式就像一种魅力。  您能告诉我 是否需要对汇编代码进行任何其他更改、以 避免此类错误吗?(汇编语言中的错误不好)

    另外、您能否详细介绍一下我们如何将汇编语言代码从闪存系列 MCU 移植到 fram 系列 MCU? 是否有任何指南可以帮助我理解这一点?

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

    论坛上有一些 MSP430汇编向导、但我不是其中之一。 (我为其他系统编写了足够多的汇编代码、我可以找到自己的方法。)

    搜索几分钟后、SLAA380B 就出现了一些主题:

    https://www.ti.com/lit/an/slaa380b/slaa380b.pdf

    msp430x 的区别不在于闪存与 FRAM、您只需知道。 CCS 知道--当你指定 MCU 时它会做出-mspx 选择--这是一个很长的路。 避免组装是避免这种冲突的最简单方法。

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

    您好、Bruce、

    感谢您提供的信息和说明。 我将进行介绍。