View previous topic :: View next topic |
Author |
Message |
tesla80
Joined: 23 May 2007 Posts: 81
|
why delay function disables interrupts? |
Posted: Fri Jun 04, 2010 7:37 am |
|
|
Hi all,
I'm getting a warning when I compile my code.
Quote: | interrupts disabled during call to prevent re-entrancy: (@delay_us1) |
How can I workaround that?
is there a delay function which does not disable interrupts?
Does anyone know how to do delay function using timers to wait 1us or more? |
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Jun 04, 2010 8:01 am |
|
|
The reason it comes up with the error is because you are using the delay function in one or more of your interrupts.
This is a bad idea.
There are many ways to do what you are trying to do and I can say this without even looking at your code.
Try removing the need for a delay within the interrupt.
If you really can't find any other way to do it then create your own delay routine. there are many ways to do this. |
|
![](templates/subSilver/images/spacer.gif) |
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Fri Jun 04, 2010 8:18 am |
|
|
Thanks for the replay,
I use modbus.c in libraries of CCS. But I've made it interrupt driven. In the code there are delay routines.
I don't want to touch the modbus code. I only want to write a delay function which doesn't disable interrupts.
Yes, there are many ways to do this, but is there a delay library with timers? |
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Jun 04, 2010 8:26 am |
|
|
This depends on what timers you are already using and what they are being used for.
You can't use a timer interrupt because you are already in an interrupt. You would need to manually read one of your timer values and then wait for a count, depending on the settings for your timer your count will be x.
To make sure you do not disrupt what the timer is already used for you should not reset it but you need to take in to account wrap around. if it is a 16 bit timer then it will count 65535, 0, 1 etc.
If you have a free timer then use that as there could be other issues.
An easier option is to use closed loops, you know how fast the clock is just create some loops which delay for the time period required. |
|
![](templates/subSilver/images/spacer.gif) |
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Fri Jun 04, 2010 9:10 am |
|
|
Just know that a delay, inside an ISR, is not ideal. ISR's should be short, get in and out.
Ronald |
|
![](templates/subSilver/images/spacer.gif) |
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Fri Jun 04, 2010 9:20 am |
|
|
Code: | delay_us(3500000/MODBUS_SERIAL_BAUD); //3.5 character delay |
This is my longest delay routine in interrupt. it is 364uS (9600baud)
I've generated delay codes in asm using this generator.
But I think they are wrong.
I've asked in another topic too,
Quote: | In my fuse configurations ccs uses 4xpll to multiply 8Mhz internal clock.
And it's written "4 x 8Mhz" by the ccs pic wizard.
Quote:
#FUSES INTRC_IO
#use delay(clock=32M,restart_wdt) // 4 x 8Mhz
But my timer does not enter in interrupt routine in every 104ms
Quote:
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
Which is configured by pic wizard too, there was written exactly 104ms. |
I'm not sure that my clock frequency is 32Mhz. |
|
![](templates/subSilver/images/spacer.gif) |
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Fri Jun 04, 2010 11:30 am |
|
|
Which PIC are you using? That is most certainly not the right fuse setting to PLL up to 32 MHz. You have to check the datasheet to see what the proper fuse setting is. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 04, 2010 12:01 pm |
|
|
This thread has sample code from ckielstra for timer delays.
It also has a link to a quick fix, which shows how to create a 2nd
instance of the CCS delay library routines.
http://www.ccsinfo.com/forum/viewtopic.php?t=39120 |
|
![](templates/subSilver/images/spacer.gif) |
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Fri Jun 04, 2010 1:54 pm |
|
|
mkuang wrote: | Which PIC are you using? That is most certainly not the right fuse setting to PLL up to 32 MHz. You have to check the datasheet to see what the proper fuse setting is. |
I use 18F4520
@PCM programmer,
I use this method too, if you see again my previous topic, you'll see the same idea for timing/delaying. My problem is I don't know my mcu's clock frequency. is it 32Mhz? or? |
|
![](templates/subSilver/images/spacer.gif) |
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
![](templates/subSilver/images/spacer.gif) |
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Sat Jun 05, 2010 11:05 am |
|
|
I use 3 uarts and some delays. All of them work without problem.
The timer only seems does not enter in interrupt at the said time by pic wizard (104ms). |
|
![](templates/subSilver/images/spacer.gif) |
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Sat Jun 05, 2010 11:59 am |
|
|
The fact that the UARTS work doesn't mean you are working at 32M. If you are at 32 Mhz you should be getting a timer1 interrupt every 16 ms. You can check that. The instruction clock would be 32M/4 = 8M. You get a tick every (1/8M)*prescaler = (0.125us )*2 = 0.25 us. Timer1 is 16 bits so it would overflow in 65536*(0.25us) = 0.016384s or about 16.4ms. I don't know how you come up with 104ms. |
|
![](templates/subSilver/images/spacer.gif) |
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Mon Jun 07, 2010 2:33 pm |
|
|
Thank you mkuang,
I understood that the compiler automatically sets PLLEN bit.
I've added PLLEN = 1; row in my code and there is no change.
Timer1 overflows in 16ms really, but the CCS PIC Wizard says it is 104ms when is used T1_DIV_BY_2 option. This was the problem. |
|
![](templates/subSilver/images/spacer.gif) |
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Mon Jun 07, 2010 3:19 pm |
|
|
Why don't you try a test program toggling a pin at a fixed interval and see whether you get the right interval with your current fuse settings. Something like:
Code: |
main()
{
output_high(TEST_PIN);
while(1)
{
delay_ms(500);
output_toggle(TEST_PIN);
}
}
|
See whether you see the pin go on for half a second and then off for half a second. |
|
![](templates/subSilver/images/spacer.gif) |
Ken Johnson
Joined: 23 Mar 2006 Posts: 197 Location: Lewisburg, WV
|
|
Posted: Tue Jun 08, 2010 8:55 am |
|
|
delay_us(3500000/MODBUS_SERIAL_BAUD); //3.5 character delay
This is my longest delay routine in interrupt. it is 364uS (9600baud)
This bothers me . . .
3.5 characters at 9600 baud is 3.64 msec, not 364 usec
Mebbe I'm mis-understanding something here?
But, I agree with the others - don't delay in an isr - keep 'em short.
Ken |
|
![](templates/subSilver/images/spacer.gif) |
|