CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Warning 216

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
russk2txb



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

Warning 216
PostPosted: Sun Apr 13, 2008 10:51 am     Reply with quote

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

View user's profile Send private message

More on Warning 216
PostPosted: Sun Apr 13, 2008 11:07 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Apr 13, 2008 11:09 am     Reply with quote

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

View user's profile Send private message

More on Warning 216
PostPosted: Sun Apr 13, 2008 11:43 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Apr 13, 2008 12:07 pm     Reply with quote

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

View user's profile Send private message

Warning 216
PostPosted: Sun Apr 13, 2008 1:25 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Apr 13, 2008 1:43 pm     Reply with quote

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

View user's profile Send private message

Warning 216
PostPosted: Sun Apr 13, 2008 8:13 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

Re: Warning 216
PostPosted: Sun Apr 13, 2008 11:07 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 14, 2008 7:29 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 14, 2008 11:25 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 14, 2008 1:10 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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