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

Interrupts disabled during call to prevent re-entrancy

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



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

Interrupts disabled during call to prevent re-entrancy
PostPosted: Fri Jul 14, 2006 2:20 am     Reply with quote

Getting the above error in my code, is there anyway to determine where interrupts are being disabled.

My int_rda getch()s, and based on what character it is/what flags are set, either writes it to a command buffer or sets flags, or discards

When compiling it, I get 'interrupts disabled to prevent re-entrancy', yet my int_rda only calls the fgetc(), and sets some other flags....

I do use delay_ms(); in other functions called from main() though - could this be the cause?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 14, 2006 2:26 am     Reply with quote

Quote:

I do use delay_ms(); in other functions called from main()
though - could this be the cause?

See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=27345
bwgames



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

PostPosted: Fri Jul 14, 2006 2:34 am     Reply with quote

I've seen that, but I wasn't sure if:

"There must be some function that you're calling from inside the isr
and outside as well. It would help if you could post a small but
complete test program."

relates to functions called from functions?

I.e. I call fgetc from the int_rda, which I believe has delay_ms in it? Even though I haven't called delay_ms specifically in my interrupt, it would still say interrupts disabled due to fgetc using it, and also my using delay_ms in my other code?

This is my int_rda - Am I doing too much in it?

Code:

#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=fgetc(Wireless);
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!



if((buffer[next_in] =='~')&&(cmdflag==1)&&(cmdbfr_size==14)&&(px_cmd==0))
{
//Signifies END OF COMMAND
output_low(PIN_E2); //Flashes debug LED
cmdflag =0;
dataflag=1;
cmdrx=1;
cmdbfr_size=0;
error_cmdrx=0;
// In the command buffer will be: "RX001DATATX001" (or whatever)
}//End of Command IF



if((cmdflag==1)&&(px_cmd==0))
{



if(cmdbfr_size==14)
{
//BUFFER FULL, EITHER CMD TOO LONG, OR ~ CHARACTER LOST - SET CMDFLAG = 0
cmdflag=0;
error_CMDRX=1;
cmdbfr_size=0;
} //end of errror buffer if

cmdbuffer[cmdbfr_size]=buffer[next_in];
cmdbfr_size++;

}//end of cmdflg=1


if((buffer[next_in] == '$')&&(px_cmd==0))
{
// $ signifies START OF COMMAND
output_high(PIN_E2); //debug LED
cmdflag = 1;
cmdbfr_size=0;
cmdrx=0;
}


}//end of int_RDA



Also, I read of people just having a while(1) loop in main, whilst everything else is handled by interrupts. I'm keen to do this this way - however, in my main I have

Code:

void main() {
//Store a variable that has the TYPE in a fprint'able format
if(TYPE==1) //TX
{
ttype[0]='T';
ttype[1]='X';
ttype[2]=NULL;
}
if(TYPE==2) //RX
{
ttype[0]='R';
ttype[1]='X';
ttype[2]=NULL;
}

   fprintf(Computer, "\r\n\Running...\r\n");

   enable_interrupts(global);
   enable_interrupts(int_rda);

while(1)

{
if((cmdrx==1)&&(error_cmdrx==0)&&(cmdflag==0))

{
//IF CMD RX
px_cmd=1; //FORCE INT_RDA TO NOT ACCEPT ANY MORE *COMMANDS* WHILST PROCESSING THIS ONE





process_cmd();
}//end of cmdrx

} //end of while 1
} //end of main


It is mostly just initialisation, which I can't put anywhere else, I don't think... but my if((cmdrx==1)&&(error_cmdrx==0)&&(cmdflag==0)), I'd like to get rid of.

Those variables (cmdrx,error_cmdrx, cmdflag) are set in int_rda.
Is there any way to remove that if from main and place it elsewhere.
The logical place would be int_rda, but calling a function would be a big no-no?
px_cmd is a variable that int_rda checks to see whether the routine is processing any command at the moment, so it knows whether or not it can touch the command buffer.

I guess what I'm looking for is "interrupt-on-variable-change"..?
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Jul 14, 2006 5:10 am     Reply with quote

You did not submit your #use rs232 statement

You can rule out fgetc() simply by using your own RS232 Uart handler. A quick and dirty test (dirty because it does not handle errors) is replace your fget(c) with a your variable = RCREG (read the UART directly). You will need to specify the address of the register with a #byte RCREG 0x0Fxx where 0xFxx is the address of this register for your processor.

Quote:
Also, I read of people just having a while(1) loop in main, whilst everything else is handled by interrupts. I'm keen to do this this way - however, in my main I have


That's because they do not understand how to write good interrupt handlers. Its obvious if you think about it - the mainline is doing nothing - the only thing the processor does is handle interrupts. In which case interrupts are of no value - may as well put the code in the mainline and make everything simpler.

Are you doing too much in the handler? Absolutely. You are doing stuff that does not need to be done in the handler and it provides you no value with it being there.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
bwgames



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

PostPosted: Fri Jul 14, 2006 5:35 am     Reply with quote

Thanks for the info...

What I'm not too clear on....

You seem to be saying that most of the stuff I'm doing in int_rda I could do somewhere else, I agree with this.

What I'd like to do, is simply have int_rda read into a buffer, set a flag to signify new data received in the buffer, and for a routine to do all the 'post-processing' - i.e. if(buffer[next_in... e.g.

Code:

#int_rda
void rda_isr()
{
buffer[buffersize++] = fgetc(Wireless);
buffer_new=1;
}


What I don't get, is how to run this other routine when that flag is set.
I could keep checking the buffer as I go through my program, i.e. if(buffer_new==1) processbuffer();, but ideally what I want is for a routine to be ran when a flag is set, e.g. a command indicator ($ etc) is received on the buffer.

All my ISR does is check if the input matches a certain character, then sets some flags, or if a flag is set, it puts it into the corronsponding buffer.

I would prefer to have int_rda like above, and have another routine sorting it into the correct sub-buffer (command/data etc) depending on character/flags previously set.
But, I don't see any other way of doing this apart from putting it all in int_rda?

Perhaps I should explain what I am trying to do...

The UART is connected to a wireless receiver, with several other devices that will also be transmitting. The start of a command is signified by $ and the end by ~, when the command buffer that int_rda is reading into has a complete command, the if( in main sends it to process_cmd(); which looks at the command to check if it is for that device, if it is, it processes it, if it isn't, it gets discarded.
Ideally I would like process_cmd to be ran straight after a full command is received (signified by cmdrx==1, which is set in int_rda), rather than having to keep checking whether one is received as I am now.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Interupt driven Comms
PostPosted: Fri Jul 14, 2006 6:01 am     Reply with quote

I suggest looking at the way the code in this thread is written. It does what you want but with a different protocol.

http://www.ccsinfo.com/forum/viewtopic.php?t=19306
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Jul 14, 2006 6:01 am     Reply with quote

What you are trying to do is a pretty common requirement.

Here is an example of how to code an interrupt handler to read into a ring buffer.

Code:
#int_RDA
void serial_isr()
   {
   // ; test for overrun error
   if (bit_test(RCSTA, OERR))
      {
      bit_clear(RCSTA, CREN);      // clear continous receive bit
      bit_set(RCSTA, CREN);      // set continous receive bit
      }

   RxBaseC[RxHeadC++]=getc();
   RxHeadC %= RxCQsize;
   }



Here's an example of a function you call from your main while loop:

Code:
void ServiceRxQConsole()
///////////////////////////////////////////////////////////////////////////
// ServiceRxQConsole
//
//   Basic polled Console Rx Q service subroutine (NON BLOCKING)
//   Receives a byte from the Console Rx buffer and queues it to the
//   console command buffer.
//
//  Once a <CR> has been detected SrvCMD is invoked.
//
///////////////////////////////////////////////////////////////////////////
   {
   char LastC;

   while (RxTailC != RxHeadC)
      {
      LastC = getc_QConsole();

      switch (LastC)
         {
         case 0x0d:      // <CR>
            CCRC[CntCmdC] = 0;      // terminate the string with a NULL
            SrvCmd(CCRC);         // go service the command
            CntCmdC = 0;         // initialise number of characters in the command buffer
            break;

         case 0x0a:       // <LF>
            break;

         default :
            CCRC[CntCmdC] = LastC;   // put into the command construction register
            CntCmdC = (CntCmdC + 1) % CCRSize;   // ensure command register does not overflow
            break;
         }
      }
   }


This code extracts a sequence from a ring buffer to a linear buffer based on your start and end character delimiter. Once you have it all the function SrvCmd is invoked with the string in a linear buffer.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
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