![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Franck26
Joined: 29 Dec 2007 Posts: 122 Location: Ireland
|
Code bug, maybe during interrupt |
Posted: Mon Apr 12, 2010 2:28 am |
|
|
Hello,
I've got an annoying bug in my code and I'm trying to find the root.
The problem is that it's not happening often, sometimes there is no problem for 1 month, sometimes it happens after 1 week and it never happens when it's me who test the boards!!!
The bug does not stop the board from running, it's just that 1 of the pin which is meant to go low every x ms stays high until manual reset. This pin is cleared by timer IT.
My first guess is that the global IT is disabled, and I wonder if it could come from this few lines which are used to stop the IT during some functions:
Code: | static unsigned int1 IT_Save;
static void IT_Push(void)
{
if(INTCON.GIE)
{
INTCON.GIE = 0;
IT_Save = TRUE;
}
else
IT_Save = FALSE;
}
#define IT_Pull() INTCON.GIE = IT_Save
|
IT_Push() save the global interrupt bit and clear it.
IT_Pull() set the global interrupt bit to its previous state.
Those 2 functions can be called at anytime, during normal operation or during IT. I don't know why I used a static declaration for IT_Push, but I suppose that the problem is not here.
Do you think that the problem can come from those functions, or should I look somewhere else in my code?
Thanks for any help,
Franck. |
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Mon Apr 12, 2010 4:01 am |
|
|
When is it re-enabled ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Mon Apr 12, 2010 4:08 am |
|
|
Yes, it could come from those functions. Specifically the IT_Pull define. What you don't say, is what PIC is involved?.
If you look at the code to enable the global interrupt bit generated by CCS, for some processors, it effectively generates:
Code: |
do {
ITCON.GIE=1;
} while (ITCON.GIE==0);
|
This is done, because on some processors, if an interrupt is pending, when GIE is set, it executes immediately, and the GIE value restored on the return, is the one applying at the _start_ of the instruction (when GIE was off)....
Hence to set the GIE, you have to set it, then test if it has set, and keep retrying, till it does set.
You should fix this, either by coding as above, or simply using the 'enable_interrupts(GLOBAL)' routine, which does this. So:
Code: |
#define IT_PULL() if(IT_Save) enable_interrupts(GLOBAL)
|
It is a very low probability problem, but it sounds exactly what could be happening to you....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Franck26
Joined: 29 Dec 2007 Posts: 122 Location: Ireland
|
|
Posted: Mon Apr 12, 2010 9:49 am |
|
|
@Wayne_:
The IT is re-enable when the function IT_Pull() is used. Usually after few instructions. Thanks.
@Ttelmah:
What you describe could really be my bug.
If this is the problem, you'll save me from a lot worries !!!
2 processors used this code: 18F2520 and 18F67J60.
Do you know where I can check if those processor are prone to this GIE restore? Is it in the standard datasheet?
I don't really understand what is the purpose of this automatic GIE restore. Is it done on purpose, or is it a bug?
Thanks,
Franck. |
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Mon Apr 12, 2010 9:59 am |
|
|
Franck26 wrote: | @Wayne_:
The IT is re-enable when the function IT_Pull() is used. Usually after few instructions. Thanks.
|
LOL, I knew that. What I was thinking was if the button is pressed twice, the second time before the interrupt is re-enabled (may be due to bounce) your flag will be false and the interrupt will be disabled, if you then try to re-enable the interrupt using the flag you will just be disabling it again. |
|
![](templates/subSilver/images/spacer.gif) |
Franck26
Joined: 29 Dec 2007 Posts: 122 Location: Ireland
|
|
Posted: Mon Apr 12, 2010 11:06 am |
|
|
@Wayne_
OK, I understand what you have in mind.
Fortunately (or unfortunately, since that it would fix the problem), the function IT_Push() is never called a second time before IT_Pull().
It could be call twice if an IT using IT_Push() is triggered, but it shouldn't be possible since the IT are disabled by IT_Push()...
Thanks,
Franck. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Mon Apr 12, 2010 2:45 pm |
|
|
Except that the problem I describe, can also apply to clearing the GIE flag as well, which could then hit the double press problem. Again if you look at the code generated for 'disable_interrupts(GLOBAL);', you will find on some processors it is coded effectively as:
Code: |
do {
GIE=0;
} while (GIE==1);
|
This is why it is much better/safer, to code your routines as:
Code: |
static unsigned int1 IT_Save;
static void IT_Push(void)
{
if(INTCON.GIE)
{
clear_interrupts(GLOBAL);
IT_Save = TRUE;
}
else
IT_Save = FALSE;
}
#define IT_Pull() if (IT_save==1) enable_interrupts(GLOBAL)
|
If you are going to direct set/clear the bits, _you_ will need to check both the data sheet, errata, and 'product line' documentation, and verify what does happen if an interrupt occurs in the set/clear instructions, and handle this...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Franck26
Joined: 29 Dec 2007 Posts: 122 Location: Ireland
|
|
Posted: Mon Apr 12, 2010 3:21 pm |
|
|
@Ttelmah:
Sure that I'm going to implement your code suggestion. That's a good practice even if the processor used is not prone to this GIE restore issue .
It looks like I'll have a lot of reading tomorrow. I'll post an update if I find a documentation.
Thanks,
Franck. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|