Other Parts Discussed in Thread: MSP430FG4619
Hi all,
I'm a relative newbie with the MSP430. After 5 days solid debugging, and googling, I'm beginning to get to know the 430 and
IAR IDE.
- My wife thinks I'm getting to know it too well!
I'm playing with
a software RTC on the Olimex MSP430-4619LCD development board connected to an alphanumeric character display on Port 10. I know,
the MSP430FG461x has it's own RTC, but a) it has it's own bugs, b)
I'll possibly not use this device in any final project.
I've
managed to get the character display to show static text, no problem. When I implement the Timer_A ISR
for the RTC, the device resets after actioning the ISR, i.e. it resets at or close to the
Timer_A (1sec) interval, and after displaying the initialised time. (Code below.)
I'm using the 'typical clock' application from SLAA290.pdf (Using the Real-Time-Clock Library), modified as per slap116.pdf (Timer_A Presentation 2006).
The dev board has a functioning 32,768Hz crystal on XIN/XOUT. I checked this using the buffered ACLK (32,768Hz) and MCLK (~2MHz) outputs on Port 1.5 and 1.1 respectively.
I'm using IAR Kickstart V4 - from slac050t.zip.
In this related Timer_A thread:
http://community.ti.com/forums/p/873/7684.aspx
Chrispy
says, "I've also found that the ISR is only executed when I place a
breakpoint within the ISR. Otherwise the ISR does not execute. Very
strange."
That's exactly the symptom I'm seeing. The difference between that thread and my problem is I have a 32768Hz XTAL.
After reading about EMI problems, I checked the RST pin - it's always high.
I moved the 'display-writing' code from the while(1) loop to the Timer_A ISR. When I put a break in the ISR, I can see the TI_second variable is incremented and written to the display. Watching the registers, I've also noticed the WDTIFG in the IFG1 Special Function register changes from 0 to 1 after I initiate a reset (even though the WDT is stopped.) Is this normal?
I tried using a "__low_level_init(void)" - made no difference.
My only thought now is the bug notified in slaz028h.pdf (MSP430FG461x Device Erratasheet ) is responsible :
TA12 TA12 - Bug description
Module: Timer_A, Function: Interrupt is lost (slow ACLK)
Timer_A counter is running with slow clock (external TACLK or ACLK) compared to MCLK. The
compare mode is selected for the capture/compare channel and the CCRx register is incremented
by 1 with the occurring compare interrupt (if TAR = CCRx). Due to the fast MCLK, the CCRx
register increment (CCRx = CCRx + 1) happens before the Timer_A counter has incremented
again. Therefore, the next compare interrupt should happen at once with the next Timer_A counter
increment (if TAR = CCRx + 1). This interrupt is lost.
Workaround:
Switch capture/compare mode to capture mode before the CCRx register increment. Switch back
to compare mode afterwards.
I don't quite understand how to implement the above workaround. I had a go in the code below, but it made no difference.
Thanks for any suggestions.
Cheers, hairy_kiwi
//------------- ALPHANUMERIC DISPLAY RTC ---------------//
#include "msp430xG46x.h"
#include "RTC_Calendar.h"
#include "LCD_AlphaNumeric_4_20.h"
//Define global variables
..
//
void main ( void )
{
// Watchdog Timer //
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer write WDTCTL = 0x5A80; READ as: 0x6980
// FLL+ Control Register 0 //
FLL_CTL0 |= DCOPLUS + XCAP18PF; // DCO+ set
so freq = xtal 2 x N+1 (Where SCFQCTL is set with N), Oscillator
capacitor ~18 pF
// System Clock Control Register //
SCFQCTL = 30; // fDCOCLK
= (N + 1) * fcrystal ~ fDCOCLK = (30+1) * 32768 = 2 031 616 Hz ~ 2MHz
// FLL+ Control Register 1 //
FLL_CTL1 = SMCLKOFF + XT2OFF + SELM0 + FLL_DIV_1; // SMCLK off, XT2 off, DCO for main oscilator, ACLK By 1
P1DIR |= 0x66; // Test Purposes ONLY - P1.1, 1.2, 1.4, 1.5 outputs
P1SEL |= 0x36; // Test
Purposes ONLY - Configure outputs P1.1 = MCLK, P1.2 = TA1 (Not Used),
1.4 = TBCLK, 1.5 = ACLK
LCD_InitPort();
LCD_Init();
// Until LFXTL is stable, wait, by continuosly clearing the OSCFault flag //
int f;
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (f = 0xFF; f > 0; f--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?
setTime( 0x12, 0x11, 0x24, 1 ); //initialise time to 12:00:00 AM
setDate( 2008, 12, 15 );
/* From Slau290 Documentation **************************
CCR0 = 32768-1;
TACTL = TASSEL_1 + MC_1; //Timer A clock source select: 1 - ACLK, UP Mode
CCTL0 |= CCIE; //enable CCR0 interupt
_EINT();
*/
/* From Timer A Presentation **************************
TACTL = TASSEL_1 + TACLR; //Clock = ACLK(32768), Clear
TACCTL0 |= CCIE; //CCR0 interupt enabled
TACCR0 = 32768-1; //Number of counts for 1s
TACTL |= MC_1; //Setting Mode Bits starts timer
_BIS_SR(GIE);
*/
// Timer A Presentation - TRIAL MODIFICATION as per Errata - DOESN'T HAVE DESIRED EFFECT
TACTL = TASSEL_1 + TACLR; //Clock = ACLK(32768), Clear
TACCTL0 |= CCIE; //CCR0 interupt enabled
TACCTL0 |= CAP; // Enable capture Mode - Here???
TACCTL0 |= CM0; //Capture on rising edge
TACCR0 = 32768-1; //Number of counts for 1s
TACTL |= MC_1; //Setting Mode Bits starts timer
TACCTL0 &= ~CAP; //No capture - Here???
TACCTL0 &= ~CM0; //No capture - Here/Required???
_BIS_SR(GIE);
while( 1 )
{
LPM3;
_NOP(); //Only for debug
}
}
//Timer A0 Interrupt Service Routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
incrementSeconds();
//Output code placed here to see SOMETHING on display
BCDtoStr(TI_second,TimeStringSecs);
LCD_PosnCursor ( LCD_Line_1 );
LCD_Print( TimeStringSecs );
LPM3_EXIT;
}