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).
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.
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 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.
So I have a device set as the I2C master, and the rest of the devices on the bus are set as slaves. The master sends a command to each slave, and the slave executes this task (running motors, etc, important time-sensitive code). I would like to be able to know when the slave is finished executing its task. The only way I can see to do this is to constantly have the master poll the slave, but this creates an issue, because every time the master polls the slave, it triggers and i2c interrupt on the slave and quits running the motor code for a short amount of time.
Is there anyway to solve this? I was thinking of setting all devices as a master, so then when each device finishes it task, it can send the data over saying that it is done, without the need for polling. The issue with this is I'm worried about data collision over the bus with devices possibly trying to talk at the same time.
What is the correct way to solve this issue?
Let the slave disable its I2C interface while it's running a time-critical task, and re-enable afterwards. Then, the master can poll as often as it wants to, it would get no ACK from the busy slave, and the slave won't get any interrupts either.
I'm a beginner. I'm trying to understand about I2C Initialization of TMP102. It is a temperature sensor. It is connected via I2C. So, the initialization must be of I2C. But, my leader told we have to initialize GPIO also in this case, since interrupt pin is connected via GPIO. He also told it is not necessary in other cases. I couldn't understand the original purpose.
Why do we initialize GPIO?
In other cases, where does the slave's interrupt pin gets connected?(if not in GPIO)
Also, in case of large message, TX/RX FIFO may not fit. So, draining feature is used (XDR/RDR bit is set). What exactly is draining feature and what it does?
Why do we initialize GPIO?
Since interrupt pin is connected via GPIO.
In other cases, where does the slave's interrupt pin gets connected?
If slave has an interrupt pin, you SHOULD initialize corresponding GPIO/IOMUX.
Some slave devices may not contain interrupt. In that case, no need to initialize any GPIO.
Summary:
You should initialize ALL GPIO/IOMUX for all input/output from processor to slave device.