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.
Related
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.
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'm making a quadcopter with SparkFun ESP32 Thing module and using MPU9255 Waveshare IMU.
It looks like when I'm reading PWM signals from RC receiver with interrupts (6 interrupts for 6 chanels) I2C fails after some time. I am using interrupt over MPU9250 either (but not the DMP module, just sync for accel and gyro data). I am not sure if the connection fails, MPU9250 or ESP32.
It looks like this:
After 10-50sec, MPU9250 fails, and MPUs interrupt works at 8kHz (instead of 1,6kHz), and values wont change.
No idea what is happening ;/ Anyone?
Without interrupts, I2C works fine...
Your ISRs must save and restore ALL registers and flags that are used. If you are calling any external functions from your ISRs, there could be reentrancy issues. Without a look at the code, that's the best I can offer.
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.
Is it possible to wake a Microchip PIC16F1825 from sleep using RS232 without looking characters?
Because one of the permissible RX pins supports interrupt on change, I thought this might be possible.
Has anybody implemented this successfully?
Sure!
From datasheet PIC16(L)F1825/1829:
9.1 Wake-up from Sleep
The device can wake-up from Sleep through one of the following events:
1. External Reset input on MCLR pin, if enabled
2. BOR Reset, if enabled
3. POR Reset
4. Watchdog Timer, if enabled
5. Any external interrupt
6. Interrupts by peripherals capable of running
during Sleep (see individual peripheral for more information)
So you can use:
1)External interrupt INTERRUPT-ON-CHANGE, if you are connecting RX pin with one of other pins which is configured as interrupt-on-change.
2)Peripheral interrupt RCIF: USART Receive Interrupt Flag bit. When receiver buffer is full (one UART word is received), an interrupt is pending and your CPU should wake up.