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.
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.
It would be interesting to know your clock system setup code.
Clock system, LPM and debugging are three that don't work together too well. WHiel debug interface is attached, LPM isn't entered as expected. In your code, you do an active switch to drive the output high and low. It might jut be that you're missing the right switching point due to different CPU wakeup times with or without debug interface attached.
I agree that this is strange, but I'm sure there is an explanation and things are as they should be - while most likely the code doesn't (or cannot) do what it is intended to do.
Thank you for looking at this. It's much appreciated.
The clock initialisations are as follows:
void Init_Clock (void)
{
P7SEL |= 0x0C; // Select XT2 pins for MSP430F5636
while(BAKCTL & LOCKIO) // Unlock XT1 pins for operation
BAKCTL &= ~(LOCKIO);
UCSCTL6 &= ~XCAP_3; // force all pad caps off
UCSCTL6 |= XCAP_2; // gives 32768.02Hz on prototype PCB with 2 x 10pF pad caps on board
// this works to this point and XT1 will be disabled and ACLK will be sourced from REFO
// if we don't turn XT1 on. If we do then ACLK will be sourced from it and it will be the FLL ref.
LFXT_Start(XT1DRIVE_0); // Start XT1, Lowest Drive.
// Use XT1 as FLL reference.
UCSCTL3 = (UCSCTL3 & ~(SELREF_7)) | (SELREF__XT1CLK);
// Use XT1 for ACLK
UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELREF__XT1CLK);
// ACLK = 16,384Hz
UCSCTL5 |= DIVA_1;
// MCLK will be driven by the FLL (not by XT2), referenced to the XT1
// Start the FLL, at the freq indicated by the config constant USB_MCLK_FREQ
// USB_MCLK_FREQ = 8000000 in this case.
Init_FLL_Settle(USB_MCLK_FREQ / 1000, USB_MCLK_FREQ / 32768);
// For debug
P1SEL |= 0x01; // ACLK on TP2.
P1DIR |= 0x01;
//
P3SEL |= 0x10; // SMCLK on TP3.
P3DIR |= 0x10;
}
My expectation is that we will transition from LPM to run the timer A0 ISR and then return to LPM. That is happening but it is as if timer A0 has missed 2 ticks if we enter from LPM and USB power is disconnected. XT1 is also being used for RTC_B. This is used to provide a compensated 1Hz reference for a software epoch based clock. RTC_B is in the backup power domain and I have tried disabling it to ensure it's not a factor. It is not. We are using Timer A1 and A2 for other things, but all have been disabled without effect on this issue. I will try using timer A1 and A2 instead of A0 and post the results here soon.
...
I've just tried using Timer A1 and Timer A2 and get exactly the same result. I also had a look at the generated pulse and ACLK phasing on the scope. When good, (2T wide pulses), the edges of the pulse change on the rising edge of ACLK. When bad (4T wide pulses) they change on the falling edge. It's absoultely stable in both cases. Note: When USB is connected but not active, good 2T pulses are generated and we still transition to LPM. The DCO only runs for the duration of the ISR. XT2 has a 4MHz USB reference crystal and it is running in this case. In the other good case, no USB connected but debugger connected (JTAG), XT2 is disabled. We still enter LPM in this case when not running the ISR.
Best, Dean.
Footnote:
I've tried changing the ACLK divisor to clock timer A at 32,768Hz and 8,192Hz instead of 16,384Hz. At 32,768 it works as exected with the same conditions except that now the 2T period is metastable in the no USB and no debug case. It alternates between 4T and 2T. At 8,192Hz the behaviour is the same as 16,384Hz. i.e. 2T for USB or debug, 4T for no USB and no debug. I think there is definately something wrong here. The fact that the clock edge changes (discussed in the previous post) looks bad. Metastability also looks bad.
I know this is a bit of a boring post but it appears there's a hardware bug with the MSP430F5636. This is the only part from this group we are using at the moment. There's a new design in progress with the first prototypes arriving in a couple of weeks. It uses the MSP5510IRGC. Until then, I haven't got anything else here to try this on. Is there anyone out there with a part on a board and enough time to quickly try this? Are there any TI staff that have heard of an issue like this? Thanks..
Hi Dean,
I'm going through the code and trying to make an example to reproduce your issue on my board here. I am still working on it, but one quick thing I found was a mistake with this line of code in your clock initialization
// Use XT1 for ACLK UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELREF__XT1CLK);
This should be:
// Use XT1 for ACLK UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELA__XT1CLK);
You used SELREF__XT1CLK in this field, but that mnemonic is meant for the SELREF field in UCSCTL3, not the SELA field in UCSCTL4. It happens to work in this instance because both of those have a value for XT1 of 0, but the bitfields are actually in different locations so normally this wouldn't work.
One other note - if you are using UCSCTL4 = instead of |=, you don't actually need the (UCSCTL4 & ~(SELA_7)) because when an = is used any bits you don't explicitly set will be zeroed out. You'd only need that clearing of the field if you were using |=.
However, in this instance by using the = you are also clearing out the SELS and SELM bits, which you maybe aren't meaning to do because this would source all three clocks from XT1CLK. So really the line of code should probably be:
// Use XT1 for ACLK UCSCTL4 |= (UCSCTL4 & ~(SELA_7)) | (SELA__XT1CLK);
I'm still working on setting up an example to see if I can reproduce your problem and I'll post my code and results once I've tested it.
Regards,
Katie
Hi Dean,
I think I've figured out what your problem is. By default, the SVS is configured for normal mode (not high-performance mode) - see SVSMLCTL register and the SVSLFP description. When in the default normal mode, you can see in the datasheet that the wake-up time will be tWAKE-UP-SLOW = 150us on p. 59 of the F5636 datasheet. This is longer than the ~122us that is your 2 ACLK tick wake period. So the interrupt doesn't get serviced fast enough because the part doesn't wake up fast enough.
If you change your SVS to using high-performance mode, you should see something more like 3-6us wake up time for tWAKE-UP-FAST in the datasheet on p. 59 (at the cost of increased current consumption while in LPM3), and so your interrupt should be able to be serviced fast enough (assuming no other interrupts in the system that could be blocking).
The reason you might not see the issue while in debug mode is that while debugging, the part can't truly fully enter LPM3 because the debugger still needs access to the part (as Jens-Michael mentioned earlier in the thread) - so you see some different wakeup timing. I tried my code at first with the SVS in the default normal mode, and was able to reproduce something like your behavior - the code worked correctly with the debugger, but not without a debug session running. Once I switched to using the SVS in a setup optimized for fast wake up, everything now works as you are intending even when running standalone. I've attached the code I am using - I used functions MSP430ware driverlib to configure the DCO+ FLL and the PMM as it helps simplify correctly enabling these peripherals.
There is a good example for setting up the PMM for fast wakeup in MSP430ware Driverlib - it's called pmm_ex2_fastWakeUp.c. If you are using CCSv5 with MSP430ware, you can go to View > TI Resource Explorer, then navigate to this example at MSP430ware > Libraries > Driver Library > MSP430F5xx_6xx > Example Projects > PMM.
So you have a few options:
1. If you can tolerate the increased current consumption, use the SVS in full performance mode
2. If you need low current consumption in LPM3, and you have any Timer output pins like TA0.1 available, use the timer output. (Are there no timer pins available in your design? Perhaps you are already using most pins.) If you have any timer pins available this is definitely the overall ideal solution because then everything can be done in hardware with no software intervention.
3. If you aren't already using the DMA for many other things, you might be able to do a clever set up of the DMA to automatically set your output pin high and low (by transferring the value for the pin into the PxOUT register), internally triggering the DMA off of the TA0.1 signal. This would also allow everything to be handled in hardware, but it might not be possible if you are using other pins on the same port (since writing to PxOUT would be setting the entire register, not just the one pin).
Regards,
Katie
Hi Katie,
Many thanks for looking at this for us. I think most of the clock initialisers came from the TI USB Developers Package.
When you state UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELREF__XT1CLK) you are performing a logical OR of the existing contents of UCSCTL4 with the SELA_7 bits masked out, with SELREF_XT1CLK. That is valid and will result in the SELA_7 bits being all set to zero (masked out). The (UCSCTL4 & ~(SELA_7)) part of the expression is not redundant.
If instead you stated UCSCTL4 |= (UCSCTL4 & ~(SELA_7)) | (SELREF__XT1CLK) as you have suggested this will expand to UCSCTL4 = UCSCTL4 | (UCSCTL4 & ~(SELA_7)) | (SELREF__XT1CLK). This will not mask out the SELA_7 bits. If you didn’t mind using a couple of lines of code to do this, a more readable method would be to say:
UCSCTL4 &= ~SELA_7;
UCSCTL4 |= SELREF__XT1CLK;
Anyway thanks for pointing out that we've got the wrong field. SELREF__XT1CLK instead of SELA__XT1CLK. I will fix this. SELREF_XT1CLK and SELA_XT1CLK are both = 0 as you have pointed out which is why this is working now. Still I should use the correct field. Of course oring in a zero is also redundant but makes the code readable. ie. you can clearly see you intend to use XT1CLK as the reference in this case.
I've seen your post that follows this and again thanks for putting the effort into helping us with this. I will follow up on this as soon as I get a chance to test it.
Best,
Dean.
Hi Kate,
I'd say you've nailed it. So far I've been able to confirm about 150uS of latency on startup from LPM3 from the timer interrupt with JTAG and USB disconnected. With either of these connected latency is < 4uS, so we clearly aren't fully entering LPM3 as you have discussed. I've quickly hacked in the PMM code to give high performance mode but it isn't working yet. I'm probably not doing it properly and/or there are other settings required to make it work. We used the TI F5xx_F6xx_Core_Lib in the original development. It has a module HAL_PMM.c. We only use one function from that module to set VCORE to 3V. It doesn't have the functions you've used in your testing. (as in the zip attached).
I confess to not having fully read the manual on the PMM. So many things to think about. As soon as I get a minute to work on this I will make sure I am correctly configuring high performance mode and then post an update on the result.
Thanks also for suggesting using a timer output instead of the approach we've taken. This is how we normally do this but it isn't an option unfortunately with the existing design due to other pin priorities etc. DMA also a clever suggestion but again there are other things happenning. I miss the simplicity of the 1xx and 2xxx parts.
for(;;) thanks,
Dean.
Hi Dean,
Dean Cooper said:When you state UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELREF__XT1CLK) you are performing a logical OR of the existing contents of UCSCTL4 with the SELA_7 bits masked out, with SELREF_XT1CLK. That is valid and will result in the SELA_7 bits being all set to zero (masked out). The (UCSCTL4 & ~(SELA_7)) part of the expression is not redundant.
You are totally right, that one was definitely my bad. I missed the intent of your code there.
Dean Cooper said:I've quickly hacked in the PMM code to give high performance mode but it isn't working yet. I'm probably not doing it properly and/or there are other settings required to make it work. We used the TI F5xx_F6xx_Core_Lib in the original development. It has a module HAL_PMM.c. We only use one function from that module to set VCORE to 3V. It doesn't have the functions you've used in your testing. (as in the zip attached).
I'm glad to hear that you think we've found your issue. The PMM module on F5xx devices is complex to use correctly. This is why even though I did the rest of my example using simple register accesses, I always use the driverlib APIs for setting up the PMM module as they will do everything in the correct sequence and catch the little details for you. For getting the PMM set up for the fastest wakeup, I simply used the settings from the driverlib PMM fast wake-up example.
If you want to use the driverlib functions just for the PMM, you can simply drop in the driverlib folder from my example and include the pmm.h header (and maybe set up some of your include paths in the project settings to look in this folder). Driverlib has replaced the the 5xx/6xx core library that hal_pmm.c comes from. The driverlib pmm.c file will include versions of the SetVcore function you mentioned as well as all the other functions I used in my example. If you are interested, driverlib is part of the MSP430Ware download (of if you use CCSv5.5 it probably is already in your installation).
Best of luck getting the PMM set up, and please let me know if you have any questions about using driverlib.
Regards,
Katie
Hi Katie,
I ended up disabling the low side SVS/SVM as a brute force method to ensure a full speed startup and it works. This problem is resolved!! One thing I'd like to say at this point is:
There should be something clear on the data sheets or family guide to help users porting to the 5/6xx series. We naturally have an expectation that the transition from LPM3 to AM will be as fast as the DCO can be started and certainly not dependent on PMM. Alternately, the default settings should allow a normal full speed startup. The user guide at no point explains the reason for the delay. It turns out the low side SVS/SVM is actually powered down in LP modes. The 150us delay is so that it can power up and settle. I think the PMM is a little over the top although it might help bump up TI’s patent portfolio.
These comments don't in any way detract from the excellent work you did to solve this problem for me. It's interesting that no one else could see this on the forum, so I suspect the PMM is a bit of a black hole? It's great to have this resolved!
Best,
Dean.
Hi Dean,
Awesome - I'm so glad to hear that your issue is resolved!
Dean Cooper said:There should be something clear on the data sheets or family guide to help users porting to the 5/6xx series. We naturally have an expectation that the transition from LPM3 to AM will be as fast as the DCO can be started and certainly not dependent on PMM. Alternately, the default settings should allow a normal full speed startup. .
This is definitely valid feedback.
There is a brief 5xx quick start guide here www.ti.com/lit/pdf/slaa395, though its section on PMM mostly is meant as an intro on what the PMM module does and doesn't mention the particular issue you ran into. It would probably be good to add mention of the wake-up time effect in this app note. You'll see that in our new FR57xx and FR59xx families we have tried to simplify this module a lot to make it easier for people to understand and use - it has less options/configurations but is easier to use, and more things are handled for you (no more having to set Vcore levels, etc). This is also part of why we made the 5xx_6xx_core_libraries and later on, driverlib.
The reason the default setting is for the slow wake up is because this conserves power - with MSP430's focus on low power, in most typical MSP430 applications the low-power slower wake up mode makes sense. But we have the option of the faster wake-up for when it is needed (like in your case).
Dean Cooper said:It turns out the low side SVS/SVM is actually powered down in LP modes. The 150us delay is so that it can power up and settle.
The SVS isn't powered down in LP modes, its just that it is running in a lower power state where it cannot respond as quickly - you could say more parts of the module our powered down internally, but the SVS detection itself is still enabled. You can still detect a drop in your supply voltage using the SVS while in LPM, you just cannot handle the event as quickly. This is why the users guide says: "Full-performance mode might be considered in applications in which the decoupling of the external power supply cannot adequately prevent fast spikes on DVCC from occurring, or when the application has a particular intolerance to failure."
I'll pass along your feedback, thanks again, and I'm really glad your code is working now :-)
Regards,
Katie
**Attention** This is a public forum