|
|
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
A question about disable_interrupts() |
Posted: Wed Dec 09, 2020 10:39 am |
|
|
As I continue to work through some I2C bus lockup issues, I found some routines that do global interrupt masking like this:
Code: |
disable_interrupts(GLOBAL);
// Do something here...
enable_interrupts(GLOBAL);
|
Would this cause an I2C interrupt to be MISSED if the Master wrote at the moment the code was masked? Or would be interrupt be pending and be handled as soon as interrupts are re-enabled?
Some test code I wrote looks like it just drops the interrupts, rather than leave them pending. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Wed Dec 09, 2020 11:35 am |
|
|
In all my tests on my PIC24 chips, the interrupt is waiting for me when I get back with enable interrupts. Specifically I have a blurb in my code like:
Code: |
while(TRUE){
handle_interrupts();
main_processing();
// Disable all interrupts to they don't get serviced right before going to sleep
disable_interrupts(GLOBAL);
// make sure no interrupts happened between the last call to
// handle_interrupts() and the upcoming sleep() call
if (all_interrupts_handled()){
sleep();
delay_cycles(1); // one NOP after waking
}
enable_interrupts(GLOBAL);
}
|
even with interrupt handling disabled, external interrupts still fire while asleep and wake me from sleep and when I enable interrupts I see the ISR fire right after (I used some inserted I/O line toggling and delays to verify the timing) |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Dec 09, 2020 11:57 am |
|
|
Right -
The disable_interrupts(GLOBAL) (IIRC) only flips the GLOBAL interrupt bit and not the interrupt flags for individual peripherals. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Dec 09, 2020 12:30 pm |
|
|
bkamen wrote: | The disable_interrupts(GLOBAL) (IIRC) only flips the GLOBAL interrupt bit and not the interrupt flags for individual peripherals. |
Question about this... I thought GLOBAL meant "all" interrupts?
If I understand -- as long as I don't have interrupts masked to long (longer than 2 bytes of I2C data coming in), I should not miss a Master write.
But when I see this in our code:
Code: |
disable_interrupts (GLOBAL);
// Loop
// Write flash
enable_interrupts (GLOBAL);
|
...that could be long enough that multiple bytes could have been written to this Slave PIC by the Master. When interrupts are re-enabled, would the:
i2c_isr_state()
...be returning the initial Master Write value (0x00) or, if that byte had passed, would it be coming back with 0x01, etc. indicating which byte it is receiving? _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Wed Dec 09, 2020 2:26 pm |
|
|
Disabling global means none of the normal interrupts can fire an ISR (ISRs for things like Address Errors, divide by zero, etc. can still fire), the interrupts still are seen (meaning all the individual IF flags will get set, chip will still wake from sleep, etc.) but just none of your interrupt code will work until they are re-enabled and if the IF flag was set, then the ISR will then fire (the order is platform specific and settings specific if you use priorities).
For the case of the same interrupt firing more than once, then yes, you'll miss out on running the ISR for some of them and will only get one I2C isr at the enable, so that will cause you problems.
In general you'll have to address this using your internal message protocol. the other side will need to know you cannot receive data yet until you tell it you are ready or you need a separate small micro to handle your I2C separately from your other code (or a chip with two cores potentially). |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Dec 09, 2020 2:31 pm |
|
|
jeremiah wrote: | In general you'll have to address this using your internal message protocol. the other side will need to know you cannot receive data yet until you tell it you are ready or you need a separate small micro to handle your I2C separately from your other code (or a chip with two cores potentially). |
Thanks. I should be on the same page now.
I'm wondering if I even need to mask around write_program_memory() -- or if that was added to work around some issue where IRQs were expected to cause them.
Actually, looking at the code, if there was concern over interrupting the actual write, it looks like I could reduce the time things are masked by disabling/enabled around that call itself inside the loop, rather than at the start and end of the function. More stuff on the TO DO list! _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|