Other Parts Discussed in Thread: MSP430FR6989
Hi,
I hope this post will be a bit clearer than the previous one.
The context is the same. Our application runs on custom board developed around msp430fr5989 and we use PCF8523 to supply an external clock on PJ.4 LXFIN.
We have a test in the application than uses the internal RTC_C block to give us an interrupt on various time events. The one we use in this particular test is a time event every minute.
During the minute waiting for the interrupt we want to go in LPM3.5 low power mode. We use for this the FRAM utility ctpl.
The test can be invoked with or without entering the LPM3.5 mode.
In this case the interrupt occurs as expected and we can resume the execution of code.
in the case the LPM3.5 is invoked the low power mode is entered via the ctpl api.
upon return from the deep sleep we get in the ISR of the RTC_C. the RTCIV gives us a vector 0 RTCIV_NONE instead of the RTCIV_RTCTEVIFG that we are exepting.
Here below some snippets of code showing what we try to do:
Your kind assistance in solving this problem would be greatly appreciated.
I fear another stupid mistake of mine but can not figure it out at this time.
We initially developed this code on the eval board MSP430FR6989 and this test was passing then.
in any case thank you so much for having a look.
Jean-Pierre Sainfeld
==================================== TEST code =================================
void testTimeEventMinute(void) { uint16_t count = 0; uint8_t answer; log_print(LOG_ALWAYS,"%s\n\r", __FUNCTION__); static Calendar cm = { 0, //! Seconds of minute between 0-59 0, //! Minutes of hour between 0-59 14, //! Hour of day between 0-23 3, //! Day of week between 0-6 16, //! Day of month between 1-31 6, //! Month between 1-12 2020 //! Year between 0-4095 }; test_event_minute_continue = true; /* * Clear all interrupts from Calendar Module * before making decision about notifications */ CM_clearInterrupt(RTC_C_TIME_EVENT_INTERRUPT | RTC_C_CLOCK_READ_READY_INTERRUPT | RTC_C_CLOCK_ALARM_INTERRUPT); /* * Disable all interrupts from Calendar Module * before making decision about notifications */ CM_disableInterrupt(RTC_C_TIME_EVENT_INTERRUPT | RTC_C_CLOCK_READ_READY_INTERRUPT | RTC_C_CLOCK_ALARM_INTERRUPT); /* * Initialize the Calendar Manager */ CM_init(&cm); /* * Notified every time a minute has elapsed */ CM_registerEvent(RTC_C_CALENDAREVENT_MINUTECHANGE); /* * Generate interrupt on time events */ CM_enableInterrupt(RTC_C_TIME_EVENT_INTERRUPT ); /* * Start the Calendar */ CM_start(); // Ask user if he wants to go to deep sleep // waiting for this event mp_print(BACK_CHANNEL,"%s\n\r","Do you want to go to Low Power Mode waiting for this event (y/n)? "); answer = mp_getchar(BACK_CHANNEL); mp_print(BACK_CHANNEL,"%s %c\n\r","Your ANSWER ->", answer); while (test_event_minute_continue == true) { if (answer == 'y') { /* * Enter Low Power Mode with interrupts enabled */ __enable_interrupt(); // this code for deep sleep - does work but cannot debug through it yet log_print(LOG_ALWAYS,"%s going to deep sleep\n\r", __FUNCTION__); ctpl_enterLpm35(CTPL_DISABLE_RESTORE_ON_RESET);<----------------------------------------- This is where we enter the LPM3.5 using the CTPL Library API. log_print(LOG_ALWAYS,"%s returned from deep sleep\n\r", __FUNCTION__); } count++; if (count == 0) { mp_print(BACK_CHANNEL,"."); LED_toggle(1); } /* * Check if event Second was triggered */ unsigned long val = 0; val = BIT_CHK(eventBitmap, rtcReadyInterruptTriggered); if (val == 1) { /* * Log the per Second Interrupt event */ mp_print(BACK_CHANNEL,"Interrupt for SECOND was triggered\n\r"); /* * Ask calendar manager to handle the event */ CM_handleSecondEvent(); } /* * Check if the event Minute was triggered */ val = BIT_CHK(eventBitmap, rtcTimeEventMinuteInterruptTriggered); if ( val == 1) { mp_print(BACK_CHANNEL,"Interrupt for MINUTE was triggered\n\r"); /* * let the test event handler process the event */ test_handleMinuteEvent(); } /* * Check if the event Hour was triggered */ val = BIT_CHK(eventBitmap, rtcTimeEventHourInterruptTriggered); if ( val == 1) { mp_print(BACK_CHANNEL,"Interrupt for Hour was triggered\n\r"); /* * let the test event handler process the event */ test_handleHourEvent(); } /* * Check if the event Noon was triggered */ val = BIT_CHK(eventBitmap, rtcTimeEventNoonInterruptTriggered); if ( val == 1) { mp_print(BACK_CHANNEL,"Interrupt for Noon was triggered\n\r"); /* * let the test event handler process the event */ test_handleNoonEvent(); } /* * Check if the event Midnight was triggered */ val = BIT_CHK(eventBitmap, rtcTimeEventMidnightInterruptTriggered); if ( val == 1) { mp_print(BACK_CHANNEL,"Interrupt for Midnight was triggered\n\r"); /* * let the test event handler process the event */ test_handleMidnightEvent(); } } log_print(LOG_ALWAYS,"%s Complete\n\r", __FUNCTION__); return; }
======================== ISR =======================================
/* *================================== * Interrupts Service Routine (ISR) *================================== */ #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) { switch (__even_in_range(RTCIV, RTCIV_RT1PSIFG)) { /* * Vector 0 * No Interrupt */ case RTCIV_NONE: { _no_operation(); <-------------------------------- Upon return from Deep Sleep we get the interrupt but we have RTCIV_NONE instead of the time event one } break; /* * Vector 2 * RTCOFIFG * 32-kHz crystal oscillator fault interrupt flag. * This interrupt can be used as LPM3.5 wake-up event. * It also indicates a clock failure during backup operation. * 0b = No interrupt pending * 1b = Interrupt pending. * A 32-kHz crystal oscillator fault occurred after last reset. */ case RTCIV_RTCOFIFG: { RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_OSCILLATOR_FAULT_INTERRUPT); _no_operation(); } break; /* * Vector 4 * RTCRDYIFG * This vector correspond to * RTC_C_CLOCK_READ_READY_INTERRUPT * Real-time clock ready interrupt flag * 0b = RTC cannot be read safely * 1b = RTC can be read safely * */ case RTCIV_RTCRDYIFG: { /* * Interrupt every second */ eventBitmap = BIT_SET(eventBitmap, rtcReadyInterruptTriggered); RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_CLOCK_READ_READY_INTERRUPT); } break; /* * Vector 6 * RTCEVIFG */ case RTCIV_RTCTEVIFG: { /* * Real-time clock time event interrupt flag. * In modules supporting LPM3.5 this interrupt * can be used as LPM3.5 wake-up event. * 0b = No time event occurred * 1b = Time event occurred */ /* * We use Calendar Mode (RTCMODE =1) * * Read Register control 1 bit 0 an 1 * 1-0 RTCTEVx RW 0h Real-time clock time event * 00b = Minute changed * 01b = Hour changed * 10b = Every day at midnight (00:00) * 11b = Every day at noon (12:00) */ switch(HWREG8(RTC_C_BASE + OFS_RTCCTL13_L ) & RTCTEV_3 ) { case RTCTEV__MIN: { /* * Interrupts every minute */ eventBitmap = BIT_SET(eventBitmap, rtcTimeEventMinuteInterruptTriggered); RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_TIME_EVENT_INTERRUPT); } break; case RTCTEV__HOUR: { /* * Interrupts every hour */ eventBitmap = BIT_SET(eventBitmap, rtcTimeEventHourInterruptTriggered); RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_TIME_EVENT_INTERRUPT); } break; /* * Interrupt every day at midnight */ case RTCTEV__0000: { eventBitmap = BIT_SET(eventBitmap, rtcTimeEventMidnightInterruptTriggered); RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_TIME_EVENT_INTERRUPT); } break; /* * Interrupt every day at noon */ case RTCTEV__1200: { eventBitmap = BIT_SET(eventBitmap, rtcTimeEventNoonInterruptTriggered); RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_TIME_EVENT_INTERRUPT); } break; default: { RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_TIME_EVENT_INTERRUPT); RTC_C_disableInterrupt(RTC_C_BASE, RTC_C_TIME_EVENT_INTERRUPT); } break; } } break; /* * Vector 8 * RTCAIFG */ case RTCIV_RTCAIFG: { eventBitmap = BIT_SET(eventBitmap, rtcAlarmInterruptTriggered); RTC_C_clearInterrupt(RTC_C_BASE, RTC_C_CLOCK_ALARM_INTERRUPT); } break; /* * Vector A * RT0PSIFG */ case RTCIV_RT0PSIFG: { _no_operation(); } break; /* * Vector C * RT1PSIFG */ case RTCIV_RT1PSIFG: { _no_operation(); } break; /* * Default Case */ default: { _no_operation(); } break; } }