TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: jfmateos2 en 28 de Enero de 2008, 07:51:41

Título: No entiendo enable_interrupts(global)
Publicado por: jfmateos2 en 28 de Enero de 2008, 07:51:41
Según traduzco del manual de CCS:

"enable_interrupts(global) no habilita ninguna interrupción en concreto, pero sí activa las interrupciones que hayan sido previamente habilitadas".

¿En qué se diferencia habilitar de activar?

Imaginen que quiero usar las interrupciones INT_EXT1 e INT_TIMER1, pero que la segunda sólo esté habilitada mientas se mantiene pulsado un botón conectado a la primera. En otras palabras, que el timer1 sólo esté activo mientras el botón esté pulsado.

El código que he usado es el siguiente:

Código: [Seleccionar]
int1 botonPulsado=0;
#INT_EXT1
void int1_handler(){
   if(!botonPulsado){
      botonPulsado=1;
      ciclosTimer1=400;               
      ext_int_edge(1,L_TO_H);
      enable_interrupts(INT_TIMER1);   
      clear_interrupt(INT_TIMER1);   
      //1. ¿Debería poner aquí otro enable_interrupts(global)?
   }else{
      disable_interrupts(INT_TIMER1);
      botonPulsado=0;     
      ext_int_edge(1,H_TO_L);     

   }
}
#INT_TIMER1
void timer1_handler(){
   if(botonPulsado){ //2. Entiendo que esto no sería necesario, pues si el botón no está pulsado la interrupción timer1 estaría deshabilitada ¿no?
      if(--ciclosTimer1==0){         
         write_eeprom(0,read_eeprom(1));
         delay_ms(20);     
         reset_cpu();
      }
   }
main(){
      ext_int_edge(1,H_TO_L);
      enable_interrupts(INT_EXT1);   
      clear_interrupt(INT_EXT1);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
      enable_interrupts(INT_TIMER1); //3. ¿es necesario habilitarlo si sólo quiero que entre en funcionamiento cuando se produzca INT_EXT1?
      clear_interrupt(INT_TIMER1);
      enable_interrupts(GLOBAL);
      disable_interrupts(INT_TIMER1);//4. la deshabilito porque no quiero que entre en funcionamiento aún
      while(true){...};
}

Y una última cosa: si tengo un delay en el programa, ¿las interrupciones no esperan a que termine el delay, verdad?
Título: Re: No entiendo enable_interrupts(global)
Publicado por: Modulay en 28 de Enero de 2008, 07:59:59
En los registros de control de las interrupciones del micro hay un bit de habilitación para cada fuente de interrupción y otro que es global para todas.Para habilitar una interrupción deben estar seteados tanto uno como otro.

El enable_interrupts(global) basta con que lo pongas una vez al comienzo del programa y después trabajar con los bits de habilitación específicos para cada fuente de interrupción.

Los delays no entorpecen a las interrupciones,estas se producen si se da el caso,a no ser que el delay esté dentro de alguna rutina de atención a la interrupción,cosa que no es nada recomendable.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfh900 en 28 de Enero de 2008, 10:18:32
Podríamos añadir a lo dicho por Modulay que si tienes tropecientas mil interrupciones y quieres deshabilitarlas todas, no tienes que ir una por una, si no que con la global las deshabilitas de un plumazo.

Un saludo.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: Jorge_ en 28 de Enero de 2008, 10:22:02
Se suele utilizar cuando grabas en la memoria eeprom, así lo recomienda Microchip.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfmateos2 en 28 de Enero de 2008, 11:12:12
El problema era que tenía un delay en una interrupción pues requería escribir un dato en la EEPROM y, aunque la interrupción estaba deshabitilitada, CCS se empeñaba en deshabilitarme las interrupciones en el main para evitar la re-entrada.

Ya sé que suena raro, pero eso es lo que me parece que estaba ocurriendo. En cuanto he eliminado el delay (extrayendo la rutina de escritura de la EEPROM al main y activándola mediante un flag) todo funciona correctamente, aún no estando habilitada la interrupción.

Es como si CCS tuviera alergia a los delay en las interrupciones cuando hay bucles en el main.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: Nocturno en 28 de Enero de 2008, 11:31:13
No es bueno hacer delays dentro de interrupciones.
En tu caso, si no quieres sacar la escritura de la eeprom al main, también podrías haber dejado un while() chequeando el bit que indica que finalizó la escritura en la eeprom.
De todas formas, la solución de sacarlo al main es también muy buena.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfmateos2 en 28 de Enero de 2008, 12:04:52
Después de la escritura en la EEPROM había un reset_cpu(), por lo que no importaba demasiado el delay.

Lo que no acabo de entender es: estando la interrupción deshabilitada, por qué CCS se preocupaba de que contuviese un delay. ¡qué cosas más raras! Simplemente quito el delay y ya todo funciona bien. Sospecho que debe haber algo más...
Título: Re: No entiendo enable_interrupts(global)
Publicado por: maunix en 28 de Enero de 2008, 12:34:03
Después de la escritura en la EEPROM había un reset_cpu(), por lo que no importaba demasiado el delay.
Si importa, para que le de tiempo a la eeprom de grabarse (tipicamente entre 4 a 10mseg), de todas formas si es un 16F como en realidad no se 'resetea' funcionará igual pero con el tiempo la aplicación dejará de andar bien.

En cuanto al reset_cpu() depende para que micro lo uses, si es para un 16F lo último que había visto del assembler generado por dicha instrucción era para tener 'excesivo' cuidado.  CCS debiera (si es que no lo hizo) avisar que el uso de dicha función para los 16F debe ser solo en el main.

Si quieres ahondar en el tema, te dejo este link.

http://www.todopic.com.ar/foros/index.php?topic=13890.0


Lo que no acabo de entender es: estando la interrupción deshabilitada, por qué CCS se preocupaba de que contuviese un delay. ¡qué cosas más raras! Simplemente quito el delay y ya todo funciona bien. Sospecho que debe haber algo más...

Bueno, si estás en un 16F, irremediablemente se llenará el stack... provocando un funcionamiento errático a tu software.

Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfmateos2 en 28 de Enero de 2008, 12:41:18
Hola Maunix, es un 18F2455.

Me pongo a estudiar el hilo que me aconsejas. Muchas gracias.

Abandoné el ASM en tiempos del 6502, pero viendo que es la respuesta para todo en esto de los PIC voy a tener que volver sobre él.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: maunix en 28 de Enero de 2008, 12:54:37
Hola Maunix, es un 18F2455.

Me pongo a estudiar el hilo que me aconsejas. Muchas gracias.

Abandoné el ASM en tiempos del 6502, pero viendo que es la respuesta para todo en esto de los PIC voy a tener que volver sobre él.

El assembly ayuda a comprender el funcionamiento del hardware, pero si lees el funcionamiento del hardware, de cada módulo, etc, no te hará falta usar el assembly.   Lo digo como fan del assembly  :mrgreen: , pero es cierto cuando hay 'problemas' un profundo conocimiento de la arquitectura y del set de instrucciones ayudan bastante a detectar y resolver rápidamente un problema.

Título: Re: No entiendo enable_interrupts(global)
Publicado por: reiniertl en 28 de Enero de 2008, 13:01:47
Otra cosa, CCS tiene por costumbre deshabilitar las interrupciones cuando se entra en una ISR, de modo que no se aniden las ISR. Una vez que se atiende la ISR se vuelven a habilitar las interrupciones y como es lógico si alguna se ha activado durante la atención de la ISR anterior se atiende.

Creo que hay una directiva para evitar que CCS te deshabilite las interrupciones cuando entras en una ISR, pero ahora no recuerdo cual es.

Saludos
Reinier
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfmateos2 en 28 de Enero de 2008, 13:13:32
Gracias Maunix. Los datasheet de 400 hojas asustan un poco; sólo me leo algunas partes, pero poco a poco voy aprendiendo cosas nuevas gracias a vosotros.

Gracias reiniertl; lo investigaré.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: maunix en 28 de Enero de 2008, 13:52:48
Otra cosa, CCS tiene por costumbre deshabilitar las interrupciones cuando se entra en una ISR, de modo que no se aniden las ISR. Una vez que se atiende la ISR se vuelven a habilitar las interrupciones y como es lógico si alguna se ha activado durante la atención de la ISR anterior se atiende.
:shock:, sencillamente lo veo innecesario.  El microhardware del PIC automáticamente deshabilita el GIE al ingresar al vector de interrupción y este se rehabilita con un RETFIE.  No le veo el sentido a que el CCS además deshabilite los IE de cada interrupción en particular, jamás se encadenaran.

En un 18F puede que uno inhabilite las interrupciones de alto nivel al ingresar en el bajo nivel, es esto a lo que te refieres? pero llegado el caso no tiene sentido hacer eso porque significa que algo elegimos mal ya que deshabilitar las interrupciones de alto nivel para que las de bajo se ejecuten sin molestias es lo mismo que usar todas de bajo nivel o todas de alto nivel y listo.




Título: Re: No entiendo enable_interrupts(global)
Publicado por: Nocturno en 28 de Enero de 2008, 14:26:05
Yo diría que no se pierden, Reinier. Creo recordar que me ha pasado el caso de llegar una interrupción durante el transcurso de otra y ejecutarse si era más prioritaria, o esperar a la finalización de la actual y ejecutarse luego si era menos prioritaria.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: reiniertl en 28 de Enero de 2008, 14:35:36
Me parece que no he entendido bien el concepto, tal vez lo leí luego de un toque de carambuco (tendré que beber buen ron o me van a hechar de aquí)

Bueno nada, es probable que me haya equivocado.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: Nocturno en 28 de Enero de 2008, 15:06:45
Vamos, Reinier, que no se diga, no te pega nada el garrafón  :lol:
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfh900 en 28 de Enero de 2008, 15:27:55
Pero eso no es en todos los micros. En los de la gama baja 16F solo se admite una interrupción, no tiene prioridades.

Un saludo.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: maunix en 28 de Enero de 2008, 15:59:13
Me parece que no he entendido bien el concepto, tal vez lo leí luego de un toque de carambuco (tendré que beber buen ron o me van a hechar de aquí)

Todo bien reinier, tus intenciones son buenas y eso es lo importante, nadie duda de eso.

Manolo se pone malo cuando le tocan a diego pero no cuando alguien se equivoca  :mrgreen:

Título: Re: No entiendo enable_interrupts(global)
Publicado por: PalitroqueZ en 29 de Enero de 2008, 21:21:58
...
¿En qué se diferencia habilitar de activar?
...

hablando desde el punto de vista hardware.

yo diria que seleccionar es el término correcto en vez de habilitar.

selecciono mi fuente de interrupción y después habilito el sistema de interrupciones. Al usar GIE, el pic mira quien fué seleccionado y usa esa interrupción.



Título: Re: No entiendo enable_interrupts(global)
Publicado por: maunix en 29 de Enero de 2008, 21:50:17
Para mi activar y habilitar son sinónimos.

El término que he visto siempre usado es "máscara" de interrupción.  eso da la idea de que si está habilitada la máscara , la interrupción está habilitada y sino, no.

En el caso de los PIE son máscaras individuales, en el caso del GIE es una máscara General o Global.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: reiniertl en 29 de Enero de 2008, 21:54:45
En este caso coincido con maunix
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfmateos2 en 30 de Enero de 2008, 05:37:09
Gracias, chicos, queda clara la diferencia entre habilitar y activar.
Título: Re: No entiendo enable_interrupts(global)
Publicado por: jfh900 en 30 de Enero de 2008, 07:57:57
Para mi activar y habilitar son sinónimos.

Conceptualmente no son lo mismo.

Habilitar: es dar permiso para que la interrupción se pueda "disparar" o "activar". Por lo tanto se pone el micro en disposición de recibir interrupciones.

Activar: es la acción que desencadena la interrupción. Por ejemplo al poner una patilla a masa, podemos activar una interrupción, pero nunca podremos habilitar la interrupción.

Por consiguiente habilitar es dar permiso para que se pueda ejecutar una interrupción y ejecutar es el echo en si mísmo de la ejecución de la interrupción.

Un saludo.