|
|
View previous topic :: View next topic |
Author |
Message |
Milos Guest
|
Interrupts disabled during call to prevent re-entrancy |
Posted: Thu Apr 03, 2008 5:46 am |
|
|
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
|
|
Posted: Thu Apr 03, 2008 6:30 am |
|
|
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
|
|
Posted: Thu Apr 03, 2008 6:34 am |
|
|
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
|
|
Posted: Thu Apr 03, 2008 6:50 am |
|
|
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 |
Posted: Thu Apr 03, 2008 8:38 am |
|
|
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
|
|
Posted: Thu Apr 03, 2008 8:43 am |
|
|
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
|
|
Posted: Thu Apr 03, 2008 9:16 am |
|
|
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
|
|
Posted: Sat Apr 12, 2008 8:48 am |
|
|
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... |
|
|
|
|
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
|