2º BUG: ¡ mal funcionamiento del tratamiento de las prioridades con PICs18 !
Si un PIC18 tengo 2 interrupciones y una de ellas la declaro como de alta prioridad, si cuando se está ejecutando la instrucción de baja prioridad, llega la de alta prioridad se debe de abandonar inmediatamente la primera rutina e ir a atender a la rutina de alta prioridad.
Cuando finalice la rutina de alta prioridad retornará al punto donde se había quedado en la rutina de baja prioridad. Bueno, el caso es que esto no funciona.
Os pongo un programa de ejemplo y os digo como reacciona.
#include <18F4550.h>
#fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,NOPBADEN
#DEVICE HIGH_INTS=true
#use delay(clock=48000000) //Cristal de 4 MHz (PLL1)
#use fast_io(B)
#byte port_a = 0xF80
#byte port_b = 0xF81
//#PRIORITY int_ext,int_rb
//#PRIORITY int_rb,int_ext
#INT_TIMER0 // Interrupción externa en RB0
//#INT_TIMER0 HIGH
interrupcion_TIMER0() // Función de atención a la interrupción
{
delay_ms(3000);
output_toggle(PIN_B1);
disable_interrupts(INT_TIMER0);
}
#INT_EXT // Interrupción externa en RB0
//#INT_EXT HIGH
interrupcion_RB0() // Función de atención a la interrupción
{
delay_ms(3000);
output_toggle(PIN_A0);
}
//#INT_RB // Interrupción externa en RB4-RB7
#INT_RB HIGH
//#INT_RB FAST
interrupcion_RB4_RB7() // Función de atención a la interrupción
{
delay_ms(3000);
#asm movf port_b,0 #endasm //Hace falta leer el portb, si no va mal
output_toggle(PIN_B3);
}
main()
{
set_tris_b(0x85); // RB4 salida, RB4-RB7,RB0 entradas.
set_tris_a(0x00);
//bit_clear(port_a,0);
//bit_clear(port_b,1);
//bit_clear(port_b,3);
output_low(PIN_A0);
output_low(PIN_B1);
output_low(PIN_B3);
setup_counters(RTCC_8_BIT,RTCC_DIV_128);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RB);
enable_interrupts(INT_EXT);
while(1)
{
if(input(pin_b2))
enable_interrupts(INT_TIMER0);
}
}
La interrupción de RB0 es de baja prioridad y la de RB4..RB7 de alta.
Si activamos la interrupción RB0 se mete dentro de su rutina (concretamente en el delay_ms(3000)) y si a continuación activamos la de RB4..RB7 tendría que dejar el delay_ms(3000) y ejecutar por completo la rutina de interrupción RB4..RB7 activando la salida RB3 para luego regresar a la rutina de interrupción RB0 (al delay_ms(3000)) y activar la salida RA0. Pués no, hace justamente lo contrario, primero activa la salida RA0 y luego la salida RB3, es decir se comporta sin tener en cuenta la prioridad de RB4..RB7.
Decididamente el tema de las prioridades con interrupciones falla. He estado probando físicamente (y con PROTEUS) otras combinaciones de prioridades (INT_TMR0,INT_EXT y INT_RB) y algunas van bien pero otras fallan.
Algunos CASOS realizados con pruebas físicas y con PROTEUS:
- Si TMR0=OFF, RBO alta prioridad y RB4..RB7 baja prioridad:
Secuencia: RB7 -- RBO ---> RA0=1 -- RB3=1 ¡BIEN!
Secuencia: RB0 -- RB7 ---> RA0=1 -- RB3=1 ¡BIEN!
- Si TMR0=OFF, RBO baja prioridad y RB4..RB7 alta prioridad:
Secuencia: RB0(baja) -- RB7(alta) ---> RA0=1 -- RB3=1 ¡MAL!
Secuencia: RB7(alta) -- RB0(baja) ---> RB3=1 -- RA0=1 ¡BIEN!
- Si TMR0 baja prioridad, RBO alta prioridad y RB4..RB7 alta prioridad:
Secuencia: TMR0 -- RB7 -- RBO ---> RB3=1 -- RA0=1 -- RB1=1 ¡BIEN!
Secuencia: TMR0 -- RB0 -- RB7 ---> RA0=1 -- RB3=1 -- RB1=1 ¡BIEN!
Secuencia: RB0 -- TMR0 -- RB7 ---> RA0=1 -- RB3=1 -- RB1=1 ¡BIEN!
- Si TMR0 alta prioridad, RBO alta prioridad y RB4..RB7 alta prioridad:
Secuencia: TMR0 -- RB0 -- RB7 ---> RB1=1 -- RA0=1 -- RB3=1 ¡BIEN!
Secuencia: TMR0 -- RB7 -- RB0 ---> RB1=1 -- RA0=1 -- RB3=1 ¡MAL!
- Si TMR0 alta prioridad, RBO baja prioridad y RB4..RB7 alta prioridad:
Secuencia: TMR0 -- RB0 -- RB7 ---> RB1=1 -- RA0=1 -- RB3=1 ¡MAL!
Secuencia: TMR0 -- RB7 -- RB0 ---> RB1=1 -- RA0=1 -- RB3=1 ¡MAL!
Las pruebas han sido realizadas con la versión del compilador 4.065
Un saludo