We are using the MSP430F5636 in an instrumentation application. The USB interface is used and the code is based on the TI Developers Package 3.20.00. MSP430_USB_API_Stacks. We implement CDC and HID classes depending on the product.
We use timer A0 running from ACLK pre-scaled to 32.768 KHz / 2 = 16.384 KHz to generate a sampling clock. T = 1 / 16.384KHz = 61uS approx. The idea is that 2T wide pulse is generated every 512T = 32 pulses per second. Ideally this pulse would be generated using one of the CCR output units so that an interrupt was only generated on the falling edge to reduce overhead. Unfortunately a timer output pin was not available. Instead a general purpose IO pin is used requiring an interrupt on both edges. In the first implementation I used Timer A in continuous mode. CCRO is first programmed to interrupt at 510T and the output pin is set low. In the ISR, the pin state is used as a toggle flag. If low, 2T is added to TA0CCRO. If high, 510T is added. The ISR code for this implementation is as follows:
__interrupt void Timer0_A0_ISR (void)
{
if ( (P5OUT & PIN_MASK) == PIN_MASK )
{
// Pin is high
/*
Code to do sampling goes here
*/
P5OUT &= ~PIN_MASK; // Drive low
TA0CCR0 += 510; // add count till drive high
}
else
{
// Pin is low
P5OUT |= PIN_MASK; // Drive high
TA0CCR0 += 2; // add count till drive low
}
}
This works as expected with a pulse high for 2T and low for 510T with a total cycle of 512T = 32Hz, providing USB is connected (it does not have to be active) OR a JTAG debugger is connected and is active. We use the IAR EWB430 toolchain and the MSP430-FETU430IF debug interface.
The moment USB is disconnected and the debugger is disabled, this approach fails. It is as if Timer A has advanced more than 2 counts by the time the ISR is called, i.e. as if interrupts have been masked for longer than 2T. The sequence then fails because it relies on adding offsets to TACCR0. If the pulse width is increased to greater than 4T this approach works. Careful checking of the USB routines reveals that interrupts are not disabled long enough to cause this problem.
A more defensive approach was then tried that doesn’t rely on offsets. Instead TAR is zeroed at the beginning of each period and TACCRO is programmed with the period required for the next interrupt. Like this:
//
{
P5OUT &= ~PIN_MASK; // Drive low
TA0CTL |= TACLR; // clear TAR (Timer Count = 0)
TA0CCR0 = 510; // set count till drive high
}
else
{
P5OUT |= PIN_MASK; // Drive high
TA0CTL |= TACLR; // clear TAR (Timer Count = 0)
TA0CCR0 = 2; // set count till drive low
}
//
This also works as expected but the same conditions apply. As soon as USB is disconnected and there is no active debug interface, the 2T high period stays high for 4T. The main loop has typically put the processor into LPM3, so these interrupts cause the CPU to wake up to run the ISR. If I monitor SMCLK, I can see that the CPU runs only during the ISR. i.e. No other code is running that could explain timer A incrementing past the expected count by the time the ISR runs. I have also tried using CCR1 instead of CCRO and get the same results. What has happened to Timer A? I have checked the errata and forums and haven’t found any mention of a problem like this.
Added: Scope captures from target running code above:
Plot 1. Shows pulse period. Scope is in envelope mode. CH-1 is the pulse generated output on P5/PIN_MASK. CH-2 is SMCLK. Shows CPU only runs in ISR's. Working as expected.
Plot 2. Shows pulse period when USB or debug interface is connected. CH-1 is the pulse with the expected pulse width of 2T. CH-2 is SMCLK. Working as expected.
Plot 3. Shows pulse period when USB is disconnected and debug interface is disabled or disconnected. CH-1 is the pulse but now the pulse width has increased to 4T. CH-2 is SMCLK. Not working as expected.
I'm actually a bit miffed by this. Why is USB and / or an active debug connection having an effect on this? By the way, ACLK is sourced for XT1 running from a 32.768KHz watch crystal. No other behavourial anomalies have been noted. I'm open for any suggestions at this point.