Jump to content
p2baron

[SOLVED] Is this code blocking suspend()/lpm4?

Recommended Posts

I am currently working on a low power application.

Using the MSP-EXP430FR5969 and the energytrace functionality in CSS I'm finally able to monitor the power usage of my sketch. (thanks for the writeup Frank!).

 

I notice that if I call the following function my MSPG2553 is unable to suspend.

// returns VCC in millivolts
int getVCC() {
  // start with the 1.5V internal reference
  analogReference(INTERNAL1V5);
  int data = analogRead(ANALOG_HALFVCC_INPUT);
  // if overflow, VCC is > 3V, switch to the 2.5V reference
  if (data==0x3ff) {
    analogReference(INTERNAL2V5);
    data = (int)map(analogRead(ANALOG_HALFVCC_INPUT), 0, 1023, 0, 5000);
  } else {
    data = (int)map(data, 0, 1023, 0, 3000);
  }
  return data;  
}

Can anybody tell me why this happens?

The complete sketch is in the attachment. It is a wireless sensor that tells me when the mailman delivered the mail.

 

 

 

post-27040-0-12180900-1446847679_thumb.png

mailboxsensor_v6-1.ino

Share this post


Link to post
Share on other sites

Hi @@p2baron,

 

I'm glad you found the article helpful.  I looked at your code quickly and while I didn't see the problem, I have two questions:

  1. Does everything in the code work as you expect other than it doesn't go into LPM4 when you call suspend()? 
  2. Have you tried using debug mode in CCS to step through and see what is happening - e.g. suspend() is called and the variables awake, newMail, etc. are what you expect?  Lately I have been using CCS Cloud with Energia when I need debug and find it more convenient than using CCS on the desktop if I don't need to view memory or registers.

Share this post


Link to post
Share on other sites
  1. Does everything in the code work as you expect other than it doesn't go into LPM4 when you call suspend()? 
  2. Have you tried using debug mode in CCS to step through and see what is happening - e.g. suspend() is called and the variables awake, newMail, etc. are what you expect?  Lately I have been using CCS Cloud with Energia when I need debug and find it more convenient than using CCS on the desktop if I don't need to view memory or registers.

 

 

1. Yes everything is working fine. Suspend is also working fine execpt once I've called reportVcc() it is unable to suspend again. 

2. I don't have much experience with CCS. I'm also having troubles setting up CCS. After I've imported my Energia sketch and do a build I receive the following error:

C:/Users/Pieter/Google Drive/03 - Workspace/CSS/lpmsp430g2553_core/Debug\liblpmsp430g2553_core.a(main.o): In function `main':
C:/Users/Pieter/Google Drive/02 - Apps/energia-0101E0016/hardware/msp430/cores/msp430/main.cpp:7: undefined reference to `setup'
C:/Users/Pieter/Google Drive/02 - Apps/energia-0101E0016/hardware/msp430/cores/msp430/main.cpp:10: undefined reference to `loop'
collect2: ld returned 1 exit status
gmake: *** [mailboxsensor_v6-1.out] Error 1
gmake: Target `all' not remade because of errors.

Share this post


Link to post
Share on other sites

I recommend trying abecedarian's suggestion and adding the debugger to your bag of tricks.  As stated above, you can also try CCS Cloud which I find a bit easier to use and convenient (but you can't look at registers).

 

After looking at your code again, it seems that if everything else is behaving then it should be looping.  And if it is looping then it should be calling suspend().  The code for suspend() is located in wiring.c and here it is....

void suspend(void)
{
	// Stop WDT for now
	WDTCTL = WDTPW | WDTHOLD;

	sleeping = true;
	stay_asleep = true;

	while (stay_asleep) {
		/* Halt all clocks; millis and micros will quit advancing, only
		 * a user ISR may wake it up using wakeup().
		 */
		__bis_status_register(LPM4_bits+GIE);
	}

	sleeping = false;

	// Re-activate WDT in SMCLK Interval mode
	enableWatchDogIntervalMode();
}

It seems to me that one reason you might not be seeing it stay in LPM4 is that the interrupt is occurring and wakeup() is being called immediately after it calls __bis_status_register(LPM4_bits+GIE) in the suspend() function.  Can you test for this?  How is the interrupt reset?

Share this post


Link to post
Share on other sites

Thanks for all the suggestions.

I tried debugging the code in CCS cloud. Thanks for the tip. I did not even know that CCS Cloud existed!

When debugging I see that the code is functioning fine and the the suspend() code is always called/entered.

 

Two questions.

Do I always need to clear an interrupt?

Is the wakeup call even needed?

 

 

 

 

Verstuurd vanaf mijn SM-G920F met Tapatalk

Share this post


Link to post
Share on other sites

How do you know it's not suspending--are you using the EnergyTrace info to determine? Holding one of the analogReference's in place might be drawing more power than expected although I am not sure that's still the case in recent versions of Energia.

Share this post


Link to post
Share on other sites

 

How do you know it's not suspending--are you using the EnergyTrace info to determine? Holding one of the analogReference's in place might be drawing more power than expected although I am not sure that's still the case in recent versions of Energia.

Thanks spirilis!  I learned something.  So p2baron can try putting analogReference(DEFAULT) at the end of getVCC().

 

 

Two questions.

Do I always need to clear an interrupt?

Is the wakeup call even needed?

Pretty sure wakeup is needed but you could try taking it out :) .  I don't understand the external interrupt that you are using so no idea how it works...

Share this post


Link to post
Share on other sites

@@Fmilburn wakeup is indeed needed :)

 

@@spirilis I'm using Energytrace to measure power consumption

I've tried setting the anologReference back to default. Unfortunately that doesn't help.

 

 

attached are three screenshots.

The first one is the EnergyTrace log without calling reportVcc() and the second one with.

 

The third screenshot shows the debug screens from CCS Cloud. It is always calling the suspend() function.

 

I'm a bit lost. Why is the MCU unable to suspend? Are there other thing I can check?

 

 

 

 

 

post-27040-0-36209200-1447098822_thumb.png

post-27040-0-49402400-1447098864_thumb.png

post-27040-0-80940600-1447100394_thumb.png

Share this post


Link to post
Share on other sites

@@p2baron

 

My skills in C++ are limited but here are some things to try.  Below are your ISRs...

void newmail()
{
  wakeup();
  awake = true;
  newMail = true;
}

void mailgone()
{
  wakeup();
  awake = true;
  newMail = false;
}

In general it is best to minimize code in an ISR.  In any event, wakeup should cause suspend to return control to the next executable line after suspend.  In your case, this is the top of loop().  So if would appear the variables in the ISR, awake and newMail, do not have their contents updated.  So move those two out of the ISR and after suspend (or at least in front of wakeup).

 

This is what wakeup (located in Energia.h) looks like. 

extern volatile boolean stay_asleep;
#define wakeup() { stay_asleep = false; }

As soon as wakeup is called in your ISR, then the while condition in suspend is made false (since stay_asleep is now false) and it exits. So if you are still having the problem after trying the change above, then put a print statement right after suspend.  If it prints something immediately after calling suspend then perhaps the ISR is being called, stay_asleep is made false, and it just isn't staying in LPM4.

Share this post


Link to post
Share on other sites

What does EnergyTrace++ say?  That's a feature supported by the FR5xxx/6xxx series chips that shows you the AM/LPM mode, not the current consumption.  Check that to see if it's actually entering LPM4 or not.

 

Also have you set a default GPIO config for all unused pins?  By default they're all set to "input" mode, which makes them susceptible to noise which will cause some current consumption.

Share this post


Link to post
Share on other sites

@@spirilis

 

The excerpt below from this link describes how EnergyTrace works...

 

In debuggers that support EnergyTrace technology, a software-controlled DC-DC converter generates the target power supply. The time density of the DC-DC converter charge pulses equals the energy consumption of the target microcontroller. A built-in calibration circuit in the debug tool defines the energy equivalent for a single charge pulse. The width of each charge pulse remains constant. The debug tool counts every charge pulse and the sum of the charge pulses are used in combination with the time elapsed to calculate an average current. Using this approach, even the shortest device activity that consumes energy contributes to the overall recorded energy.

So EnergyTrace does measure current consumption, and the FR5969 LaunchPad circuitry can measure current on other LaunchPads or boards.

 

I am pretty much a beginner when it comes to microcontrollers and the CCS debugger so I readily defer to your knowledge.  The screenshot shown from the CCS Cloud debugger shows that it reaches the call to LP4.  How would you check to see if it has actually entered LMP4?

 

The link to the actual code in the first post shows the unused pins are set to input and low in setup().  I set them to output and low in my own applications, based on a post I saw from you I think.

Share this post


Link to post
Share on other sites

@@spirilis

 

The excerpt below from this link describes how EnergyTrace works...

So EnergyTrace does measure current consumption, and the FR5969 LaunchPad circuitry can measure current on other LaunchPads or boards.

 

I am pretty much a beginner when it comes to microcontrollers and the CCS debugger so I readily defer to your knowledge.  The screenshot shown from the CCS Cloud debugger shows that it reaches the call to LP4.  How would you check to see if it has actually entered LMP4?

 

The link to the actual code in the first post shows the unused pins are set to input and low in setup().  I set them to output and low in my own applications, based on a post I saw from you I think.

Check out EnergyTrace++.  It's an "additional" feature available with MCUs that support it, the FR5969 being one (and of course the FR5969 launchpad supports it, and would support the feature if used as an external debugger for any other MSP430FRxxxx chip that supports it).  You can't use EnergyTrace and EnergyTrace++ at the same time (edit: I haven't played with this in a while, maybe it does do both simultaneously now?) but the latter, EnergyTrace++, gives tracing of the LPM modes.  It's a hardware trace method for *proving* the MCU entered LPM4.

 

I know this works with the desktop CCSv6.

 

edit: Ah, now I see the user is utilizing a G2553 here.  So that wouldn't work with EnergyTrace++ but if possible the user might be able to migrate their sketch over to an FR5969 or similar MCU...

 

edit:

http://www.ti.com/tool/energytrace

 

 

 

EnergyTrace++

Share this post


Link to post
Share on other sites

I think I've found the culprit with the help of this article: http://www.elevendroids.com/2013/06/code-recipe-reading-msp430-power-supply-voltage-level/

 

If I add "ADC10CTL0 &= ~ENC;" to wiring_analog.c the problem is solved.

 

i.e. 

#if defined(__MSP430_HAS_ADC10__)    ADC10CTL0 &= ~ADC10ENC;                 // disable ADC    ADC10CTL1 = ADC10SSEL_0 | ADC10DIV_4;   // ADC10OSC as ADC10CLK (~5MHz) / 5    ADC10CTL0 = analog_reference |          // set analog reference            ADC10ON | ADC10SHT_3 | ADC10IE; // turn ADC ON; sample + hold @ 64 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×