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 support@ccsinfo.com

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
Milos
Guest







Interrupts disabled during call to prevent re-entrancy
PostPosted: Thu Apr 03, 2008 5:46 am     Reply with quote

Hello everybody i have a problem with my program the code goes like this:

#if defined(__PCH__)
#include <18F458.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif

#include <LCD2.C>

#define INTS_PER_SECOND 152 // (10000000/(256*256))



BYTE int_count; // Number of interrupts left before a second has elapsed

void lcd_dec2str3(unsigned long x) //decimala u string
{
unsigned long y;
if (x<1000)
{
y=x/100;lcd_putc(y+0x30);x-=(y*100); // stotice
y=x/10;lcd_putc(y+0x30);x-=(y*10); // desetice
lcd_putc(x+0x30); // jedinice
}
else lcd_putc("Greska");
}

#INT_RTCC
void brojac_isr()

{
delay_ms(1000); // every second

lcd_gotoxy(0, 1);
lcd_putc(" INTERRUPT !!! ");
lcd_gotoxy(0, 0); // pozicioniraj se u prva kolona - drugi red
lcd_putc(" "); // ispisi na LCD

int_count=INTS_PER_SECOND;
}

void main()

{

long counter;
lcd_init();

int_count=INTS_PER_SECOND;
set_timer0(152);
setup_counters( RTCC_INTERNAL,RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);

printf("\n\n");

counter=0; // reset the counter

do

{
lcd_gotoxy(0, 1); // pozicioniraj se u prva kolona - drugi red
lcd_putc(" "); // ispisi na LCD
lcd_gotoxy(0, 0); // prva kolona drugi red
lcd_putc("Brojac: ");
lcd_gotoxy(10, 0); // 10ta kolona drugi red
lcd_dec2str3(counter);
counter++; // display count value and increment
delay_ms(1000); // every second
} while (TRUE);


}


The problem is that i get 5 warning massages Interrupts disabled during call to prevent re-entrancy.
The program is working counter counts on every interrupt change but in 1 moment i am getting both massages on LCD display "INTERRUPT !!!" and "Brojac XXX".
Program should do next show massage in interrupt for 1 second "INTERRUPT !!!" than increment counter and show "Brojac xxx" and so on.

Well it shows "Brojac xxx" for 1 second , but interrupt is lasting like 4 seconds and i dont know why... I wanted it to show 1 sec "Brojac xxx" , 1 sec "INTERRUPT !!!".

And after counter gets to 5-6 changes i am getting both massages on the LCD screen or i get part of 1st and part of 2nd massages.

Well now u can try to compile program but i have changed #include<LCD2.c> coz i have different pins for LCD.

Pls try to explain me why tnx and best wishes Milos.
Matro
Guest







PostPosted: Thu Apr 03, 2008 6:30 am     Reply with quote

Code:

void lcd_dec2str3(unsigned long x) //decimala u string
{
unsigned long y;
if (x<1000)
{
y=x/100;lcd_putc(y+0x30);x-=(y*100); // stotice
y=x/10;lcd_putc(y+0x30);x-=(y*10); // desetice
lcd_putc(x+0x30); // jedinice
}
else lcd_putc("Greska");
}

y is "unsigned long" but will never be greater than 100, so "unsigned int8" is sufficient.
After the line
Code:

y=x/100;lcd_putc(y+0x30);x-=(y*100); // stotice

x will always have a value of 0 so I can't understand the interest of that and following things.

Matro.
Matro
Guest







PostPosted: Thu Apr 03, 2008 6:34 am     Reply with quote

And stop working with delay_ms function. This function is just time wasting during which the MCU does nothing.
Your ISR should look like that :
Code:

#INT_RTCC
void brojac_isr()
{
int_count++;
if(int_count >= INTS_PER_SECOND)  //'>=' more secure than '='
{
  int_count = 0;
  lcd_gotoxy(0, 1);
  lcd_putc(" INTERRUPT !!! ");
  lcd_gotoxy(0, 0); // pozicioniraj se u prva kolona - spam1 red
  lcd_putc(" "); // ispisi na LCD
}
}


Matro.
Matro
Guest







PostPosted: Thu Apr 03, 2008 6:50 am     Reply with quote

Below a proposal :
Code:

#include <18F458.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include <stdlib.h>
#include <LCD2.C>

#define INTS_PER_SECOND 152 // (10000000/(256*256))

BYTE int_count; // Number of interrupts left before a second has elapsed
BOOLEAN disp_bool;

#INT_RTCC
void brojac_isr()
{
int_count++
if(int_count >= INTS_PER_SECOND) //1 second elapsed
{
   int_count = 0;
   disp_bool = !dispbool
}
}

void main()
{
long counter;
char str[5] = "\0";
lcd_init();
int_count=0;
setup_rtcc(RTCC_INTERNAL,RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
printf("\n\n");
counter=0; // reset the counter
do
{
   if(disp_bool)
   {
      lcd_gotoxy(0, 1); // pozicioniraj se u prva kolona - spam1 red
      lcd_putc(" "); // ispisi na LCD
      lcd_gotoxy(0, 0); // prva kolona spam1 red
      lcd_putc("Brojac: ");
      lcd_gotoxy(10, 0); // 10ta kolona spam1 red
      itoa(counter,10,str);
      lcd_putc(str);
   }
   else
   {
      lcd_gotoxy(0, 1);
      lcd_putc(" INTERRUPT !!! ");
      lcd_gotoxy(0, 0); // pozicioniraj se u prva kolona - spam1 red
      lcd_putc(" "); // ispisi na LCD
   }
   counter++; // display count value and increment
}while (TRUE);
}

Maybe there are still some bugs because I can't compile since LCD2.C is missing.

Matro.
Milos
Guest







ok
PostPosted: Thu Apr 03, 2008 8:38 am     Reply with quote

tnx Matro.

i ll try to compile the way u have done it.

i ll try to run program and see what went wrong with x<1000 and i ll post u code i think it counts to 1000 without problem.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu Apr 03, 2008 8:43 am     Reply with quote

When working with interrupts, placing printf(), putc() or puts() statements inside of them is highly discouraged. Interrupts should be very short. Get in, do something quick and then get out. Print statements generate loads of code and will bog down your program. If you're just printing something to help debug then I could understand.

You would, normally, set a flag and then evaluate that flag somewhere in your main() section.

Ronald
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Thu Apr 03, 2008 9:16 am     Reply with quote

rnielsen wrote:
When working with interrupts, placing printf(), putc() or puts() statements inside of them is highly discouraged. Interrupts should be very short. Get in, do something quick and then get out.


I agree. The compiler warnings about interrupts being disabled to avoid re-entrancy are because these library calls are in your interrupt service routine. Many CCS library functions are implemented using static memory to hold intermediate results. Therefore they cannot be re-entrant. If your main program is in the middle of calling one of these library functions, and then an interrupt occurs which also calls the same library function, then the interrupt call of that function will mess up the static memory that was being used by the main program call. The compiler recognizes this danger and avoids it the only way it can - by disabling interrupts around all the main program calls of the library functions that were so affected. And since you have lots of library functions implied by your use of printf(), etc., there are a lot of functions that the compiler needs to protect in the main program. This can affect the latency of your interrupt service routine, and possibly cause your application to fail. That is why the compiler issues the warning. The waring is not to be just ignored. If you choose to accept it, that means you have carefully considered the implications of interrupts being disabled at various times in your main program, and you have decided it will not cause harm to your application. If you are not sure you can come to that conclusion, then the safe thing to do is to do as rnielsen suggested and trim down your interrupt service routine to exclude these library routines. If you need to gather information on how an interrupt service routine is working, have the interrupt service routine write some data in some memory and then have the main program look at the memory and do printf() calls if necessary.

Robert Scott
Real-Time Specialties
KU5D



Joined: 10 Feb 2008
Posts: 46
Location: Asheville, North Carolina

View user's profile Send private message

PostPosted: Sat Apr 12, 2008 8:48 am     Reply with quote

Things like printf() and worse yet delays are a sin in an ISR. For a convincing demonstration, see what a delay_ms(1) does to this? The delay_ms() masks everything, and note how the RDA interrupt is stacked up until the delay expires. This is a screenshot from a DV-100 that is wired to I/O pins that I use as test points in my interrupt service routines. This is the perfect way to test your ISRs. Toggle a pin and use a 'scope or similar tool to see if they are working. It takes almost zero time.


_________________
Confidence is the feeling you have right before you fully understand the situation...
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