|
|
View previous topic :: View next topic |
Author |
Message |
tssir
Joined: 14 Feb 2016 Posts: 24
|
Warning 216 : How to prevent function mutualization |
Posted: Mon Apr 17, 2017 2:34 pm |
|
|
Hello,
I use [] operator inside and outside interruptions. Then i have warning 216.
Compiler mutualize some code into self generated functions (for code volume optimization). I found some explanations on this forum.
I can "solve" warning 216 in many other cases, but not for [] operator (and not for usb driver functions, but it is not an issue). I use a lot of [] operator, and i can not use other solutions. I have bad experience with iterators (of structure pointer) and ccs ... many bugs ...
So, i must use [] operator.
Here a simple example :
Code: |
#include <16F1705.h>
#fuses INTRC_IO,NOWDT,NOMCLR,NOPROTECT,NODEBUG,NOLVP
#use delay(clock=32MHZ)
struct SDummy
{
byte a;
unsigned int16 value;
};
struct SDummyInterruption
{
byte a;
unsigned int16 value;
};
struct SDummy _dummyTable[20];
#define setDummyTableValue(_offset,_value) {_dummyTable[_offset].value=_value;}
// Try to replace [] operator by arithmetic operation : same result, compiler use sans function in interruption and main.
#define setDummyTableValue2(_offset,_value) {((struct SDummy*)((byte*)_dummyTable+_offset*sizeof(struct SDummy)))->value=_value;}
// Try to use another symbol, with an other equivalent structure (with different call on main and interrupt) : same result, compiler use sans function in interruption and main.
#define setDummyTableValue_Interruption(_offset,_value) {((struct SDummyInterruption*)((byte*)_dummyTable+_offset*sizeof(struct SDummy)))->value=_value;}
#INT_RC
void handler_rc(void)
{
unsigned int i;
for(i=0;i<20;i++)
{
setDummyTableValue(i,2);
}
clear_interrupt(INT_RC);
}
void main(void)
{
unsigned int i;
enable_interrupts(INT_RC);
enable_interrupts(GLOBAL);
while(true)
{
for(i=0;i<20;i++)
{
setDummyTableValue(i,1);
}
}
}
|
Here is a (not really good) solution, by replacing [] operator with inline function:
Code: |
#INLINE
void setDummyTableValueFunction(unsigned int8 offset,unsigned int16 value) {_dummyTable[offset].value=value;}
|
But it raises code volume.
Any other idea ? By-pass ?
How dissociate [] operator for interruption, and [] operator for main ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 17, 2017 10:08 pm |
|
|
You should have posted the full warning message, which is this:
Quote: | >>> Warning 216 "pcm_test.c" Line 51(4,5): Interrupts disabled during call to prevent re-entrancy: (@MUL88) |
This tells us the problem is caused by your code calling the CCS math
library routine @MUL88 in the isr, and in main().
This thread explains more about the problem:
http://www.ccsinfo.com/forum/viewtopic.php?t=33837&highlight=org+default
A brute force method of doing it would be to unroll the for() loop in the isr:
Code: |
_dummyTable[0].value = 2;
_dummyTable[1].value = 2;
_dummyTable[2].value = 2;
.
.
.
_dummyTable[19].value = 2;
|
The above method is much faster. Using the Stopwatch feature of MPLAB
vs. 8.92 simulator, I got 42 instruction cycles for the unrolled loop vs.
1386 instruction cycles for the for() loop and associated math operations.
How to use the Stopwatch feature of MPLAB (vs. 8.92) simulator to
find the number of instruction cycles in a segment of your program:
http://www.ccsinfo.com/forum/viewtopic.php?t=38351 |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Tue Apr 18, 2017 3:12 am |
|
|
Thank you for answer.
For a general use, i will dissociate interruption function from main function.
Both solutions :
1) I must use only elementary operations on interruption (add, shift, ...).
As this example :
Code: |
struct SDummy
{
byte a;
unsigned int16 value;
};
struct SDummy _dummyTable[20];
struct SDummy * getDummyTablePtr(unsigned int8 offset)
{
struct SDummy * res;
unsigned int8 i;
res=_dummyTable;
for(i=0;i<offset;i++)
{
res=res+sizeof(struct SDummy);
}
return res;
}
#define setDummyTableValue_forInterruption(_offset,_value) {getDummyTablePtr(_offset)->value=_value;}
#define setDummyTableValue(_offset,_value) {_dummyTable[_offset].value=_value;}
#INT_RC
void handler_rc(void)
{
unsigned int i;
for(i=0;i<20;i++)
{
setDummyTableValue_forInterruption(i,2);
}
clear_interrupt(INT_RC);
}
void main(void)
{
unsigned int i;
enable_interrupts(INT_RC);
enable_interrupts(GLOBAL);
while(true)
{
for(i=0;i<20;i++)
{
setDummyTableValue(i,1);
}
}
}
|
2) Use #org directive. But it is risky. Especially for a large and evolutive program. You should be aware about addresses. |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Tue Apr 18, 2017 11:46 am |
|
|
#ORG solution not working with a "real world" large program (a 58ko hex file, for my current project). #ORG itself works, and puts isr code at the right place (checked on pic ROM). But [] operator (8 bits multiplication) is not dissociate, despite #ORG.
But it works perfectly with a small test program.
Anyway, i use the first solution : isr only uses elementary operations (not embedded compiler functions or ccs drivers functions).
A getenv() to check if current code is inside an ISR, should be usefull. But without this option, i write two functions for same operation (one for isr, one for main). |
|
|
|
|
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
|