Part Number: MSP432P401R
TI Devs,
I have a timing problem for delay of RTC clock start after date/time sync from PC for remainder of 1 sec provided during RTC_C_initCalendar() initialization. Essentially I sync the time to the RTC from the PC and when initializing the RTC I add 1 second so I can delay the difference between the time it took to send the date time from the PC and RTC_C_startClock() so the MSP432 RTC will exactly match the PC time. The master clock is running at 12MHz, and the software enters PCM_gotoLPM0() after initialization. This is using DriverLib, nortos.
I have done this two different ways. (1) setting a simple loop and delaying for roughly 60K iterations of a for loop; and (2) using TimerA1 with LFCLK at 32KHz to save the number of ticks of the counter it took to transmit, convert and initialize the RTC and then setting the counter to 32K - ticks - 500, enabling the compare interrupt and calling RTC_C_startClock() from the interrupt handler when it fires. The initial number of ticks to transmit/receive the time from the PC and initialize the RTC clock struct is consistently 6523 - 6533 ticks. So to wait for the remainder of the 1 sec added I end up having CCR1 count to about 25700.
The frustrating part is that I usually have to sync 4-5 times before the clocks actually end up exact -- even though I have counted fairly precisely the delay required. This is roughly the same number of times I have to sync with the for loop that just guessed at a 60000 iteration delay. While the timer does seem to become increasingly more accurate in getting the time exact, while the loop is just hit or miss by a few tenths of a second until it ends up with an exact sync. Both methods do ultimately produce an exact time sync to within a few thousandths of a second that will stay in sync with the PC over a 24 hour windows (I use a downppm offset of 6 ppm with this new MSP432, 3 with the last) I would like a way to sync once and have it precise the first time.
To measure the ticks I start TimerA in UpMode as soon as the 1st character in the date/time string is received from the PC. Then after all values are validated and MAP_RTC_C_initCalendar (¤tTime, RTC_C_FORMAT_BINARY); is called to initialize the new RTC_C_Calendar struct with seconds 1 ahead, I stop the timer and save the ticks. I then initialize the CCR1 counter with 32K - ticks - 500, enable the compare and start the counter. When TA1_N_IRQHandler() fires, I then call RTC_C_startClock() and the time sync is complete. I can't think of a better way to take the guess work out of the sync from the PC, but there must be a better way that would not require 4-5 sync attempts before the clocks are exact.
The ironic part is the ticks saved are always right around 6530 meaning the UART transfer, conversion to numeric values and initialization of the RTC clock struct with the correct time takes just under 0.2 sec. The only thing that happens after that is the delay by either loop or time and then the call to RTC_C_startClock(). I can't see where the variation in the sync is being injected. Is there a more reliable way to approach the time sync between the PC and MSP432?
Here is a short code summary of how the Timer is configured:
/* TimerA UpMode Configuration Parameter */
const Timer_A_UpModeConfig upConfig =
{
TIMER_A_CLOCKSOURCE_ACLK, // ACLK Clock Source
TIMER_A_CLOCKSOURCE_DIVIDER_1, // 32.768 KHz
INT16_MAX, // 1s period
TIMER_A_TAIE_INTERRUPT_DISABLE, // Disable Timer interrupt
TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE, // Disable CCR0 interrupt
TIMER_A_DO_CLEAR // Clear value
};
// Timer A1 Initialization (in main())
/* Configuring TimerA1 for Up Mode */
MAP_Timer_A_configureUpMode (TIMER_A1_BASE, &upConfig);
/* Enabling interrupts and going to sleep */
MAP_Interrupt_enableInterrupt(INT_TA1_N);
// UART receives first char of time/date string from PC (in UART interrupt)
MAP_Timer_A_startCounter (TIMER_A1_BASE, TIMER_A_UP_MODE);
// Transfer and conversion of values complete, ready to initialize RTC clock
/* stop clock for update with new time from PC */
MAP_RTC_C_holdClock();
/* update RTC with new time */
MAP_RTC_C_initCalendar (¤tTime, RTC_C_FORMAT_BINARY);
/* stop timer and initialize compare with exact ticks needed until
* next second before calling RTC_C_startClock() in interrupt.
*/
MAP_Timer_A_stopTimer (TIMER_A1_BASE); /* stop time get count */
/* get the number of ticks for date/time rx from PC */
rxticks = MAP_Timer_A_getCounterValue (TIMER_A1_BASE);
/* set CCR1 to 1 sec - rxticks to set exact delay needed.
* 500 represents an estimate of the number of cycles needed to
* configure, start and stop the timers and generate the interrupt.
* while working, the timer sync is slower than the loop and isn't
* as exacts as anticipated.
*/
MAP_Timer_A_setCompareValue (TIMER_A1_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
INT16_MAX - rxticks - 500);
/* enable CCR1 compare interrupt */
MAP_Timer_A_enableCaptureCompareInterrupt (TIMER_A1_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_1);
/* start counter to generate interrupt */
MAP_Timer_A_startCounter (TIMER_A1_BASE, TIMER_A_UP_MODE);
// RTC_C_startClock() in TimerA1 interrupt
/**
* Timer A1 Interrupt
*/
void TA1_N_IRQHandler(void)
{
/* get enabled interrupts for TA1CCR1 */
uint32_t status = MAP_Timer_A_getCaptureCompareEnabledInterruptStatus (TIMER_A1_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_1);
MAP_Timer_A_stopTimer (TIMER_A1_BASE); /* stop time get count */
if (status & TA1CCTL1) { /* confirm TA1 CCIFG bit 0 set */
/* restart clock */
MAP_RTC_C_startClock();
writeticks(); /* temporary write of ticks via UART (6523 - 6533 ticks of LFCLK) */
/* clear interrupt for CCR1 */
MAP_Timer_A_clearCaptureCompareInterrupt (TIMER_A1_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_1);
/* disable interrupt for TA1CCR1 */
MAP_Timer_A_disableCaptureCompareInterrupt (TIMER_A1_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_1);
/* reset TimerA1 */
MAP_Timer_A_configureUpMode (TIMER_A1_BASE, &upConfig);
}
}