|
|
View previous topic :: View next topic |
Author |
Message |
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
Warning 216 |
Posted: Sun Apr 13, 2008 10:51 am |
|
|
Ok, I got the v4.071 compiler and right away I ran into a problem. At the end of compilation there are a bunch of warning 216 messages about disabling interrupts during certain function calls. I do understand why these interrupts should be disabled when called from an interrupt, but I have some questions.
1. If the same function is called from an ISR and from main code, are the interrupts disabled in either case?
2. Is there any way to turn off this warning (pragma warning)?
3. Is there any way to turn off this behaviour?
4. Is this new behaviour for the new compiler, or just a new warning message?
Each warning message references the last line of code in my file, so it is impossible to determine what instance of the function call the warning is for - leading me to think maybe it is for all instances???
You may think it is bad programming practice to call the same function from an ISR and main code, but not really if the circumstances are right. For instance I have a Reboot function that the comiler warned about. It turns off some periphials and then resets the processor. Mostly it is called from main code, but in one place from the rda interrupt in response to a command from the controlling PC. In either case it is ok to disable the interrupts, and so I would like to not see the warning message.
Another case is a function that writes 4 bytes to the EEProm. This function is called from main code (in several places), and once from the power loss interrupt. When called from the ISR, it is may be reasonable to shut down the interrupts, but not when called from main code. So I hope this warning only applies to calls from ISR, but it's impossible to tell from the compiler message. (Actually extra instructions to shut off interrupts during power loss processing are not welcome either!)
I'd like to respectfully submit that the compiler warning message needs to be more explicit, and correctly show the line numbers for the calls where this is done.
Thanks in advance for any explanations.
Russ |
|
|
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
More on Warning 216 |
Posted: Sun Apr 13, 2008 11:07 am |
|
|
In addition to my first questions, two more. First look at this code:
void AZ_stop ()
{
output_bit (PIN_A5, 0); // Stop drive CW
output_bit (PIN_A2, 0); // Stop drive CCW
output_bit (PIN_B3, 0); // Slow off
if (gbMovingCW | gbMovingCCW)
AzStopTimer = 0;
gbMoveCW = gbMoveCCW = false;
gbMovingCW = gbMovingCCW = false;
gbAzSlow = false;
if (bJogLed)
output_bit (PIN_E2, gbElSlow); // leave it on if el is slow
}
Why would the compiler turn off interrupts for this function?
Secondly, in my first message I mentioned a function that writes 4 bytes to EEProm. here it is:
void WriteEEpromDLong (int address, int32 value)
{
write_eeprom (address, value >> 24);
write_eeprom (address+1, value >> 16);
write_eeprom (address+2, value >> 8);
write_eeprom (address+3, value & 0xff);
}
However several functions call it, like this:
void SetCurrentEl (int32 el)
{
WriteEEpromDLong (EL_CURRENT, el);
OpData.ElPosition = el;
}
Why would the compiler generate a Warning 216 for this second function, since we already know that WriteEEpromLong turns off the interrupts? Or is it smart enough to turn off the ints at the call to SetCurrentEl, and then not turn them off again when WriteEEpromLong is called?
Thanks again,
Russ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 13, 2008 11:09 am |
|
|
Quote: | 2. Is there any way to turn off this warning (pragma warning)? |
Look in the Pre-Processor section of the manual. There is a directive
to turn off individual warnings. This is on page 90 in the Acrobat reader.
Look in the "Compiler Control" section of the list.
http://www.ccsinfo.com/downloads/CReferenceManual.pdf |
|
|
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
More on Warning 216 |
Posted: Sun Apr 13, 2008 11:43 am |
|
|
Ok, I see where I can turn off the warning, but it appears to be for all instances of that warning. I want to be able to turn it off only for specific instances where I know the warning is not needed (for instance during Reboot). Other places I want the warning so I can know to watch out for problems that turning off the ints might cause.
Also, I already figured out, partially, the answer to my second post, where I asked why the warning was generated for the function AZ_Stop:
void AZ_stop ()
{
output_bit (PIN_A5, 0); // Stop drive CW
output_bit (PIN_A2, 0); // Stop drive CCW
output_bit (PIN_B3, 0); // Slow off
if (gbMovingCW | gbMovingCCW)
AzStopTimer = 0;
gbMoveCW = gbMoveCCW = false;
gbMovingCW = gbMovingCCW = false;
gbAzSlow = false;
if (bJogLed)
output_bit (PIN_E2, gbElSlow); // leave it on if el is slow
}
The problem is with this line: if (gbMovingCW | gbMovingCCW)
Changing it to "if (gbMovingCW || gbMovingCCW)" resolves the issue. But why? This is a simple bitwise OR. gbMovingCW and gbMovingCCW are both bool (typedef short bool;). This should not invoke any non-reentrant code. I have always used the single | in cases like this because it creates fewer machine instructions than the || which would generate jump or branch instructions.
Thanks,
Russ
PS: Wonder why my posted code is not showing up in code blocks like before. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 13, 2008 12:07 pm |
|
|
Quote: | I want to be able to turn it off only for specific instances. | The manual has an example. Here's another one:
Code: | #ignore_warnings 203
while(1);
#ignore_warnings NONE |
Quote: | Wonder why my posted code is not showing up in code blocks |
Here's how to put code in a code block.
1. Use your mouse to highlight all the desired code.
2. Click once on the "Code" button. This will insert the
code block tags at the start and the end of the selected text.
3. Click on the "Preview" button to see how it will look, before
you post it.
4. If it looks good, then click the Submit button.
Quote: | The problem is with this line: if (gbMovingCW | gbMovingCCW) |
Post a small but complete test program that shows the problem.
It must be compilable. ie., It should compile without errors if it's
copied and pasted into an MPLAB project source window. It needs
to have a #include, #fuses, #use delay(), etc., and all variable
declarations, and a main(), etc. Short, but compilable. Also, post
the error message from the compiler. |
|
|
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
Warning 216 |
Posted: Sun Apr 13, 2008 1:25 pm |
|
|
Ok PCM, thanks for your help. Here is a test program:
Code: | #include <18F4680.h>
#device HIGH_INTS=true
#fuses HS,NOWDT,NOPROTECT,BROWNOUT,NOLVP,PUT
#use delay(clock=20000000)
#priority ext,rb,timer1,rda
typedef short bool;
bool gbMovingCW, gbMovingCCW;
int AzStopTimer;
void AZ_stop ();
void AZ_stop2 ();
void main ()
{
AzStopTimer = 10;
Az_stop ();
AZ_stop2 ();
}
void AZ_stop ()
{
if (gbMovingCW | gbMovingCCW)
AzStopTimer = 0;
}
void AZ_stop2 ()
{
if (gbMovingCW || gbMovingCCW)
AzStopTimer = 0;
}
#int_rda
void rs232_handler ()
{
Az_stop ();
AZ_stop2 ();
} |
Of course this program will not work, but it compiles and demonstrates the problem.
Here is the compiler output:
errr, the complier will not allow me to cut and paste lines from the output window, but it generates warning 216, like this:
Quote: | >>> Warning 216 "test.c" Line 43(0,1): Interrupts disabled during call to prevent re-entrancy. (AZ_stop) |
Note that it does not generate a warning for the call to the AZ_stop2 function. Also note that the line number referenced is 43, but line 42 is the last line of the program.
Russ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 13, 2008 1:43 pm |
|
|
You can see it in the .LST file. The bitwise-OR operation uses a
temporary variable, while the logical OR does not.
Here's the bitwise OR. It uses temporary variable "@@1C":
Code: | ... if(gbMovingCW | gbMovingCCW)
000AE: MOVLW 00
000B0: BTFSC gbMovingCW
000B2: MOVLW 01
000B4: MOVWF @@1C // Temp var
000B6: MOVLW 00
000B8: BTFSC gbMovingCCW
000BA: MOVLW 01
000BC: IORWF @@1C,W // Temp var
000BE: BZ 00C2
|
Here's the logical OR. It doesn't use a temp variable.
Code: | ... if(gbMovingCW || gbMovingCCW)
000C4: BTFSC 19.0
000C6: BRA 00CC
000C8: BTFSS 19.1
000CA: BRA 00CE |
The compiler has to disable interrupts because of that temporary
variable. Suppose you were in the middle of that bitwise OR routine,
and then an interrupt occurred. The temp variable @@1C could get
changed when it's called by the isr. Then when the interrupt is over
and the main program resumes, it's running with a variable that has
been trashed. Operation would be erratic. So that's why the compiler
has to protect you by disabling interrupts. |
|
|
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
Warning 216 |
Posted: Sun Apr 13, 2008 8:13 pm |
|
|
PCM, yes I do see. And not only that but the bitwise OR uses a lot more instructions - completely opposite from any processor I have used before. It does not make sense to me... Even the lowly 8008 microprossor had a way to OR a register with the accumulator and leave the result plus flags in the accumulator - with a single instruction. However it is what it is and I will have to work with it.
Now if you can answer one more thing I think I will be done. If I have a routine like that AZ_stop, and I call it from another function, StopAll. Both AZ_stop and StopAll will be flagged with warning 216 (if I am calling both from main code as well as ISR). Why is that - if StopAll does not have any code that needs to be protected then I would think only AZ_stop would be flagged with the warning. And are interrupts really disabled when calling StopAll, or only when StopAll calls AZ_Stop? I will look at the .lst file to find that answer, but beyond the simple question of what does it do, I'd appreciate an answer to why.
Thanks,
Russ |
|
|
andrewg
Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia
|
Re: Warning 216 |
Posted: Sun Apr 13, 2008 11:07 pm |
|
|
russk2txb wrote: | Even the lowly 8008 microprossor had a way to OR a register with the accumulator and leave the result plus flags in the accumulator |
What you're missing is that the CCS compiler, unlike "regular" compilers, supports bit allocations - other compilers usually don't go any smaller than bytes. Short ints in CCS are bits (int1) by default. If you changed your gbMoving variables to bytes (int8), the bitwise comparison is probably more like what you were expecting: Code: | 000AE: MOVF gbMovingCW,W
000B0: IORWF gbMovingCCW,W
000B2: BZ 00B6 | You can save EEPROM space, at the cost of RAM. _________________ Andrew |
|
|
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
|
Posted: Mon Apr 14, 2008 7:29 am |
|
|
PCM programmer wrote: | You can see it in the .LST file. The bitwise-OR operation uses a
temporary variable, while the logical OR does not. |
Here's the bitwise OR. It uses temporary variable "@@1C":
Code: | ... if(gbMovingCW | gbMovingCCW)
000AE: MOVLW 00
000B0: BTFSC gbMovingCW
000B2: MOVLW 01
000B4: MOVWF @@1C // Temp var
000B6: MOVLW 00
000B8: BTFSC gbMovingCCW
000BA: MOVLW 01
000BC: IORWF @@1C,W // Temp var
000BE: BZ 00C2
|
I have a question though, where is the code to disable interrupts? I cannot see anything either above on in the calls to the routine.
From main:
Code: | .................... Az_stop ();
00106: RCALL 00AE
00108: BTFSC 18.6
0010A: BSF FF2.6
0010C: BTFSC 18.7
0010E: BSF FF2.7 |
I wanted to see exactly where the disable interrupts occurs, but I cannot figure it out.
Thanks,
Russ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 14, 2008 11:25 am |
|
|
In MPLAB, go to the Project menu, and then to Build Options.
In that window, select Symbolic format for the List file.
Then you will see this:
Code: |
... AzStopTimer = 10;
000F2: MOVLW 0A
000F4: MOVWF AzStopTimer
000F6: CLRF 18
000F8: BTFSC INTCON.PEIE/GIEL
000FA: BSF 18.6
000FC: BCF INTCON.PEIE/GIEL
000FE: BTFSC INTCON.GIE/GIEH
00100: BSF 18.7
00102: BCF INTCON.GIE/GIEH
... Az_stop ();
00104: RCALL 00AE
00106: BTFSC 18.6
00108: BSF INTCON.PEIE/GIEL
0010A: BTFSC 18.7
0010C: BSF INTCON.GIE/GIEH
... AZ_stop2 (); |
|
|
|
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
|
Posted: Mon Apr 14, 2008 1:10 pm |
|
|
PCM, I have now studied the .lst files for several examples and I see what I think is incorrect application of this disabling of interrupts.
Suppose you have a program with functions f1, f2, main, and int_rda. Only f1 has code that must be protected from reentrance, but f1 is called from f2. Now if f1 and f2 are both called from main and from int_rda, the 216 warning will be shown for both f1 and f2. From the lst file the ints are disabled prior to the call to both f1 and f2 in main. But this means that all of the code in f2, both prior to and after the call to f1, are protected from interrupts, even though it is not necessary. Interrupts will remain disabled for a lot longer than necessary.
This could cause significant problems to programs that depend on fast interrupt handling. This is especially a problem since we don't have dependable ways of knowing when a routine will disable interrupts (except by compiling with the new compiler and seeing if it generates a warning 216). People with the version 3 compiler will never figure it out, and people with v4 compiler will perhaps write a lot of code, only to discover they have to restructure to prevent this problem.
If, in my example, the ints were disabled inside of f2, just before calling f1, then the problem would be significantly reduced and it would not be necessary to warn for or disable interrupts for each call to f2.
I also think a list of operators and functions that cause interrupt disabling, and perhaps some syntax coloring in the editor when one of these operators or instructions are used would be very helpful. Even better would be to have a compiler switch that could cause code generation that does not require reentrancy protection.
If my suggestions are valid, can you make sure they are forwarded to the proper peoople?
Thank you,
Russ |
|
|
|
|
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
|