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

large int_rda causes problems with int_rda2 -HELP

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



Joined: 30 Apr 2007
Posts: 9

View user's profile Send private message

large int_rda causes problems with int_rda2 -HELP
PostPosted: Wed Jul 04, 2007 10:47 pm     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 05, 2007 11:25 am     Reply with quote

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 ?
kahnm



Joined: 30 Apr 2007
Posts: 9

View user's profile Send private message

Post subject: large int_rda causes problems with int_rda2 -H
PostPosted: Thu Jul 05, 2007 11:36 pm     Reply with quote

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     
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 12:28 am     Reply with quote

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.
kahnm



Joined: 30 Apr 2007
Posts: 9

View user's profile Send private message

large int_rda causes problems with int_rda2 -HELP
PostPosted: Fri Jul 06, 2007 1:12 am     Reply with quote

Thank you for your reply.

Maybe I'm not explaining it clearly. Embarassed

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
kahnm



Joined: 30 Apr 2007
Posts: 9

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 1:31 am     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 1:46 am     Reply with quote

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.
kahnm



Joined: 30 Apr 2007
Posts: 9

View user's profile Send private message

PostPosted: Sun Jul 08, 2007 11:46 pm     Reply with quote

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
Pret



Joined: 18 Jul 2006
Posts: 92
Location: Iasi, Romania

View user's profile Send private message

PostPosted: Mon Jul 09, 2007 1:13 am     Reply with quote

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.
Ttelmah
Guest







PostPosted: Mon Jul 09, 2007 2:50 am     Reply with quote

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
Pret



Joined: 18 Jul 2006
Posts: 92
Location: Iasi, Romania

View user's profile Send private message

PostPosted: Mon Jul 09, 2007 4:45 am     Reply with quote

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.
grasspuddle



Joined: 15 Jun 2006
Posts: 66

View user's profile Send private message

PostPosted: Mon Jul 09, 2007 7:46 am     Reply with quote

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?
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