![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
kahnm
Joined: 30 Apr 2007 Posts: 9
|
large int_rda causes problems with int_rda2 -HELP |
Posted: Wed Jul 04, 2007 10:47 pm |
|
|
Hello,
Compiler version: 4.042
Device 18F66J11
Problem: I'm using both int_rda and int_rda2
int_rda has a good amount of code (maybe 50 lines of code) which when enabled works perfectly. However, at the time it is disabled
int_rda is already disabled, however int_rda2 seems to be running slow. However, when I "comment" out all the code from int_rda then int_rda2 works well.
I'm just commenting out code of a disabled interrupt. This seems like a memory mapping problem. Has anyone run into this?
Thanks, Gary |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 05, 2007 11:25 am |
|
|
1. Fifty lines sounds like a lot. Post that isr, and the other one.
Post the variable declarations for the isrs.
2. Post the #use statements for both UARTs.
3. Do you disable interrupts for the isrs at any time in your program ? |
|
![](templates/subSilver/images/spacer.gif) |
kahnm
Joined: 30 Apr 2007 Posts: 9
|
Post subject: large int_rda causes problems with int_rda2 -H |
Posted: Thu Jul 05, 2007 11:36 pm |
|
|
Thanks for your help. Here's the int code. int_RDA is disabled and never gets executed. When I comment out the call to the function rdaIntCode, the int_RDA2 works perfectly.
Thanks,
Gary
Code: | #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,restart_wdt,STREAM=RMUVI232,ERRORS)
#use rs232(baud=9600,parity=N,xmit=PIN_G1,rcv=PIN_G2,bits=8,restart_wdt,STREAM=SATGSM232,ERRORS)
#int_RDA
void RDA_isr()
{
char currentByte;
currentByte=fgetc(RMUVI232);
rdaIntCode(currentByte); // if I comment this out int_RDA2 works and
// I don't get overruns
}
#int_RDA2
void RDA2_isr(void)
{
modembuffer[byteCount++]=fgetc(SATGSM232);
if(byteCount>100)disable_interrupts(INT_RDA2);
}
#int_TIMER1
void TIMER1_isr(void)
{
t1Count++;
}
void rdaIntCode(char currentByte)
{
int i,t,i1,k;
char lastByte;
lastByte=0;
bufferLocation++; // increment position
if(currentByte==0x02&&previousByte!=0x10)bufferLocation=0; // initialize buffer point when 0x02 is read
if(previousByte==0x02&&previousByte!=0x10)packetSize=currentByte; // acquire packetSize ; byte after 0x02
if(bufferLocation==2)
{
priorPriorBuffer2=priorBuffer2; // save priorBuffer2
priorBuffer2=buffer[2]; // save previous buffer[2] in variable
}
buffer[bufferLocation]=currentByte; // save current byte into buffer
previousByte=currentByte; // currentByte will be previousByte during next read
if(bufferLocation==packetSize)lastByte=1; // set flag indicating last byte has been read
if(lastByte==1)
{
packetReceived=1;
disable_interrupts(INT_RDA);
for(i=0;i<packetSize;i++){bufferSaved[i]=buffer[i];BufferSavedReal[i]=buffer[i];}
i1=0;
for(i=3;i<packetSize;i++) // Strip out 0x10's
{
if(bufferSaved[i]==0x10&&bufferSaved[i-1]!=0x10)continue;
BufferSavedReal[3+i1++]=bufferSaved[i];
}
// initialization code
if(initComplete==0)
{
if(buffer[2]==0x41)
{pastInit=0;c89count=0;priorBuffer2=0;c25Count=0;c892Count=0;c92Flag=0;}
if(buffer[2]==0x25)received25=1;
if( (buffer[2]==0x74&&priorbuffer2==0x05)|| (buffer[2]==0x05&&priorbuffer2==0x89&&pastInit==0))sendc89pre=1;
if( (buffer[2]==0x05&&priorBuffer2==0x89&&priorPriorBuffer2==0x67) )sendc891=1;
if( (buffer[2]==0x05&&priorBuffer2==0x25&&priorPriorBuffer2==0x89) )sendc91=1;
if( (buffer[2]==0x05&&priorBuffer2==0x89&&sentc91==1))sendc91=1;
if( (buffer[2]==0x05&&priorBuffer2==0x89&&pastInit==1&&c25count++<2)){sendc892=1;if(c25count>=100)c25count=3;}
if( (buffer[2]==0x05&&priorBuffer2==0x89&&pastInit==1&&c25count++>=2)){sendc25=1;}
if(sendc89pre==1)
{
for(k=0;k<10;k++)fputc(c89pre[k],RMUVI232);
//fprintf(DEBUG232,"a");
sendc89pre=0;
}
if(sendc891==1)
{
for(k=0;k<10;k++)fputc(c891[k],RMUVI232);
//fprintf(DEBUG232,"b");
sendc891=0;
}
if(sendc91==1)
{
for(k=0;k<6;k++)fputc(c91[k],RMUVI232);
sendc91=0;
if(sentc91==1){sentc91=0;c25count=0;pastInit=1;}
else sentc91=1;
//fprintf(DEBUG232,"c");
}
if(sendc892==1)
{
for(k=0;k<6;k++)fputc(c892[k],RMUVI232);
sendc892=0;
//fprintf(DEBUG232,"d");
}
if(sendc25==1)
{
for(k=0;k<5;k++)fputc(c25[k],RMUVI232);
sendc25=0;
received25=0;
initComplete=1;
//fprintf(DEBUG232,"e");
//packetReceived=0;
//enable_interrupts(INT_RDA);
//continue;
}
}
else
{
if(bufferSavedReal[2]==0x05)
{
for(k=0;k<10;k++){fputc(c892[k],RMUVI232);}
//fprintf(DEBUG232,"f");
}
if(resetCount++==40)
{
send2RMU(191+channel2Read++); // get reading
if(channel2Read>=4)channel2Read=0;
//resetCount=0;
}
if(resetCount==140)resetCount=0;
if(bufferSavedReal[2]==0x05&&received25==1)
{
for(i=0;i<5;i++)fputc(c25[i],RMUVI232);
//fprintf(DEBUG232,"z");
received25=0;
}
if(bufferSavedReal[2]==0x25)
{
reading=( bufferSavedReal[5]<<8 | bufferSavedReal[6]);
channelNum=(bufferSavedReal[3]&0x0f);
resolution=(bufferSavedReal[4]&0x03);
channelState=(bufferSavedReal[4]&0xfc)>>2;
// if(channelNum==0x01)voltageReading=reading;
// elseif(channelNum==0x02)currentReading=reading;
floatReading= (float)reading;
floatReading=floatReading/10.0;
fprintf(DEBUG232," %d=%5.1f r%d s%d ",channelNum,floatReading,resolution,channelState);
//for(i=0;i<=packetSize;i++)fprintf(DEBUG232,"x%02x",bufferSavedReal[i]);
}
}
//fprintf(DEBUG232,"%d",packetSize);
packetReceived=0;
enable_interrupts(INT_RDA);
} // end if last byte
} // end of rdaIntCode
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 06, 2007 12:28 am |
|
|
Quote: | if(sendc892==1)
{
for(k=0;k<6;k++)
fputc(c892[k],RMUVI232);
sendc892=0;
//fprintf(DEBUG232,"d");
}
if(sendc25==1)
{
for(k=0;k<5;k++)
fputc(c25[k],RMUVI232);
sendc25=0;
if(sendc891==1)
{
for(k=0;k<10;k++)
fputc(c891[k],RMUVI232);
//fprintf(DEBUG232,"b");
sendc891=0;
}
Etc.
|
The lines shown in bold guarantee that you will have overrun errors
in the receiver. These lines send 5, 6, or 10 bytes. The UART transmitter
has only a 1-deep fifo, plus the transmit shift register itself. This means
that after you send it the first two bytes, your code has to wait for 3, 4,
or 8 character times, respectively, before the isr exits. The hardware
receive fifo for other UART is 2-deep, plus the receiver shift register.
It will quickly fill up, and then get over-run, while the first isr is sitting
there in a loop, sending out 10 characters (in the one case).
You could change the #int_RDA isr so that it puts incoming characters
into a software receive fifo (see the CCS example, Ex_Sisr.c). Then
move all the time-intensive fputc() code into a loop in main(), where it
won't block the RDA2 interrupts.
One other possibility is to create an interrupt-driven transmit fifo.
See the CCS example file, Ex_Stisr.c. Instead of waiting for the UART
transmitter to go ready while inside the RDA isr, you put the out-going
characters into a buffer. When you exit the RDA isr, the TBE interrupt
will fire, and the #int_TBE isr will call fputc() to send one character. |
|
![](templates/subSilver/images/spacer.gif) |
kahnm
Joined: 30 Apr 2007 Posts: 9
|
large int_rda causes problems with int_rda2 -HELP |
Posted: Fri Jul 06, 2007 1:12 am |
|
|
Thank you for your reply.
Maybe I'm not explaining it clearly.
The problem is that this code (the function) is just present in int_RDA. The interrupt is disabled, the code you mention doesn't get executed.
When I add this code (function call) in int_RDA (with int_RDA disabled), int_RDA2 gets overruns.
When all that code is added to int_RDA, even though it isn't enabled, problems occur with int_RDA2. When I comment out the function inside int_RDA, then int_RDA2 doesn't overrun. int_RDA was always disabled.
Do you think the size of what goes in the int_RDA could be a problem. I've sent in some obvious bugs to CCS regarding the 18F66J11 and compiler version 4.042. I'm not sure they have completely tested the compiler with this chip.
Thanks again, Gary |
|
![](templates/subSilver/images/spacer.gif) |
kahnm
Joined: 30 Apr 2007 Posts: 9
|
|
Posted: Fri Jul 06, 2007 1:31 am |
|
|
For example, I've sent in obvious bugs having to do with registers.
1) setup_wdt(WDT_OFF) writes to an incorrect register. It is almost like they used the template for the 18F8722 chips
2) the pic wizard embeds setup_psp(PSP_DISABLED) in the code which isn't correct, this writes to the SPBRG register
I've noticed these and I am wondering if there is something regarding the memory map which is causing this problem I am explaining ( A large amount of code in int_RDA causes int_RDA2 to malfunction, even though int_RDA is disabled).
Thank you, Gary |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 06, 2007 1:46 am |
|
|
Then post a new test program with all that isr code removed (since it's
commented out). Write the program in such a way that it demonstrates
the problem. Then write an explanation of how this test program fails.
Post a program that's compilable -- in other words, it can be pasted
directly into MPLAB without change, and it will compile with no errors.
This means it has all #include, #use, #fuses and #define statements
and all variable declarations. |
|
![](templates/subSilver/images/spacer.gif) |
kahnm
Joined: 30 Apr 2007 Posts: 9
|
|
Posted: Sun Jul 08, 2007 11:46 pm |
|
|
Thanks a great deal for your help. I'll try to see if I can duplicate this problem with a similar type program I can load to the website. I'm not certain I'll be able to do this in a timely fashion or if I'll be able to do it as I am in tremendous time pressure. However, I really appreciate all the help you have provided.
Gary |
|
![](templates/subSilver/images/spacer.gif) |
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Mon Jul 09, 2007 1:13 am |
|
|
There there is still a problem with large ISRs. It took me 2 days to figure it out. Inside RDA i had some CRC calculations and some other things. The behaviour was a mess. I used debugger.. and i was stepping line by line. The processor was skipping jumps and for's in an inexplicable manner. Till i was doing someting like this: Code: | void usart_isr()
{
int8 b;
b = getc();
buff[count++] = b;
return;
crc();
} | Basically crc() is not executed, however still added by compiler. But this code was having a undefined behaviour. If i just comment the crc() call, everything works fine.
Same thing is happening if you have complex printf's inside isr, even if is not executed. I tested smth like: Code: | int8 x = 0;
void isr()
{
....
if (x)
{
printf(...)
printf(...)
}
....
} | Again, weird behaviour inside isr. Those printf's were to a second serial with a high baudrate. But still, losing data coz of the overhead was not a problem. This is happening on every compiler version 3x or 4x. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Jul 09, 2007 2:50 am |
|
|
Your problem is the classic 'reentrancy' one.
If you place a printf, to a particular destination in an ISR, _even if it is never executed_, then any other printf to the same destination, in the 'main' code, _will have interrupts disabled for it's entire duration_. The same applies to routines like your CRC one. The problem here is that the PIC, does not have a 'register stack', only having a stack for function calls. hence, if a call is used inside an interrupt, using registers, the compiler has to make absolutely sure, that this call, can never occur inside another copy of itself outside the interrupt. So it disables interrupts round any external version, which can lead to large areas of code with interrupts disabled, and hence poblems with other interrupts. The answer is to never use the same code inside an ISR, and outside. For routines like 'crc', this means generating two copies of the routine, and using one inside the ISR, and one outside. Bulky both in terms of code size, and RAM storage, but if you must have routines in both locations it is the only solution.
The compiler assumes that all code inside the routine, _is_ used, so the test with the crc after the return, does not prevent the behaviour.
If you want to print to a device, or receive data from a serial port, then use a interrupt driven serial buffer for both transmit and receive on these, and in the ISR, only add characters to the output buffer, or retrieve characters from the input buffer, never talk to the device itself.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Mon Jul 09, 2007 4:45 am |
|
|
Finding a solution to work at the and of the day was not an issue after i detected the problem. The fact that routines are protected by enable/disable int's, that the crc is executed or not, is not an explanation nor excuse for an unpredictable behaviour. If this supposed to be a problem, this should be warned or even forbidden. But not silently "managed". I know the warning (more like a hint) that says that a specific routine is protected from ints. But does not say "do not" or "find another solution". Like i said, i used the debugger, and he jumps over intructions blindly. Breakpoints from some parts of isr were ignored. A simply comment to a call inside isr, and everything works fine. In my opinion, this is a bug situation.
It's true that into isr's - by definition - code shold be as smaller as posible, but this due to other reasons... not coz of a risk to an unpredictable behaviour.
Regards. |
|
![](templates/subSilver/images/spacer.gif) |
grasspuddle
Joined: 15 Jun 2006 Posts: 66
|
|
Posted: Mon Jul 09, 2007 7:46 am |
|
|
Whenever I need a large amount of code executed during an interrupt I set a flag and execute the code during the main while loop. So basically the only thing in my interrupts is a flag being set.
I might be just rambling since your interrupt isn't turned on and you're just calling it instead? |
|
![](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
|