View previous topic :: View next topic |
Author |
Message |
VincentJ
Joined: 21 Oct 2020 Posts: 9
|
INT_RDA2 issue PIC18LF46k80 |
Posted: Wed Oct 21, 2020 10:49 am |
|
|
Hello,
I have a problem for a few days with UART2 ISR in a PIC18LF46k80 project.
I am using a radio module which sends a 5 bytes message to the PIC as a toggle occurs on a pin.
This message is visible on the oscilloscope so I know that 5 bytes are transmitted whereas only the 2 first bytes are received in the buffer.
Everything is ok with UART1.
I have tried several things to fix this issue and I noticed that if I remove the code of both INT_EXT and INT_EXT1, everything works fine… The 5 bytes are received.
INT_EXT and INT_EXT1 are never triggered.
I need help.
Any idea ? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Oct 21, 2020 11:09 am |
|
|
a) Do you have the HIGH option enabled for the external interrupt?
b) Describe the electrical environment. Is there any electrical noise and/or are "heavy current" loads being switched? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Oct 21, 2020 2:13 pm |
|
|
Need to see the code....
Have you set 'ERRORS' option in the USE #RS232(.....commands....) ??
Do you buffer the incoming data ? |
|
|
VincentJ
Joined: 21 Oct 2020 Posts: 9
|
|
Posted: Wed Oct 21, 2020 10:36 pm |
|
|
a) The HIGH option is not enabled for the external interrupts
b) The EMC is ok and the external interrupts are not triggered.
The problem continues even if I disable those interrupts.
Parts of the code:
Code: |
#use delay(clock=64000000,crystal=16000000,restart_wdt)
#use rs232(UART1, baud=115200, parity=N, bits=8, stream=PORT1, errors)
#use rs232(UART2, baud=115200, parity=N, bits=8, stream=PORT2, errors)
#INT_TIMER0
void TIMER0_isr(void)
{
//Time out de l'UART2
if (TO_UART2_ON == 1)
{
RDA2_TimeOUT++;
//Test de dépassement
if (RDA2_TimeOUT >= 3) //3: <=> 20ms
{
//Données reçues
//Invalidation de l'interruption RDA2 le temps de copier le buffer temporaire
disable_interrupts(INT_RDA2);
//RAZ du compteur de données
DataCount2 = 0;
//TimeOut Off
TO_UART2_ON = 0;
//RAZ du compteur
RDA2_TimeOUT = 0;
//Set du flag de réception d'une trame
UART2_TrameRecue = 1;
}
}
}
#INT_EXT
void EXT_isr(void)
{
...
}
#INT_EXT1 // interruption des I2C IO EXTENDER
void EXT1_isr(void)
{
...
}
#INT_RDA2
void RDA2_isr(void)
{
TAB_DataReceived2_Temp[DataCount2]=fgetc(PORT2);
DataCount2++;
//RAZ du compteur TimeOut 2
RDA2_TimeOUT = 0;
//Valider le timeoutr de l'UART 2
TO_UART2_ON = 1;
}
|
(Timer0 is always ON.)
To sum up:
With the code above, only the 2 first bytes of each frame are received.
With the changes below, everything works fine:
Code: |
#INT_EXT
void EXT_isr(void)
{
/* ... */
}
#INT_EXT1 // interruption des I2C IO EXTENDER
void EXT1_isr(void)
{
/* ... */
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Oct 22, 2020 1:14 am |
|
|
One thing you say does not make sense. That the problem continues even
if you disable INT_EXT, and INT_EXT1. I would suspect you are not actually
disabling these. Something is enabling them.
Your problem is occurring because you are spending too much time
somewhere in the handler for INT_EXT, or INT_EXT1. Interrupt handlers
need to be quick. If (for example), you had an interrupt handler that
wanted to delay for a time, then you must not do this. Instead you would
have to just set a flag, and perhaps start a timer, then have this interrupt
when the delay is finished and do the rest of your work in the handler
for this.
Now for most interrupts, there would be a potential solution for this,
by making INT_RDA 'HIGH' priority, so that it can be called while the chip
is handling he other interrupt. However in this case this can't be done.
The 'reason', is that if interrupt priorities are used, the INT_EXT interrupt
will always be 'HIGH' priority.
So solutions are:
1) Shorten the time taken in INT_EXT and INT_EXT1. Best solution.
2) Stop using INT_EXT, use INT_EXT1 & INT_EXT2 instead. Then enable
nested interrupts and make INT_RDA2 'HIGH' priority.
3) Also make sure your #USE RS232 setup, has 'ERRORS' enabled. This
should _always_ be done for handlers for hardware UART's, unless you
are adding your own error handling code. Adding this would mean that
though a character (or more) would be lost when the problem happens,
the UART would recover.
Honestly reducing the time code stays in the interrupt handlers is the
'correct' way to fix this.
Repeat the mantra fifty times, 'interrupt handlers should always be quick'.... |
|
|
VincentJ
Joined: 21 Oct 2020 Posts: 9
|
|
Posted: Thu Oct 22, 2020 2:06 am |
|
|
I am aware of these elements and I stand by what I said.
The problem persists even if RDA2 is the only high priority interrupt.
I had already tried to monitor bits 1 and 2 of RCSTA2 (using #byte RCSTA2 = getenv("sfr:RCSTA2") and no error occurs.
The EXT interrupts are not triggered :
#INT_EXT
void EXT_isr(void)
{
while (TRUE);
/* ... */
}
#INT_EXT1 // interruption des I2C IO EXTENDER
void EXT1_isr(void)
{
while (TRUE);
/* ... */
}
WORKS fine and the program continues to run.
#INT_EXT
void EXT_isr(void)
{
while (TRUE);
...
}
#INT_EXT1 // interruption des I2C IO EXTENDER
void EXT1_isr(void)
{
while (TRUE);
...
}
DOES NOT WORK (only 2 byte per trame) but the program still continues to run. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Oct 22, 2020 2:13 am |
|
|
The point is _you can't have INT_RDA2 as the 'only' high priority interrupt_.
The _chip does not allow this_.
If interrupt nesting is enabled INT_EXT, _will always be a high priority
interrupt_.
This is why interrupt nesting will not fix the problem, unless you change
your design and use INT_EXT1 and INT_EXT2 instead of INT_EXT.
Shortening the time in the INT_EXT and INT_EXT1 handlers (which (of course)
is what you do when you REM the code out), is the proper solution. |
|
|
VincentJ
Joined: 21 Oct 2020 Posts: 9
|
|
Posted: Thu Oct 22, 2020 2:58 am |
|
|
I agree, it works if I shorten the code in the EXT interrupt handlers. But I’d like to understand.
How the duration of a non executed code can have an influence on the RDA2 interrupt behaviour ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Oct 22, 2020 3:17 am |
|
|
Because while it is in the INT_EXT handler, it can't execute the INT_RDA2
handler. Now you say 'non executed', but I suspect it is being executed.
Some part of your code is enabling INT_EXT. Possibly an incorrect value
being written to a register, or some subroutine you have forgotten about
is resulting in the interrupt being enabled. It is being enabled somewhere.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Thu Oct 22, 2020 4:57 am |
|
|
A simple test to do...
disable the INT_EXT interrupt. This is different(well should be..) than having 'no code', in the handler and the ISR enabled.
If this works, then it proves that 'somewhere' INT_EXT has been enabled and is being serviced and as Mr. T. says has a higher priority than INT_RDA2.
it's possible, if your program is huge, having 'evolved' from 'cut and paste' trials, that one of them has enabled the ISR even though 'up top' you havent'.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Oct 22, 2020 5:48 am |
|
|
He said quite early on, that he had tried this.
I suspect something 'else' in the code is enabling the interrupt. A full search
of all the source files, would be a place to start. |
|
|
VincentJ
Joined: 21 Oct 2020 Posts: 9
|
|
Posted: Thu Oct 22, 2020 6:31 am |
|
|
I have a LED on my board so I tried this experience :
The LED is set ON at the beginning of the program and I added the instruction to set it OFF (not toggle) in both the EXT_INT and the EXT1_INT handlers.
When the program is running, the LED remains ON whether it is with the program that works as with the one that does not. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Oct 22, 2020 7:00 am |
|
|
You realise that as posted, timer3, will result in the UART being disabled.
Since TO_UART2_ON is set to 1 by the INT_RDA, after 3 characters
INT_RDA2 will be disabled, and the characters will stop receiving. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Thu Oct 22, 2020 7:02 am |
|
|
I read he 'removed' code inside the ISR but not that he disabled the actual interrupt.To me there's a bg difference between the two operations.
Having a 'nulled' (do nothing) ISR ,enabled should mean the PIC might go there if the 'flag' was set,do nothing, then come back. If it's disabled, then the PIC would never go 'there' if the 'flag' was set.
I don't know if the compiler is smart enough to 'see' that with no code inside the ISR, that it will automatically disable the 'enable_ISR' code.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Oct 22, 2020 7:06 am |
|
|
He said right at the start of his post:
Quote: |
The problem continues even if I disable those interrupts.
|
|
|
|
|