|
|
View previous topic :: View next topic |
Author |
Message |
Tagge
Joined: 23 Aug 2005 Posts: 93
|
Interrupts? |
Posted: Mon Feb 06, 2006 7:51 am |
|
|
Hi,
Im wondering about the priority of interrupts, can I make one interrupt "prio1", that is, that this one is allways done even if I am in an other interrupt?
I want this beacuse I got an interrupt CCP1 that drives a sort of internal clock and some math code that MUST be executed at programmed times, every 10mS.
My interrupts are as follow:
Code: |
// Interrupts
#int_CCP1 //compare interrupt, this MUST be done every time!!!!!!
void CCP1_isr()
{
//code...do something every 10mS
}
#int_RB //portB interrupt no problem, only executed by switch pressing
void RB_isr()
{
code..
}
#int_rda //this can be a problem, it MUST NOT interfere with the CCP1_issr!
void serial_isr()
{
#use rs232(baud=300, xmit=PIN_C6, rcv=PIN_C7, bits=7, parity=E)
//code...
}
|
Can I make a priority of isr's?
Have a nice day
/Tagge |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Mon Feb 06, 2006 8:46 am |
|
|
I know that there is the #priority in CCS, but I think I have to be able to even jump in to the CCR1 isr when the rs232-isr is in progress..
Can I do this without loosing chars in the buffer?
And can I jump out from the rs-232 in progress at all? or should it be done..
I didnt found any good answers at the forum, anyway.. |
|
|
Ttelmah Guest
|
|
Posted: Mon Feb 06, 2006 9:15 am |
|
|
It depends on the PIC involved.
Older PIC's (12/14/16 chips), do not support interrupts inside interrupts. The hardware disables the global interrupt flag, when an interrupt handler is being called. All '#priority' does, is set the order in which the interrupts are 'parsed' in the global handler. If #priority is not used, the parsing order is dependant on the order in which the interrupt handlers are defined.
On the 18 PICs, there is seperate support for hardware priority. Look in the 'readme.txt', for details of how this is used (the #int_xxx HIGH) command. Beware, that on many chips, there are 'caveats', about which particular interrupts can be high priority, and in some cases caveats about how they work. On the chips with this ability, a 'HIGH' priority interrupt can interrupt another interrupt handler.
Best Wishes |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon Feb 06, 2006 9:52 am |
|
|
If you are talking of interrupt priority I assume you are talking of PIC18Fxxxx wich can handle priorities.
The highest priority is reserved for the #int_CCP1 (compare interrupt) every 10ms.
The lowest priority is reserved for the #int_rda at @300 bauds, that is: it will long 33ms just to get a single char.
IMO this will be very difficult to get a char because a low priority interrupt cannot interrupt a high priority ISR, that is the #int_rda will be served only after high priority interrupts have been served
Humberto |
|
|
Ttelmah Guest
|
|
Posted: Mon Feb 06, 2006 10:10 am |
|
|
The priorities are not 'reserved' for any particular interrupts, they are setable by the priority flags. There are only two priorities in the hardware. So, on the 18F4525, the flag 'CCP1IP' (bit2 of IPR1), determines whether the CCP1 interrupt is high or low priority. Provided the high priority interrupt source, can be handled in significantly less than the gap between successive interrupts, there will still be time to handle the low priority devices, and a latency of up to 3mSec, will be acceptable at 300bps, for the interrupt handling of the RS232 code.
The thing that worries me, is the mention of 'math code', since this could easily involve significant time....
Best Wishes |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon Feb 06, 2006 10:33 am |
|
|
Telmah, I know that the priorities are not reserved.
I wrote this:
Quote: |
The highest priority is reserved for the #int_CCP1 (compare interrupt) every 10ms.
The lowest priority is reserved for the #int_rda at @300 bauds, that is: it will long 33ms just to get a single char.
|
following the initial poster headline criteria:
#int_CCP1 // compare interrupt, this MUST be done every time!!!!!!
#int_rda // it MUST NOT interfere with the CCP1_issr!
Humberto |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Mon Feb 06, 2006 11:39 am |
|
|
Yes, Im using a PIC18f2525, and no, dont worry, the "math" is done under "normal" operation in main() and some subroutines.
But it seems that the CCP1 isr is affected by the rs232 isr anyway? I get some missed "times" during a longer time of operation (a day or so).
The rs232 isr gets a burst of chars at least every ~10sec..
Everything in the code works as planned, but the missing "times"....
and they are really important
So I would love to have an CCP1 interrupt done during a rs232 interrupt.
I will try the tips that I greatfully have recived here, thanks. |
|
|
DragonPIC
Joined: 11 Nov 2003 Posts: 118
|
Customize |
Posted: Mon Feb 06, 2006 2:29 pm |
|
|
Sounds like you are going to have to do a customized ISR for the RS232 that checks the CCP1 interrupt flag and then calls a math function from inside that ISR.
You might be able to check the CCP1 interrupt in between each routine too (Example: in between #int_RB and #int_rda).
Quote: | The rs232 isr gets a burst of chars at least every ~10sec..
Everything in the code works as planned, but the missing "times".... |
Is there anyway you can cut and spread out the burst of characters sent to the RS232? That way you can catch the CCP1 interrupt in between and not spenf too much time in the the RS232 interrupt. _________________ -Matt |
|
|
Ttelmah Guest
|
|
Posted: Mon Feb 06, 2006 3:28 pm |
|
|
So, have you tried using the HIGH keyword with the INT_CCP?. How old is your compiler (this is critical - on some versions, you will need #device HIGH_INTS=true, and on older versions, the high priority interrupts do not save the registers)?.
Best Wishes |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Tue Feb 07, 2006 3:24 am |
|
|
Hi again,
i got the 3.242 compiler I think its the newest one.
I now tryed to insert the #int_xxx HIGH, and it did ask for the
#device HIGH_INTS=true, wich I then also implemented.
Don't I have to save any registers manually, really?
It seems to work alright, but I cant be sure until the box is tested by a third part. That is one of my problems, I cant test the functionallity by myself. Depending on that we dont have equipmemt for it. And this error of missing "times" did also appear after third part testing.
I tougt everything worked fine, but life is not only living its mostly learning...
Thanks to you all, I will be back with the results from testing. |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Wed Feb 08, 2006 5:32 am |
|
|
Hi again,
I think I have found at least one problem that makes the error of missing "times".
I have a printf() in my code, this will disable interrupts during it?
can I make it some other way? by "clean" putc(), and still remaine my bcc calkulation?
But on the other hand, thus it matter, printf is only activ during one char at the time? or is it disabling interrupts during the whole string?
Or should I rewrite the code to make an interruptdriven TX,
void serialtx_isr (void)?
Code: |
void putcsum(int8 val)
{
bcc^=val; //xor on every byte
putc(val); //write string
}
//------------------------------------------------------------
putc(0x02); //stx, startbit text
printf(putcsum, "F.F(00)\r\nC.1.0(%s)\r\n0.0(%lu)\r\n1.8.1(%09.1f*kWh)\r\n1.8.2(%09.1f*kWh)\r\n32.7(%lu*V)\r\C.5.0(00)%C%C%C%C",
METER_NO,CUST_NO,energy_A,energy_A2,voltage,0x21,0x0d,0x0a,0x03);
putc(bcc); //as last, print checksum of above printf()
|
|
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 08, 2006 8:21 am |
|
|
Printf, should not disable interrupts, _unless_ you are using any of the functions it calls_, inside an interrupt. So if 'putcsum' is used in an interrupt, then interrupts will be disabled.
This is a general problem. Basically, any function used inside an interrupt, _will_ cause interrupts to be disabled, if it is also used outside the interrupt. There are a couple of other things that will also disable interrupts. Certain types of memory movement (table based memcpy routines), and writes to the program memory. Now printf, can be made to disable interrupts with certain operations, but your example does not look like it would trigger these, unless putcsum is the culprit.
There was a longish thread a few weeks ago, about which operations would disable interrupts. This may help.
Best Wishes |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Wed Feb 08, 2006 8:37 am |
|
|
I think I read it, and there was someone who claimed that a printf does disable interrupts, thats why I asked.
None of the functions it calls are inside any isr. But it seems that I get a better stability by using an isr driven TX. Altough I havent implemented all the way yet.
For some reason I only get about half (1'st) of the string out of this, maybe due to that I have an CCP1 isr set as #int_ccp1 HIGH.
It seems that what one gains at one side, makes you loose at the other...
Code: |
#int_tbe
void serial_tx_isr()
{
//if there are characters to be transmitted....
if(TX_Counter != 0)
{
putc(TX_Buffer[TX_Rd_Index]);
// send char out port
// test and wrap the pointer
if(++TX_Rd_Index > TX_BUFFER_SIZE)
TX_Rd_Index = 0;
TX_Counter--; // keep track of the counter
if (TX_Counter == 0)
disable_interrupts(int_tbe);
}
}
// write a character to the serial transmit buffer
void bputc(INT8 c)
{
INT8 restart = 0;
while(TX_Counter > (TX_BUFFER_SIZE-1))
; // WAIT!! Buffer is getting full!!
if(TX_Counter == 0) // if buffer empty, setup for interrupt
restart = 1;
TX_Buffer[TX_Wr_Index++]=c; // jam the char in the buffer..
if(TX_Wr_Index > TX_BUFFER_SIZE) // wrap the pointer
TX_Wr_Index = 0;
// keep track of buffered chars
TX_Counter++;
// do we have to "Prime the pump"?
if(restart == 1)
enable_interrupts(int_tbe);
}
//and in subroutines
void putcsum(int8 val)
{
bcc^=val; //xor p� varje byte
bputc(val); //skriv ut str�ng
}
void putmsg(int8 chr)
{
bputc(chr);
}
//------------------------------------------------
...
bputc(0x02); //stx, startbit text
printf(putcsum, "F.F(00)\r\nC.1.0(%s)\r\n0.0(%lu)\r\n1.8.1(%09.1f*kWh)\r\n1.8.2(%09.1f*kWh)\r\n32.7(%lu*V)\r\C.5.0(00)%C%C%C%C",
METER_NO,CUST_NO,energy_A,energy_A2,voltage,0x21,0x0d,0x0a,0x03);
bputc(bcc); //as last, print checksum of above string
|
Do I gaine anything from this? |
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 08, 2006 10:34 am |
|
|
Do you have 'ERRORS' enabled in the RS232 setup?.
If not, and the receive routine is not called often enough, so there is a hardware buffer overrun, the UART will effectively lockup.
Printf, will disable interrupts for the accesses to the constant string. The thread about this (and other similar problems), is entitled:
"How to prevent inbuilt functions to disable interrupts".
There was a workaround in this for the printf behaviour.
Generally the advantage of interrupt drive transmit, is that if (as you mention), you are doing things like maths in the main code loop, the processor can get on with this while the data is sending. Otherwise there will be long gaps in the time available for such things...
Best Wishes |
|
|
|
|
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
|