We have a product that uses an MSP430F5436A. It has been in production for several years. Over the past several months we have had reports from production that a few units are not shutting down completely, their power LED is staying on. The power LED is driven by an I2C GPIO expander, it's not connected directly to the MSP430.
When the user hits the power button the MSP430 is supposed to shut down a lot of peripherals, turn off the power LED, and enter LPM2. Periodically a timer interrupt wakes it up from LPM2 to check to see if the power button has been hit to turn the device back on and to do some other house keeping.
After the user hits the power button there is a delay before the device powers off which is driven via a timer ISR. I ripped that out and put in a delay loop. Within that delay loop I am rapidly toggling a different LED that is connected directly to the MSP430.
If I make the loop duration shorter than two seconds the device is able to get into LPM successfully and the LED stops toggling. If I set the loop longer than two seconds I can observe the lock up behavior I am seeing. Sometimes the LED is left in an on or off state, that is random.
I have attempted to disable all maskable interrupts prior to entering the loop. That had no effect. I also put code in the SYSNMI and UNMI vectors to detect if either of those were firing and neither is firing. Also, there is no RTOS, this is a cooperative multi-tasking system. So it seems to be locking up while executing the loop its self.
Eventually my device reboots from this lockup but it is due to a watchdog reset. I print the reset source at startup. The device also recovers if I pull out and reinsert the battery. However, the device stays in a locked up state if I pull the reset line low. I also have trouble JTAGGing firmware onto the device once it is locked up.
I've looked in the errata for the MSP430F5436A for mentions of lock up behavior and the only mention isn't relevant.
Unfortunately, due to the packing and construction of the device it is difficult to probe some of the nets, but not impossible.
I can connect to the device with a debugger, but the debugger (CCS 7 + MSP-FET430UIF) looses its connection with the device shortly after the device starts running. That is something that is always true and is a design issue. We have frequent timer interrupts occurring so this behavior may not be avoidable.
The power source for the device is stable and it is operating on my bench and not in a high EMI/EMF environment. However, when this loop occurs some peripherals and power supplies would have been shut down. So it is possible some sort of anomaly is occurring on one of the MSP430's power rails or a GPIO pin.
What could be causing this lock up behavior? Are there any persistent registers I can read on reset that would give me a clue, or are there any pins/nets I can probe that would give me a clue?
Update:
I have probed VCC for the MSP430, rails that power peripherals the MSP430 is connected to, and the reset line. I see no changes on any of these at the time of the lock-up.
Edit:
The following is the delay loop that I added
dprintf(PRINT_LOG, "Entering delay loop");
__disable_interrupt();
enable_backlight();
for(uint16_t j = 4u; 0u < j; --j)
{
__delay_cycles(14680064/20); // ~50mS delay w/ 14.680064 MHz MCLK
toggle_backlight();
}
disable_backlight();
__enable_interrupt();
dprintf(PRINT_LOG, "Exiting delay loop");
I incorrectly assumed that the hang was occurring within my delay loop because interrupts were disabled, and that the loop wasn't completing. It turns out the loop is running to completion, and after interrupts are enabled an ISR is entered for an event that occurred during the execution of the loop. The hang occurs in that ISR.
Shortly after the delay loop (in time, but somewhere else altogether in code) a GPIO interrupt is disabled. When I power down the device a peripheral that is holding a pin high is shut off, and that pin eventually drops. If I make the delay loop short the loop is exited and that particular interrupt is disabled before the pin drops. If the delay loop is long the pin drops and when the GIE bit is reset by __enable_interrupt(); a context switch to that GPIO interrupt begins.
Related
I currently have an ESP32-S2 QT Py that I am using to send sensor data to a PC via wifi using TCP. I want to preserve battery life while not sensing, so I put it into deep sleep. I see that there are timer, pin, and touch alarms to wake it back up, but none of these work well for my design. Is there any way that I can wake up a deep sleeping ESP32-S2 with a TCP packet send from the PC server?
This functionality is commonly called "wake on LAN" and is generally used, as you described, to allow a "magic" packet to wake up a sleeping or hibernating device.
In this case, no. The ESP32's wifi radio is off during deep sleep. With the radio off there's nothing active that can receive or detect a packet.
If you're trying to conserve power and maximize battery life, you need to keep the radio off as it uses quite a bit of power just to stay connected to a wifi network.
The only parts of the ESP32 that are active and available during deep sleep are the ULP ("Ultra Low Power") processor, a very limited slow processor that can perform a few I/O actions during sleep, and a small amount of static RAM associated with the real time clock. You can learn more about the ULP and what it can do in Espressif's documentation.
Currently working on msp430fr5969. I have multiple interrupt like SPI, I2C, Timer and the requirement is the SPI protocol is the highest priority.
However, according the datasheet, the priority of I2C(eUSCI_B0) higher than SPI(eUSCI_A1) and cant change the interrupt priority.
Link: http://mikrokontroler.pl/wp-content/uploads/pliki/msp430fr5969.pdf (page 21).
How I can get into SPI interrupt as fast as possible while I2C process?
I got stuck while I2C's reading and It has a data sent from another MCU. the MCU notify a timeout in that case. Its rarely but I want to fix it.
Note: use SPI to communicate with another MCU so its importance data.
Use I2C for readding information from sensor.
The interrupt priorities matter only if two interrupt flags are set before the CPU is able to handle one of them, and the CPU has to decide which one to handle first. In practice, this almost never happens.
When an interrupt handler executes, all other interrupts are blocked (GIE is cleared by default), regardless of priority. This means that when the I²C interrupt handler is currently executing and the SPI interrupt happens, the SPI handler begins execution only after the I²C handler has finished.
To execute the SPI handler with a high priority, you have to ensure that all other interrupts do not block it, at least not for a long time. This is typically done by those interrupt handlers just setting a flag that indicates that the device needs attention, and then handling these conditions in the main loop of your application.
You could technically reenable gie withing other interrupts to enable interrupt nesting.
This way you can manage interrupts execution order by adding some logic as preamble to interrupts. Personally I'd rather avoid it and keep it as last resort. Try to keep other interrupts code short, manage logic outside interrupts, and if it is not enough try to disable other interrupts while you expect the critical interrupt to come (if it is possible).
I am counting pulses using an external interrupt, but I put the processor to sleep in between pulses using wdt_enable, using the 8-second interval.
When the interrupt occurs and the processor wakes up to service the interrupt, is it possible to find out how long into the 8-second period I am? That is, can I read the wdt timer to see how long it has been running (or how long it has to go)?
The ATMEL328p Datasheet Page 51 shows the architecture of the Watchdog. There does not seem to be a method to read back the Watchdog Prescaler. The answer assumes you are using an Arduino with a 328p.
I am using an Arduino Pro Mini 328P (3.3v, 8Mhz) with Xbee series 1. I have set the frequency to 1 Mhz and the baudrate to 9600. Also I have set baudrate to 9600 in the Xbee. I have also tested that at this baudrate Xbee is sending the data properly in a normal scenario.
Now what I have done in my project:
I have registered my Xbee with the gateway and then it will go to sleep (I have used pin hibernate mode) then it will wake up by a digital pin of the Pro Mini. I have put a delay of 19ms, after which the Xbee will try to send data. After sending the data it will go back to sleep.
The problem is that it behaves randomly when sending data to the gateway (which also has the same Xbee series1). Sometimes it sends the data perfectly, sometimes sending fails. I have also enabled RR to retry 6 times in case the Xbee fails to send the data the first time.
I have no idea how to solve this problem because of the randomness in sending the data.
I have put two Xbees nearer (I have two nodes with the same hardware and the same code). There is an interval between of around 4 minutes. So when one Xbee sends the data perfectly, after that 4 minutes gae (time difference of two RTC on different nodes) the other one fails to send the data. In this condition what can I conclude?
As a side note, the Xbee will try to send the data every hour. To calculate that hour I have to use an RTC, which seems to work fine (I am sure because I have taken the logs, the RTC never fails to generate an interrupt).
So I am wondering what could be the possible reason and how can I fix this problem (without restarting anything if it is possible then nothing will be better than that).
And I have no choice to restart my controller.
How to debug this?
A few things. If possible, increase your baud rate so you spend less time sending data to/from the XBee. If you have a limited power budget, faster baud rates save time and energy. I don't know how the UARTs work on the Arduino, so I can't say whether 115,200bps is possible with a 1MHz CPU clock.
Second, make sure you wait for the XBee to assert CTS back to the Arduino after you wake it up. Never send to the XBee unless it's "clear to send".
Third, if you use API mode, you can watch for a "Transmit Status" frame from the local XBee back to the Arduino which will let you know when the module has successfully sent the frame, and it's safe for you to put it back to sleep.
I came across this website when trying to find a reliable way to use the watchdog for preventing failures (code lock ups) and saving battery using an Arduino.
I tried the code and it worked fine. However, i would also like to use the serial monitor. I tried adding Serial.begin(9600); in the setup, however, most of what is shown in the serial monitor (from the code within the main loop) are strange characters (the baud rate is set to 9600). Is this something to do with the function to configure the wdt and the placement of Serial.begin(9600) in the code?
I'd also like to use an external interrupt (via a button on Digital pin 3) to wake the board from sleep. How can be achieved based on the current code? I know how to implement using a different method of making the board go to sleep without using any watchdog at all, however, i have been unsuccessful in making it work with this code.
Many thanks for any help.
As said above, the serial communication should work fine. Are you sure you are able to make your serial communication work fine without the watchdog part of the code? I have used the watchdog tips given on the website along with serial communications without any problem on Arduino Uno, so I would guess the serial communication problem lies somewhere else in your code.
Can you write a bare bone example of your code with the watchdog management part, a serial communication or two somewhere in your loop(), and if you want some delays / infinite loops to test the watchdog firing, post it here, test it on your board and indicate if / where you have problems?
I have never used a pin interrupt, but it seems that google gives some nice results with example code. Have you tried the results given by google?
https://www.arduino.cc/en/Reference/AttachInterrupt
http://www.allaboutcircuits.com/technical-articles/using-interrupts-on-arduino/
You will have to be careful regarding the choice of the pin on which you put the interrupt, as explained in the Arduino Reference only pins 2 and 3 support interrupt on the Uno.