|
|
View previous topic :: View next topic |
Author |
Message |
peter_dufault
Joined: 25 Jul 2006 Posts: 6
|
RB0 / EXT interrupt blocked by various functions |
Posted: Wed Jun 20, 2007 6:53 pm |
|
|
My system is: 18F4620, 20 MHz, CCS PCWH 3.249.
Code: | ROM used: 27832 bytes (42%)
Largest free fragment is 37704
RAM used: 397 (10%) at main() level
483 (12%) worst case
Stack: 21 worst case (13 in main + 8 for interrupts)
|
I use a 60 Hz power line zero cross interrupt on RB0 for 120 events / second. I have less frequent interrupts on EXT1 and EXT2. I also use TIMER1 and TIMER2 interrupts.
Timing measurements on a scope show that the interrupt routines are fairly short.
When the system is otherwise "idle" the interrupt timing works as expected. As more activity is performed, the jitter on the interrupt response increases, up to perhaps 30% of the 1/120 s interrupt period. This much occurs 1 or 2 times per second. The system being run can handle perhaps 5% jitter.
After searching on this forum I found hints to similar situations here:
http://www.ccsinfo.com/forum/viewtopic.php?t=29105
http://www.ccsinfo.com/forum/viewtopic.php?t=25535
which clued me in to look for "BCF FF2.7" which clears the GIE bit in the INTCON register.
A search through my listing reveals around 170 instances of GIE being cleared before some operations. The operations that result in this process seem to include "putc()", "read_eeprom()", "spi_read()", "delay_X()", '*', '/', and perhaps others.
There may be things I can do to alleviate some situations, but I would rather remove the clearing of GIE. The other operations don't need fast response. I have a lot of RAM left over, so stack issues should not be a problem.
Questions:
1) Can I disable the compiler from clearing GIE?
2) If I rewrite the suspect functions so they don't clear GIE, what problems can I expect? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 20, 2007 7:02 pm |
|
|
Quote: |
A search through my listing reveals around 170 instances of GIE being
cleared before some operations. The operations that result in this
process seem to include "putc()", "read_eeprom()", "spi_read
()", "delay_X()", '*', '/', and perhaps others. |
How many of these functions are you calling from inside interrupt
service routines ? |
|
|
peter_dufault
Joined: 25 Jul 2006 Posts: 6
|
|
Posted: Wed Jun 20, 2007 9:43 pm |
|
|
Quote: | How many of these functions are you calling from inside interrupt
service routines ?
|
#INT_RDA: None
#INT_EXT1: None
#INT_EXT2: None
#INT_TIMER1: None
#INT_TIMER2: None
and then...
#INT_EXT: "putc()", "read_eeprom()", "spi_read()", "delay_X()", '*', '/', ...
I think I see what might be going on. Note that the jitter delay happens before the interrupt. Even though the execution time of the interrupt is fairly short, because those routines are not inline and because it's possible to be called from within the interrupt routine, it seems that the compiler will insert the "BCF INTCON, GIE" for all conditions, whether inside or outside the interrupt routine.
I did take into account the interrupt execution time. The individual cycles are split into a number of time slices that execute only a bit at a time; it never goes through everything in one pass. Some parts of the ISR are executed in only some conditions as well. I should be able to push some out of the interrupt handler. I will try it out tomorrow. I foresee many flags a flappin'.
Does my explanation seem reasonable? |
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 21, 2007 2:49 am |
|
|
What is happening, has been explained many times in the past.
The PIC, does not have a 'value' stack. As such, storage used inside routines, is the same in all copies of the routine. Hence to prevent 'reentrancy', if a routine is used inside an interrupt, and also used outside an interrupt,then interrupts _must_ be disabled whenever the routine is called. The same also applies to anything using 'hardware' flags for operations.
There are ways round parts of this. You can force the compiler to develop two copies of the 'delay' routines (basically you have one #use delay statement, declare the interrupt routines, and then have another #use delay statement). This has been documented here in the past.
For SPI_READ, you might just want to leave interrupts being disabled. You could code this yourself (it is only a matter of reading the SPI data register), but what happens if in the main code, the SPI_READ routine, checks the flag to see if data is waiting, sees that it is, and goes to read the data, then at that moment the interrupt occurs?. The code will arrive to read the data with the data already having been read.
The same applies to putc, and read_eeprom. In the former, the 'main' code, sees the flag to say that there is space in the transmit buffer, goes to write the data, and in between whiles, there has been an interrupt, and the buffer has been filled. Similarly, for read_eeprom, all the registers are setup to read the required byte, and then the code interrupts, and changes the byte addressed...
Most of the routines involved are fast. The main one that is probably causing problems, is the use of delays, which can be easily fixed as outlined above. The other that might (depending on how long the strings involved are), is the 'putc'. Consider not using putc. Instead use the code in the examples directory, for an interrupt driven RS232 transmit routine. Then sending characters, is just a matter of adding them to the much larger software transmit buffer. Though interrupts will be disabled during the write to this, this takes only a few uSec, against the time needed to actually 'send' the data.
Best Wishes |
|
|
|
|
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
|